From 46e514926942f019a5365de624cd752e675357fd Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Thu, 6 Jan 2011 14:06:04 +0000 Subject: HUGO: Implement DOS player svn-id: r55132 --- engines/hugo/hugo.cpp | 2 +- engines/hugo/schedule_v1d.cpp | 6 +-- engines/hugo/schedule_v2d.cpp | 6 +-- engines/hugo/sound.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++ engines/hugo/sound.h | 8 ++++ 5 files changed, 122 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index 2b010737cb..64b4116527 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -278,7 +278,7 @@ Common::Error HugoEngine::run() { while (!_status.doQuitFl) { g_system->updateScreen(); - + _sound->pcspkr_player(); runMachine(); // Handle input Common::Event event; diff --git a/engines/hugo/schedule_v1d.cpp b/engines/hugo/schedule_v1d.cpp index e224c8acd0..f49ce1b238 100644 --- a/engines/hugo/schedule_v1d.cpp +++ b/engines/hugo/schedule_v1d.cpp @@ -260,10 +260,8 @@ event_t *Scheduler_v1d::doAction(event_t *curEvent) { insertActionList(action->a29.actFailIndex); break; case OLD_SONG: - //TODO For DOS versions: The songs were not stored in a DAT file, but directly as - //strings. the current play_music should be modified to use a strings instead of reading - //the file, in those cases. This replaces, for those DOS versions, act26. - warning("STUB: doAction(act49) %s", _vm->_textData[action->a49.songIndex]); + // Replaces ACT26 for DOS games. + _vm->_sound->DOSSongPtr = _vm->_textData[action->a49.songIndex]; break; default: error("An error has occurred: %s", "doAction"); diff --git a/engines/hugo/schedule_v2d.cpp b/engines/hugo/schedule_v2d.cpp index 04302caf61..8764826e52 100644 --- a/engines/hugo/schedule_v2d.cpp +++ b/engines/hugo/schedule_v2d.cpp @@ -376,10 +376,8 @@ event_t *Scheduler_v2d::doAction(event_t *curEvent) { _vm->_object->_objects[action->a48.objNumb].currImagePtr = _vm->_object->_objects[action->a48.objNumb].currImagePtr->nextSeqPtr; break; case OLD_SONG: - //TODO For DOS versions: The songs were not stored in a DAT file, but directly as - //strings. the current play_music should be modified to use a strings instead of reading - //the file, in those cases. This replaces, for those DOS versions, act26. - warning("STUB: doAction(act49) %s", _vm->_textData[action->a49.songIndex]); + // Replaces ACT26 for DOS games. + _vm->_sound->DOSSongPtr = _vm->_textData[action->a49.songIndex]; break; default: error("An error has occurred: %s", "doAction"); diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp index d2b1e8d089..77bd4a19d9 100644 --- a/engines/hugo/sound.cpp +++ b/engines/hugo/sound.cpp @@ -231,9 +231,15 @@ SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) { MidiDriver *driver = MidiDriver::createMidi(dev); _midiPlayer = new MidiPlayer(driver); + _speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate()); + _vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle, + _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); + DOSSongPtr = 0; } SoundHandler::~SoundHandler() { + _vm->_mixer->stopHandle(_speakerHandle); + delete _speakerStream; delete _midiPlayer; } @@ -363,4 +369,107 @@ void SoundHandler::checkMusic() { } } } + +/** +* Decrement last note's timer and see if time to play next note yet. +* If so, interpret next note in string and play it. Update ptr to string +* Timer: >0 - song still going, 0 - Stop note, -1 - Set next note +*/ +void SoundHandler::pcspkr_player() { + static char pcspkrTimer = 0; // Timer (ticks) for note being played + static char pcspkrOctave = 3; // Current octave 1..7 + static byte pcspkrNoteDuration = 2; // Current length of note (ticks) + static uint16 pcspkrNotes[8] = {1352, 1205, 2274, 2026, 1805, 1704, 1518}; // The 3rd octave note counts A..G + static uint16 pcspkrSharps[8] = {1279, 1171, 2150, 1916, 1755, 1611, 1435}; // The sharps, A# to B# + static uint16 pcspkrFlats[8] = {1435, 1279, 2342, 2150, 1916, 1755, 1611}; // The flats, Ab to Bb + + uint16 count; // Value to set timer chip to for note + bool cmd_note; + + if (!_config.soundFl || !_vm->_mixer->isReady()) + return; // Poo! User doesn't want sound! + + if (!DOSSongPtr) + return; + + if (!*DOSSongPtr) // Song has finished + return; + + if (!--pcspkrTimer) { // timer zero, stop note + _speakerStream->stop(); + return; + } else if (pcspkrTimer >= 0) { // Note still going + return; + } + + /* Time to play next note */ + do { + cmd_note = true; + switch (*DOSSongPtr) { + case 'O': // Switch to new octave 1..7 + DOSSongPtr++; + pcspkrOctave = *DOSSongPtr - '0'; + if ((pcspkrOctave < 0) || (pcspkrOctave > 7)) + error("pcspkr_player() - Bad octave"); + DOSSongPtr++; + break; + case 'L': // Switch to new duration (in ticks) + DOSSongPtr++; + pcspkrNoteDuration = *DOSSongPtr - '0'; + if (pcspkrNoteDuration < 0) + error("pcspkr_player() - Bad duration"); + pcspkrNoteDuration--; + DOSSongPtr++; + break; + case '<': + case '^': // Move up an octave + pcspkrOctave++; + DOSSongPtr++; + break; + case '>': + case 'v': // Move down an octave + pcspkrOctave--; + DOSSongPtr++; + break; + default: + cmd_note = false; + break; + } + } while (cmd_note); + + switch (*DOSSongPtr) { + case 'A': // The notes. + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + count = pcspkrNotes[*DOSSongPtr - 'A']; + switch (DOSSongPtr[1]) { // Check for sharp or flat (#, -) + case '#': + count = pcspkrSharps[*DOSSongPtr++ - 'A']; + break; + case 'b': + count = pcspkrFlats[*DOSSongPtr++ - 'A']; + break; + default: + break; + } + if (pcspkrOctave > 3) // Adjust for octave + count /= (1 << (pcspkrOctave - 3)); + else if (pcspkrOctave < 3) + count *= (1 << (3 - pcspkrOctave)); + _speakerStream->play(Audio::PCSpeaker::kWaveFormSaw, kHugoCNT / count, (int32) ((1 + pcspkrNoteDuration) * _vm->_normalTPS) * 8); + pcspkrTimer = pcspkrNoteDuration; + DOSSongPtr++; + break; + case '.': /* A rest note */ + _speakerStream->stop(); + pcspkrTimer = pcspkrNoteDuration; + DOSSongPtr++; + break; + } +} + } // End of namespace Hugo diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h index 91a50fe24f..74f87d790e 100644 --- a/engines/hugo/sound.h +++ b/engines/hugo/sound.h @@ -36,9 +36,12 @@ #include "sound/mixer.h" #include "sound/mididrv.h" #include "sound/midiparser.h" +#include "sound/softsynth/pcspk.h" namespace Hugo { +#define kHugoCNT 1190000 + class MidiPlayer : public MidiDriver { public: @@ -92,9 +95,12 @@ public: SoundHandler(HugoEngine *vm); ~SoundHandler(); + char *DOSSongPtr; + void toggleMusic(); void toggleSound(); void setMusicVolume(); + void pcspkr_player(); void playMusic(int16 tune); void playSound(int16 sound, stereo_t channel, byte priority); void initSound(); @@ -105,6 +111,8 @@ private: HugoEngine *_vm; Audio::SoundHandle _soundHandle; MidiPlayer *_midiPlayer; + Audio::PCSpeaker *_speakerStream; + Audio::SoundHandle _speakerHandle; void stopSound(); void stopMusic(); -- cgit v1.2.3