aboutsummaryrefslogtreecommitdiff
path: root/engines/hugo
diff options
context:
space:
mode:
authorArnaud Boutonné2011-01-06 14:06:04 +0000
committerArnaud Boutonné2011-01-06 14:06:04 +0000
commit46e514926942f019a5365de624cd752e675357fd (patch)
tree44558dc76ec77e0365b053d89d048d9325544608 /engines/hugo
parentbb9ad6afe44e2411742985dad6d7888a276970fe (diff)
downloadscummvm-rg350-46e514926942f019a5365de624cd752e675357fd.tar.gz
scummvm-rg350-46e514926942f019a5365de624cd752e675357fd.tar.bz2
scummvm-rg350-46e514926942f019a5365de624cd752e675357fd.zip
HUGO: Implement DOS player
svn-id: r55132
Diffstat (limited to 'engines/hugo')
-rw-r--r--engines/hugo/hugo.cpp2
-rw-r--r--engines/hugo/schedule_v1d.cpp6
-rw-r--r--engines/hugo/schedule_v2d.cpp6
-rw-r--r--engines/hugo/sound.cpp109
-rw-r--r--engines/hugo/sound.h8
5 files changed, 122 insertions, 9 deletions
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();