aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp')
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp79
1 files changed, 60 insertions, 19 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 03c96792f6..b73030e416 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -288,9 +288,9 @@ void TownsPC98_FmSynthOperator::decayRate(uint32 value) {
}
void TownsPC98_FmSynthOperator::sustainRate(uint32 value) {
- _specifiedSustainRate = value;
- recalculateRates();
- }
+ _specifiedSustainRate = value;
+ recalculateRates();
+}
void TownsPC98_FmSynthOperator::sustainLevel(uint32 value) {
_sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5;
@@ -337,6 +337,7 @@ public:
void init(const int *rsTable, const int *rseTable);
void reset();
void writeReg(uint8 address, uint8 value, bool force = false);
+ uint8 readReg(uint8 address) const;
void nextTick(int32 *buffer, uint32 bufferSize);
@@ -348,10 +349,10 @@ public:
_volMaskA = channelMaskA;
_volMaskB = channelMaskB;
}
-
- uint8 chanEnable() const {
- return _chanEnable;
+ void setOutputLevel(int vol) {
+ _volumeT = vol;
}
+
private:
void updateRegs();
@@ -393,6 +394,7 @@ private:
uint16 _volumeA;
uint16 _volumeB;
+ uint16 _volumeT;
int _volMaskA;
int _volMaskB;
@@ -410,6 +412,7 @@ public:
void init(const uint8 *instrData = 0);
void reset();
void writeReg(uint8 address, uint8 value);
+ uint8 readReg(uint8 address) const;
void nextTick(int32 *buffer, uint32 bufferSize);
@@ -470,7 +473,7 @@ private:
TownsPC98_FmSynthSquareSineSource::TownsPC98_FmSynthSquareSineSource(const uint32 timerbase, const uint32 rtt) : _tlTable(0),
_rtt(rtt), _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1),
_nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true),
- _timer(0), _noiseGenerator(0), _chanEnable(0),
+ _timer(0), _noiseGenerator(0), _chanEnable(0), _volumeT(0x60),
_volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
memset(_channels, 0, sizeof(_channels));
@@ -579,6 +582,13 @@ void TownsPC98_FmSynthSquareSineSource::writeReg(uint8 address, uint8 value, boo
*_reg[address] = value;
}
+uint8 TownsPC98_FmSynthSquareSineSource::readReg(uint8 address) const {
+ if (!_ready || address > 10)
+ return 0;
+
+ return *_reg[address];
+}
+
void TownsPC98_FmSynthSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
if (!_ready)
return;
@@ -635,7 +645,7 @@ void TownsPC98_FmSynthSquareSineSource::nextTick(int32 *buffer, uint32 bufferSiz
finOut += finOutTemp;
}
- finOut /= 3;
+ finOut = (finOut * _volumeT) / Audio::Mixer::kMaxMixerVolume;
buffer[i << 1] += finOut;
buffer[(i << 1) + 1] += finOut;
@@ -781,6 +791,13 @@ void TownsPC98_FmSynthPercussionSource::writeReg(uint8 address, uint8 value) {
}
}
+uint8 TownsPC98_FmSynthPercussionSource::readReg(uint8 address) const {
+ if (!_ready || address > 0x0F)
+ return 0;
+
+ return *_reg[address];
+}
+
void TownsPC98_FmSynthPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
if (!_ready)
return;
@@ -861,12 +878,14 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type, bool ext
_hasPercussion(type == kType86 ? true : false),
_oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
_rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()),
- _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
- _regProtectionFlag(false), _externalMutex(externalMutexHandling), _ready(false) {
+ _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _externalMutex(externalMutexHandling), _ready(false) {
memset(&_timers[0], 0, sizeof(ChipTimer));
memset(&_timers[1], 0, sizeof(ChipTimer));
+ memset(_registers[0], 0, 255);
+ memset(_registers[1], 0, 255);
+
_timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback;
_timerbase = (uint32)(_baserate * 1000000.0f);
}
@@ -931,6 +950,9 @@ bool TownsPC98_FmSynth::init() {
}
void TownsPC98_FmSynth::reset() {
+ if (!_ready)
+ return;
+
Common::StackLock lock(_mutex);
for (int i = 0; i < _numChan; i++) {
for (int ii = 0; ii < 4; ii++)
@@ -942,6 +964,9 @@ void TownsPC98_FmSynth::reset() {
_chanInternal[i].updateEnvelopeParameters = false;
}
+ memset(_registers[0], 0, 255);
+ memset(_registers[1], 0, 255);
+
writeReg(0, 0x27, 0x33);
if (_ssg)
@@ -954,13 +979,20 @@ void TownsPC98_FmSynth::reset() {
}
void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
- if (_regProtectionFlag || !_ready)
+ if (!_ready)
return;
+ if (part > 1) {
+ warning("TownsPC98_FmSynth::writeReg(): invalid part argument '%d'", part);
+ part = 1;
+ }
+
Common::StackLock lock(_mutex);
static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
+ _registers[regAddress][part] = value;
+
uint8 h = regAddress & 0xf0;
uint8 l = (regAddress & 0x0f);
@@ -1141,6 +1173,18 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
}
}
+uint8 TownsPC98_FmSynth::readReg(uint8 part, uint8 regAddress) {
+ if (!_ready || part > 1)
+ return 0;
+
+ if (!(regAddress & 0xF0) && _ssg)
+ return _ssg->readReg(regAddress & 0x0F);
+ else if ((regAddress & 0xF0) == 0x10 && _prc)
+ return _prc->readReg(regAddress & 0x0F);
+
+ return _registers[regAddress][part];
+}
+
int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
memset(buffer, 0, sizeof(int16) * numSamples);
int32 *tmp = new int32[numSamples];
@@ -1242,14 +1286,6 @@ void TownsPC98_FmSynth::deinit() {
_timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback;
}
-void TownsPC98_FmSynth::toggleRegProtection(bool prot) {
- _regProtectionFlag = prot;
-}
-
-uint8 TownsPC98_FmSynth::readSSGStatus() {
- return _ssg->chanEnable();
-}
-
void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
Common::StackLock lock(_mutex);
_volumeA = CLIP<uint16>(volA, 0, Audio::Mixer::kMaxMixerVolume);
@@ -1274,6 +1310,11 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB
#endif
}
+void TownsPC98_FmSynth::setLevelSSG(int vol) {
+ if (_ssg)
+ _ssg->setOutputLevel(vol);
+}
+
void TownsPC98_FmSynth::generateTables() {
delete[] _oprRates;
_oprRates = new uint8[128];