aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/fmtowns_pc98
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth/fmtowns_pc98')
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.cpp1029
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.h83
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp9
3 files changed, 4 insertions, 1117 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
deleted file mode 100644
index c02b047153..0000000000
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ /dev/null
@@ -1,1029 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
-#include "audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h"
-#include "common/textconsole.h"
-#include "common/system.h"
-
-class TownsMidiOutputChannel {
-friend class TownsMidiInputChannel;
-public:
- TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanId);
- ~TownsMidiOutputChannel();
-
- void noteOn(uint8 msb, uint16 lsb);
- void noteOnPitchBend(uint8 msb, uint16 lsb);
- void setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara);
- void setupEffects(int index, uint8 flags, const uint8 *effectData);
- void setModWheel(uint8 value);
-
- void connect(TownsMidiInputChannel *chan);
- void disconnect();
-
- bool update();
-
- enum CheckPriorityStatus {
- kDisconnected = -2,
- kHighPriority = -1
- };
-
- int checkPriority(int pri);
-
-private:
- struct EffectEnvelope {
- uint8 state;
- int32 currentLevel;
- int32 duration;
- int32 maxLevel;
- int32 startLevel;
- uint8 loop;
- uint8 stateTargetLevels[4];
- uint8 stateModWheelLevels[4];
- int8 modWheelSensitivity;
- int8 modWheelState;
- int8 modWheelLast;
- uint16 numSteps;
- uint32 stepCounter;
- int32 incrPerStep;
- int8 dir;
- uint32 incrPerStepRem;
- uint32 incrCountRem;
- } *_effectEnvelopes;
-
- struct EffectDef {
- int32 phase;
- uint8 type;
- uint8 useModWheel;
- uint8 loopRefresh;
- EffectEnvelope *s;
- } *_effectDefs;
-
- void startEffect(EffectEnvelope *s, const uint8 *effectData);
- void updateEffectGenerator(EffectEnvelope *s, EffectDef *d);
- int advanceEffectEnvelope(EffectEnvelope *s, EffectDef *d);
- void initNextEnvelopeState(EffectEnvelope *s);
- int16 getEffectStartLevel(uint8 type);
- int getEffectModLevel(int lvl, int mod);
-
- void keyOn();
- void keyOff();
- void keyOnSetFreq(uint16 frq);
- void out(uint8 reg, uint8 val);
-
- TownsMidiInputChannel *_in;
- TownsMidiOutputChannel *_prev;
- TownsMidiOutputChannel *_next;
- uint8 _adjustModTl;
- uint8 _chan;
- uint8 _note;
- uint8 _operator2Tl;
- uint8 _operator1Tl;
- uint8 _sustainNoteOff;
- int16 _duration;
-
- uint16 _freq;
- int16 _freqAdjust;
-
- MidiDriver_TOWNS *_driver;
-
- static const uint8 _chanMap[];
- static const uint8 _chanMap2[];
- static const uint8 _effectDefaults[];
- static const uint16 _effectEnvStepTable[];
- static const uint8 _freqMSB[];
- static const uint16 _freqLSB[];
-};
-
-class TownsMidiInputChannel : public MidiChannel {
-friend class TownsMidiOutputChannel;
-public:
- TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex);
- ~TownsMidiInputChannel();
-
- MidiDriver *device() { return _driver; }
- byte getNumber() { return _chanIndex; }
- bool allocate();
- void release();
-
- void send(uint32 b);
-
- void noteOff(byte note);
- void noteOn(byte note, byte velocity);
- void programChange(byte program);
- void pitchBend(int16 bend);
- void controlChange(byte control, byte value);
- void pitchBendFactor(byte value);
- void priority(byte value);
- void sysEx_customInstrument(uint32 type, const byte *instr);
-
-private:
- void controlModulationWheel(byte value);
- void controlVolume(byte value);
- void controlPanPos(byte value);
- void controlSustain(byte value);
-
- void releasePedal();
-
- TownsMidiOutputChannel *_out;
-
- uint8 *_instrument;
- uint8 _chanIndex;
- uint8 _priority;
- uint8 _tl;
- int8 _transpose;
- int8 _detune;
- int8 _modWheel;
- uint8 _sustain;
- uint8 _pitchBendFactor;
- int16 _pitchBend;
- uint16 _freqLSB;
-
- bool _allocated;
-
- MidiDriver_TOWNS *_driver;
-
- static const uint8 _programAdjustLevel[];
-};
-
-class TownsMidiChanState {
-public:
- TownsMidiChanState();
- ~TownsMidiChanState() {}
- uint8 get(uint8 type);
-
- uint8 unk1;
- uint8 mulAmsFms;
- uint8 tl;
- uint8 attDec;
- uint8 sus;
- uint8 fgAlg;
- uint8 unk2;
-};
-
-TownsMidiChanState::TownsMidiChanState() {
- unk1 = mulAmsFms = tl = attDec = sus = fgAlg = unk2 = 0;
-}
-
-uint8 TownsMidiChanState::get(uint8 type) {
- switch (type) {
- case 0:
- return unk1;
- case 1:
- return mulAmsFms;
- case 2:
- return tl;
- case 3:
- return attDec;
- case 4:
- return sus;
- case 5:
- return fgAlg;
- case 6:
- return unk2;
- default:
- break;
- }
- return 0;
-}
-
-TownsMidiOutputChannel::TownsMidiOutputChannel(MidiDriver_TOWNS *driver, int chanIndex) : _driver(driver), _chan(chanIndex),
- _in(0), _prev(0), _next(0), _adjustModTl(0), _operator2Tl(0), _note(0), _operator1Tl(0), _sustainNoteOff(0), _duration(0), _freq(0), _freqAdjust(0) {
- _effectEnvelopes = new EffectEnvelope[2];
- _effectDefs = new EffectDef[2];
-
- memset(_effectEnvelopes, 0, 2 * sizeof(EffectEnvelope));
- memset(_effectDefs, 0, 2 * sizeof(EffectDef));
- _effectDefs[0].s = &_effectEnvelopes[1];
- _effectDefs[1].s = &_effectEnvelopes[0];
-}
-
-TownsMidiOutputChannel::~TownsMidiOutputChannel() {
- delete[] _effectEnvelopes;
- delete[] _effectDefs;
-}
-
-void TownsMidiOutputChannel::noteOn(uint8 msb, uint16 lsb) {
- _freq = (msb << 7) + lsb;
- _freqAdjust = 0;
- keyOnSetFreq(_freq);
-}
-
-void TownsMidiOutputChannel::noteOnPitchBend(uint8 msb, uint16 lsb) {
- _freq = (msb << 7) + lsb;
- keyOnSetFreq(_freq + _freqAdjust);
-}
-
-void TownsMidiOutputChannel::setupProgram(const uint8 *data, uint8 mLevelPara, uint8 tLevelPara) {
- // This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
- // since it is just a modified AdLib driver. It also uses AdLib programs.
- // There are no FM-TOWNS specific programs. This is the reason for the low quality of the FM-TOWNS
- // music (unsuitable data is just forced into the wrong audio device).
-
- static const uint8 mul[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 };
- uint8 chan = _chanMap[_chan];
-
- uint8 mulAmsFms1 = _driver->_chanState[chan].mulAmsFms = data[0];
- uint8 tl1 = _driver->_chanState[chan].tl = (data[1] | 0x3f) - mLevelPara;
- uint8 attDec1 = _driver->_chanState[chan].attDec = ~data[2];
- uint8 sus1 = _driver->_chanState[chan].sus = ~data[3];
- _driver->_chanState[chan].unk2 = data[4];
- chan += 3;
-
- out(0x30, mul[mulAmsFms1 & 0x0f]);
- out(0x40, (tl1 & 0x3f) + 15);
- out(0x50, ((attDec1 >> 4) << 1) | ((attDec1 >> 4) & 1));
- out(0x60, ((attDec1 << 1) | (attDec1 & 1)) & 0x1f);
- out(0x70, (mulAmsFms1 & 0x20) ^ 0x20 ? (((sus1 & 0x0f) << 1) | 1) : 0);
- out(0x80, sus1);
-
- uint8 mulAmsFms2 = _driver->_chanState[chan].mulAmsFms = data[5];
- uint8 tl2 = _driver->_chanState[chan].tl = (data[6] | 0x3f) - tLevelPara;
- uint8 attDec2 = _driver->_chanState[chan].attDec = ~data[7];
- uint8 sus2 = _driver->_chanState[chan].sus = ~data[8];
- _driver->_chanState[chan].unk2 = data[9];
-
- uint8 mul2 = mul[mulAmsFms2 & 0x0f];
- tl2 = (tl2 & 0x3f) + 15;
- uint8 ar2 = ((attDec2 >> 4) << 1) | ((attDec2 >> 4) & 1);
- uint8 dec2 = ((attDec2 << 1) | (attDec2 & 1)) & 0x1f;
- uint8 sus2r = (mulAmsFms2 & 0x20) ^ 0x20 ? (((sus2 & 0x0f) << 1) | 1) : 0;
-
- for (int i = 4; i < 16; i += 4) {
- out(0x30 + i, mul2);
- out(0x40 + i, tl2);
- out(0x50 + i, ar2);
- out(0x60 + i, dec2);
- out(0x70 + i, sus2r);
- out(0x80 + i, sus2);
- }
-
- _driver->_chanState[chan].fgAlg = data[10];
-
- uint8 alg = 5 + 2 * (data[10] & 1);
- uint8 fb = 4 * (data[10] & 0x0e);
- out(0xb0, fb | alg);
- uint8 t = mulAmsFms1 | mulAmsFms2;
- out(0xb4, (0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)));
-}
-
-void TownsMidiOutputChannel::setupEffects(int index, uint8 flags, const uint8 *effectData) {
- uint16 effectMaxLevel[] = { 0x2FF, 0x1F, 0x07, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3F, 0x0F, 0x0F, 0x0F, 0x03, 0x3E, 0x1F };
- uint8 effectType[] = { 0x1D, 0x1C, 0x1B, 0x00, 0x03, 0x04, 0x07, 0x08, 0x0D, 0x10, 0x11, 0x14, 0x15, 0x1e, 0x1f, 0x00 };
-
- EffectEnvelope *s = &_effectEnvelopes[index];
- EffectDef *d = &_effectDefs[index];
-
- d->phase = 0;
- d->useModWheel = flags & 0x40;
- s->loop = flags & 0x20;
- d->loopRefresh = flags & 0x10;
- d->type = effectType[flags & 0x0f];
- s->maxLevel = effectMaxLevel[flags & 0x0f];
- s->modWheelSensitivity = 31;
- s->modWheelState = d->useModWheel ? _in->_modWheel >> 2 : 31;
-
- switch (d->type) {
- case 0:
- s->startLevel = _operator2Tl;
- break;
- case 13:
- s->startLevel = _operator1Tl;
- break;
- case 30:
- s->startLevel = 31;
- d->s->modWheelState = 0;
- break;
- case 31:
- s->startLevel = 0;
- d->s->modWheelSensitivity = 0;
- break;
- default:
- s->startLevel = getEffectStartLevel(d->type);
- break;
- }
-
- startEffect(s, effectData);
-}
-
-void TownsMidiOutputChannel::setModWheel(uint8 value) {
- if (_effectEnvelopes[0].state != kEnvReady && _effectDefs[0].type)
- _effectEnvelopes[0].modWheelState = value >> 2;
-
- if (_effectEnvelopes[1].state != kEnvReady && _effectDefs[1].type)
- _effectEnvelopes[1].modWheelState = value >> 2;
-}
-
-void TownsMidiOutputChannel::connect(TownsMidiInputChannel *chan) {
- if (!chan)
- return;
-
- _in = chan;
- _next = chan->_out;
- _prev = 0;
- chan->_out = this;
- if (_next)
- _next->_prev = this;
-}
-
-void TownsMidiOutputChannel::disconnect() {
- keyOff();
-
- TownsMidiOutputChannel *p = _prev;
- TownsMidiOutputChannel *n = _next;
-
- if (n)
- n->_prev = p;
- if (p)
- p->_next = n;
- else
- _in->_out = n;
- _in = 0;
-}
-
-bool TownsMidiOutputChannel::update() {
- if (!_in)
- return false;
-
- if (_duration) {
- _duration -= 17;
- if (_duration <= 0) {
- disconnect();
- return true;
- }
- }
-
- for (int i = 0; i < 2; i++) {
- if (_effectEnvelopes[i].state != kEnvReady)
- updateEffectGenerator(&_effectEnvelopes[i], &_effectDefs[i]);
- }
-
- return false;
-}
-
-int TownsMidiOutputChannel::checkPriority(int pri) {
- if (!_in)
- return kDisconnected;
-
- if (!_next && pri >= _in->_priority)
- return _in->_priority;
-
- return kHighPriority;
-}
-
-void TownsMidiOutputChannel::startEffect(EffectEnvelope *s, const uint8 *effectData) {
- s->state = kEnvAttacking;
- s->currentLevel = 0;
- s->modWheelLast = 31;
- s->duration = effectData[0] * 63;
- s->stateTargetLevels[0] = effectData[1];
- s->stateTargetLevels[1] = effectData[3];
- s->stateTargetLevels[2] = effectData[5];
- s->stateTargetLevels[3] = effectData[6];
- s->stateModWheelLevels[0] = effectData[2];
- s->stateModWheelLevels[1] = effectData[4];
- s->stateModWheelLevels[2] = 0;
- s->stateModWheelLevels[3] = effectData[7];
- initNextEnvelopeState(s);
-}
-
-void TownsMidiOutputChannel::updateEffectGenerator(EffectEnvelope *s, EffectDef *d) {
- uint8 f = advanceEffectEnvelope(s, d);
-
- if (f & 1) {
- switch (d->type) {
- case 0:
- _operator2Tl = s->startLevel + d->phase;
- break;
- case 13:
- _operator1Tl = s->startLevel + d->phase;
- break;
- case 30:
- d->s->modWheelState = d->phase;
- break;
- case 31:
- d->s->modWheelSensitivity = d->phase;
- break;
- default:
- break;
- }
- }
-
- if (f & 2) {
- if (d->loopRefresh)
- keyOn();
- }
-}
-
-int TownsMidiOutputChannel::advanceEffectEnvelope(EffectEnvelope *s, EffectDef *d) {
- if (s->duration) {
- s->duration -= 17;
- if (s->duration <= 0) {
- s->state = kEnvReady;
- return 0;
- }
- }
-
- int32 t = s->currentLevel + s->incrPerStep;
-
- s->incrCountRem += s->incrPerStepRem;
- if (s->incrCountRem >= s->numSteps) {
- s->incrCountRem -= s->numSteps;
- t += s->dir;
- }
-
- int retFlags = 0;
-
- if (t != s->currentLevel || (s->modWheelState != s->modWheelLast)) {
- s->currentLevel = t;
- s->modWheelLast = s->modWheelState;
- t = getEffectModLevel(t, s->modWheelState);
- if (t != d->phase) {
- d->phase = t;
- retFlags |= 1;
- }
- }
-
- if (--s->stepCounter)
- return retFlags;
-
- if (++s->state > kEnvReleasing) {
- if (!s->loop) {
- s->state = kEnvReady;
- return retFlags;
- }
- s->state = kEnvAttacking;
- retFlags |= 2;
- }
-
- initNextEnvelopeState(s);
-
- return retFlags;
-}
-
-void TownsMidiOutputChannel::initNextEnvelopeState(EffectEnvelope *s) {
- uint8 v = s->stateTargetLevels[s->state - 1];
- int32 e = _effectEnvStepTable[_driver->_operatorLevelTable[((v & 0x7f) << 5) + s->modWheelSensitivity]];
-
- if (v & 0x80)
- e = _driver->randomValue(e);
-
- if (!e)
- e = 1;
-
- s->numSteps = s->stepCounter = e;
- int32 d = 0;
-
- if (s->state != kEnvSustaining) {
- v = s->stateModWheelLevels[s->state - 1];
- e = getEffectModLevel(s->maxLevel, (v & 0x7f) - 31);
-
- if (v & 0x80)
- e = _driver->randomValue(e);
-
- if (e + s->startLevel > s->maxLevel) {
- e = s->maxLevel - s->startLevel;
- } else {
- if (e + s->startLevel < 0)
- e = -s->startLevel;
- }
-
- d = e - s->currentLevel;
- }
-
- s->incrPerStep = d / s->numSteps;
- s->dir = (d < 0) ? -1 : 1;
- d *= s->dir;
- s->incrPerStepRem = d % s->numSteps;
- s->incrCountRem = 0;
-}
-
-int16 TownsMidiOutputChannel::getEffectStartLevel(uint8 type) {
- uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
-
- if (type == 28)
- return 15;
- else if (type == 29)
- return 383;
- else if (type > 29)
- return 0;
- else if (type > 12)
- type -= 13;
-
- const uint8 *def = &_effectDefaults[type << 2];
- uint8 res = (_driver->_chanState[chan].get(def[0] >> 5) & def[2]) >> def[1];
- if (def[3])
- res = def[3] - res;
-
- return res;
-}
-
-int TownsMidiOutputChannel::getEffectModLevel(int lvl, int mod) {
- if (mod == 0)
- return 0;
-
- if (mod == 31)
- return lvl;
-
- if (lvl > 63 || lvl < -63)
- return ((lvl + 1) * mod) >> 5;
-
- if (mod < 0) {
- if (lvl < 0)
- return _driver->_operatorLevelTable[((-lvl) << 5) - mod];
- else
- return -_driver->_operatorLevelTable[(lvl << 5) - mod];
- } else {
- if (lvl < 0)
- return -_driver->_operatorLevelTable[((-lvl) << 5) + mod];
- else
- return _driver->_operatorLevelTable[(lvl << 5) + mod];
- }
-
- return 0;
-}
-
-void TownsMidiOutputChannel::keyOn() {
- out(0x28, 0x30);
-}
-
-void TownsMidiOutputChannel::keyOff() {
- out(0x28, 0);
-}
-
-void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) {
- uint16 note = (frq << 1) >> 8;
- frq = (_freqMSB[note] << 11) | _freqLSB[note];
- out(0xa4, frq >> 8);
- out(0xa0, frq & 0xff);
- //out(0x28, 0x00);
- out(0x28, 0x30);
-}
-
-void TownsMidiOutputChannel::out(uint8 reg, uint8 val) {
- static const uint8 chanRegOffs[] = { 0, 1, 2, 0, 1, 2 };
- static const uint8 keyValOffs[] = { 0, 1, 2, 4, 5, 6 };
-
- if (reg == 0x28)
- val = (val & 0xf0) | keyValOffs[_chan];
- if (reg < 0x30)
- _driver->_intf->callback(17, 0, reg, val);
- else
- _driver->_intf->callback(17, _chan / 3, (reg & ~3) | chanRegOffs[_chan], val);
-}
-
-const uint8 TownsMidiOutputChannel::_chanMap[] = {
- 0, 1, 2, 8, 9, 10
-};
-
-const uint8 TownsMidiOutputChannel::_chanMap2[] = {
- 3, 4, 5, 11, 12, 13
-};
-
-const uint8 TownsMidiOutputChannel::_effectDefaults[] = {
- 0x40, 0x00, 0x3F, 0x3F, 0xE0, 0x02, 0x00, 0x00, 0x40, 0x06, 0xC0, 0x00,
- 0x20, 0x00, 0x0F, 0x00, 0x60, 0x04, 0xF0, 0x0F, 0x60, 0x00, 0x0F, 0x0F,
- 0x80, 0x04, 0xF0, 0x0F, 0x80, 0x00, 0x0F, 0x0F, 0xE0, 0x00, 0x03, 0x00,
- 0x20, 0x07, 0x80, 0x00, 0x20, 0x06, 0x40, 0x00, 0x20, 0x05, 0x20, 0x00,
- 0x20, 0x04, 0x10, 0x00, 0xC0, 0x00, 0x01, 0x00, 0xC0, 0x01, 0x0E, 0x00
-};
-
-const uint16 TownsMidiOutputChannel::_effectEnvStepTable[] = {
- 0x0001, 0x0002, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
- 0x000A, 0x000C, 0x000E, 0x0010, 0x0012, 0x0015, 0x0018, 0x001E,
- 0x0024, 0x0032, 0x0040, 0x0052, 0x0064, 0x0088, 0x00A0, 0x00C0,
- 0x00F0, 0x0114, 0x0154, 0x01CC, 0x0258, 0x035C, 0x04B0, 0x0640
-};
-
-const uint8 TownsMidiOutputChannel::_freqMSB[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x80, 0x81, 0x83, 0x85,
- 0x87, 0x88, 0x8A, 0x8C, 0x8E, 0x8F, 0x91, 0x93, 0x95, 0x96, 0x98, 0x9A,
- 0x9C, 0x9E, 0x9F, 0xA1, 0xA3, 0xA5, 0xA6, 0xA8, 0xAA, 0xAC, 0xAD, 0xAF,
- 0xB1, 0xB3, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0xBD, 0xBF, 0xC1, 0xC3, 0xC4,
- 0xC6, 0xC8, 0xCA, 0xCB, 0xCD, 0xCF, 0xD1, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA,
- 0xDB, 0xDD, 0xDF, 0xE1, 0xE2, 0xE4, 0xE6, 0xE8, 0xE9, 0xEB, 0xED, 0xEF
-};
-
-const uint16 TownsMidiOutputChannel::_freqLSB[] = {
- 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6,
- 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x02D6, 0x0301, 0x032F,
- 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
- 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403,
- 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F,
- 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
- 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403,
- 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F,
- 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
- 0x055B, 0x02D6, 0x0301, 0x032F, 0x0360, 0x0393, 0x03C9, 0x0403,
- 0x0440, 0x0481, 0x04C6, 0x050E, 0x055B, 0x02D6, 0x0301, 0x032F,
- 0x0360, 0x0393, 0x03C9, 0x0403, 0x0440, 0x0481, 0x04C6, 0x050E,
- 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B,
- 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B,
- 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B,
- 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B, 0x055B
-};
-
-TownsMidiInputChannel::TownsMidiInputChannel(MidiDriver_TOWNS *driver, int chanIndex) : MidiChannel(), _driver(driver), _out(0), _chanIndex(chanIndex),
- _priority(0), _tl(0), _transpose(0), _pitchBendFactor(0), _pitchBend(0), _sustain(0), _freqLSB(0), _detune(0), _modWheel(0), _allocated(false) {
- _instrument = new uint8[30];
- memset(_instrument, 0, 30);
-}
-
-TownsMidiInputChannel::~TownsMidiInputChannel() {
- delete[] _instrument;
-}
-
-bool TownsMidiInputChannel::allocate() {
- if (_allocated)
- return false;
- _allocated = true;
- return true;
-}
-
-void TownsMidiInputChannel::release() {
- _allocated = false;
-}
-
-void TownsMidiInputChannel::send(uint32 b) {
- _driver->send(b | _chanIndex);
-}
-
-void TownsMidiInputChannel::noteOff(byte note) {
- if (!_out)
- return;
-
- for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) {
- if (oc->_note != note)
- continue;
-
- if (_sustain)
- oc->_sustainNoteOff = 1;
- else
- oc->disconnect();
- }
-}
-
-void TownsMidiInputChannel::noteOn(byte note, byte velocity) {
- TownsMidiOutputChannel *oc = _driver->allocateOutputChannel(_priority);
-
- if (!oc)
- return;
-
- oc->connect(this);
-
- oc->_adjustModTl = _instrument[10] & 1;
- oc->_note = note;
- oc->_sustainNoteOff = 0;
- oc->_duration = _instrument[29] * 63;
-
- oc->_operator1Tl = (_instrument[1] & 0x3f) + _driver->_operatorLevelTable[((velocity >> 1) << 5) + (_instrument[4] >> 2)];
- if (oc->_operator1Tl > 63)
- oc->_operator1Tl = 63;
-
- oc->_operator2Tl = (_instrument[6] & 0x3f) + _driver->_operatorLevelTable[((velocity >> 1) << 5) + (_instrument[9] >> 2)];
- if (oc->_operator2Tl > 63)
- oc->_operator2Tl = 63;
-
- oc->setupProgram(_instrument, oc->_adjustModTl == 1 ? _programAdjustLevel[_driver->_operatorLevelTable[(_tl >> 2) + (oc->_operator1Tl << 5)]] : oc->_operator1Tl, _programAdjustLevel[_driver->_operatorLevelTable[(_tl >> 2) + (oc->_operator2Tl << 5)]]);
- oc->noteOn(note + _transpose, _freqLSB);
-
- if (_instrument[11] & 0x80)
- oc->setupEffects(0, _instrument[11], &_instrument[12]);
- else
- oc->_effectEnvelopes[0].state = kEnvReady;
-
- if (_instrument[20] & 0x80)
- oc->setupEffects(1, _instrument[20], &_instrument[21]);
- else
- oc->_effectEnvelopes[1].state = kEnvReady;
-}
-
-void TownsMidiInputChannel::programChange(byte program) {
- // Not implemented (The loading and assignment of programs
- // is handled externally by the SCUMM engine. The programs
- // get sent via sysEx_customInstrument.)
-}
-
-void TownsMidiInputChannel::pitchBend(int16 bend) {
- _pitchBend = bend;
- _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
- for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
- oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB);
-}
-
-void TownsMidiInputChannel::controlChange(byte control, byte value) {
- switch (control) {
- case 1:
- controlModulationWheel(value);
- break;
- case 7:
- controlVolume(value);
- break;
- case 10:
- controlPanPos(value);
- break;
- case 64:
- controlSustain(value);
- break;
- case 123:
- while (_out)
- _out->disconnect();
- break;
- default:
- break;
- }
-}
-
-void TownsMidiInputChannel::pitchBendFactor(byte value) {
- _pitchBendFactor = value;
- _freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
- for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
- oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB);
-}
-
-void TownsMidiInputChannel::priority(byte value) {
- _priority = value;
-}
-
-void TownsMidiInputChannel::sysEx_customInstrument(uint32 type, const byte *instr) {
- memcpy(_instrument, instr, 30);
-}
-
-void TownsMidiInputChannel::controlModulationWheel(byte value) {
- _modWheel = value;
- for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
- oc->setModWheel(value);
-}
-
-void TownsMidiInputChannel::controlVolume(byte value) {
- /* This is all done inside the imuse code
- uint16 v1 = _ctrlVolume + 1;
- uint16 v2 = value;
- if (_chanIndex != 16) {
- _ctrlVolume = value;
- v2 = _player->getEffectiveVolume();
- }
- _tl = (v1 * v2) >> 7;*/
-
- _tl = value;
-}
-
-void TownsMidiInputChannel::controlPanPos(byte value) {
- // not implemented
-}
-
-void TownsMidiInputChannel::controlSustain(byte value) {
- _sustain = value;
- if (!value)
- releasePedal();
-}
-
-void TownsMidiInputChannel::releasePedal() {
- for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next) {
- if (oc->_sustainNoteOff)
- oc->disconnect();
- }
-}
-
-const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
- 0x00, 0x04, 0x07, 0x0B, 0x0D, 0x10, 0x12, 0x14,
- 0x16, 0x18, 0x1A, 0x1B, 0x1D, 0x1E, 0x1F, 0x21,
- 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
- 0x2A, 0x2B, 0x2C, 0x2C, 0x2D, 0x2E, 0x2F, 0x2F,
- 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35,
- 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39,
- 0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3C,
- 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F
-};
-
-MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0),
- _baseTempo(10080), _chanState(0), _operatorLevelTable(0), _tickCounter(0), _rand(1), _allocCurPos(0), _isOpen(false) {
- // We set exteral mutex handling to true to avoid lockups in SCUMM which has its own mutex.
- _intf = new TownsAudioInterface(mixer, this, true);
-
- _channels = new TownsMidiInputChannel*[32];
- for (int i = 0; i < 32; i++)
- _channels[i] = new TownsMidiInputChannel(this, i > 8 ? (i + 1) : i);
-
- _out = new TownsMidiOutputChannel*[6];
- for (int i = 0; i < 6; i++)
- _out[i] = new TownsMidiOutputChannel(this, i);
-
- _chanState = new TownsMidiChanState[32];
-
- _operatorLevelTable = new uint8[2048];
- for (int i = 0; i < 64; i++) {
- for (int ii = 0; ii < 32; ii++)
- _operatorLevelTable[(i << 5) + ii] = ((i * (ii + 1)) >> 5) & 0xff;
- }
- for (int i = 0; i < 64; i++)
- _operatorLevelTable[i << 5] = 0;
-}
-
-MidiDriver_TOWNS::~MidiDriver_TOWNS() {
- close();
- delete _intf;
-
- if (_channels) {
- for (int i = 0; i < 32; i++)
- delete _channels[i];
- delete[] _channels;
- }
- _channels = 0;
-
- if (_out) {
- for (int i = 0; i < 6; i++)
- delete _out[i];
- delete[] _out;
- }
- _out = 0;
-
- delete[] _chanState;
- _chanState = 0;
- delete[] _operatorLevelTable;
- _operatorLevelTable = 0;
-}
-
-int MidiDriver_TOWNS::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- if (!_intf->init())
- return MERR_CANNOT_CONNECT;
-
- _intf->callback(0);
-
- _intf->callback(21, 255, 1);
- _intf->callback(21, 0, 1);
- _intf->callback(22, 255, 221);
-
- _intf->callback(33, 8);
- _intf->setSoundEffectChanMask(~0x3f);
-
- _allocCurPos = 0;
-
- _isOpen = true;
-
- return 0;
-}
-
-void MidiDriver_TOWNS::close() {
- if (!_isOpen)
- return;
-
- _isOpen = false;
-
- setTimerCallback(0, 0);
- g_system->delayMillis(20);
-}
-
-void MidiDriver_TOWNS::send(uint32 b) {
- if (!_isOpen)
- return;
-
- byte param2 = (b >> 16) & 0xFF;
- byte param1 = (b >> 8) & 0xFF;
- byte cmd = b & 0xF0;
-
- TownsMidiInputChannel *c = _channels[b & 0x0F];
-
- switch (cmd) {
- case 0x80:
- c->noteOff(param1);
- break;
- case 0x90:
- if (param2)
- c->noteOn(param1, param2);
- else
- c->noteOff(param1);
- break;
- case 0xB0:
- c->controlChange(param1, param2);
- break;
- case 0xC0:
- c->programChange(param1);
- break;
- case 0xE0:
- c->pitchBend((param1 | (param2 << 7)) - 0x2000);
- break;
- case 0xF0:
- warning("MidiDriver_TOWNS: Receiving SysEx command on a send() call");
- break;
-
- default:
- break;
- }
-}
-
-void MidiDriver_TOWNS::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
- _timerProc = timer_proc;
- _timerProcPara = timer_param;
-}
-
-uint32 MidiDriver_TOWNS::getBaseTempo() {
- return _baseTempo;
-}
-
-MidiChannel *MidiDriver_TOWNS::allocateChannel() {
- if (!_isOpen)
- return 0;
-
- for (int i = 0; i < 32; ++i) {
- TownsMidiInputChannel *chan = _channels[i];
- if (chan->allocate())
- return chan;
- }
-
- return 0;
-}
-
-MidiChannel *MidiDriver_TOWNS::getPercussionChannel() {
- return 0;
-}
-
-void MidiDriver_TOWNS::timerCallback(int timerId) {
- if (!_isOpen)
- return;
-
- switch (timerId) {
- case 1:
- updateParser();
- updateOutputChannels();
- break;
- default:
- break;
- }
-}
-
-void MidiDriver_TOWNS::updateParser() {
- if (_timerProc)
- _timerProc(_timerProcPara);
-}
-
-void MidiDriver_TOWNS::updateOutputChannels() {
- _tickCounter += _baseTempo;
- while (_tickCounter >= 16667) {
- _tickCounter -= 16667;
- for (int i = 0; i < 6; i++) {
- if (_out[i]->update())
- return;
- }
- }
-}
-
-TownsMidiOutputChannel *MidiDriver_TOWNS::allocateOutputChannel(uint8 pri) {
- TownsMidiOutputChannel *res = 0;
-
- for (int i = 0; i < 6; i++) {
- if (++_allocCurPos == 6)
- _allocCurPos = 0;
-
- int s = _out[_allocCurPos]->checkPriority(pri);
- if (s == TownsMidiOutputChannel::kDisconnected)
- return _out[_allocCurPos];
-
- if (s != TownsMidiOutputChannel::kHighPriority) {
- pri = s;
- res = _out[_allocCurPos];
- }
- }
-
- if (res)
- res->disconnect();
-
- return res;
-}
-
-int MidiDriver_TOWNS::randomValue(int para) {
- _rand = (_rand & 1) ? (_rand >> 1) ^ 0xb8 : (_rand >> 1);
- return (_rand * para) >> 8;
-}
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.h b/audio/softsynth/fmtowns_pc98/towns_midi.h
deleted file mode 100644
index 1143dbaa02..0000000000
--- a/audio/softsynth/fmtowns_pc98/towns_midi.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef TOWNS_MIDI_H
-#define TOWNS_MIDI_H
-
-#include "audio/softsynth/fmtowns_pc98/towns_audio.h"
-#include "audio/mididrv.h"
-
-
-class TownsMidiOutputChannel;
-class TownsMidiInputChannel;
-class TownsMidiChanState;
-
-class MidiDriver_TOWNS : public MidiDriver, public TownsAudioInterfacePluginDriver {
-friend class TownsMidiInputChannel;
-friend class TownsMidiOutputChannel;
-public:
- MidiDriver_TOWNS(Audio::Mixer *mixer);
- ~MidiDriver_TOWNS();
-
- int open();
- bool isOpen() const { return _isOpen; }
- void close();
-
- void send(uint32 b);
-
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
-
- uint32 getBaseTempo();
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel();
-
- void timerCallback(int timerId);
-
-private:
- void updateParser();
- void updateOutputChannels();
-
- TownsMidiOutputChannel *allocateOutputChannel(uint8 pri);
-
- int randomValue(int para);
-
- TownsMidiInputChannel **_channels;
- TownsMidiOutputChannel **_out;
- TownsMidiChanState *_chanState;
-
- Common::TimerManager::TimerProc _timerProc;
- void *_timerProcPara;
-
- TownsAudioInterface *_intf;
-
- uint32 _tickCounter;
- uint8 _allocCurPos;
- uint8 _rand;
-
- bool _isOpen;
-
- uint8 *_operatorLevelTable;
-
- const uint16 _baseTempo;
-};
-
-#endif
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
index 194bfc41f9..41034846eb 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp
@@ -20,7 +20,6 @@
*
*/
-#include "audio/softsynth/fmtowns_pc98/towns_midi.h"
#include "audio/musicplugin.h"
#include "common/translation.h"
#include "common/error.h"
@@ -48,8 +47,8 @@ MusicDevices TownsEmuMusicPlugin::getDevices() const {
}
Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_TOWNS(g_system->getMixer());
- return Common::kNoError;
+ *mididriver = 0;
+ return Common::kUnknownError;
}
class PC98EmuMusicPlugin : public MusicPluginObject {
@@ -73,8 +72,8 @@ MusicDevices PC98EmuMusicPlugin::getDevices() const {
}
Common::Error PC98EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- //*mididriver = /**/
- return Common::kNoError;
+ *mididriver = 0;
+ return Common::kUnknownError;
}
//#if PLUGIN_ENABLED_DYNAMIC(TOWNS)