[Scummvm-git-logs] scummvm master -> 9d62caa684feb2e403783a0b8f1fd11a1457436d
csnover
csnover at users.noreply.github.com
Tue Jul 18 06:56:53 CEST 2017
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
2528ecf26e SCI32: Fix playback of looped audio
afe344cc1f SCI32: Add guest additions support for LSL7
09ef11a8cb SCI32: Remove ENABLE_SCI3_GAMES ifdef, now that they are supported
ba4fccdb26 SCI32: Add workaround for Torin/LSL7 running with subtitles only
64d090dcb8 SCI32: Fix stream leaks in Audio32/SOLStream
dcb6c32215 SCI32: Destroy audio streams in Audio32 using DisposeAfterUse flag
9d62caa684 SCI32: Promote LSL7 to ADGF_TESTING
Commit: 2528ecf26e0b3767aca53019262d0c133827ddbb
https://github.com/scummvm/scummvm/commit/2528ecf26e0b3767aca53019262d0c133827ddbb
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T22:42:18-05:00
Commit Message:
SCI32: Fix playback of looped audio
This fixes at least Lighthouse audio 808 in room 270, and audio
801 in room 810.
Changed paths:
engines/sci/sound/audio32.cpp
engines/sci/sound/audio32.h
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index cfbab8b..0bef60b 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -46,6 +46,64 @@
namespace Sci {
+class MutableLoopAudioStream : public Audio::AudioStream {
+public:
+ MutableLoopAudioStream(Audio::RewindableAudioStream *stream, const bool loop_, const DisposeAfterUse::Flag dispose = DisposeAfterUse::YES) :
+ _stream(stream, dispose),
+ _loop(loop_) {}
+
+ virtual int readBuffer(int16 *buffer, int numSamples) override {
+ int totalSamplesRead = 0;
+ int samplesRead;
+ do {
+ if (_loop && _stream->endOfStream()) {
+ _stream->rewind();
+ }
+
+ samplesRead = _stream->readBuffer(buffer, numSamples);
+ totalSamplesRead += samplesRead;
+ numSamples -= samplesRead;
+ } while (samplesRead > 0 && _loop && numSamples > 0);
+ return totalSamplesRead;
+ }
+
+ virtual bool isStereo() const override {
+ return _stream->isStereo();
+ }
+
+ virtual int getRate() const override {
+ return _stream->getRate();
+ }
+
+ virtual bool endOfData() const override {
+ return !_loop && _stream->endOfData();
+ }
+
+ virtual bool endOfStream() const override {
+ return !_loop && _stream->endOfStream();
+ }
+
+ bool &loop() {
+ return _loop;
+ }
+
+ bool loop() const {
+ return _loop;
+ }
+
+ virtual Audio::Timestamp getLength() const {
+ Audio::SeekableAudioStream *stream = dynamic_cast<Audio::SeekableAudioStream *>(_stream.get());
+ if (stream == nullptr) {
+ error("Cannot get length from a non-seekable stream");
+ }
+ return stream->getLength();
+ }
+
+private:
+ Common::DisposablePtr<Audio::RewindableAudioStream> _stream;
+ bool _loop;
+};
+
bool detectSolAudio(Common::SeekableReadStream &stream) {
const size_t initialPosition = stream.pos();
@@ -138,43 +196,10 @@ Audio32::~Audio32() {
#pragma mark -
#pragma mark AudioStream implementation
-int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume, const bool loop) {
- int samplesToRead = numSamples;
-
- // The parent rate converter will request N * 2
- // samples from this `readBuffer` call, because
- // we tell it that we send stereo output, but
- // the source stream we're mixing in may be
- // mono, in which case we need to request half
- // as many samples from the mono stream and let
- // the converter double them for stereo output
- samplesToRead >>= 1;
-
- int samplesWritten = 0;
-
- do {
- if (loop && sourceStream->endOfStream()) {
- Audio::RewindableAudioStream *rewindableStream = dynamic_cast<Audio::RewindableAudioStream *>(sourceStream);
- if (rewindableStream == nullptr) {
- error("[Audio32::writeAudioInternal]: Unable to cast stream");
- }
- rewindableStream->rewind();
- }
-
- const int loopSamplesWritten = converter->flow(*sourceStream, targetBuffer, samplesToRead, leftVolume, rightVolume);
-
- if (loopSamplesWritten == 0) {
- break;
- }
-
- samplesToRead -= loopSamplesWritten;
- samplesWritten += loopSamplesWritten;
- targetBuffer += loopSamplesWritten << (sourceStream->isStereo() ? 0 : 1);
- } while (loop && samplesToRead > 0);
-
- samplesWritten <<= 1;
-
- return samplesWritten;
+int Audio32::writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume) {
+ const int samplePairsToRead = numSamples >> 1;
+ const int samplePairsWritten = converter->flow(*sourceStream, targetBuffer, samplePairsToRead, leftVolume, rightVolume);
+ return samplePairsWritten << 1;
}
int16 Audio32::getNumChannelsToMix() const {
@@ -357,7 +382,7 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
memset(_monitoredBuffer, 0, _monitoredBufferSize);
- _numMonitoredSamples = writeAudioInternal(channel.stream, channel.converter, _monitoredBuffer, numSamples, leftVolume, rightVolume, channel.loop);
+ _numMonitoredSamples = writeAudioInternal(channel.stream, channel.converter, _monitoredBuffer, numSamples, leftVolume, rightVolume);
Audio::st_sample_t *sourceBuffer = _monitoredBuffer;
Audio::st_sample_t *targetBuffer = buffer;
@@ -369,7 +394,7 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
if (_numMonitoredSamples > maxSamplesWritten) {
maxSamplesWritten = _numMonitoredSamples;
}
- } else if (!channel.stream->endOfStream() || channel.loop) {
+ } else if (!channel.stream->endOfStream()) {
if (playOnlyMonitoredChannel) {
// Audio that is not on the monitored channel is silent
// when the monitored channel is active, but the stream still
@@ -380,7 +405,7 @@ int Audio32::readBuffer(Audio::st_sample_t *const buffer, const int numSamples)
leftVolume = rightVolume = 0;
}
- const int channelSamplesWritten = writeAudioInternal(channel.stream, channel.converter, buffer, numSamples, leftVolume, rightVolume, channel.loop);
+ const int channelSamplesWritten = writeAudioInternal(channel.stream, channel.converter, buffer, numSamples, leftVolume, rightVolume);
if (channelSamplesWritten > maxSamplesWritten) {
maxSamplesWritten = channelSamplesWritten;
}
@@ -495,15 +520,7 @@ void Audio32::freeUnusedChannels() {
for (int16 channelIndex = 0; channelIndex < _numActiveChannels; ++channelIndex) {
const AudioChannel &channel = getChannel(channelIndex);
if (!channel.robot && channel.stream->endOfStream()) {
- if (channel.loop) {
- Audio::SeekableAudioStream *stream = dynamic_cast<Audio::SeekableAudioStream *>(channel.stream);
- if (stream == nullptr) {
- error("[Audio32::freeUnusedChannels]: Unable to cast stream for resource %s", channel.id.toString().c_str());
- }
- stream->rewind();
- } else {
- stop(channelIndex--);
- }
+ stop(channelIndex--);
}
}
@@ -634,7 +651,6 @@ bool Audio32::playRobotAudio(const RobotAudioStream::RobotAudioPacket &packet) {
if (isNewChannel) {
channel.id = ResourceId();
channel.resource = nullptr;
- channel.loop = false;
channel.robot = true;
channel.fadeStartTick = 0;
channel.pausedAtTick = 0;
@@ -704,7 +720,7 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
if (channelIndex != kNoExistingChannel) {
AudioChannel &channel = getChannel(channelIndex);
- Audio::SeekableAudioStream *stream = dynamic_cast<Audio::SeekableAudioStream *>(channel.stream);
+ MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
if (stream == nullptr) {
error("[Audio32::play]: Unable to cast stream for resource %s", resourceId.toString().c_str());
}
@@ -770,7 +786,6 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
AudioChannel &channel = getChannel(channelIndex);
channel.id = resourceId;
channel.resource = resource;
- channel.loop = loop;
channel.robot = false;
channel.fadeStartTick = 0;
channel.soundNode = soundNode;
@@ -784,10 +799,12 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
Common::SeekableReadStream *dataStream = channel.resourceStream = resource->makeStream();
+ Audio::RewindableAudioStream *audioStream;
+
if (detectSolAudio(*dataStream)) {
- channel.stream = makeSOLStream(dataStream, DisposeAfterUse::NO);
+ audioStream = makeSOLStream(dataStream, DisposeAfterUse::NO);
} else if (detectWaveAudio(*dataStream)) {
- channel.stream = Audio::makeWAVStream(dataStream, DisposeAfterUse::NO);
+ audioStream = Audio::makeWAVStream(dataStream, DisposeAfterUse::NO);
} else {
byte flags = Audio::FLAG_LITTLE_ENDIAN;
if (_globalBitDepth == 16) {
@@ -800,9 +817,10 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
flags |= Audio::FLAG_STEREO;
}
- channel.stream = Audio::makeRawStream(dataStream, _globalSampleRate, flags, DisposeAfterUse::NO);
+ audioStream = Audio::makeRawStream(dataStream, _globalSampleRate, flags, DisposeAfterUse::NO);
}
+ channel.stream = new MutableLoopAudioStream(audioStream, loop);
channel.converter = Audio::makeRateConverter(channel.stream->getRate(), getRate(), channel.stream->isStereo(), false);
// NOTE: SCI engine sets up a decompression buffer here for the audio
@@ -813,7 +831,7 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
// use audio streams, and allocate and fill the monitoring buffer
// when reading audio data from the stream.
- Audio::SeekableAudioStream *stream = dynamic_cast<Audio::SeekableAudioStream *>(channel.stream);
+ MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
if (stream == nullptr) {
error("[Audio32::play]: Unable to cast stream for resource %s", resourceId.toString().c_str());
}
@@ -994,7 +1012,10 @@ void Audio32::setLoop(const int16 channelIndex, const bool loop) {
}
AudioChannel &channel = getChannel(channelIndex);
- channel.loop = loop;
+
+ MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
+ assert(stream);
+ stream->loop() = loop;
}
#pragma mark -
@@ -1259,6 +1280,7 @@ void Audio32::printAudioList(Console *con) const {
Common::StackLock lock(_mutex);
for (int i = 0; i < _numActiveChannels; ++i) {
const AudioChannel &channel = _channels[i];
+ const MutableLoopAudioStream *stream = dynamic_cast<MutableLoopAudioStream *>(channel.stream);
con->debugPrintf(" %d[%04x:%04x]: %s, started at %d, pos %d/%d, vol %d, pan %d%s%s\n",
i,
PRINT_REG(channel.soundNode),
@@ -1268,7 +1290,7 @@ void Audio32::printAudioList(Console *con) const {
channel.duration,
channel.volume,
channel.pan,
- channel.loop ? ", looping" : "",
+ stream && stream->loop() ? ", looping" : "",
channel.pausedAtTick ? ", paused" : "");
if (channel.fadeStartTick) {
con->debugPrintf(" fade: vol %d -> %d, started at %d, pos %d/%d%s\n",
diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h
index 510fbc1..59f96a8 100644
--- a/engines/sci/sound/audio32.h
+++ b/engines/sci/sound/audio32.h
@@ -85,12 +85,6 @@ struct AudioChannel {
uint32 pausedAtTick;
/**
- * Whether or not the audio in this channel should loop
- * infinitely.
- */
- bool loop;
-
- /**
* The time, in ticks, that the channel fade began.
* If 0, the channel is not being faded.
*/
@@ -205,7 +199,7 @@ private:
* Mixes audio from the given source stream into the
* target buffer using the given rate converter.
*/
- int writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume, const bool loop);
+ int writeAudioInternal(Audio::AudioStream *const sourceStream, Audio::RateConverter *const converter, Audio::st_sample_t *targetBuffer, const int numSamples, const Audio::st_volume_t leftVolume, const Audio::st_volume_t rightVolume);
#pragma mark -
#pragma mark Channel management
Commit: afe344cc1f001bffc40f04f9b14f8af8b2c5349c
https://github.com/scummvm/scummvm/commit/afe344cc1f001bffc40f04f9b14f8af8b2c5349c
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T22:42:18-05:00
Commit Message:
SCI32: Add guest additions support for LSL7
Changed paths:
engines/sci/engine/features.cpp
engines/sci/engine/guest_additions.cpp
engines/sci/engine/script_patches.cpp
engines/sci/engine/selector.cpp
engines/sci/engine/selector.h
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index bddcac9..e64cf9c 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -556,6 +556,7 @@ bool GameFeatures::supportsSpeechWithSubtitles() const {
case GID_GK1:
case GID_KQ7:
case GID_LSL6HIRES:
+ case GID_LSL7:
case GID_PQ4:
case GID_QFG4:
case GID_SQ6:
@@ -573,6 +574,7 @@ bool GameFeatures::audioVolumeSyncUsesGlobals() const {
case GID_GK1:
case GID_GK2:
case GID_LSL6HIRES:
+ case GID_LSL7:
case GID_PHANTASMAGORIA:
case GID_TORIN:
// TODO: SCI3
@@ -600,6 +602,7 @@ MessageTypeSyncStrategy GameFeatures::getMessageTypeSyncStrategy() const {
return g_sci->isCD() ? kMessageTypeSyncStrategyDefault : kMessageTypeSyncStrategyNone;
case GID_KQ7:
+ case GID_LSL7:
case GID_MOTHERGOOSEHIRES:
case GID_PHANTASMAGORIA:
case GID_SQ6:
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index 873152b..2cfed13 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -141,9 +141,9 @@ bool GuestAdditions::shouldSyncAudioToScummVM() const {
objName == "dacVolDown" ||
objName == "dacVolUp")) {
return true;
- } else if (gameId == GID_TORIN && (objName == "oMusicScroll" ||
- objName == "oSFXScroll" ||
- objName == "oAudioScroll")) {
+ } else if ((gameId == GID_LSL7 || gameId == GID_TORIN) && (objName == "oMusicScroll" ||
+ objName == "oSFXScroll" ||
+ objName == "oAudioScroll")) {
return true;
#endif
}
@@ -227,7 +227,9 @@ void GuestAdditions::instantiateScriptHook(Script &script, const bool ignoreDela
return;
}
- if (g_sci->getGameId() == GID_TORIN && script.getScriptNumber() == 64866) {
+ if ((g_sci->getGameId() == GID_LSL7 || g_sci->getGameId() == GID_TORIN) &&
+ script.getScriptNumber() == 64866) {
+
patchGameSaveRestoreTorin(script);
} else if (script.getScriptNumber() == 64990) {
// 64990 is the system script containing SRDialog. This script is used
@@ -381,9 +383,9 @@ void GuestAdditions::patchGameSaveRestoreSCI32(Script &script) const {
}
static const byte SRTorinPatch[] = {
- 0x38, 0x8d, 0x00, // pushi $8d (new)
+ 0x38, 0xFF, 0xFF, // pushi new
0x76, // push0
- 0x51, 0x0f, // class $f (Str)
+ 0x51, 0x0f, // class Str
0x4a, 0x04, 0x00, // send 4
0xa3, 0x01, // sal 1
0x76, // push0
@@ -396,6 +398,12 @@ void GuestAdditions::patchGameSaveRestoreTorin(Script &script) const {
const uint32 address = script.validateExportFunc(2, true);
byte *patchPtr = const_cast<byte *>(script.getBuf(address));
memcpy(patchPtr, SRTorinPatch, sizeof(SRTorinPatch));
+
+ const Selector newSelector = SELECTOR(new_);
+ assert(newSelector != -1);
+ patchPtr[1] = newSelector & 0xFF;
+ patchPtr[2] = (newSelector >> 8) & 0xFF;
+
if (g_sci->isBE()) {
SWAP(patchPtr[1], patchPtr[2]);
SWAP(patchPtr[8], patchPtr[9]);
@@ -403,7 +411,7 @@ void GuestAdditions::patchGameSaveRestoreTorin(Script &script) const {
}
reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) const {
- if (g_sci->getGameId() == GID_TORIN) {
+ if (g_sci->getGameId() == GID_LSL7 || g_sci->getGameId() == GID_TORIN) {
return promptSaveRestoreTorin(s, argc, argv);
}
@@ -811,6 +819,7 @@ void GuestAdditions::syncAudioVolumeGlobalsFromScummVM() const {
break;
}
+ case GID_LSL7:
case GID_TORIN: {
const int16 musicVolume = (ConfMan.getInt("music_volume") + 1) * 100 / Audio::Mixer::kMaxMixerVolume;
const int16 sfxVolume = (ConfMan.getInt("sfx_volume") + 1) * 100 / Audio::Mixer::kMaxMixerVolume;
@@ -960,6 +969,7 @@ void GuestAdditions::syncAudioVolumeGlobalsToScummVM(const int index, const reg_
}
break;
+ case GID_LSL7:
case GID_TORIN:
if (index == kGlobalVarTorinMusicVolume ||
index == kGlobalVarTorinSFXVolume ||
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 8c000dd..6dcdaac 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -262,6 +262,22 @@ static const uint16 sci2BenchmarkPatch[] = {
PATCH_END
};
+// Torin/LSL7-specific version of sci2NumSavesSignature1/2
+// Applies to at least: English CD
+static const uint16 torinNumSavesSignature[] = {
+ SIG_MAGICDWORD,
+ 0x36, // push
+ 0x35, 0x14, // ldi 20
+ 0x20, // ge?
+ SIG_END
+};
+
+static const uint16 torinNumSavesPatch[] = {
+ PATCH_ADDTOOFFSET(+1), // push
+ 0x35, 0x63, // ldi 99
+ PATCH_END
+};
+
#endif
// ===========================================================================
@@ -2565,6 +2581,61 @@ static const SciScriptPatcherEntry larry6HiresSignatures[] = {
#pragma mark -
#pragma mark Leisure Suit Larry 7
+// The init code that runs when LSL7 starts up unconditionally resets the audio
+// volumes to defaults, but the game should always use the volume stored in
+// ScummVM. This patch is basically identical to the patch for Torin, except
+// that they left line numbers in the LSL7 scripts and changed the music volume.
+// Applies to at least: English CD
+static const uint16 larry7VolumeResetSignature1[] = {
+ SIG_MAGICDWORD,
+ 0x35, 0x41, // ldi $41
+ 0xa1, 0xe3, // sag $e3 (music volume)
+ 0x7e, SIG_ADDTOOFFSET(2), // line whatever
+ 0x35, 0x3c, // ldi $3c
+ 0xa1, 0xe4, // sag $e4 (sfx volume)
+ 0x7e, SIG_ADDTOOFFSET(2), // line whatever
+ 0x35, 0x64, // ldi $64
+ 0xa1, 0xe5, // sag $e5 (speech volume)
+ SIG_END
+};
+
+static const uint16 larry7VolumeResetPatch1[] = {
+ 0x33, 0x10, // jmp [past volume resets]
+ PATCH_END
+};
+
+// The init code that runs when LSL7 starts up unconditionally resets the
+// audio volumes to values stored in larry7.prf, but the game should always use
+// the volume stored in ScummVM. This patch is basically identical to the patch
+// for Torin, except that they left line numbers in the LSL7 scripts.
+// Applies to at least: English CD
+static const uint16 larry7VolumeResetSignature2[] = {
+ SIG_MAGICDWORD,
+ 0x38, SIG_UINT16(0x19d), // pushi readWord
+ 0x76, // push0
+ SIG_ADDTOOFFSET(6), // advance file stream
+ 0xa1, 0xe3, // sag $e3 (music volume)
+ SIG_ADDTOOFFSET(3), // line whatever
+ SIG_ADDTOOFFSET(10), // advance file stream
+ 0xa1, 0xe4, // sag $e4 (sfx volume)
+ SIG_ADDTOOFFSET(3), // line whatever
+ SIG_ADDTOOFFSET(10), // advance file stream
+ 0xa1, 0xe5, // sag $e5 (speech volume)
+ SIG_END
+};
+
+static const uint16 larry7VolumeResetPatch2[] = {
+ PATCH_ADDTOOFFSET(10), // advance file stream
+ 0x18, 0x18, // waste bytes
+ PATCH_ADDTOOFFSET(3), // line whatever
+ PATCH_ADDTOOFFSET(10), // advance file stream
+ 0x18, 0x18, // waste bytes
+ PATCH_ADDTOOFFSET(3), // line whatever
+ PATCH_ADDTOOFFSET(10), // advance file stream
+ 0x18, 0x18, // waste bytes
+ PATCH_END
+};
+
// ===========================================================================
// In room 540 of Leisure Suit Larry 7, Larry will use 4 items on a so called cheese maker.
// A short cutscene will then play.
@@ -2628,10 +2699,33 @@ static const uint16 larry7PatchMakeCheesePriority[] = {
PATCH_END
};
+// LSL7 tries to reset the message type twice at startup, first with a default
+// value in script 0, then with a stored value from larry7.prf (if that file
+// exists) or the same default value (if it does not) in script 64000. Since
+// message type sync relies on the game only setting this value once at startup,
+// we must stop the second attempt or the value from ScummVM will be
+// overwritten.
+// Applies to at least: English CD
+static const uint16 larry7MessageTypeResetSignature[] = {
+ SIG_MAGICDWORD,
+ 0x35, 0x02, // ldi 2
+ 0xa1, 0x5a, // sag $5a
+ SIG_END
+};
+
+static const uint16 larry7MessageTypeResetPatch[] = {
+ 0x33, 0x02, // jmp [past reset]
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry larry7Signatures[] = {
+ { true, 0, "disable message type reset on startup", 1, larry7MessageTypeResetSignature, larry7MessageTypeResetPatch },
{ true, 540, "fix make cheese cutscene (cycler)", 1, larry7SignatureMakeCheese, larry7PatchMakeCheese },
{ true, 540, "fix make cheese cutscene (priority)", 1, larry7SignatureMakeCheesePriority, larry7PatchMakeCheesePriority },
+ { true, 64000, "disable volume reset on startup 1/2", 1, larry7VolumeResetSignature1, larry7VolumeResetPatch1 },
+ { true, 64000, "disable volume reset on startup 2/2", 1, larry7VolumeResetSignature2, larry7VolumeResetPatch2 },
+ { true, 64866, "increase number of save games", 1, torinNumSavesSignature, torinNumSavesPatch },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -5652,8 +5746,9 @@ static const SciScriptPatcherEntry sq6Signatures[] = {
#pragma mark Torins Passage
// The init code that runs when Torin starts up unconditionally resets the
-// master music volume to defaults, but the game should always use the volume
-// stored in ScummVM.
+// audio volumes to defaults, but the game should always use the volume stored
+// in ScummVM. This patch is basically identical to the patch for LSL7, except
+// that they left line numbers in the LSL7 scripts and changed the music volume.
// Applies to at least: English CD
static const uint16 torinVolumeResetSignature1[] = {
SIG_MAGICDWORD,
@@ -5672,8 +5767,9 @@ static const uint16 torinVolumeResetPatch1[] = {
};
// The init code that runs when Torin starts up unconditionally resets the
-// master music volume to values stored in torin.prf, but the game should always
-// use the volume stored in ScummVM.
+// audio volumes to values stored in torin.prf, but the game should always use
+// the volume stored in ScummVM. This patch is basically identical to the patch
+// for LSL7, except that they left line numbers in the LSL7 scripts.
// Applies to at least: English CD
static const uint16 torinVolumeResetSignature2[] = {
SIG_MAGICDWORD,
@@ -5698,22 +5794,6 @@ static const uint16 torinVolumeResetPatch2[] = {
PATCH_END
};
-// Torin-specific version of sci2NumSavesSignature1/2
-// Applies to at least: English CD
-static const uint16 torinNumSavesSignature[] = {
- SIG_MAGICDWORD,
- 0x36, // push
- 0x35, 0x14, // ldi 20
- 0x20, // ge?
- SIG_END
-};
-
-static const uint16 torinNumSavesPatch[] = {
- PATCH_ADDTOOFFSET(+1), // push
- 0x35, 0x63, // ldi 99
- PATCH_END
-};
-
// In Escarpa, it is possible for Boogle to be left outside of Torin's bag
// when fast-forwarding through the exit animation of the seraglio. If this
// happens, when the player goes from the seraglio to the dragon's cave and then
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index e28ae79..9c6921b 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -217,6 +217,7 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(setPos);
FIND_SELECTOR(setSize);
FIND_SELECTOR(displayValue);
+ FIND_SELECTOR2(new_, "new");
#endif
}
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index 1db9e4b..d97a883 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -174,6 +174,7 @@ struct SelectorCache {
Selector setPos; // for Torin volume sync
Selector setSize; // for PQ4 volume sync
Selector displayValue; // for PQ:SWAT volume sync
+ Selector new_; // for Torin/LSL7 save/load patching
#endif
};
Commit: 09ef11a8cbd86375458d0ea8efd3a2e770dd3b89
https://github.com/scummvm/scummvm/commit/09ef11a8cbd86375458d0ea8efd3a2e770dd3b89
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T22:42:18-05:00
Commit Message:
SCI32: Remove ENABLE_SCI3_GAMES ifdef, now that they are supported
Changed paths:
engines/sci/detection_tables.h
engines/sci/graphics/palette32.cpp
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index ab504cb..5a5c878 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -24,9 +24,6 @@ namespace Sci {
#include "sci/sci.h"
-// SCI3 games have a different script format (in CSC files) and are currently unsupported
-#define ENABLE_SCI3_GAMES
-
#define FANMADE_L(name, resMapMd5, resMapSize, resMd5, resSize, lang) \
{"sci-fanmade", name, { \
{"resource.map", 0, resMapMd5, resMapSize}, \
@@ -2710,7 +2707,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO_LSL7_DEMO },
-#ifdef ENABLE_SCI3_GAMES
// Larry 7 - English DOS CD (from spookypeanut)
// SCI interpreter version 3.000.000
{"lsl7", "", {
@@ -2754,8 +2750,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#undef GUIO_LSL7_DEMO
#undef GUIO_LSL7
-#endif
-
// TODO: Correct GUIOs
#define GUIO_LIGHTHOUSE_DEMO GUIO3(GUIO_NOSPEECH, \
GUIO_NOASPECT, \
@@ -2773,7 +2767,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO_LIGHTHOUSE_DEMO },
-#ifdef ENABLE_SCI3_GAMES
// Lighthouse - English Windows Demo
// Executable scanning reports "3.000.000", VERSION file reports "1.00"
{"lighthouse", "Demo", {
@@ -2825,8 +2818,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#undef GUIO_LIGHTHOUSE_DEMO
#undef GUIO_LIGHTHOUSE
-#endif // ENABLE_SCI3_GAMES
-
#endif // ENABLE_SCI32
// Mixed-Up Fairy Tales v1.000 - English DOS Non-Interactive Demo
@@ -3133,8 +3124,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#undef GUIO_PHANTASMAGORIA
#undef GUIO_PHANTASMAGORIA_MAC
-#ifdef ENABLE_SCI3_GAMES
-
// TODO: Correct GUIOs
#define GUIO_PHANTASMAGORIA2 GUIO5(GUIO_NOASPECT, \
GUIO_NOMIDI, \
@@ -3238,7 +3227,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
//{"ressfx.001", 0, "343a6ca9ddd614541b11b155de6368ac", 90268706},
AD_LISTEND},
Common::JA_JPN, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO_PHANTASMAGORIA2 },
-#endif // ENABLE_SCI3_GAMES
#endif // ENABLE_SCI32
@@ -4002,7 +3990,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformWindows, ADGF_DEMO | ADGF_UNSTABLE, GUIO_RAMA_DEMO },
-#ifdef ENABLE_SCI3_GAMES
// RAMA - English Windows (from jvprat)
// Executable scanning reports "3.000.000", VERSION file reports "1.100.000"
{"rama", "", {
@@ -4060,8 +4047,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#undef GUIO_RAMA_DEMO
#undef GUIO_RAMA
-#endif // ENABLE_SCI3_GAMES
-
#define GUIO_SHIVERS_DEMO GUIO6(GUIO_NOSUBTITLES, \
GUIO_NOMIDI, \
GUIO_NOLAUNCHLOAD, \
diff --git a/engines/sci/graphics/palette32.cpp b/engines/sci/graphics/palette32.cpp
index 0ea64d6..4b008dd 100644
--- a/engines/sci/graphics/palette32.cpp
+++ b/engines/sci/graphics/palette32.cpp
@@ -391,9 +391,6 @@ static const uint8 gammaTables[GfxPalette32::numGammaTables][256] = {
}
GfxPalette32::~GfxPalette32() {
-#ifdef ENABLE_SCI3_GAMES
- unloadClut();
-#endif
varyOff();
cycleAllOff();
}
Commit: ba4fccdb26ff050fad32d24956e9eba7e8fa6268
https://github.com/scummvm/scummvm/commit/ba4fccdb26ff050fad32d24956e9eba7e8fa6268
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T23:56:21-05:00
Commit Message:
SCI32: Add workaround for Torin/LSL7 running with subtitles only
Since these later SCI32 games weren't really designed to work with
subtitles-only message mode, if this doesn't work consistently or
breaks the games a lot in other places, the subtitles-only message
type could possibly be implemented in some other way, like by
messing with the game's speech volume global instead.
Changed paths:
engines/sci/engine/workarounds.cpp
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index a43df75..9eab4b3 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -348,6 +348,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_LSL6HIRES, -1, 85, 0, "washcloth", "doVerb", NULL, 0, { WORKAROUND_FAKE, 0 } }, // when interacting with the wet washcloth in the inventory - Trac#9811
{ GID_LSL6HIRES, -1, 64950, 1, "Feature", "handleEvent", NULL, 0, { WORKAROUND_FAKE, 0 } }, // at least when entering swimming pool area
{ GID_LSL6HIRES, -1, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // during the game
+ { GID_LSL7, -1, 64029, 0, "oMessager", "nextMsg", NULL, 4, { WORKAROUND_FAKE, 0 } }, // when running the game with subtitles only
{ GID_LSL7, -1, 64017, 0, "oFlags", "clear", NULL, 0, { WORKAROUND_FAKE, 0 } }, // demo version, when it starts, and whenever the player chooses to go to the "Strip Liar's Dice" mini game
{ GID_LSL7, -1, 64017, 0, "oActorFlags", "clear", NULL, 0, { WORKAROUND_FAKE, 0 } }, // after an NPC walks off the left side of the screen at the Clothing Optional Pool
{ GID_LSL7, -1, 64892, 0, "oEventHandler", "killAllEventHogs", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when looking at the swordfish in the kitchen
@@ -423,7 +424,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_SQ6, -1, 64994, -1, "Game", "restore", NULL, 1, { WORKAROUND_FAKE, 0 } }, // When trying to load an invalid save game from the launcher
{ GID_SQ6, -1, 64921, -1, "Print", "addEdit", NULL, 1, { WORKAROUND_FAKE, 0 } }, // When trying to use the game debugger's flag setting command
{ GID_TORIN, -1, 64017, 0, "oFlags", "clear", NULL, 0, { WORKAROUND_FAKE, 0 } }, // entering Torin's home in the French version
- { GID_TORIN, 10000, 64029, 0, "oMessager", "nextMsg", NULL, 3, { WORKAROUND_FAKE, 0 } }, // start of chapter one
+ { GID_TORIN, -1, 64029, 0, "oMessager", "nextMsg", NULL, 3, { WORKAROUND_FAKE, 0 } }, // start of chapter one, or when running with subtitles only
{ GID_TORIN, -1, 64892, 0, "oEventHandler", "killAllEventHogs", NULL, 1, { WORKAROUND_FAKE, 0 } }, // when pressing the hint button when the game is about to transition to a new room (race condition) - Trac#9810
{ GID_TORIN, 20100, 64964, 0, "DPath", "init", NULL, 1, { WORKAROUND_FAKE, 0 } }, // going down the cliff at the first screen of chapter 2 (washing area)
{ GID_TORIN, 61100, 64888, 0, "Torin", "autorestore", NULL, 11, { WORKAROUND_FAKE, 0 } }, // after attempting to restore a save game saved with the wrong game version
Commit: 64d090dcb82377daa09587f92b7c00c8f96b3a0c
https://github.com/scummvm/scummvm/commit/64d090dcb82377daa09587f92b7c00c8f96b3a0c
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T23:56:21-05:00
Commit Message:
SCI32: Fix stream leaks in Audio32/SOLStream
makeSOLStream was leaking the SeekableSubReadStream object it
creates itself if it was not called with DisposeAfterUse::YES. That
substream is an implementation detail which should not rely on
the caller to be destroyed.
Changed paths:
engines/sci/sound/decoders/sol.cpp
diff --git a/engines/sci/sound/decoders/sol.cpp b/engines/sci/sound/decoders/sol.cpp
index d060fae..50d353c 100644
--- a/engines/sci/sound/decoders/sol.cpp
+++ b/engines/sci/sound/decoders/sol.cpp
@@ -254,20 +254,20 @@ Audio::SeekableAudioStream *makeSOLStream(Common::SeekableReadStream *stream, Di
if (flags & kCompressed) {
if (flags & kStereo && flags & k16Bit) {
- return new SOLStream<true, true, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), disposeAfterUse, sampleRate, dataSize);
+ return new SOLStream<true, true, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), DisposeAfterUse::YES, sampleRate, dataSize);
} else if (flags & kStereo) {
if (getSciVersion() < SCI_VERSION_2_1_EARLY) {
error("SCI2 and earlier did not support stereo SOL audio");
}
- return new SOLStream<true, false, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), disposeAfterUse, sampleRate, dataSize);
+ return new SOLStream<true, false, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), DisposeAfterUse::YES, sampleRate, dataSize);
} else if (flags & k16Bit) {
- return new SOLStream<false, true, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), disposeAfterUse, sampleRate, dataSize);
+ return new SOLStream<false, true, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), DisposeAfterUse::YES, sampleRate, dataSize);
} else {
if (getSciVersion() < SCI_VERSION_2_1_EARLY) {
- return new SOLStream<false, false, true>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), disposeAfterUse, sampleRate, dataSize);
+ return new SOLStream<false, false, true>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), DisposeAfterUse::YES, sampleRate, dataSize);
} else {
- return new SOLStream<false, false, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), disposeAfterUse, sampleRate, dataSize);
+ return new SOLStream<false, false, false>(new Common::SeekableSubReadStream(stream, initialPosition, initialPosition + dataSize, disposeAfterUse), DisposeAfterUse::YES, sampleRate, dataSize);
}
}
}
Commit: dcb6c3221523b19857d0f5fcbb7409140a80e903
https://github.com/scummvm/scummvm/commit/dcb6c3221523b19857d0f5fcbb7409140a80e903
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T23:56:21-05:00
Commit Message:
SCI32: Destroy audio streams in Audio32 using DisposeAfterUse flag
Since Resource::makeStream returns a MemoryReadStream which will
not attempt to free the resource memory, it is fine to always
dispose those streams and get rid of the separate resourceStream
property, which was a holdover from some past WIP resource design
which no longer exists.
Changed paths:
engines/sci/sound/audio32.cpp
engines/sci/sound/audio32.h
diff --git a/engines/sci/sound/audio32.cpp b/engines/sci/sound/audio32.cpp
index 0bef60b..04d1a47 100644
--- a/engines/sci/sound/audio32.cpp
+++ b/engines/sci/sound/audio32.cpp
@@ -557,8 +557,6 @@ void Audio32::freeChannel(const int16 channelIndex) {
channel.resource = nullptr;
delete channel.stream;
channel.stream = nullptr;
- delete channel.resourceStream;
- channel.resourceStream = nullptr;
}
delete channel.converter;
@@ -797,14 +795,14 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
_monitoredChannelIndex = channelIndex;
}
- Common::SeekableReadStream *dataStream = channel.resourceStream = resource->makeStream();
+ Common::SeekableReadStream *dataStream = resource->makeStream();
Audio::RewindableAudioStream *audioStream;
if (detectSolAudio(*dataStream)) {
- audioStream = makeSOLStream(dataStream, DisposeAfterUse::NO);
+ audioStream = makeSOLStream(dataStream, DisposeAfterUse::YES);
} else if (detectWaveAudio(*dataStream)) {
- audioStream = Audio::makeWAVStream(dataStream, DisposeAfterUse::NO);
+ audioStream = Audio::makeWAVStream(dataStream, DisposeAfterUse::YES);
} else {
byte flags = Audio::FLAG_LITTLE_ENDIAN;
if (_globalBitDepth == 16) {
@@ -817,7 +815,7 @@ uint16 Audio32::play(int16 channelIndex, const ResourceId resourceId, const bool
flags |= Audio::FLAG_STEREO;
}
- audioStream = Audio::makeRawStream(dataStream, _globalSampleRate, flags, DisposeAfterUse::NO);
+ audioStream = Audio::makeRawStream(dataStream, _globalSampleRate, flags, DisposeAfterUse::YES);
}
channel.stream = new MutableLoopAudioStream(audioStream, loop);
diff --git a/engines/sci/sound/audio32.h b/engines/sci/sound/audio32.h
index 59f96a8..a994113e 100644
--- a/engines/sci/sound/audio32.h
+++ b/engines/sci/sound/audio32.h
@@ -52,11 +52,6 @@ struct AudioChannel {
Resource *resource;
/**
- * Data stream containing the raw audio for the channel.
- */
- Common::SeekableReadStream *resourceStream;
-
- /**
* The audio stream loaded into this channel. Can cast
* to `SeekableAudioStream` for normal channels and
* `RobotAudioStream` for robot channels.
Commit: 9d62caa684feb2e403783a0b8f1fd11a1457436d
https://github.com/scummvm/scummvm/commit/9d62caa684feb2e403783a0b8f1fd11a1457436d
Author: Colin Snover (github.com at zetafleet.com)
Date: 2017-07-17T23:56:22-05:00
Commit Message:
SCI32: Promote LSL7 to ADGF_TESTING
Changed paths:
engines/sci/detection_tables.h
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 5a5c878..4d8290d 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -2705,7 +2705,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"ressci.000", 0, "5cc6159688b2dc03790a67c90ccc67f9", 10195878},
{"resmap.000", 0, "6a2b2811eef82e87cde91cf1de845af8", 2695},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_UNSTABLE, GUIO_LSL7_DEMO },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_DEMO | ADGF_TESTING, GUIO_LSL7_DEMO },
// Larry 7 - English DOS CD (from spookypeanut)
// SCI interpreter version 3.000.000
@@ -2713,7 +2713,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "eae93e1b1d1ccc58b4691c371281c95d", 8188},
{"ressci.000", 0, "89353723488219e25589165d73ed663e", 66965678},
AD_LISTEND},
- Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO_LSL7 },
+ Common::EN_ANY, Common::kPlatformDOS, ADGF_CD | ADGF_TESTING, GUIO_LSL7 },
// Larry 7 - German DOS (from Tobis87)
// SCI interpreter version 3.000.000
@@ -2721,7 +2721,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "c11e6bfcfc2f2d05da47e5a7df3e9b1a", 8188},
{"ressci.000", 0, "a8c6817bb94f332ff498a71c8b47f893", 66971724},
AD_LISTEND},
- Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO_LSL7 },
+ Common::DE_DEU, Common::kPlatformDOS, ADGF_CD | ADGF_TESTING, GUIO_LSL7 },
// Larry 7 - French DOS (provided by richiefs in bug report #2670691)
// SCI interpreter version 3.000.000
@@ -2729,7 +2729,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "4407849fd52fe3efb0c30fba60cd5cd4", 8206},
{"ressci.000", 0, "dc37c3055fffbefb494ff22b145d377b", 66964472},
AD_LISTEND},
- Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO_LSL7 },
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_CD | ADGF_TESTING, GUIO_LSL7 },
// Larry 7 - Italian DOS CD (from glorifindel)
// SCI interpreter version 3.000.000
@@ -2737,7 +2737,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "9852a97141f789413f29bf956052acdb", 8212},
{"ressci.000", 0, "440b9fed89590abb4e4386ed6f948ee2", 67140181},
AD_LISTEND},
- Common::IT_ITA, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO_LSL7 },
+ Common::IT_ITA, Common::kPlatformDOS, ADGF_CD | ADGF_TESTING, GUIO_LSL7 },
// Larry 7 - Spanish DOS (from the Leisure Suit Larry Collection)
// Executable scanning reports "3.000.000", VERSION file reports "1.0s"
@@ -2745,7 +2745,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{"resmap.000", 0, "8f3d603e1acc834a5d598b30cdfc93f3", 8188},
{"ressci.000", 0, "32792f9bc1bf3633a88b382bb3f6e40d", 67071418},
AD_LISTEND},
- Common::ES_ESP, Common::kPlatformDOS, ADGF_CD | ADGF_UNSTABLE, GUIO_LSL7 },
+ Common::ES_ESP, Common::kPlatformDOS, ADGF_CD | ADGF_TESTING, GUIO_LSL7 },
#undef GUIO_LSL7_DEMO
#undef GUIO_LSL7
More information about the Scummvm-git-logs
mailing list