mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-05 09:49:14 +00:00
TSAGE: Beginnings of SoundBlaster sound driver
This commit is contained in:
parent
925347bd4d
commit
ab7fdccc3b
@ -126,7 +126,10 @@ Common::List<SoundDriverEntry> &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<SoundDriverEntry> &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<SoundDriverEntry> &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];
|
||||
if (_sound)
|
||||
updateVoice(channel);
|
||||
|
||||
_v4409E[channel] = dataP + offset - _patchData;
|
||||
// TODO: Stuff
|
||||
|
||||
// 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 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
|
||||
|
@ -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<RegisterValue> _queue;
|
||||
GroupData _groupData;
|
||||
Audio::Mixer *_mixer;
|
||||
FM_OPL *_opl;
|
||||
Audio::SoundHandle _soundHandle;
|
||||
int _sampleRate;
|
||||
byte _portContents[256];
|
||||
int _masterVolume;
|
||||
Common::Queue<RegisterValue> _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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user