diff options
author | Jordi Vilalta Prat | 2010-06-22 19:21:05 +0000 |
---|---|---|
committer | Jordi Vilalta Prat | 2010-06-22 19:21:05 +0000 |
commit | 33b991ee9d987acf013606341a60c8e3ff95ca77 (patch) | |
tree | 96eb7493799352a0bfa548c8fcb8aa3da1adf258 /engines | |
parent | 38cf6aa3e4c0415f507f5ec514834440bfbf90ca (diff) | |
download | scummvm-rg350-33b991ee9d987acf013606341a60c8e3ff95ca77.tar.gz scummvm-rg350-33b991ee9d987acf013606341a60c8e3ff95ca77.tar.bz2 scummvm-rg350-33b991ee9d987acf013606341a60c8e3ff95ca77.zip |
Groovie: Add support for the compressed MIDI files of T7G Mac.
svn-id: r50163
Diffstat (limited to 'engines')
-rw-r--r-- | engines/groovie/music.cpp | 63 | ||||
-rw-r--r-- | engines/groovie/music.h | 3 |
2 files changed, 57 insertions, 9 deletions
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 7166432e02..7e8f21bbbc 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -703,20 +703,65 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF); if (file) { - // TODO: A form of LZSS, not supported by the current Groovie decoder. - // The offset/length uint16 is BE, but not sure the amount of length bits - // nor whether the offset is absolute/relative. - warning("TODO: Mac Compressed MIDI: cmid 0x%04x", fileref & 0x3FF); + // Found the resource, decompress it + Common::SeekableReadStream *tmp = decompressMidi(file); delete file; + file = tmp; + } else { + // Otherwise, it's uncompressed + file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); + if (!file) + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); return false; } - // Otherwise, it's uncompressed - file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); - if (!file) - error("Groovie::Music: Couldn't find resource 0x%04X", fileref); - return loadParser(file, loop); } +Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadStream *stream) { + // Initialize an output buffer of the given size + uint32 size = stream->readUint32BE(); + byte *output = (byte *)malloc(size); + + byte *current = output; + uint32 decompBytes = 0; + while ((decompBytes < size) && !stream->eos()) { + // 8 flags + byte flags = stream->readByte(); + + for (byte i = 0; (i < 8) && !stream->eos(); i++) { + if (flags & 1) { + // 1: Next byte is a literal + *(current++) = stream->readByte(); + if (stream->eos()) + continue; + decompBytes++; + } else { + // 0: It's a reference to part of the history + uint16 args = stream->readUint16BE(); + if (stream->eos()) + continue; + + // Length = 4bit unsigned (3 minimal) + uint8 length = (args >> 12) + 3; + + // Offset = 12bit signed (all values are negative) + int16 offset = (args & 0xFFF) | 0xF000; + + // Copy from the past decompressed bytes + decompBytes += length; + while (length > 0) { + *(current) = *(current + offset); + current++; + length--; + } + } + flags = flags >> 1; + } + } + + // Return the output buffer wrapped in a MemoryReadStream + return new Common::MemoryReadStream(output, size, DisposeAfterUse::YES); +} + } // End of Groovie namespace diff --git a/engines/groovie/music.h b/engines/groovie/music.h index 2feef9cbf7..5b5f5bd346 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -161,6 +161,9 @@ public: protected: bool load(uint32 fileref, bool loop); + +private: + Common::SeekableReadStream *decompressMidi(Common::SeekableReadStream *stream); }; } // End of Groovie namespace |