aboutsummaryrefslogtreecommitdiff
path: root/engines/tsage
diff options
context:
space:
mode:
authorPaul Gilbert2011-06-13 16:31:35 +1000
committerPaul Gilbert2011-06-13 16:31:35 +1000
commit34fd272841c0dc80e3de2dd66b671eb84fe78aba (patch)
treeea4237c138b04a9374fd07492ea62378523a808d /engines/tsage
parentdc1c9224abb9b2ac1e79e8512d98ceba2436a889 (diff)
downloadscummvm-rg350-34fd272841c0dc80e3de2dd66b671eb84fe78aba.tar.gz
scummvm-rg350-34fd272841c0dc80e3de2dd66b671eb84fe78aba.tar.bz2
scummvm-rg350-34fd272841c0dc80e3de2dd66b671eb84fe78aba.zip
TSAGE: Completed initial implementation of _sfRethinkVoiceTypes
Diffstat (limited to 'engines/tsage')
-rw-r--r--engines/tsage/sound.cpp326
-rw-r--r--engines/tsage/sound.h81
2 files changed, 361 insertions, 46 deletions
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index ac7217a753..1976013946 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -358,7 +358,6 @@ void SoundManager::_sfSoundServer() {
do {
_sfProcessFading();
} while (sfManager()._serverSuspendedCount > 0);
- sfManager()._serverSuspendedCount = 0;
// Poll all sound drivers in case they need it
for (Common::List<SoundDriver *>::iterator i = sfManager()._installedDrivers.begin();
@@ -416,12 +415,14 @@ void SoundManager::_sfProcessFading() {
// Loop through the voiceType list
for (int voiceIndex = 0; voiceIndex < SOUND_ARR_SIZE; ++voiceIndex) {
- VoiceTypeStruct &voiceType = *sfManager()._voiceTypeStructPtrs[voiceIndex];
+ VoiceTypeStruct *vtStruct = sfManager()._voiceTypeStructPtrs[voiceIndex];
+ if (!vtStruct)
+ continue;
- if (voiceType._voiceType == VOICETYPE_1) {
- for (uint idx = 0; idx < voiceType._entries.size(); ++idx) {
- if (voiceType._entries[idx]._type1._field6 >= -1)
- ++voiceType._entries[idx]._type1._field6;
+ if (vtStruct->_voiceType == VOICETYPE_1) {
+ for (uint idx = 0; idx < vtStruct->_entries.size(); ++idx) {
+ if (vtStruct->_entries[idx]._type1._field6 >= -1)
+ ++vtStruct->_entries[idx]._type1._field6;
}
}
}
@@ -430,6 +431,8 @@ void SoundManager::_sfProcessFading() {
void SoundManager::_sfUpdateVoiceStructs() {
for (int voiceIndex = 0; voiceIndex < SOUND_ARR_SIZE; ++voiceIndex) {
VoiceTypeStruct *vs = sfManager()._voiceTypeStructPtrs[voiceIndex];
+ if (!vs)
+ continue;
for (uint idx = 0; idx < vs->_entries.size(); ++idx) {
VoiceStructEntry &vse = vs->_entries[idx];
@@ -496,6 +499,7 @@ void SoundManager::listenerSynchronize(Serializer &s) {
/*--------------------------------------------------------------------------*/
SoundManager &SoundManager::sfManager() {
+ assert(_soundManager);
return *_soundManager;
}
@@ -584,18 +588,15 @@ void SoundManager::_sfRethinkSoundDrivers() {
}
if (total) {
- int dataSize = !flag ? total * 28 + 30 : total * 26 + 30;
- debugC(9, ktSageSound, "data Size = %d\n", dataSize);
-
VoiceTypeStruct *vs = new VoiceTypeStruct();
sfManager()._voiceTypeStructPtrs[idx] = vs;
if (!flag) {
vs->_voiceType = VOICETYPE_0;
- vs->_field1 = total;
+ vs->_total = total;
} else {
vs->_voiceType = VOICETYPE_1;
- vs->_field1 = vs->_numVoices = total;
+ vs->_total = vs->_numVoices = total;
}
for (Common::List<SoundDriver *>::iterator i = sfManager()._installedDrivers.begin();
@@ -608,6 +609,8 @@ void SoundManager::_sfRethinkSoundDrivers() {
byte byteVal = *groupData++;
if (byteVal == idx) {
+ ++groupData;
+
if (!flag) {
while ((byteVal = *groupData++) != 0xff) {
VoiceStructEntry ve;
@@ -628,7 +631,7 @@ void SoundManager::_sfRethinkSoundDrivers() {
VoiceStructEntry ve;
ve._voiceNum = idx;
ve._driver = driver;
- ve._type1._field4 = 0xff;
+ ve._type1._field4 = -1;
ve._type1._field5 = 0;
ve._type1._field6 = 0;
ve._type1._sound = NULL;
@@ -642,6 +645,8 @@ void SoundManager::_sfRethinkSoundDrivers() {
if (*groupData++ != 0) {
while (*groupData != 0xff)
++groupData;
+ } else {
+ groupData += 2;
}
}
}
@@ -1171,6 +1176,8 @@ void SoundManager::_sfRethinkVoiceTypes() {
}
}
}
+
+ --sfManager()._serverSuspendedCount;
}
void SoundManager::_sfUpdateVolume(Sound *sound) {
@@ -1287,7 +1294,7 @@ void SoundManager::_sfUnInstallDriver(SoundDriver *driver) {
}
void SoundManager::_sfInstallPatchBank(SoundDriver *driver, const byte *bankData) {
- driver->installPatchBank(bankData);
+ driver->installPatch(bankData);
}
/**
@@ -1392,7 +1399,6 @@ void Sound::play(int soundNum) {
}
void Sound::stop() {
- _soundManager->removeFromPlayList(this);
_unPrime();
}
@@ -1458,7 +1464,8 @@ void Sound::_unPrime() {
}
_trackInfo._numTracks = 0;
- _soundManager->removeFromSoundList(this);
+ if (_soundManager)
+ _soundManager->removeFromSoundList(this);
_primed = false;
_stoppedAsynchronously = false;
@@ -1738,7 +1745,8 @@ void Sound::_soPrimeChannelData() {
int mode = *d;
int channelNum = (int8)*(d + 1);
assert((channelNum >= 0) && (channelNum < 16));
-
+
+ _trkChannel[idx] = channelNum;
_chProgram[idx] = *(d + 10);
_chModulation[idx] = 0;
_chVolume[idx] = *(d + 11);
@@ -1784,6 +1792,7 @@ void Sound::_soServiceTrackType0(int trackIndex, const byte *channelData) {
return;
int channelNum = _trkChannel[trackIndex];
+ assert((channelNum >= 0) && (channelNum < SOUND_ARR_SIZE));
int chFlags = (channelNum == -1) ? 0 : _chFlags[channelNum];
int voiceNum = -1;
SoundDriver *driver = NULL;
@@ -1847,7 +1856,7 @@ void Sound::_soServiceTrackType0(int trackIndex, const byte *channelData) {
if (chFlags & 0x10)
_soProc42(vtStruct, channelNum, chVoiceType, v);
else
- _soProc32(vtStruct, channelNum, chVoiceType, v);
+ _soProc32(vtStruct, channelNum, chVoiceType, v, b);
} else if (voiceNum != -1) {
assert(driver);
driver->proc20(voiceNum, chVoiceType);
@@ -2011,7 +2020,7 @@ void Sound::_soUpdateDamper(VoiceTypeStruct *voiceType, int channelNum, VoiceTyp
}
}
-void Sound::_soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0) {
+void Sound::_soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0, int v1) {
int entryIndex = _soFindSound(vtStruct, channelNum);
if (entryIndex != -1) {
SoundDriver *driver = vtStruct->_entries[entryIndex]._driver;
@@ -2021,7 +2030,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]);
+ driver->proc32(vtStruct->_entries[entryIndex]._voiceNum, _chProgram[channelNum], v0, v1);
}
}
@@ -2039,8 +2048,7 @@ 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, voiceType,
- _channelData[trackCtr], this, 0x7f, 0xff, 0xE);
+ driver->proc32(vtStruct->_entries[entryIndex]._voiceNum, -1, v0, 0x7F);
driver->proc42(vtStruct->_entries[entryIndex]._voiceNum, voiceType, 0);
}
break;
@@ -2168,8 +2176,7 @@ 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, voiceType,
- _channelData[trackIndex], this, 0x7f, 0xff, 0xE);
+ driver->proc32(vtStruct->_entries[entryIndex]._voiceNum, -1, *(channelData + 1), 0x7f);
}
} else {
@@ -2295,9 +2302,34 @@ SoundDriver::SoundDriver() {
const byte adlib_group_data[] = { 1, 1, 9, 1, 0xff };
-AdlibSoundDriver::AdlibSoundDriver() {
+const byte v440B0[9] = { 0, 1, 2, 6, 7, 8, 12, 13, 14 };
+
+const byte v440B9[9] = { 3, 4, 5, 9, 10, 11, 15, 16, 17 };
+
+const byte v440C2[18] = {
+ 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
+};
+
+const byte v44134[64] = {
+ 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 54, 55,
+ 56, 56, 57, 57, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61,
+ 61, 62, 62, 62, 62, 63, 63, 63
+};
+
+const int v440D4[48] = {
+ 343, 348, 353, 358, 363, 369, 374, 379, 385, 391, 396,
+ 402, 408, 414, 420, 426, 432, 438, 445, 451, 458, 465,
+ 471, 478, 485, 492, 499, 507, 514, 521, 529, 537, 544,
+ 552, 560, 569, 577, 585, 594, 602, 611, 620, 629, 638,
+ 647, 657, 666, 676
+};
+
+AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
_minVersion = 0x102;
_maxVersion = 0x10A;
+ _masterVolume = 0;
_groupData.groupMask = 9;
_groupData.v1 = 0x46;
@@ -2305,6 +2337,252 @@ AdlibSoundDriver::AdlibSoundDriver() {
_groupData.pData = &adlib_group_data[0];
_mixer = _vm->_mixer;
+ _sampleRate = _mixer->getOutputRate();
+ _opl = makeAdLibOPL(_sampleRate);
+
+ memset(_channelVoiced, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ memset(_channelVolume, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ memset(_v4405E, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ memset(_v44067, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ memset(_v44070, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ memset(_v44079, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ memset(_v44082, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+ _v44082[ADLIB_CHANNEL_COUNT] = 0x90;
+ Common::set_to(_v4408C, _v4408C + ADLIB_CHANNEL_COUNT, 0x2000);
+ memset(_v4409E, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
+}
+
+AdlibSoundDriver::~AdlibSoundDriver() {
+ DEALLOCATE(_patchData);
+}
+
+bool AdlibSoundDriver::open() {
+ write(1, 0x20);
+ if (!reset())
+ return false;
+
+ write(8, 0);
+ for (int idx = 0x20; idx < 0xF6; ++idx)
+ write(idx, 0);
+
+ write(0xBD, 0);
+ return true;
+}
+
+void AdlibSoundDriver::close() {
+ for (int idx = 0xB0; idx < 0xB8; ++idx)
+ write(idx, _portContents[idx] & 0xDF);
+ for (int idx = 0x40; idx < 0x55; ++idx)
+ write(idx, 0x3F);
+ reset();
+}
+
+bool AdlibSoundDriver::reset() {
+ write(1, 0x20);
+ write(4, 0x80);
+/*
+ * code fragment originally part of testing Adlib timer speed
+ write(2, 1);
+ write(4, 1);
+*/
+ return true;
+}
+
+const GroupData *AdlibSoundDriver::getGroupData() {
+ return &_groupData;
+}
+
+void AdlibSoundDriver::installPatch(const byte *data) {
+ _patchData = data;
+}
+
+int AdlibSoundDriver::setMasterVolume(int volume) {
+ int oldVolume = _masterVolume;
+ _masterVolume = volume;
+
+ for (int channelNum = 0; channelNum < ADLIB_CHANNEL_COUNT; ++channelNum)
+ updateChannelVolume(channelNum);
+
+ return oldVolume;
+}
+
+void AdlibSoundDriver::proc32(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;
+
+ for (int 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];
+
+ // Set sustain/release
+ int portNum = v440C2[v440B0[channel]] + 0x80;
+ write(portNum, (_portContents[portNum] & 0xF0) | 0xF);
+
+ 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 AdlibSoundDriver::updateVoice(int channel) {
+ if (_channelVoiced[channel])
+ clearVoice(channel);
+}
+
+void AdlibSoundDriver::proc38(int channel, int cmd, int value) {
+ if (cmd == 7) {
+ // Set channel volume
+ _channelVolume[channel] = value;
+ updateChannelVolume(channel);
+ }
+}
+
+void AdlibSoundDriver::proc40(int channel, int pitchBlend) {
+ _v4408C[channel] = pitchBlend;
+ setFrequency(channel);
+}
+
+void AdlibSoundDriver::write(byte reg, byte value) {
+static int num = 0;
+debug("%d [%x]=%x", ++num, reg, value);//***DEBUG****
+ _portContents[reg] = value;
+ OPLWriteReg(_opl, reg, value);
+}
+
+void AdlibSoundDriver::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 AdlibSoundDriver::setVoice(int channel) {
+ int portNum = 0xB0 + channel;
+ write(portNum, _portContents[portNum] | 0x20);
+ _channelVoiced[channel] = true;
+}
+
+void AdlibSoundDriver::clearVoice(int channel) {
+ write(0xB0 + channel, _portContents[0xB0 + channel] & ~0x20);
+ _channelVoiced[channel] = false;
+}
+
+void AdlibSoundDriver::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));
+
+ 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] = *(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 + portOffset, (_portContents[0xE0 + portOffset] & 0xF0)
+ | (*(dataP + 16) << 1) | *(dataP + 3));
+
+ _v44082[channel] = *(dataP + 3);
+}
+
+void AdlibSoundDriver::setFrequency(int channel) {
+ int offset, ch;
+
+ int v = _v4408C[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 >= 128)
+ 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));
}
} // End of namespace tSage
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 1dc40b2e4c..fec065e0d2 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -78,24 +78,28 @@ public:
const Common::String &getShortDriverDescription() { return _shortDescription; }
const Common::String &getLongDriverDescription() { return _longDescription; }
- virtual bool open() { return true; }
- virtual void close() {}
- virtual const GroupData *getGroupData() = 0;
- virtual void installPatchBank(const byte *data) {}
- virtual void poll() {}
- virtual void setMasterVolume(int volume) {}
- virtual void proc18(int al, VoiceType voiceType) {}
- virtual void proc20(int al, VoiceType voiceType) {}
- virtual void proc22(int al, VoiceType voiceType, int v3) {}
+ virtual bool open() { return true; } // Method #0
+ virtual void close() {} // Method #1
+ virtual bool reset() { return true; } // Method #2
+ virtual const GroupData *getGroupData() { return NULL; } // Method #3
+ virtual void installPatch(const byte *data) {} // Method #4
+ virtual void poll() {} // Method #5
+ virtual void proc12() {} // Method #6
+ virtual int setMasterVolume(int volume) { return 0; } // Method #7
+ virtual void proc16() {} // Method #8
+ virtual void proc18(int al, VoiceType voiceType) {} // Method #9
+ virtual void proc20(int al, VoiceType voiceType) {} // Method #10
+ virtual void proc22(int al, VoiceType voiceType, int v3) {} // Method #11
virtual void proc24(int channel, int voiceIndex, Sound *sound, int v1, int v2) {}
- virtual void setProgram(int channel, int program) {}
+ 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) {}
- virtual void proc32(int voiceNum, int program, ...) {} // TODO: Determine params
- virtual void proc38(int voiceNum, int cmd, int value) {}
- virtual void proc40(int voiceNum, int pitchBlend) {}
- virtual void proc42(int voiceNum, ...) {} // TODO: Determine params
- virtual void updateVoice(int voiceNum) {}
+ virtual void setPitchBlend(int channel, int pitchBlend) {} // Method #15
+ virtual void proc32(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 proc40(int channel, int pitchBlend) {} // Method #20
+ virtual void proc42(int channel, int v0, int v1) {} // Method #21
};
struct VoiceStructEntryType0 {
@@ -141,7 +145,7 @@ struct VoiceStructEntry {
class VoiceTypeStruct {
public:
VoiceType _voiceType;
- int _field1;
+ int _total;
int _numVoices;
int _field3;
@@ -332,7 +336,7 @@ public:
void _soRemoteReceive();
void _soServiceTrackType0(int trackIndex, const byte *channelData);
void _soUpdateDamper(VoiceTypeStruct *voiceType, int channelNum, VoiceType mode, int v0);
- void _soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0);
+ void _soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0, int v1);
void _soProc42(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0);
void _soProc38(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int cmd, int value);
void _soProc40(VoiceTypeStruct *vtStruct, int channelNum, int pitchBlend);
@@ -381,16 +385,49 @@ public:
void release() { _sound.release(); }
};
+#define ADLIB_CHANNEL_COUNT 9
+
class AdlibSoundDriver: public SoundDriver {
private:
GroupData _groupData;
Audio::Mixer *_mixer;
+ FM_OPL *_opl;
+ int _sampleRate;
+ byte _portContents[256];
+ const byte *_patchData;
+ int _masterVolume;
+
+ 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 _v4408C[ADLIB_CHANNEL_COUNT];
+ int _v4409E[ADLIB_CHANNEL_COUNT];
+
+
+ void write(byte reg, byte value);
+ void updateChannelVolume(int channel);
+ void setVoice(int channel);
+ void clearVoice(int channel);
+ void updateChannel(int channel);
+ void setFrequency(int channel);
public:
AdlibSoundDriver();
-
- virtual void setVolume(int volume) {}
- virtual void installPatchBank(const byte *data) {}
- virtual const GroupData *getGroupData() { return &_groupData; }
+ ~AdlibSoundDriver();
+
+ virtual bool open();
+ virtual void close();
+ virtual bool reset();
+ virtual const GroupData *getGroupData();
+ virtual void installPatch(const byte *data);
+ virtual int setMasterVolume(int volume);
+ virtual void proc32(int channel, int program, int v0, int v1);
+ virtual void updateVoice(int channel);
+ virtual void proc38(int channel, int cmd, int value);
+ void proc40(int channel, int pitchBlend);
};
} // End of namespace tSage