diff options
author | Paweł Kołodziejski | 2002-10-01 17:20:05 +0000 |
---|---|---|
committer | Paweł Kołodziejski | 2002-10-01 17:20:05 +0000 |
commit | e3cd40f700dce76229b7748cd1f3243528cc50e0 (patch) | |
tree | 0bd0773e83c718146d5faff242260bc76f076e05 | |
parent | 969a74720c33df8f4ba1717d07bff74187b25c0d (diff) | |
download | scummvm-rg350-e3cd40f700dce76229b7748cd1f3243528cc50e0.tar.gz scummvm-rg350-e3cd40f700dce76229b7748cd1f3243528cc50e0.tar.bz2 scummvm-rg350-e3cd40f700dce76229b7748cd1f3243528cc50e0.zip |
synced with local sources - imuse
svn-id: r5060
-rw-r--r-- | scumm/imuse.cpp | 67 | ||||
-rw-r--r-- | scumm/imuse.h | 20 |
2 files changed, 75 insertions, 12 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp index 1b5f848352..9325011df9 100644 --- a/scumm/imuse.cpp +++ b/scumm/imuse.cpp @@ -4867,18 +4867,23 @@ void IMuseDigital::handler() { uint32 new_size = _channel[l]._mixerSize; uint32 mixer_size = new_size; - if (_channel[l]._offset + _channel[l]._mixerSize > _channel[l]._size) { - new_size = _channel[l]._size - _channel[l]._offset; - if(_channel[l]._isLoop == false) { + + if(_channel[l]._isLoop == false) { + if (_channel[l]._offset + _channel[l]._mixerSize > _channel[l]._size) { + new_size = _channel[l]._size - _channel[l]._offset; _channel[l]._toBeRemoved = true; mixer_size = new_size; } + } else { + if (_channel[l]._offset + _channel[l]._mixerSize >= _channel[l]._jump[0]._offset) { + new_size = _channel[l]._jump[0]._offset - _channel[l]._offset; + } } byte *buf = (byte*)malloc(mixer_size); memcpy(buf, _channel[l]._data + _channel[l]._offset, new_size); if ((new_size != _channel[l]._mixerSize) && (_channel[l]._isLoop == true)) { - memcpy(buf + new_size, _channel[l]._data, _channel[l]._mixerSize - new_size); + memcpy(buf + new_size, _channel[l]._data + _channel[l]._jump[0]._dest, _channel[l]._mixerSize - new_size); } new_mixer = false; @@ -4907,7 +4912,7 @@ void IMuseDigital::handler() { _scumm->_system->unlock_mutex(_scumm->_mixer->_mutex); if ((new_size != _channel[l]._mixerSize) && (_channel[l]._isLoop == true)) { - _channel[l]._offset = _channel[l]._mixerSize - new_size; + _channel[l]._offset = _channel[l]._jump[0]._dest + (_channel[l]._mixerSize - new_size); } else { _channel[l]._offset += _channel[l]._mixerSize; } @@ -4922,12 +4927,15 @@ void IMuseDigital::startSound(int sound) { for(l = 0; l < MAX_DIGITAL_CHANNELS; l++) { if(_channel[l]._used == false) { byte *ptr = _scumm->getResourceAddress(rtSound, sound); + byte *s_ptr = ptr; if(ptr == NULL) { warning("IMuseDigital::startSound(%d) NULL resource pointer", sound); return; } _channel[l]._idSound = sound; _channel[l]._offset = 0; + _channel[l]._numRegions = 0; + _channel[l]._numJumps = 0; ptr += 16; uint32 tag, size; @@ -4945,17 +4953,33 @@ void IMuseDigital::startSound(int sound) { size = READ_BE_UINT32(ptr); ptr += size + 4; break; case MKID_BE('REGN'): - size = READ_BE_UINT32(ptr); ptr += size; - _channel[l]._offsetRegion = READ_BE_UINT32(ptr); ptr += 4; + ptr += 4; + if (_channel[l]._numRegions >= MAX_IMUSE_REGIONS) { + warning("IMuseDigital::startSound(%d) Not enough space for Region"); + ptr += 8; + break; + } + _channel[l]._region[_channel[l]._numRegions]._offset = READ_BE_UINT32(ptr); ptr += 4; + _channel[l]._region[_channel[l]._numRegions]._length = READ_BE_UINT32(ptr); ptr += 4; + _channel[l]._numRegions++; break; case MKID_BE('STOP'): - size = READ_BE_UINT32(ptr); ptr += size; + ptr += 4; _channel[l]._offsetStop = READ_BE_UINT32(ptr); ptr += 4; break; case MKID_BE('JUMP'): - size = READ_BE_UINT32(ptr); ptr += size; - _channel[l]._offsetJump = READ_BE_UINT32(ptr); ptr += 4; + ptr += 4; + if (_channel[l]._numJumps >= MAX_IMUSE_JUMPS) { + warning("IMuseDigital::startSound(%d) Not enough space for Jump"); + ptr += 16; + break; + } + _channel[l]._jump[_channel[l]._numJumps]._offset = READ_BE_UINT32(ptr); ptr += 4; + _channel[l]._jump[_channel[l]._numJumps]._dest = READ_BE_UINT32(ptr); ptr += 4; + _channel[l]._jump[_channel[l]._numJumps]._id = READ_BE_UINT32(ptr); ptr += 4; + _channel[l]._jump[_channel[l]._numJumps]._unk = READ_BE_UINT32(ptr); ptr += 4; _channel[l]._isLoop = true; + _channel[l]._numJumps++; break; case MKID_BE('DATA'): size = READ_BE_UINT32(ptr); ptr += 4; @@ -4966,6 +4990,29 @@ void IMuseDigital::startSound(int sound) { if (tag == MKID_BE('DATA')) break; } + uint32 header_size = ptr - s_ptr; + _channel[l]._offsetStop -= header_size; + if (_channel[l]._bits == 12) { + _channel[l]._offsetStop = (_channel[l]._offsetStop / 3) * 4; + } + uint32 r; + for (r = 0; r < _channel[l]._numRegions; r++) { + _channel[l]._region[r]._offset -= header_size; + if (_channel[l]._bits == 12) { + _channel[l]._region[r]._offset = (_channel[l]._region[r]._offset / 3) * 4; + _channel[l]._region[r]._length = (_channel[l]._region[r]._length / 3) * 4; + } + } + if (_channel[l]._numJumps > 0) { + for (r = 0; r < _channel[l]._numJumps; r++) { + _channel[l]._jump[r]._offset -= header_size; + _channel[l]._jump[r]._dest -= header_size; + if (_channel[l]._bits == 12) { + _channel[l]._jump[r]._offset = (_channel[l]._jump[r]._offset / 3) * 4; + _channel[l]._jump[r]._dest = (_channel[l]._jump[r]._dest / 3) * 4; + } + } + } _channel[l]._mixerTrack = -1; _channel[l]._mixerSize = 22050 / 5; _channel[l]._mixerFlags = SoundMixer::FLAG_AUTOFREE; diff --git a/scumm/imuse.h b/scumm/imuse.h index a2a9e59a6c..1723d8e570 100644 --- a/scumm/imuse.h +++ b/scumm/imuse.h @@ -61,17 +61,33 @@ private: }; #define MAX_DIGITAL_CHANNELS 10 +#define MAX_IMUSE_JUMPS 1 +#define MAX_IMUSE_REGIONS 3 class IMuseDigital { private: + struct region { + uint32 _offset; // begin of region + uint32 _length; // lenght of region + }; + + struct jump { + uint32 _offset; // jump position + uint32 _dest; // jump to + uint32 _id; // id of jump + uint32 _unk; // allmost 500 except one value: 2 + }; + struct channel { int8 _volumeLeft; int8 _volumeRight; bool _isLoop; uint32 _offsetStop; - uint32 _offsetJump; - uint32 _offsetRegion; + jump _jump[MAX_IMUSE_JUMPS]; + uint32 _numJumps; + region _region[MAX_IMUSE_REGIONS]; + uint32 _numRegions; uint32 _offset; byte *_data; uint32 _freq; |