From ab7fdccc3b69d6ded7eb0c978da8804901ff95a9 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 2 Jul 2011 10:39:57 +1000 Subject: TSAGE: Beginnings of SoundBlaster sound driver --- engines/tsage/sound.cpp | 288 +++++++++++++++++------------------------------- engines/tsage/sound.h | 46 ++++---- 2 files changed, 123 insertions(+), 211 deletions(-) diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp index 01e770a77a..7f454bf801 100644 --- a/engines/tsage/sound.cpp +++ b/engines/tsage/sound.cpp @@ -126,7 +126,10 @@ Common::List &SoundManager::buildDriverList(bool detectFlag) { assert(__sndmgrReady); _availableDrivers.clear(); - // Build up a list of available drivers. Currently we only implement an Adlib driver + // Build up a list of available drivers. Currently we only implement an Adlib music + // and SoundBlaster FX driver + + // Adlib driver SoundDriverEntry sd; sd.driverNum = ADLIB_DRIVER_NUM; sd.status = detectFlag ? SNDSTATUS_DETECTED : SNDSTATUS_SKIPPED; @@ -136,12 +139,23 @@ Common::List &SoundManager::buildDriverList(bool detectFlag) { sd.longDescription = "3812fm"; _availableDrivers.push_back(sd); + // SoundBlaster entry + SoundDriverEntry sdFx; + sdFx.driverNum = SBLASTER_DRIVER_NUM; + sdFx.status = detectFlag ? SNDSTATUS_DETECTED : SNDSTATUS_SKIPPED; + sdFx.field2 = 0; + sdFx.field6 = 15000; + sdFx.shortDescription = "SndBlast"; + sdFx.longDescription = "SoundBlaster"; + _availableDrivers.push_back(sdFx); + _driversDetected = true; return _availableDrivers; } void SoundManager::installConfigDrivers() { installDriver(ADLIB_DRIVER_NUM); + installDriver(SBLASTER_DRIVER_NUM); } Common::List &SoundManager::getDriverList(bool detectFlag) { @@ -2125,7 +2139,7 @@ void Sound::_soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voice vtStruct->_entries[entryIndex]._type1._field4 = v0; vtStruct->_entries[entryIndex]._type1._field5 = 0; - driver->proc32(vtStruct->_entries[entryIndex]._voiceNum, _chProgram[channelNum], v0, v1); + driver->proc32(this, vtStruct->_entries[entryIndex]._voiceNum, _chProgram[channelNum], v0, v1); } } @@ -2143,8 +2157,9 @@ void Sound::_soProc42(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voice vtStruct->_entries[entryIndex]._type1._field4 = v0; vtStruct->_entries[entryIndex]._type1._field5 = 0; - driver->proc32(vtStruct->_entries[entryIndex]._voiceNum, -1, v0, 0x7F); - driver->proc42(vtStruct->_entries[entryIndex]._voiceNum, voiceType, 0); + int v1, v2; + driver->proc32(this, vtStruct->_entries[entryIndex]._voiceNum, -1, v0, 0x7F); + driver->proc42(vtStruct->_entries[entryIndex]._voiceNum, voiceType, 0, &v1, &v2); } break; } @@ -2271,11 +2286,33 @@ void Sound::_soServiceTrackType1(int trackIndex, const byte *channelData) { vtStruct->_entries[entryIndex]._type1._field4 = *(channelData + 1); vtStruct->_entries[entryIndex]._type1._field5 = 0; - driver->proc32(vtStruct->_entries[entryIndex]._voiceNum, -1, *(channelData + 1), 0x7f); + int v1, v2; + driver->proc32(this, vtStruct->_entries[entryIndex]._voiceNum, -1, *(channelData + 1), 0x7f); + driver->proc42(vtStruct->_entries[entryIndex]._voiceNum, *(channelData + 1), _loop ? 1 : 0, + &v1, &v2); } } else { + int channel = 0; // Is this correct?! + for (uint entryIndex = 0; entryIndex < vtStruct->_entries.size(); ++entryIndex) { + VoiceStructEntry &vte = vtStruct->_entries[entryIndex]; + VoiceStructEntryType1 &vse = vte._type1; + if ((vse._sound == this) && (vse._channelNum == channel) && (vse._field4 == vtStruct->_total)) { + SoundDriver *driver = vte._driver; + + int v1, v2; + driver->proc42(vte._voiceNum, vtStruct->_total, _loop ? 1 : 0, &v1, &v2); + if (v2) { + _trkState[trackIndex] = 0; + } else if (vtStruct->_total) { + _timer = 0; + } + } + } + _trkState[trackIndex] = 0; } + } else { + _trkState[trackIndex] = 0; } } } @@ -2511,7 +2548,7 @@ int AdlibSoundDriver::setMasterVolume(int volume) { return oldVolume; } -void AdlibSoundDriver::proc32(int channel, int program, int v0, int v1) { +void AdlibSoundDriver::proc32(Sound *sound, int channel, int program, int v0, int v1) { if (program == -1) return; @@ -2735,7 +2772,7 @@ AdlibFxSoundDriver::AdlibFxSoundDriver(): SoundDriver() { _maxVersion = 0x10A; _masterVolume = 0; - _groupData.groupMask = 9; + _groupData.groupMask = 1; _groupData.v1 = 0x3E; _groupData.v2 = 0; _groupData.pData = &adlib_group_data[0]; @@ -2765,31 +2802,25 @@ AdlibFxSoundDriver::~AdlibFxSoundDriver() { } bool AdlibFxSoundDriver::open() { + write209(); + write(64); + write(165); + // for (int idx = 0; idx < 5000 * 16; ++idx) al = port[21h] - write(1, 0x20); - if (!reset()) - return false; +// _v45071 = 1; +// _v4506F = 0; - write(8, 0); - for (int idx = 0x20; idx < 0xF6; ++idx) - write(idx, 0); - - write(0xBD, 0); return true; } void AdlibFxSoundDriver::close() { - for (int idx = 0xB0; idx < 0xB8; ++idx) - write(idx, _portContents[idx] & 0xDF); - for (int idx = 0x40; idx < 0x55; ++idx) - write(idx, 0x3F); - reset(); + write(208); + write211(); + } bool AdlibFxSoundDriver::reset() { - write(1, 0x20); - write(1, 0x20); return true; } @@ -2798,77 +2829,72 @@ const GroupData *AdlibFxSoundDriver::getGroupData() { return &_groupData; } +void AdlibFxSoundDriver::poll() { + if (!_masterVolume || !_channelVolume) { + if (_v45046) + write211(); + } else { + if (!_v45046) + write209(); + } +} + int AdlibFxSoundDriver::setMasterVolume(int volume) { int oldVolume = _masterVolume; _masterVolume = volume; - for (int channelNum = 0; channelNum < ADLIB_CHANNEL_COUNT; ++channelNum) - updateChannelVolume(channelNum); - return oldVolume; } -void AdlibFxSoundDriver::proc32(int channel, int program, int v0, int v1) { +void AdlibFxSoundDriver::proc32(Sound *sound, int channel, int program, int v0, int v1) { if (program == -1) return; -/* - int offset = READ_LE_UINT16(_patchData + program * 2); - if (offset) { - const byte *dataP = _patchData + offset; - int id; - - for (offset = 2, id = 0; id != READ_LE_UINT16(dataP); offset += 30, ++id) { - if ((dataP[offset] <= v0) && (dataP[offset + 1] >= v0)) { - if (dataP[offset + 2] != 0xff) - v0 = dataP[offset + 2]; - _v4409E[channel] = dataP + offset - _patchData; + if (_sound) + updateVoice(channel); - // Set sustain/release - int portNum = v440C2[v440B0[channel]] + 0x80; - write(portNum, (_portContents[portNum] & 0xF0) | 0xF); + // TODO: Stuff - portNum = v440C2[v440B9[channel]] + 0x80; - write(portNum, (_portContents[portNum] & 0xF0) | 0xF); - if (_channelVoiced[channel]) - clearVoice(channel); - _v44067[channel] = v0; - _v4405E[channel] = v1; - - updateChannel(channel); - setFrequency(channel); - updateChannelVolume(channel); - setVoice(channel); - break; - } - } - } - */ } void AdlibFxSoundDriver::updateVoice(int channel) { - if (_channelVoiced[channel]) - clearVoice(channel); + if (_sound) { + write(208); + + _sound = NULL; + _v45062 = 0; + _v45066 = 0; + _v45068 = 0; + } } void AdlibFxSoundDriver::proc38(int channel, int cmd, int value) { if (cmd == 7) { // Set channel volume - _channelVolume[channel] = value; - updateChannelVolume(channel); + _channelVolume = value; } } -void AdlibFxSoundDriver::setPitch(int channel, int pitchBlend) { - _pitchBlend[channel] = pitchBlend; - setFrequency(channel); +void AdlibFxSoundDriver::proc42(int channel, int cmd, int value, int *v1, int *v2) { + _v4506A = value; + *v1 = _v4506B; + *v2 = 0; + _v4506B = 0; + + if (!_sound) + *v2 = 1; } -void AdlibFxSoundDriver::write(byte reg, byte value) { - _portContents[reg] = value; - _queue.push(RegisterValue(reg, value)); +void AdlibFxSoundDriver::write(int v) { + /* + port[adlib_port + 12] = v; + for (int i = 0; i < 100; ++i) { + if (!port[adlib_port + 12] & 0x80) + break; + } + */ } void AdlibFxSoundDriver::flush() { @@ -2880,127 +2906,7 @@ void AdlibFxSoundDriver::flush() { } } -void AdlibFxSoundDriver::updateChannelVolume(int channelNum) { - int volume = (_masterVolume * _channelVolume[channelNum] / 127 * _v4405E[channelNum] / 127) / 2; - int level2 = 63 - v44134[volume * _v44079[channelNum] / 63]; - int level1 = !_v44082[channelNum] ? 63 - _v44070[channelNum] : - 63 - v44134[volume * _v44070[channelNum] / 63]; - - int portNum = v440C2[v440B0[channelNum]] + 0x40; - write(portNum, (_portContents[portNum] & 0x80) | level1); - - portNum = v440C2[v440B9[channelNum]] + 0x40; - write(portNum, (_portContents[portNum] & 0x80) | level2); -} - -void AdlibFxSoundDriver::setVoice(int channel) { - int portNum = 0xB0 + channel; - write(portNum, _portContents[portNum] | 0x20); - _channelVoiced[channel] = true; -} - -void AdlibFxSoundDriver::clearVoice(int channel) { - write(0xB0 + channel, _portContents[0xB0 + channel] & ~0x20); - _channelVoiced[channel] = false; -} - -void AdlibFxSoundDriver::updateChannel(int channel) { -/* - const byte *dataP = _patchData + _v4409E[channel]; - int portOffset = v440C2[v440B0[channel]]; - - int portNum = portOffset + 0x20; - int portValue = 0; - if (*(dataP + 4)) - portValue |= 0x80; - if (*(dataP + 5)) - portValue |= 0x40; - if (*(dataP + 8)) - portValue |= 0x20; - if (*(dataP + 6)) - portValue |= 0x10; - portValue |= *(dataP + 7); - write(portNum, portValue); - - portValue = (_portContents[0x40 + portOffset] & 0x3F) | (*(dataP + 9) << 6); - write(0x40 + portOffset, portValue); - - _v44070[channel] = 63 - *(dataP + 10); - write(0x60 + portOffset, *(dataP + 12) | (*(dataP + 11) << 4)); - write(0x80 + portOffset, *(dataP + 14) | (*(dataP + 13) << 4)); - write(0xE0 + portOffset, (_portContents[0xE0 + portOffset] & 0xFC) | *(dataP + 15)); - - portOffset = v440C2[v440B9[channel]]; - portNum = portOffset + 0x20; - portValue = 0; - if (*(dataP + 17)) - portValue |= 0x80; - if (*(dataP + 18)) - portValue |= 0x40; - if (*(dataP + 21)) - portValue |= 0x20; - if (*(dataP + 19)) - portValue |= 0x10; - portValue |= *(dataP + 20); - write(portNum, portValue); - - write(0x40 + portOffset, (_portContents[0x40 + portOffset] & 0x3f) | (*(dataP + 22) << 6)); - _v44079[channel] = 0x3F - *(dataP + 23); - write(0x60 + portOffset, *(dataP + 25) | (*(dataP + 24) << 4)); - write(0x80 + portOffset, *(dataP + 27) | (*(dataP + 26) << 4)); - write(0xE0 + portOffset, (_portContents[0xE0 + portOffset] & 0xFC) | *(dataP + 28)); - - write(0xC0 + channel, (_portContents[0xC0 + channel] & 0xF0) - | (*(dataP + 16) << 1) | *(dataP + 3)); - - _v44082[channel] = *(dataP + 3); - */ -} - -void AdlibFxSoundDriver::setFrequency(int channel) { - int offset, ch; - - int v = _pitchBlend[channel]; - if (v == 0x2000) { - offset = 0; - ch = _v44067[channel]; - } else if (v > 0x2000) { - ch = _v44067[channel]; - v -= 0x2000; - if (v == 0x1fff) - v = 0x2000; - - offset = (v / 170) & 3; - ch += (v / 170) >> 2; - - if (ch >= 128) - ch = 127; - } else { - ch = _v44067[channel]; - int tempVal = (0x2000 - v) / 170; - int tempVal2 = 4 - (tempVal & 3); - - if (tempVal2 == 4) - offset = 0; - else { - offset = tempVal2; - --ch; - } - - ch -= tempVal >> 2; - if (ch < 0) - ch = 0; - } - - int var2 = ch / 12; - if (var2) - --var2; - int dataWord = v440D4[((ch % 12) << 2) + offset]; - write(0xA0 + channel, dataWord & 0xff); - write(0xB0 + channel, (_portContents[0xB0 + channel] & 0xE0) | - ((dataWord >> 8) & 3) | (var2 << 2)); -} int AdlibFxSoundDriver::readBuffer(int16 *buffer, const int numSamples) { update(buffer, numSamples); @@ -3025,4 +2931,14 @@ void AdlibFxSoundDriver::update(int16 *buf, int len) { } } +void AdlibFxSoundDriver::write209() { + write(209); + _v45046 = true; +} + +void AdlibFxSoundDriver::write211() { + write(211); + _v45046 = false; +} + } // End of namespace tSage diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h index 27f30b9b08..26bf3e6d33 100644 --- a/engines/tsage/sound.h +++ b/engines/tsage/sound.h @@ -40,6 +40,7 @@ class Sound; #define SOUND_ARR_SIZE 16 #define ROLAND_DRIVER_NUM 2 #define ADLIB_DRIVER_NUM 3 +#define SBLASTER_DRIVER_NUM 4 struct trackInfoStruct { int _numTracks; @@ -106,12 +107,12 @@ public: virtual void setProgram(int channel, int program) {} // Method #13 virtual void setVolume1(int channel, int v2, int v3, int volume) {} virtual void setPitchBlend(int channel, int pitchBlend) {} // Method #15 - virtual void proc32(int channel, int program, int v0, int v1) {}// Method #16 + virtual void proc32(Sound *sound, int channel, int program, int v0, int v1) {}// Method #16 virtual void updateVoice(int channel) {} // Method #17 virtual void proc36() {} // Method #18 virtual void proc38(int channel, int cmd, int value) {} // Method #19 virtual void setPitch(int channel, int pitchBlend) {} // Method #20 - virtual void proc42(int channel, int v0, int v1) {} // Method #21 + virtual void proc42(int channel, int cmd, int value, int *v1, int *v2) {} // Method #21 }; struct VoiceStructEntryType0 { @@ -439,7 +440,7 @@ public: virtual const GroupData *getGroupData(); virtual void installPatch(const byte *data, int size); virtual int setMasterVolume(int volume); - virtual void proc32(int channel, int program, int v0, int v1); + virtual void proc32(Sound *sound, int channel, int program, int v0, int v1); virtual void updateVoice(int channel); virtual void proc38(int channel, int cmd, int value); virtual void setPitch(int channel, int pitchBlend); @@ -455,33 +456,28 @@ public: class AdlibFxSoundDriver: public SoundDriver, Audio::AudioStream { private: + Common::Queue _queue; GroupData _groupData; Audio::Mixer *_mixer; FM_OPL *_opl; Audio::SoundHandle _soundHandle; int _sampleRate; - byte _portContents[256]; - int _masterVolume; - Common::Queue _queue; - - bool _channelVoiced[ADLIB_CHANNEL_COUNT]; - int _channelVolume[ADLIB_CHANNEL_COUNT]; - int _v4405E[ADLIB_CHANNEL_COUNT]; - int _v44067[ADLIB_CHANNEL_COUNT]; - int _v44070[ADLIB_CHANNEL_COUNT]; - int _v44079[ADLIB_CHANNEL_COUNT]; - int _v44082[ADLIB_CHANNEL_COUNT + 1]; - int _pitchBlend[ADLIB_CHANNEL_COUNT]; - int _v4409E[ADLIB_CHANNEL_COUNT]; + int _v45062; + int _v45066; + int _v45068; + int _v4506A; + int _v4506B; + bool _v45046; + byte _masterVolume; + byte _channelVolume; + Sound *_sound; - void write(byte reg, byte value); + void write(int v); void flush(); - void updateChannelVolume(int channel); - void setVoice(int channel); - void clearVoice(int channel); - void updateChannel(int channel); - void setFrequency(int channel); + void sub_4556E(); + void write209(); + void write211(); public: AdlibFxSoundDriver(); virtual ~AdlibFxSoundDriver(); @@ -490,12 +486,12 @@ public: virtual void close(); virtual bool reset(); virtual const GroupData *getGroupData(); - virtual void installPatch(const byte *data, int size) {} + virtual void poll(); virtual int setMasterVolume(int volume); - virtual void proc32(int channel, int program, int v0, int v1); + virtual void proc32(Sound *sound, int channel, int program, int v0, int v1); virtual void updateVoice(int channel); virtual void proc38(int channel, int cmd, int value); - virtual void setPitch(int channel, int pitchBlend); + virtual void proc42(int channel, int cmd, int value, int *v1, int *v2); // AudioStream interface virtual int readBuffer(int16 *buffer, const int numSamples); -- cgit v1.2.3