aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorathrxx2019-10-28 00:49:23 +0100
committerathrxx2019-12-18 20:50:39 +0100
commit900dcc4de57e68ed11409de13138adb3ca549814 (patch)
tree26cabd51a3b4896edb135776d6699258236c56b5
parent711034b74dd291286943a5b4aa17077ef05a39b2 (diff)
downloadscummvm-rg350-900dcc4de57e68ed11409de13138adb3ca549814.tar.gz
scummvm-rg350-900dcc4de57e68ed11409de13138adb3ca549814.tar.bz2
scummvm-rg350-900dcc4de57e68ed11409de13138adb3ca549814.zip
AUDIO: (FM-TOWNS/PC-98) - improve timer flags handling
Timers should be reset only the first time the enable flag is sent. This also requires some updates to drivers which didn't send these flags accurately.
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp8
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp36
2 files changed, 29 insertions, 15 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
index ed1b85170b..4a93d42454 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
@@ -1242,6 +1242,8 @@ void TownsPC98_AudioDriver::reset() {
_sfxData = 0;
_pc98a->reset();
+ setMusicTempo(84);
+ setSfxTempo(654);
for (int i = 0; i < _numChanFM; i++)
_channels[i]->reset();
@@ -1404,13 +1406,15 @@ void TownsPC98_AudioDriver::startSoundEffect() {
void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) {
writeReg(0, 0x26, tempo);
- writeReg(0, 0x27, 0x33);
+ writeReg(0, 0x27, 0x3D);
+ writeReg(0, 0x27, 0x3F);
}
void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) {
writeReg(0, 0x24, tempo & 0xff);
writeReg(0, 0x25, tempo >> 8);
- writeReg(0, 0x27, 0x33);
+ writeReg(0, 0x27, 0x3E);
+ writeReg(0, 0x27, 0x3F);
}
const uint8 TownsPC98_AudioDriver::_channelPreset[36] = {
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 0ecf0e45c9..558c389ebd 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -981,10 +981,10 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
}
TownsPC98_FmSynth::~TownsPC98_FmSynth() {
- Common::StackLock lock(_mutex);
if (_ready)
deinit();
+ Common::StackLock lock(_mutex);
delete _ssg;
#ifndef DISABLE_PC98_RHYTHM_CHANNEL
delete _prc;
@@ -1065,7 +1065,7 @@ void TownsPC98_FmSynth::reset() {
_waitCycleRemainder = 0;
#endif
- writeReg(0, 0x27, 0x33);
+ writeReg(0, 0x27, 0x30);
if (_ssg)
_ssg->reset();
@@ -1147,18 +1147,28 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
int render = inSamplesLeft;
for (int i = 0; i < 2; i++) {
- if (_timers[i].enabled && _timers[i].cb) {
+ if (_timers[i].enabled) {
if (!_timers[i].smpTillCb) {
+ int spc = i ? ((0x100 - _timers[i].value) << 4) << _rateScale : (0x400 - _timers[i].value) << _rateScale;
+ if (spc < 1)
+ spc = 1;
+
+ _timers[i].smpPerCb = (int32)spc;
+ _timers[i].smpPerCbRem = (uint32)((spc - (float)_timers[i].smpPerCb) * 1000000.0f);
+
if (_timers[i].cb) {
if (_timers[i].cb->isValid())
(*_timers[i].cb)();
- }
+ }
+
_timers[i].smpTillCb = _timers[i].smpPerCb;
_timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
- if (_timers[i].smpTillCbRem >= 1000000) {
+ while (_timers[i].smpTillCbRem >= 1000000) {
_timers[i].smpTillCb++;
_timers[i].smpTillCbRem -= 1000000;
}
+
+ _timers[i].enabled = _registers[0x27][0] & (4 << i);
}
render = MIN(render, _timers[i].smpTillCb);
}
@@ -1428,7 +1438,7 @@ void TownsPC98_FmSynth::writeRegInternal(uint8 part, uint8 regAddress, uint8 val
// Timer B
_timers[1].value = value & 0xff;
} else if (l == 7) {
- if (value & 1) {
+ if ((value & 1) && !_timers[0].enabled) {
int spc = (0x400 - _timers[0].value) << _rateScale;
if (spc < 1) {
warning("TownsPC98_FmSynth: Invalid Timer A setting: %d", _timers[0].value);
@@ -1440,11 +1450,11 @@ void TownsPC98_FmSynth::writeRegInternal(uint8 part, uint8 regAddress, uint8 val
_timers[0].smpTillCb = _timers[0].smpPerCb;
_timers[0].smpTillCbRem = _timers[0].smpPerCbRem;
_timers[0].enabled = true;
- } else {
+ } else if (!(value & 1)) {
_timers[0].enabled = false;
}
- if (value & 2) {
+ if ((value & 2) && !_timers[1].enabled) {
int spc = ((0x100 - _timers[1].value) << 4) << _rateScale;
if (spc < 1) {
warning("TownsPC98_FmSynth: Invalid Timer B setting: %d", _timers[1].value);
@@ -1456,18 +1466,18 @@ void TownsPC98_FmSynth::writeRegInternal(uint8 part, uint8 regAddress, uint8 val
_timers[1].smpTillCb = _timers[1].smpPerCb;
_timers[1].smpTillCbRem = _timers[1].smpPerCbRem;
_timers[1].enabled = true;
- } else {
+ } else if (!(value & 2)) {
_timers[1].enabled = false;
}
if (value & 0x10) {
- _timers[0].smpTillCb = _timers[0].smpPerCb;
- _timers[0].smpTillCbRem = _timers[0].smpPerCbRem;
+ // clear timer a over flag
+ // Unneeded / not implemented for ScummVM
}
if (value & 0x20) {
- _timers[1].smpTillCb = _timers[1].smpPerCb;
- _timers[1].smpTillCbRem = _timers[1].smpPerCbRem;
+ // clear timer b over flag
+ // Unneeded / not implemented for ScummVM
}
} else if (l == 2) {