[Scummvm-git-logs] scummvm master -> aa209212aa9e59350ec43b2180d98b897d9e7e1d

bluegr noreply at scummvm.org
Mon Sep 28 09:21:59 UTC 2026


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

Summary:
80009088ac MOHAWK: Zoombini - Add loop support on tSND
2eadd9b5db MOHAWK: Wrap makeMohawkWaveStream signature
e6ed831fa6 MOHAWK: Zoombini - Clarify tSND loop comments
aa209212aa MOHAWK: Zoombini - Infinite loop support on tSND (2)


Commit: 80009088ac2e194974050a359b44bed45a31ec18
    https://github.com/scummvm/scummvm/commit/80009088ac2e194974050a359b44bed45a31ec18
Author: Hajin Jang (jb6804 at naver.com)
Date: 2026-09-28T12:21:52+03:00

Commit Message:
MOHAWK: Zoombini - Add loop support on tSND

Assisted-by: Codex:gpt-5.6

Changed paths:
    engines/mohawk/sound.cpp
    engines/mohawk/sound.h


diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index f87c3612b57..acf1e25fc89 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -109,13 +109,30 @@ void scanAndFixAudioPops(DataChunk &dataChunk, uint32 &dataSize, Common::Seekabl
 	}
 }
 
-Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) {
+/**
+ * Decode an MHWK/WAVE resource and optionally export a supported loop range.
+ *
+ * Loop metadata stays separate from the returned decoder stream so existing
+ * callers retain the public rewindable-stream contract.
+ * Zoombini playback always requests @p loopInfo and applies the exported
+ * infinite loop.
+ *
+ * @param stream The resource stream, which is consumed and deleted.
+ * @param cueList Optional destination for parsed Cue# entries.
+ * @param loopInfo Optional destination for a validated embedded-loop range.
+ * @return The decoded seekable stream, or nullptr when decoding fails.
+ */
+Audio::SeekableAudioStream *makeMohawkWaveStream(
+		Common::SeekableReadStream *stream, CueList *cueList,
+		MohawkWaveLoopInfo *loopInfo) {
 	uint32 tag = 0;
 	ADPCMStatus adpcmStatus;
 	DataChunk dataChunk;
 	uint32 dataSize = 0;
 
 	memset(&dataChunk, 0, sizeof(DataChunk));
+	if (loopInfo)
+		*loopInfo = MohawkWaveLoopInfo();
 
 	if (stream->readUint32BE() != ID_MHWK) // MHWK tag again
 		error ("Could not find tag 'MHWK'");
@@ -199,8 +216,10 @@ Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *s
 				break;
 			case ID_DATA:
 				debug(2, "Found Tag DATA");
-				// We subtract 20 from the actual chunk size, which is the total size
-				// of the chunk's header
+				// The Data payload begins with a 20-byte big-endian format header.
+				// The declared chunk size includes this header.
+				// loopStart is inclusive and loopEnd is exclusive.
+				// Both loop positions use source sample frames rather than byte offsets.
 				dataSize = stream->readUint32BE() - 20;
 				dataChunk.sampleRate = stream->readUint16BE();
 				dataChunk.sampleCount = stream->readUint32BE();
@@ -211,21 +230,14 @@ Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *s
 				dataChunk.loopStart = stream->readUint32BE();
 				dataChunk.loopEnd = stream->readUint32BE();
 
-			// For unsigned 8-bit PCM, check for and fix a potential pop/click at the end of the sample.
-			if (dataChunk.encoding == kCodecRaw && dataChunk.bitsPerSample == 8 && dataChunk.sampleCount >= 4) {
-				MohawkEngine *mohawkEngine = static_cast<MohawkEngine *>(g_engine);
-				const char *gameId = mohawkEngine->getGameId();
-				// Myst does not have pops and Riven does not have unsigned 8-bit PCM and so is ignored.
-				if (strcmp(gameId, "myst") != 0 && strcmp(gameId, "riven") != 0 && ConfMan.getBool("fix_audio_pops")) {
-					scanAndFixAudioPops(dataChunk, dataSize, stream);
+				// For unsigned 8-bit PCM, check for and fix a potential pop/click at the end of the sample.
+				if (dataChunk.encoding == kCodecRaw && dataChunk.bitsPerSample == 8 && dataChunk.sampleCount >= 4) {
+					MohawkEngine *mohawkEngine = static_cast<MohawkEngine *>(g_engine);
+					const char *gameId = mohawkEngine->getGameId();
+					// Myst does not have pops and Riven does not have unsigned 8-bit PCM and so is ignored.
+					if (strcmp(gameId, "myst") != 0 && strcmp(gameId, "riven") != 0 && ConfMan.getBool("fix_audio_pops"))
+						scanAndFixAudioPops(dataChunk, dataSize, stream);
 				}
-			}
-
-				// NOTE: We currently ignore all of the loop parameters here. Myst uses the
-				// loopCount variable but the loopStart and loopEnd are always 0 and the size of
-				// the sample. Myst ME doesn't use the Mohawk Sound format and just standard WAVE
-				// files and therefore does not contain any of this metadata and we have to specify
-				// whether or not to loop elsewhere.
 
 				dataChunk.audioData = stream->readStream(dataSize);
 				break;
@@ -251,6 +263,21 @@ Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *s
 		else
 			flags |= Audio::FLAG_UNSIGNED;
 
+		// Publish only the verified raw 8-bit infinite-loop form.
+		// Available Zoombini looped SND resources use this form.
+		// Finite loops are not published because
+		// @ref Audio::SubLoopingAudioStream ends at the exclusive loop end
+		// after its final iteration instead of continuing through the tail.
+		// Validate after the optional pop fix so the exclusive loop end cannot
+		// exceed a truncated sample payload.
+		if (loopInfo && dataChunk.bitsPerSample == 8 &&
+			dataChunk.loopCount == 0xFFFF &&
+			dataChunk.loopStart < dataChunk.loopEnd &&
+			dataChunk.loopEnd <= dataChunk.sampleCount) {
+			loopInfo->start = dataChunk.loopStart;
+			loopInfo->end = dataChunk.loopEnd;
+		}
+
 		return Audio::makeRawStream(dataChunk.audioData, dataChunk.sampleRate, flags);
 	} else if (dataChunk.encoding == kCodecADPCM) {
 		uint32 blockAlign = dataChunk.channels * dataChunk.bitsPerSample / 8;
@@ -268,7 +295,7 @@ Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *s
 	return nullptr;
 }
 
-Sound::Sound(MohawkEngine* vm) :
+Sound::Sound(MohawkEngine *vm) :
 		_vm(vm) {
 }
 
@@ -276,12 +303,12 @@ Sound::~Sound() {
 	stopSound();
 }
 
-Audio::RewindableAudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
-	Audio::RewindableAudioStream *audStream = nullptr;
+Audio::SeekableAudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList, MohawkWaveLoopInfo *loopInfo) {
+	Audio::SeekableAudioStream *audStream = nullptr;
 
 	switch (_vm->getGameType()) {
 	case GType_ZOOMBINI:
-		audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id));
+		audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id), cueList, loopInfo);
 		break;
 	case GType_LIVINGBOOKSV1:
 		audStream = makeLivingBooksWaveStream_v1(_vm->getResource(ID_WAV, id));
@@ -302,18 +329,30 @@ Audio::RewindableAudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList
 Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop, CueList *cueList) {
 	debug (0, "Playing sound %d", id);
 
-	Audio::RewindableAudioStream *rewindStream = makeAudioStream(id, cueList);
+	MohawkWaveLoopInfo loopInfo;
+	Audio::SeekableAudioStream *seekableStream = makeAudioStream(id, cueList, &loopInfo);
 
-	if (rewindStream) {
+	if (seekableStream) {
 		SndHandle *handle = getHandle();
 		handle->type = kUsedHandle;
 		handle->id = id;
-		handle->samplesPerSecond = rewindStream->getRate();
-
-		// Set the stream to loop here if it's requested
-		Audio::AudioStream *audStream = rewindStream;
-		if (loop)
-			audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
+		handle->samplesPerSecond = seekableStream->getRate();
+
+		// Logical Journey of the Zoombinis make use of loop.
+		// Playback starts with the resource prefix from frame zero.
+		// Reaching the exported exclusive end then seeks to the inclusive start.
+		// @ref Audio::SubLoopingAudioStream uses zero iterations to mean an infinite loop.
+		// It takes ownership of the decoded seekable stream. The mixer owns the wrapper.
+		// The ordinary whole-resource loop policy remains the fallback
+		// only when the resource has no supported embedded loop.
+		Audio::AudioStream *audStream = seekableStream;
+		if (loopInfo.isValid()) {
+			audStream = new Audio::SubLoopingAudioStream(seekableStream, 0,
+				Audio::Timestamp(0, loopInfo.start, seekableStream->getRate()),
+				Audio::Timestamp(0, loopInfo.end, seekableStream->getRate()));
+		} else if (loop) { // Set the stream to loop here if it's requested
+			audStream = Audio::makeLoopingAudioStream(seekableStream, 0);
+		}
 
 		_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle->handle, audStream, -1, volume);
 		return &handle->handle;
@@ -322,7 +361,7 @@ Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop, CueList
 	return nullptr;
 }
 
-Audio::RewindableAudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
+Audio::SeekableAudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
 	uint16 header = stream->readUint16BE();
 	uint16 rate = 0;
 	uint32 size = 0;
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index f5553c5b7c9..51bebc9d0c3 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -33,7 +33,7 @@ class MidiDriver;
 class MidiParser;
 
 namespace Audio {
-class RewindableAudioStream;
+class SeekableAudioStream;
 }
 
 namespace Mohawk {
@@ -45,35 +45,83 @@ enum SndHandleType {
 	kUsedHandle
 };
 
+/**
+ * Tracks one mixer playback instance created by @ref Mohawk::Sound.
+ *
+ * The sound manager reuses an entry after its mixer handle becomes inactive.
+ * Resource identity and sample rate are retained separately because the mixer
+ * handle does not expose the Mohawk SND ID or a source-frame position.
+ */
 struct SndHandle {
+	/** Mixer handle used to stop the instance and query its playback state. */
 	Audio::SoundHandle handle;
+	/** Allocation state of this entry in @ref Mohawk::Sound::_handles. */
 	SndHandleType type;
+	/** Source sample rate used to convert elapsed milliseconds to sample frames. */
 	uint samplesPerSecond;
+	/** Mohawk SND resource ID associated with the active mixer instance. */
 	uint16 id;
 };
 
-struct ADPCMStatus { // Holds ADPCM status data, but is irrelevant for us.
+/**
+ * Parsed contents of an MHWK/WAVE ADPC seek-state chunk.
+ *
+ * Each item captures enough per-channel decoder state to resume ADPCM decoding
+ * at a particular source sample frame. The current decoder parses and validates
+ * these records but does not yet use them for seeking.
+ */
+struct ADPCMStatus {
+	/** Serialized ADPC chunk payload size in bytes. */
 	uint32 size;
+	/** Number of seek-state records stored in @ref Mohawk::ADPCMStatus::statusItems. */
 	uint16 itemCount;
+	/** Number of channel states serialized in each seek-state record. */
 	uint16 channels;
 
+	/** Decoder state associated with one source sample-frame position. */
 	struct StatusItem {
+		/** Source sample frame at which this decoder state becomes valid. */
 		uint32 sampleFrame;
+		/** Predictor and step-table state needed to resume one ADPCM channel. */
 		struct {
+			/** Most recently decoded sample, used as the ADPCM predictor. */
 			int16 last;
+			/** Index into the ADPCM step-size table. */
 			uint16 stepIndex;
+		/**
+		 * Per-channel decoder state.
+		 *
+		 * Only the first @ref Mohawk::ADPCMStatus::channels entries are serialized.
+		 */
 		} channelStatus[MAX_CHANNELS];
-	} *statusItems;
+	} *statusItems; /**< Dynamically allocated array containing
+	                * @ref Mohawk::ADPCMStatus::itemCount records.
+	                * The MHWK decoder owns this array while parsing the ADPC
+	                * chunk and releases it immediately because ADPCM seeking
+	                * is not currently implemented.
+	                */
 };
 
+/** One named synchronization point parsed from an MHWK/WAVE Cue# chunk. */
 struct CueListPoint {
+	/** Source sample frame at which the cue occurs. */
 	uint32 sampleFrame;
+	/** Serialized cue label used by consumers to identify the synchronization point. */
 	Common::String name;
 };
 
+/**
+ * Parsed synchronization-point list from an MHWK/WAVE Cue# chunk.
+ *
+ * Callers may use these points to synchronize animation or other game state
+ * with sound playback.
+ */
 struct CueList {
+	/** Serialized Cue# chunk payload size in bytes. */
 	uint32 size;
+	/** Number of cue records declared by the chunk. */
 	uint16 pointCount;
+	/** Cue records in their serialized order. */
 	Common::Array<CueListPoint> points;
 };
 
@@ -83,24 +131,92 @@ enum {
 	kCodecMPEG2 = 2
 };
 
+/**
+ * Parsed state for the 20-byte MHWK/WAVE Data header and its payload.
+ *
+ * The loop positions are source sample-frame positions, not byte offsets.
+ * @ref Mohawk::DataChunk::loopStart is inclusive.
+ * @ref Mohawk::DataChunk::loopEnd is exclusive and must not exceed
+ * @ref Mohawk::DataChunk::sampleCount.
+ *
+ * A loop count of zero disables the embedded loop.
+ * A loop count of 0xFFFF requests an infinite loop.
+ * Another nonzero value requests that many additional passes through the
+ * loop range.
+ *
+ * Zoombini playback applies every supported embedded infinite loop automatically.
+ * Finite loop counts remain parsed but are not yet applied by the ScummVM stream wrapper.
+ */
 struct DataChunk {
+	/** Number of source sample frames played per second. */
 	uint16 sampleRate;
+	/** Total number of source sample frames declared by the Data header. */
 	uint32 sampleCount;
+	/** Number of encoded bits for each sample in one channel. */
 	byte bitsPerSample;
+	/** Number of interleaved audio channels in each source sample frame. */
 	byte channels;
+	/**
+	 * Payload codec, using @ref Mohawk::kCodecRaw,
+	 * @ref Mohawk::kCodecADPCM, or @ref Mohawk::kCodecMPEG2.
+	 */
 	uint16 encoding;
-	uint16 loopCount; // 0 == no looping, 0xFFFF == infinite loop
+	/**
+	 * Number of requested repeats for the embedded loop range.
+	 *
+	 * 0x0000 disables looping, 0xFFFF is an infinite loop.
+	 */
+	uint16 loopCount;
+	/** Inclusive source sample frame at which an embedded loop begins. */
 	uint32 loopStart;
+	/** Exclusive source sample frame at which playback returns to @ref DataChunk::loopStart. */
 	uint32 loopEnd;
+	/**
+	 * Stream containing only the encoded sample payload after the Data header.
+	 *
+	 * Ownership transfers to the codec-specific audio stream factory.
+	 */
 	Common::SeekableReadStream *audioData;
 };
 
-Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = nullptr);
+/**
+ * Embedded-loop range exported by the MHWK decoder.
+ *
+ * Both positions use source sample frames.
+ * @ref Mohawk::MohawkWaveLoopInfo::start is inclusive.
+ * @ref Mohawk::MohawkWaveLoopInfo::end is exclusive.
+ * An empty range means that the resource has no supported embedded loop.
+ */
+struct MohawkWaveLoopInfo {
+	uint32 start = 0;
+	uint32 end = 0;
+
+	bool isValid() const { return start < end; }
+};
+
+/**
+ * Decode an MHWK/WAVE resource as a seekable stream.
+ *
+ * This low-level decoder returns the linear sample stream and can optionally
+ * export a validated embedded-loop range. Zoombini's @ref Mohawk::Sound
+ * playback layer requests that range and wraps the decoded stream
+ * automatically.
+ *
+ * @param stream The MHWK resource stream, which is consumed and deleted.
+ * @param cueList Optional destination for parsed Cue# entries.
+ * @param loopInfo Optional destination for a validated embedded-loop range.
+ * @return The decoded stream, or nullptr when the resource cannot be decoded.
+ */
+Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream,
+		CueList *cueList = nullptr, MohawkWaveLoopInfo *loopInfo = nullptr);
 
 class MohawkEngine;
 
 class Sound {
 public:
+	/**
+	 * Create a common Mohawk sound manager.
+	 */
 	explicit Sound(MohawkEngine *vm);
 	~Sound();
 
@@ -115,11 +231,12 @@ public:
 private:
 	MohawkEngine *_vm;
 
-	static Audio::RewindableAudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
+	static Audio::SeekableAudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
 
 	Common::Array<SndHandle> _handles;
 	SndHandle *getHandle();
-	Audio::RewindableAudioStream *makeAudioStream(uint16 id, CueList *cueList = nullptr);
+	Audio::SeekableAudioStream *makeAudioStream(uint16 id, CueList *cueList = nullptr,
+			MohawkWaveLoopInfo *loopInfo = nullptr);
 };
 
 } // End of namespace Mohawk


Commit: 2eadd9b5db49b1d9e46e419f987e7b70be1df409
    https://github.com/scummvm/scummvm/commit/2eadd9b5db49b1d9e46e419f987e7b70be1df409
Author: Hajin Jang (jb6804 at naver.com)
Date: 2026-09-28T12:21:52+03:00

Commit Message:
MOHAWK: Wrap makeMohawkWaveStream signature

Assisted-by: Codex:gpt-5.6

Changed paths:
    engines/mohawk/sound.cpp
    engines/mohawk/sound.h


diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index acf1e25fc89..101a27aff9d 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -122,9 +122,7 @@ void scanAndFixAudioPops(DataChunk &dataChunk, uint32 &dataSize, Common::Seekabl
  * @param loopInfo Optional destination for a validated embedded-loop range.
  * @return The decoded seekable stream, or nullptr when decoding fails.
  */
-Audio::SeekableAudioStream *makeMohawkWaveStream(
-		Common::SeekableReadStream *stream, CueList *cueList,
-		MohawkWaveLoopInfo *loopInfo) {
+Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList, MohawkWaveLoopInfo *loopInfo) {
 	uint32 tag = 0;
 	ADPCMStatus adpcmStatus;
 	DataChunk dataChunk;
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 51bebc9d0c3..2c78dd48b4d 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -207,8 +207,7 @@ struct MohawkWaveLoopInfo {
  * @param loopInfo Optional destination for a validated embedded-loop range.
  * @return The decoded stream, or nullptr when the resource cannot be decoded.
  */
-Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream,
-		CueList *cueList = nullptr, MohawkWaveLoopInfo *loopInfo = nullptr);
+Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = nullptr, MohawkWaveLoopInfo *loopInfo = nullptr);
 
 class MohawkEngine;
 


Commit: e6ed831fa63ada4ee6c6a9ed01fe5d238b331b65
    https://github.com/scummvm/scummvm/commit/e6ed831fa63ada4ee6c6a9ed01fe5d238b331b65
Author: Hajin Jang (jb6804 at naver.com)
Date: 2026-09-28T12:21:52+03:00

Commit Message:
MOHAWK: Zoombini - Clarify tSND loop comments

Changed paths:
    engines/mohawk/sound.cpp


diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 101a27aff9d..7ee6accc7e3 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -237,6 +237,10 @@ Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *str
 						scanAndFixAudioPops(dataChunk, dataSize, stream);
 				}
 
+				// Myst uses the loopCount variable but the loopStart and loopEnd are always 0 and the size of the sample.
+				// Myst ME doesn't use the Mohawk Sound format and just standard WAVE files and therefore does not contain
+				// any of this metadata and we have to specify whether or not to loop elsewhere.
+
 				dataChunk.audioData = stream->readStream(dataSize);
 				break;
 			default:
@@ -261,17 +265,14 @@ Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *str
 		else
 			flags |= Audio::FLAG_UNSIGNED;
 
-		// Publish only the verified raw 8-bit infinite-loop form.
-		// Available Zoombini looped SND resources use this form.
-		// Finite loops are not published because
-		// @ref Audio::SubLoopingAudioStream ends at the exclusive loop end
-		// after its final iteration instead of continuing through the tail.
-		// Validate after the optional pop fix so the exclusive loop end cannot
-		// exceed a truncated sample payload.
-		if (loopInfo && dataChunk.bitsPerSample == 8 &&
-			dataChunk.loopCount == 0xFFFF &&
-			dataChunk.loopStart < dataChunk.loopEnd &&
-			dataChunk.loopEnd <= dataChunk.sampleCount) {
+		// Export only the raw 8-bit infinite loops used by Zoombini. Filter out finite loops.
+		// @ref Mohawk::Sound::playSound() passes the range to @ref Audio::SubLoopingAudioStream.
+		// - Mohawk infnite loop: head -> loop chunk (repeat until stopped by game logic)
+		// - Mohawk finite loop: head -> loop chunk (N times) -> tail -> EOF
+		// - @ref Audio::SubLoopingAudioStream finite: head -> loop chunk (N times) -> EOF
+		// @ref Audio::SubLoopingAudioStream does not support finite loop semantics, so filter them as a safeguard.
+		// Validate against sampleCount after the optional pop truncation.
+		if (loopInfo && dataChunk.bitsPerSample == 8 && dataChunk.loopCount == 0xFFFF && dataChunk.loopStart < dataChunk.loopEnd && dataChunk.loopEnd <= dataChunk.sampleCount) {
 			loopInfo->start = dataChunk.loopStart;
 			loopInfo->end = dataChunk.loopEnd;
 		}


Commit: aa209212aa9e59350ec43b2180d98b897d9e7e1d
    https://github.com/scummvm/scummvm/commit/aa209212aa9e59350ec43b2180d98b897d9e7e1d
Author: Hajin Jang (jb6804 at naver.com)
Date: 2026-09-28T12:21:52+03:00

Commit Message:
MOHAWK: Zoombini - Infinite loop support on tSND (2)

- Do not filter out mohawk loop with bitness check.
- The only blocker behind the exporting loop data is a lack of finite loop support in Audio streams; not a bitness limitation.

Changed paths:
    engines/mohawk/sound.cpp


diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 7ee6accc7e3..9ddd66f20f5 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -272,7 +272,7 @@ Audio::SeekableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *str
 		// - @ref Audio::SubLoopingAudioStream finite: head -> loop chunk (N times) -> EOF
 		// @ref Audio::SubLoopingAudioStream does not support finite loop semantics, so filter them as a safeguard.
 		// Validate against sampleCount after the optional pop truncation.
-		if (loopInfo && dataChunk.bitsPerSample == 8 && dataChunk.loopCount == 0xFFFF && dataChunk.loopStart < dataChunk.loopEnd && dataChunk.loopEnd <= dataChunk.sampleCount) {
+		if (loopInfo && dataChunk.loopCount == 0xFFFF && dataChunk.loopStart < dataChunk.loopEnd && dataChunk.loopEnd <= dataChunk.sampleCount) {
 			loopInfo->start = dataChunk.loopStart;
 			loopInfo->end = dataChunk.loopEnd;
 		}




More information about the Scummvm-git-logs mailing list