KYRA: (EOB II/PC98) - add sound support

(still with minor issues, but mostly finished)
This commit is contained in:
athrxx
2023-06-02 17:04:20 +02:00
parent 861d0008b5
commit 2fc6dba332
13 changed files with 1568 additions and 82 deletions
+7 -4
View File
@@ -89,6 +89,7 @@ private:
uint16 _chargenMaxStats[7];
const uint8 _menuColor1, _menuColor2, _menuColor3;
const uint8 _trackNo;
const char *const *_chargenStrings1;
const char *const *_chargenStrings2;
@@ -141,7 +142,9 @@ CharacterGenerator::CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen) :
_updateBoxShapesIndex(0), _lastUpdateBoxShapesIndex(0), _magicShapesBox(6), _activeBox(0),
_menuColor1(vm->gameFlags().platform == Common::kPlatformSegaCD ? 0xFF : (vm->_configRenderMode == Common::kRenderCGA ? 1 : vm->guiSettings()->colors.guiColorWhite)),
_menuColor2(vm->gameFlags().platform == Common::kPlatformSegaCD ? 0x55 : vm->guiSettings()->colors.guiColorLightRed),
_menuColor3(vm->gameFlags().platform == Common::kPlatformSegaCD ? 0x99 : vm->guiSettings()->colors.guiColorBlack) {
_menuColor3(vm->gameFlags().platform == Common::kPlatformSegaCD ? 0x99 : vm->guiSettings()->colors.guiColorBlack),
_trackNo(vm->game() == GI_EOB1 ? (vm->gameFlags().platform == Common::kPlatformPC98 ? 1 :
(vm->gameFlags().platform == Common::kPlatformSegaCD ? 8: 20)) : (vm->gameFlags().platform == Common::kPlatformPC98 ? 53 : 13)) {
_chargenStatStrings = _vm->_chargenStatStrings;
_chargenRaceSexStrings = _vm->_chargenRaceSexStrings;
@@ -352,7 +355,7 @@ bool CharacterGenerator::createCustomParty(const uint8 ***faceShapes) {
checkForCompleteParty();
initButtonsFromList(0, 5);
_vm->snd_playSong(_vm->game() == GI_EOB1 ? (_vm->gameFlags().platform == Common::kPlatformPC98 ? 1 : (_vm->gameFlags().platform == Common::kPlatformSegaCD ? 8: 20)) : 13);
_vm->snd_playSong(_trackNo);
_activeBox = 0;
for (bool loop = true; loop && (!_vm->shouldQuit());) {
@@ -894,13 +897,13 @@ int CharacterGenerator::getInput(Button *buttonList) {
if (_vm->game() == GI_EOB1 && _vm->sound()->checkTrigger()) {
_vm->sound()->resetTrigger();
_vm->snd_playSong(20);
_vm->snd_playSong(_trackNo);
} else if (_vm->game() == GI_EOB2 && !_vm->sound()->isPlaying()) {
// WORKAROUND for EOB II: The original implements the same sound trigger check as in EOB I.
// However, Westwood seems to have forgotten to set the trigger at the end of the AdLib song,
// so that the music will not loop. We simply check whether the sound driver is still playing.
_vm->delay(3 * _vm->_tickLength);
_vm->snd_playSong(13);
_vm->snd_playSong(_trackNo);
}
return _vm->checkInput(buttonList, false, 0);
+8 -3
View File
@@ -606,6 +606,11 @@ bool DarkMoonEngine::restParty_extraAbortCondition() {
return true;
}
void DarkMoonEngine::snd_playLevelScore() {
if (_flags.platform == Common::kPlatformPC98)
snd_playSong(0);
}
void DarkMoonEngine::snd_loadAmigaSounds(int level, int sub) {
if (_flags.platform != Common::kPlatformAmiga)
return;
@@ -691,9 +696,9 @@ void DarkMoonEngine::snd_loadAmigaSounds(int level, int sub) {
_amigaCurSoundIndex = sndIndex;
}
void DarkMoonEngine::snd_playLevelScore() {
if (_flags.platform == Common::kPlatformPC98)
snd_playSong(0);
void DarkMoonEngine::snd_updateLevelScore() {
if (_flags.platform == Common::kPlatformPC98 && !_sound->isPlaying())
snd_playLevelScore();
}
void DarkMoonEngine::useHorn(int charIndex, int weaponSlot) {
+2 -1
View File
@@ -120,8 +120,9 @@ private:
bool restParty_extraAbortCondition() override;
// Sound
void snd_loadAmigaSounds(int level, int sub) override;
void snd_playLevelScore() override;
void snd_loadAmigaSounds(int level, int sub) override;
void snd_updateLevelScore() override;
const char *const *_amigaSoundFiles2;
const char *const *_amigaSoundMapExtra;
+1 -1
View File
@@ -1270,7 +1270,7 @@ protected:
void snd_stopSound();
void snd_fadeOut(int del = 160);
virtual void snd_loadAmigaSounds(int level, int sub) = 0;
virtual void snd_updateLevelScore() {}
virtual void snd_updateLevelScore() = 0;
const char **_amigaSoundMap;
const char *const *_amigaLevelSoundList1;
+3 -1
View File
@@ -218,7 +218,7 @@ Common::Error KyraRpgEngine::init() {
initStaticResource();
_envSfxDistThreshold = ((_flags.gameID == GI_EOB2 && _sound->getSfxType() == Sound::kTowns) || _sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : (_sound->getSfxType() == Sound::kAmiga ? 4 : 3);
_envSfxDistThreshold = ((_flags.gameID == GI_EOB2 && (_sound->getSfxType() == Sound::kTowns || _sound->getSfxType() == Sound::kPC98)) || _sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : (_sound->getSfxType() == Sound::kAmiga ? 4 : 3);
_dialogueButtonLabelColor1 = guiSettings()->buttons.labelColor1;
_dialogueButtonLabelColor2 = guiSettings()->buttons.labelColor2;
@@ -405,6 +405,8 @@ bool KyraRpgEngine::snd_processEnvironmentalSoundEffect(int soundId, int block)
if (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns)
_environmentSfxVol = dist ? (16 - dist) * 8 - 1 : 127;
else if (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformPC98)
_environmentSfxVol = (15 - dist) * 6 + 37;
else if (_flags.platform == Common::kPlatformAmiga)
_environmentSfxVol = dist ? (soundId != 13 ? dist : (dist >= 4) ? 4 : dist) : 1;
else if (_flags.platform == Common::kPlatformSegaCD)
+1 -1
View File
@@ -2526,7 +2526,7 @@ void GUI_EoB::runCampMenu() {
else if (_vm->_configMusic)
_vm->snd_playSong(11);
else
_vm->snd_playSong(0);
_vm->snd_stopSound();
} else {
_vm->_configSounds ^= true;
_vm->_configMusic = _vm->_configSounds ? 1 : 0;
+1 -1
View File
@@ -537,7 +537,7 @@ void EoBCoreEngine::initStaticResource() {
_sound->initAudioResourceInfo(kMusicIntro, &intro);
_sound->initAudioResourceInfo(kMusicFinale, &finale);
} else if (_flags.platform != Common::kPlatformPC98) {
} else if (_flags.platform != Common::kPlatformPC98 || _flags.gameID == GI_EOB2) {
const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
SoundResourceInfo_PC ingame(files, temp);
files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
+27 -22
View File
@@ -273,7 +273,7 @@ void DarkMoonEngine::seq_playIntro() {
// PC-98 --- SFX 0
if (!skipFlag() && !shouldQuit())
snd_playSong(12);
snd_playSong(_flags.platform == Common::kPlatformPC98 ? 54 : 12);
_screen->copyRegion(0, 0, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK);
sq.setPalette(9);
@@ -346,7 +346,8 @@ void DarkMoonEngine::seq_playIntro() {
sq.printText(3, textColor1); // The message was urgent.
// PC-98 --- SFX 1
if (_flags.platform == Common::kPlatformPC98)
snd_playSong(55);
sq.loadScene(1, 2);
sq.waitForSongNotifier(++songCurPos);
@@ -446,7 +447,8 @@ void DarkMoonEngine::seq_playIntro() {
sq.animCommand(16);
// PC-98 --- SFX 2
if (_flags.platform == Common::kPlatformPC98)
snd_playSong(56);
sq.printText(7, textColor2); // Thank you for coming so quickly
sq.animCommand(16);
@@ -592,7 +594,8 @@ void DarkMoonEngine::seq_playIntro() {
sq.animCommand(20);
sq.animCommand(18);
// PC-98 --- SFX 3
if (_flags.platform == Common::kPlatformPC98)
snd_playSong(57);
sq.fadeText();
sq.animCommand(29);
@@ -618,7 +621,7 @@ void DarkMoonEngine::seq_playIntro() {
else {
_screen->setScreenDim(17);
_screen->clearCurDim();
snd_playSoundEffect(14);
snd_playSoundEffect(_flags.platform == Common::kPlatformPC98 ? 12 : 14);
if (_configRenderMode != Common::kRenderEGA)
sq.fadePalette(10, 1);
@@ -659,7 +662,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.delay(18);
if (!skipFlag() && !shouldQuit() && _flags.platform != Common::kPlatformAmiga)
snd_playSong(1);
snd_playSong(_flags.platform == Common::kPlatformPC98 ? 52 : 1);
sq.update(2);
sq.loadScene(1, 2);
@@ -784,8 +787,10 @@ void DarkMoonEngine::seq_playFinale() {
sq.waitForSongNotifier(3);
int sfxOffset = (_flags.platform == Common::kPlatformPC98) ? -1 : 0;
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(7);
snd_playSoundEffect(7 + sfxOffset);
sq.delay(8);
sq.animCommand(10);
@@ -819,7 +824,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.waitForSongNotifier(4);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(7);
snd_playSoundEffect(7 + sfxOffset);
sq.delay(8);
sq.animCommand(10);
@@ -856,7 +861,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.delay(36);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(11);
snd_playSoundEffect(11 + sfxOffset);
sq.delay(54);
sq.fadeText();
@@ -865,7 +870,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.waitForSongNotifier(5);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(6);
snd_playSoundEffect(6 + sfxOffset);
if (_flags.platform == Common::kPlatformAmiga)
sq.copyPalette(6, 0);
@@ -882,7 +887,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.animCommand(19);
sq.animCommand(19, 36);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(12);
snd_playSoundEffect(12 + sfxOffset);
sq.fadeText();
sq.printText(17, textColor2); // Thank you
@@ -892,12 +897,12 @@ void DarkMoonEngine::seq_playFinale() {
sq.printText(18, textColor2); // You have earned my deepest respect
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(11);
snd_playSoundEffect(11 + sfxOffset);
sq.animCommand(20);
sq.animCommand(19);
sq.animCommand(19);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(11);
snd_playSoundEffect(11 + sfxOffset);
sq.delay(36);
sq.fadeText();
@@ -905,13 +910,13 @@ void DarkMoonEngine::seq_playFinale() {
sq.animCommand(19);
sq.animCommand(19, 18);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(11);
snd_playSoundEffect(11 + sfxOffset);
sq.animCommand(20, 18);
sq.fadeText();
sq.delay(28);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(12);
snd_playSoundEffect(12 + sfxOffset);
sq.delay(3);
sq.loadScene(5, 2);
@@ -919,26 +924,26 @@ void DarkMoonEngine::seq_playFinale() {
_screen->copyRegion(0, 0, 8, 8, 304, 128, 2, 0, Screen::CR_NO_P_CHECK);
} else {
sq.updateAmigaSound();
snd_playSoundEffect(6);
snd_playSoundEffect(6 + sfxOffset);
if (_configRenderMode != Common::kRenderEGA)
sq.setPaletteWithoutTextColor(0);
_screen->crossFadeRegion(0, 0, 8, 8, 304, 128, 2, 0);
}
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(12);
snd_playSoundEffect(12 + sfxOffset);
sq.delay(5);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(11);
snd_playSoundEffect(11 + sfxOffset);
sq.delay(11);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(12);
snd_playSoundEffect(12 + sfxOffset);
sq.delay(7);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(11);
snd_playSoundEffect(11 + sfxOffset);
sq.delay(12);
if (!skipFlag() && !shouldQuit())
snd_playSoundEffect(12);
snd_playSoundEffect(12 + sfxOffset);
sq.updateAmigaSound();
removeInputTop();
@@ -958,7 +963,7 @@ void DarkMoonEngine::seq_playFinale() {
sq.delay(18);
if (!skipFlag() && !shouldQuit() && _flags.platform != Common::kPlatformAmiga)
snd_playSong(_flags.platform == Common::kPlatformFMTowns ? 16 : 1);
snd_playSong(_flags.platform == Common::kPlatformFMTowns ? 16 : (_flags.platform == Common::kPlatformPC98 ? 52 : 1));
int temp = 0;
File diff suppressed because it is too large Load Diff
+18 -2
View File
@@ -24,8 +24,8 @@
#ifndef KYRA_SOUND_CAPCOM98_H
#define KYRA_SOUND_CAPCOM98_H
#include "audio/mididrv.h"
#include "common/scummsys.h"
//#include "common/array.h"
namespace Audio {
class Mixer;
@@ -37,9 +37,25 @@ class CapcomPC98AudioDriverInternal;
class CapcomPC98AudioDriver {
public:
CapcomPC98AudioDriver();
CapcomPC98AudioDriver(Audio::Mixer *mixer, MidiDriver::DeviceHandle dev);
~CapcomPC98AudioDriver();
bool isUsable() const;
// All data passed to the following functions has to be maintained by the caller.
void reset();
void loadFMInstruments(const uint8 *data);
void startSong(const uint8 *data, uint8 volume, bool loop);
void stopSong();
void startSoundEffect(const uint8 *data, uint8 volume);
void stopSoundEffect();
int checkSoundMarker() const;
bool songIsPlaying() const;
bool soundEffectIsPlaying() const;
void setMusicVolume(int volume);
void setSoundEffectVolume(int volume);
private:
CapcomPC98AudioDriverInternal *_drv;
};
+13 -1
View File
@@ -540,13 +540,14 @@ public:
~SoundPC98_Darkmoon() override;
kType getMusicType() const override;
kType getSfxType() const override;
bool init() override;
void initAudioResourceInfo(int set, void *info) override;
void selectAudioResourceSet(int set) override;
bool hasSoundFile(uint file) const override { return true; }
void loadSoundFile(uint file) override {}
void loadSoundFile(uint file) override;
void loadSoundFile(Common::String name) override;
void playTrack(uint8 track) override;
@@ -565,11 +566,22 @@ public:
void resetTrigger() override;
private:
void restartBackgroundMusic();
const uint8 *getData(uint16 track) const;
KyraEngine_v1 *_vm;
CapcomPC98AudioDriver *_driver;
uint8 *_soundData, *_fileBuffer;
int _lastTrack;
const SoundResourceInfo_PC *res() const {return _resInfo[_currentResourceSet]; }
SoundResourceInfo_PC *_resInfo[3];
int _currentResourceSet;
Common::String _soundFileLoaded;
MidiDriver::DeviceHandle _dev;
kType _drvType;
bool _ready;
};
+136 -39
View File
@@ -30,105 +30,202 @@
namespace Kyra {
SoundPC98_Darkmoon::SoundPC98_Darkmoon(KyraEngine_v1 *vm, MidiDriver::DeviceHandle dev, Audio::Mixer *mixer) : Sound(vm, mixer),
_vm(vm), _driver(0), _currentResourceSet(-1), _ready(false), _drvType(kPC98) {
MusicType type = MidiDriver::getMusicType(dev);
if (type == MT_MT32) {
_drvType = kMidiMT32;
} else if (type == MT_GM) {
_drvType = kMidiGM;
} else {
_vm(vm), _driver(nullptr), _soundData(nullptr), _currentResourceSet(-1), _ready(false), _dev(dev), _drvType(kPC98), _lastTrack(-1) {
}
memset(&_resInfo, 0, sizeof(_resInfo));
_soundData = new uint8[20600];
memset(_soundData, 0, 20600);
_fileBuffer = new uint8[10500];
memset(_fileBuffer, 0, 10500);
MusicType type = MidiDriver::getMusicType(dev);
if (type == MT_MT32)
_drvType = kMidiMT32;
else if (type == MT_GM)
_drvType = kMidiGM;
}
SoundPC98_Darkmoon::~SoundPC98_Darkmoon() {
delete _driver;
delete[] _soundData;
delete[] _fileBuffer;
for (int i = 0; i < 3; i++)
initAudioResourceInfo(i, nullptr);
}
Sound::kType SoundPC98_Darkmoon::getMusicType() const {
return _drvType;
}
Sound::kType SoundPC98_Darkmoon::getSfxType() const {
return kPC98;
}
bool SoundPC98_Darkmoon::init() {
_driver = new CapcomPC98AudioDriver();
_ready = true;
return true;
_driver = new CapcomPC98AudioDriver(_mixer, _dev);
_ready = (_soundData && _driver && _driver->isUsable());
return _ready;
}
void SoundPC98_Darkmoon::initAudioResourceInfo(int set, void *info) {
//delete _resInfo[set];
//_resInfo[set] = info ? new SoundResourceInfo_PC(*(SoundResourceInfo_PC*)info) : 0;
if (set < kMusicIntro || set > kMusicFinale)
return;
delete _resInfo[set];
_resInfo[set] = info ? new SoundResourceInfo_PC(*(SoundResourceInfo_PC*)info) : nullptr;
}
void SoundPC98_Darkmoon::selectAudioResourceSet(int set) {
if (set == _currentResourceSet || !_ready)
if (set < kMusicIntro || set > kMusicFinale || set == _currentResourceSet || !_ready)
return;
if (_resInfo[set])
_currentResourceSet = set;
}
void SoundPC98_Darkmoon::loadSoundFile(uint file) {
if (!_ready)
return;
//if (!_resInfo[set])
// return;
_currentResourceSet = set;
if (file < res()->fileListSize)
loadSoundFile(res()->fileList[file]);
}
void SoundPC98_Darkmoon::loadSoundFile(Common::String name) {
if (!_ready)
return;
//if (file >= _resInfo[_currentResourceSet]->fileListSize)
// return;
haltTrack();
stopAllSoundEffects();
//Common::SeekableReadStream *s = _vm->resource()->createReadStream(_resInfo[_currentResourceSet]->fileList[file]);
//_driver->loadMusicData(s);
//delete s;
name += (_drvType == kPC98 ? ".SDO" : ".SDM");
if (!_ready || _soundFileLoaded == name)
return;
Common::SeekableReadStream *in = _vm->resource()->createReadStream(name.c_str());
if (!in)
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
uint16 sz = in->readUint16LE();
uint8 cmp = in->readByte();
in->seek(1, SEEK_CUR);
uint32 outSize = in->readUint32LE();
if ((cmp == 0 && outSize > 10500) || (cmp != 0 && outSize > 20600))
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
sz -= in->pos();
in->seek(2, SEEK_CUR);
memset(_fileBuffer, 0, 10500);
uint16 readSize = in->read(_fileBuffer, 10500);
assert(sz == readSize);
delete in;
memset(_soundData, 0, 20600);
if (cmp == 0) {
memcpy(_soundData, _fileBuffer, outSize);
} else if (cmp == 3) {
Screen::decodeFrame3(_fileBuffer, _soundData, outSize, true);
} else if (cmp == 4) {
Screen::decodeFrame4(_fileBuffer, _soundData, outSize);
} else {
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
}
uint16 instrOffs = READ_LE_UINT16(_soundData);
if (instrOffs >= 20600)
error("SoundPC98_Darkmoon::loadSoundFile(): Failed to load sound file '%s'", name.c_str());
_driver->loadFMInstruments(_soundData + instrOffs);
_driver->reset();
}
void SoundPC98_Darkmoon::playTrack(uint8 track) {
if (!_musicEnabled || !_ready)
return;
if (track == 0 || track == 2)
_lastTrack = track;
playSoundEffect(track, 127);
}
void SoundPC98_Darkmoon::haltTrack() {
if (!_musicEnabled || !_ready)
if (!_ready)
return;
//playTrack(0);
_driver->stopSong();
_lastTrack = -1;
}
bool SoundPC98_Darkmoon::isPlaying() const {
return false;
return _ready && _driver && _driver->songIsPlaying();
}
void SoundPC98_Darkmoon::playSoundEffect(uint16 track, uint8) {
if (!_sfxEnabled || !_ready || track >= 120)
void SoundPC98_Darkmoon::playSoundEffect(uint16 track, uint8 vol) {
if (!_ready)
return;
//_driver->startSoundEffect(track);
if (track == 0 || track == 2) {
restartBackgroundMusic();
return;
}
const uint8 *data = getData(track);
if (!data)
return;
if (track < 52 || track > 67) {
if (_sfxEnabled)
_driver->startSoundEffect(data, vol);
} else if (_musicEnabled) {
_lastTrack = track;
_driver->startSong(data, vol, false);
}
}
void SoundPC98_Darkmoon::stopAllSoundEffects() {
if (_ready)
_driver->stopSoundEffect();
}
void SoundPC98_Darkmoon::beginFadeOut() {
haltTrack();
stopAllSoundEffects();
}
int SoundPC98_Darkmoon::checkTrigger() {
return 99;
return _driver ? _driver->checkSoundMarker() : 99;
}
void SoundPC98_Darkmoon::resetTrigger() {
}
void SoundPC98_Darkmoon::restartBackgroundMusic() {
if (_lastTrack == -1) {
haltTrack();
stopAllSoundEffects();
} else {
_lastTrack = -1;
const uint8 *data = getData(0);
if (!data)
return;
if (_musicEnabled)
_driver->startSong(data, 127, true);
}
}
const uint8 *SoundPC98_Darkmoon::getData(uint16 track) const {
if (!_ready || track >= 120)
return nullptr;
uint16 offset = READ_LE_UINT16(&_soundData[(track + 1) << 1]);
return (offset < 20600) ? &_soundData[offset] : nullptr;
}
void SoundPC98_Darkmoon::updateVolumeSettings() {
if (!_driver || !_ready)
return;
//bool mute = false;
//if (ConfMan.hasKey("mute"))
// mute = ConfMan.getBool("mute");
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
//_driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
//_driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
_driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
_driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
}
} // End of namespace Kyra
+1 -1
View File
@@ -97,7 +97,7 @@ void SoundPC98_EoB::playTrack(uint8 track) {
}
void SoundPC98_EoB::haltTrack() {
if (!_musicEnabled || !_ready)
if (!_ready)
return;
playTrack(0);
}