aboutsummaryrefslogtreecommitdiff
path: root/simon
diff options
context:
space:
mode:
authorOliver Kiehl2002-11-24 12:53:01 +0000
committerOliver Kiehl2002-11-24 12:53:01 +0000
commit90982259101d70f561838213b6a66b36bbe01e84 (patch)
treece992f85f6160f13454050f9e6045e30fa67a6bd /simon
parentefd0ef1e79ccd402c128157adcecf3aa7d46a6ea (diff)
downloadscummvm-rg350-90982259101d70f561838213b6a66b36bbe01e84.tar.gz
scummvm-rg350-90982259101d70f561838213b6a66b36bbe01e84.tar.bz2
scummvm-rg350-90982259101d70f561838213b6a66b36bbe01e84.zip
split simon sound
svn-id: r5706
Diffstat (limited to 'simon')
-rw-r--r--simon/items.cpp2
-rw-r--r--simon/module.mk3
-rw-r--r--simon/simon.cpp424
-rw-r--r--simon/simon.h18
-rw-r--r--simon/simonsound.cpp434
-rw-r--r--simon/simonsound.h74
-rw-r--r--simon/vga.cpp23
7 files changed, 532 insertions, 446 deletions
diff --git a/simon/items.cpp b/simon/items.cpp
index 4c87835233..daf41a45b5 100644
--- a/simon/items.cpp
+++ b/simon/items.cpp
@@ -1655,7 +1655,7 @@ void SimonState::o_unk_120(uint a)
void SimonState::o_unk_163(uint a)
{
- playEffects(a);
+ _sound->playEffects(a);
}
void SimonState::o_unk_160(uint a)
diff --git a/simon/module.mk b/simon/module.mk
index d9eb461a7d..ac0ecc7b55 100644
--- a/simon/module.mk
+++ b/simon/module.mk
@@ -5,9 +5,10 @@ MODULE_OBJS = \
simon/items.o \
simon/midi.o \
simon/res.o \
+ simon/simonsound.o \
simon/simon.o \
simon/verb.o \
- simon/vga.o
+ simon/vga.o \
# Include common rules
include common.rules
diff --git a/simon/simon.cpp b/simon/simon.cpp
index 30ced3b5bd..b05fd0b5ed 100644
--- a/simon/simon.cpp
+++ b/simon/simon.cpp
@@ -150,10 +150,6 @@ SimonState::SimonState(GameDetector *detector, OSystem *syst)
"Features of the game that depend on sound synchronization will most likely break");
set_volume(detector->_sfx_volume);
- _effects_sound = 0;
- _voice_sound = 0;
- _ambient_sound = 0;
-
_effects_paused = false;
_ambient_paused = false;
_music_paused = false;
@@ -818,7 +814,12 @@ void SimonState::loadTablesIntoMem(uint subr_id)
closeTablesFile(in);
memcpy(filename, "SFXXXX", 6);
- readSfxFile(filename);
+ if (_game == GAME_SIMON1WIN )
+ _sound->readSfxFile(filename, _gameDataPath);
+ else if (_game & GAME_SIMON2) {
+ int set = atoi(filename + 6) - 1;
+ _sound->loadSfxTable(_game_file, _game_offsets_ptr[set + gss->SOUND_INDEX_BASE], set);
+ }
alignTableMem();
@@ -3422,9 +3423,7 @@ void SimonState::video_toggle_colors(HitArea * ha, byte a, byte b, byte c, byte
bool SimonState::vc_59_helper()
{
- if (_voice_file == NULL)
- return true;
- return _voice_sound == 0;
+ return _sound->_voice_handle == 0;
}
void SimonState::video_copy_if_flag_0x8_c(FillOrCopyStruct *fcs)
@@ -3466,75 +3465,6 @@ void SimonState::showmessage_helper_2()
_fcs_ptr_1 = fcs_alloc(8, 0x90, 0x18, 6, 1, 0, 0xF);
}
-void SimonState::readSfxFile(const char *filename)
-{
- uint num = 0;
- if (_game == GAME_SIMON1WIN) { /* simon 1 win */
- uint32 size;
-
- if (_effects_offsets)
- free(_effects_offsets);
-
- if (_effects_file->isOpen() == true)
- _effects_file->close();
-
- _effects_file->open(filename, _gameDataPath);
-
- if (_effects_file->isOpen() == false) {
- warning("readSfxFile: Cannot load sfx file %s", filename);
- return;
- }
-
- vc_29_stop_all_sounds();
-
- _effects_file->seek(4, SEEK_SET);
- size = _effects_file->readUint32LE();
-
- num = size / sizeof(uint32);
-
- _effects_offsets = (uint32 *)malloc(size);
-
- _effects_file->seek(0, SEEK_SET);
- _effects_file->read(_effects_offsets, size);
-
-#if defined(SCUMM_BIG_ENDIAN)
- for (uint r = 0; r < num; r++)
- _effects_offsets[r] = FROM_LE_32(_effects_offsets[r]);
-#endif
- } else if (_game & GAME_SIMON2) { /* simon 2 */
- int num_per_set[] = {0, 188, 223, 217, 209, 179, 187, 189, 116, 174, 203,
- 173, 176, 38, 205, 134, 213, 212, 167, 141};
-
- int set;
- uint32 offs;
- uint i;
-
- vc_29_stop_all_sounds();
-
- if (_effects_offsets)
- free(_effects_offsets);
-
- set = atoi(filename + 6) - 1;
- offs = _game_offsets_ptr[set + gss->SOUND_INDEX_BASE];
- num = num_per_set[set];
-
- if (num == 0)
- return;
-
- _effects_offsets = (uint32 *)malloc(num * sizeof(uint32));
-
- _game_file->seek(offs, SEEK_SET);
- _game_file->read(_effects_offsets, num * sizeof(uint32));
-
- for (i = 0; i < num; i++) {
-#if defined(SCUMM_BIG_ENDIAN)
- _effects_offsets[i] = FROM_LE_32(_effects_offsets[i]);
-#endif
- _effects_offsets[i] += offs;
- }
- }
-}
-
void SimonState::video_putchar(FillOrCopyStruct *fcs, byte c)
{
if (c == 0xC) {
@@ -3796,7 +3726,7 @@ void SimonState::talk_with_speech(uint speech_id, uint num_1)
o_unk_99_simon1(num_1 + 201);
}
- playVoice(speech_id);
+ _sound->playVoice(speech_id);
if (num_1 < 100) {
start_vga_code(4, 2, num_1 + 201, 0, 0, 0);
@@ -3819,7 +3749,7 @@ void SimonState::talk_with_speech(uint speech_id, uint num_1)
o_unk_99_simon2(2, 5);
}
o_unk_99_simon2(2, num_1 + 2);
- playVoice(speech_id);
+ _sound->playVoice(speech_id);
start_vga_code(4, 2, num_1 + 2, 0, 0, 0);
}
@@ -4540,7 +4470,7 @@ void SimonState::go()
setup_vga_file_buf_pointers();
- initSound();
+ _sound = new SimonSound(_game, gss, _gameDataPath, _mixer);
if (!loadGamePcFile(gss->gamepc_filename))
error("Error loading gamepc file '%s' (or one of the files it depends on)",
@@ -4554,12 +4484,7 @@ void SimonState::go()
_mainscript_toggle = false;
_vgascript_toggle = false;
-
- if (_voice_type != FORMAT_NONE) {
- _vk_t_toggle = false;
- } else {
- _vk_t_toggle = true;
- }
+ _vk_t_toggle = false;
while (1) {
hitarea_stuff();
@@ -4613,16 +4538,9 @@ void SimonState::delay(uint amount)
} else if (event.kbd.ascii == 'm') {
midi.pause(_music_paused ^= 1);
} else if (event.kbd.ascii == 's') {
- _effects_paused ^= 1;
+ _sound->effectsPause(_effects_paused ^= 1);
} else if (event.kbd.ascii == 'b') {
- _ambient_paused ^= 1;
- if (_ambient_paused && _ambient_playing) {
- _mixer->stop(_ambient_index);
- } else if (_ambient_playing) {
- uint tmp = _ambient_playing;
- _ambient_playing = 0;
- playAmbient(tmp);
- }
+ _sound->ambientPause(_ambient_paused ^= 1);
} else if (event.kbd.flags == OSystem::KBD_CTRL) {
if (event.kbd.ascii == 'f') {
_fast_mode ^= 1;
@@ -4880,322 +4798,6 @@ bool SimonState::load_game(uint slot)
return true;
}
-void SimonState::initSound()
-{
-#ifdef SCUMM_BIG_ENDIAN
- uint i;
-#endif
- /* only read voice file in windows game */
- if (_game & GAME_TALKIE) {
- const char *s;
- const char *e;
-
- //
- // Load voice file
- //
- _voice_offsets = NULL;
- _voice_file = new File();
- _voice_type = FORMAT_NONE;
-
-#ifdef USE_MAD
- s = gss->mp3_filename;
- _voice_file->open(s, _gameDataPath);
- if (_voice_file->isOpen() == false) {
-#endif
- if (_game & GAME_WIN) {
- s = gss->wav_filename;
- _voice_file->open(s, _gameDataPath);
- if (_voice_file->isOpen() == false) {
- warning("Cannot open voice file %s", s);
- } else {
- _voice_type = FORMAT_WAV;
- }
- } else {
- s = gss->voc_filename;
- _voice_file->open(s, _gameDataPath);
- if (_voice_file->isOpen() == false) {
- warning("Cannot open voice file %s", s);
- } else {
- _voice_type = FORMAT_VOC;
- }
- }
-#ifdef USE_MAD
- } else
- _voice_type = FORMAT_MP3;
-#endif
-
- if (_voice_type != FORMAT_NONE) {
-#ifdef USE_MAD
- if (_voice_type == FORMAT_MP3) {
- _voice_offsets = (uint32 *)malloc((gss->NUM_VOICE_RESOURCES + 1) * sizeof(uint32));
- } else {
-#endif
- _voice_offsets = (uint32 *)malloc(gss->NUM_VOICE_RESOURCES * sizeof(uint32));
-#ifdef USE_MAD
- }
-#endif
- if (_voice_offsets == NULL)
- error("Out of memory for voice offsets");
-
- if (_voice_file->read(_voice_offsets, gss->NUM_VOICE_RESOURCES * sizeof(uint32)) != gss->NUM_VOICE_RESOURCES * sizeof(uint32))
- error("Cannot read voice offsets");
-#ifdef SCUMM_BIG_ENDIAN
- for (i = 0; i < gss->NUM_VOICE_RESOURCES; i++)
- _voice_offsets[i] = FROM_LE_32(_voice_offsets[i]);
-#endif
-#ifdef USE_MAD
- if (_voice_type == FORMAT_MP3) {
- _voice_file->seek(0, SEEK_END);
- _voice_offsets[gss->NUM_EFFECTS_RESOURCES] = _voice_file->pos();
- }
-#endif
- }
-
- //
- // Load effects
- //
- _effects_offsets = NULL;
- _effects_file = new File();
- _effects_type = FORMAT_VOC;
-
-#ifdef USE_MAD
- e = gss->mp3_effects_filename;
- _effects_file->open(e, _gameDataPath);
- if (_effects_file->isOpen() == false ) {
-#endif
- e = gss->voc_effects_filename;
- _effects_file->open(e, _gameDataPath);
-#ifdef USE_MAD
- } else {
- _effects_type = FORMAT_MP3;
- }
-#endif
- if (_effects_file->isOpen() == true)
- {
-#ifdef USE_MAD
- if (_effects_type == FORMAT_MP3) {
- _effects_offsets = (uint32 *)malloc((gss->NUM_EFFECTS_RESOURCES + 1) * sizeof(uint32));
- } else {
-#endif
- _effects_offsets = (uint32 *)malloc(gss->NUM_EFFECTS_RESOURCES * sizeof(uint32));
-#ifdef USE_MAD
- }
-#endif
- if (_effects_offsets == NULL)
- error("Out of memory for effects offsets");
-
- if (_effects_file->read(_effects_offsets, gss->NUM_EFFECTS_RESOURCES * sizeof(uint32)) != gss->NUM_EFFECTS_RESOURCES * sizeof(uint32))
- error("Cannot read effects offsets");
-#ifdef SCUMM_BIG_ENDIAN
- for (i = 0; i < gss->NUM_EFFECTS_RESOURCES; i++)
- _effects_offsets[i] = FROM_LE_32(_effects_offsets[i]);
-#endif
-#ifdef USE_MAD
- if (_effects_type == FORMAT_MP3) {
- _effects_file->seek(0, SEEK_END);
- _effects_offsets[gss->NUM_EFFECTS_RESOURCES] = _effects_file->pos();
- }
-#endif
- } else {
- _effects_type = FORMAT_NONE;
- }
-
- }
-}
-
-#if !defined(__GNUC__)
-#pragma START_PACK_STRUCTS
-#endif
-
-struct WaveHeader {
- uint32 riff;
- uint32 unk;
- uint32 wave;
- uint32 fmt;
-
- uint32 size;
-
- uint16 format_tag;
- uint16 channels;
- uint32 samples_per_sec;
- uint32 avg_bytes;
-
- uint16 block_align;
- uint16 bits_per_sample;
-} GCC_PACK;
-
-struct VocHeader {
- uint8 desc[20];
- uint16 datablock_offset;
- uint16 version;
- uint16 id;
-} GCC_PACK;
-
-struct VocBlockHeader {
- uint8 blocktype;
- uint8 size[3];
- uint8 sr;
- uint8 pack;
-} GCC_PACK;
-
-
-#if !defined(__GNUC__)
-#pragma END_PACK_STRUCTS
-#endif
-
-
-#ifdef USE_MAD
-int SimonState::playMP3(File *sound_file, uint32 *offsets, uint sound, PlayingSoundHandle *sound_handle, byte flags)
-{
- sound_file->seek(offsets[sound], SEEK_SET);
-
- uint32 size = offsets[sound+1] - offsets[sound];
-
- byte *buffer = (byte *)malloc(size);
- sound_file->read(buffer, size);
-
- return _mixer->playMP3(sound_handle, buffer, size, flags);
-}
-#endif
-
-int SimonState::playVoc(File *sound_file, uint32 *offsets, uint sound, PlayingSoundHandle *sound_handle, byte flags)
-{
- VocHeader voc_hdr;
- VocBlockHeader voc_block_hdr;
- uint32 size;
-
- sound_file->seek(offsets[sound], SEEK_SET);
-
- if (sound_file->read(&voc_hdr, sizeof(voc_hdr)) != sizeof(voc_hdr) ||
- strncmp((char *)voc_hdr.desc, "Creative Voice File\x1A", 10) != 0) {
- error("playVoc(%d): cannot read voc header", sound);
- }
-
- sound_file->read(&voc_block_hdr, sizeof(voc_block_hdr));
-
- size = voc_block_hdr.size[0] + (voc_block_hdr.size[1] << 8) + (voc_block_hdr.size[2] << 16) - 2;
- uint32 samples_per_sec;
-
- /* workaround for voc weakness */
- if (voc_block_hdr.sr == 0xa6) {
- samples_per_sec = 11025;
- } else if (voc_block_hdr.sr == 0xd2) {
- samples_per_sec = 22050;
- } else {
- samples_per_sec = 1000000L / (256L - (long)voc_block_hdr.sr);
- warning("inexact sample rate used: %i", samples_per_sec);
- }
-
- byte *buffer = (byte *)malloc(size);
- sound_file->read(buffer, size);
-
- return _mixer->playRaw(sound_handle, buffer, size, samples_per_sec, flags);
-}
-
-int SimonState::playWav(File *sound_file, uint32 *offsets, uint sound, PlayingSoundHandle *sound_handle, byte flags)
-{
- WaveHeader wave_hdr;
- uint32 data[2];
-
- sound_file->seek(offsets[sound], SEEK_SET);
-
- if (sound_file->read(&wave_hdr, sizeof(wave_hdr)) != sizeof(wave_hdr) ||
- wave_hdr.riff != MKID('RIFF') || wave_hdr.wave != MKID('WAVE')
- || wave_hdr.fmt != MKID('fmt ') || READ_LE_UINT16(&wave_hdr.format_tag) != 1
- || READ_LE_UINT16(&wave_hdr.channels) != 1
- || READ_LE_UINT16(&wave_hdr.bits_per_sample) != 8) {
- error("playWav(%d): cannot read RIFF header", sound);
- }
-
- sound_file->seek(FROM_LE_32(wave_hdr.size) - sizeof(wave_hdr) + 20, SEEK_CUR);
-
- data[0] = sound_file->readUint32LE();
- data[1] = sound_file->readUint32LE();
- if ( //fread(data, sizeof(data), 1, sound_file) != 1 ||
- data[0] != 'atad') {
- error("playWav(%d): cannot read data header", sound);
- }
-
- byte *buffer = (byte *)malloc(data[1]);
- sound_file->read(buffer, data[1]);
-
- return _mixer->playRaw(sound_handle, buffer, data[1], FROM_LE_32(wave_hdr.samples_per_sec), flags);
-}
-
-void SimonState::playVoice(uint voice)
-{
- if (_voice_offsets == NULL)
- return;
-
-#ifdef USE_MAD
- if (_voice_type == FORMAT_MP3) {
- playMP3(_voice_file, _voice_offsets, voice, &_voice_sound, SoundMixer::FLAG_AUTOFREE);
- } else {
-#endif
- if (_voice_type == FORMAT_WAV) { /* WAVE audio */
- playWav(_voice_file, _voice_offsets, voice, &_voice_sound, SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- } else if (_voice_type == FORMAT_VOC) { /* VOC audio */
- playVoc(_voice_file, _voice_offsets, voice, &_voice_sound, SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- }
-#ifdef USE_MAD
- }
-#endif
-}
-
-void SimonState::playEffects(uint sound)
-{
- if (_effects_offsets == NULL)
- return;
-
- if (_effects_paused)
- return;
-
- if (_game == GAME_SIMON1TALKIE) { /* simon 1 talkie */
-#ifdef USE_MAD
- if (_effects_type == FORMAT_MP3) {
- playMP3(_effects_file, _effects_offsets, sound, &_effects_sound, SoundMixer::FLAG_AUTOFREE);
- } else {
-#endif
- playVoc(_effects_file, _effects_offsets, sound, &_effects_sound, SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
-#ifdef USE_MAD
- }
-#endif
- } else if (_game == GAME_SIMON1WIN){ /* simon 1 win */
- playWav(_effects_file, _effects_offsets, sound, &_effects_sound, SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- } else if (_game == GAME_SIMON2WIN) { /* simon 2 win */
- playWav(_game_file, _effects_offsets, sound, &_effects_sound, SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- } else if (_game & GAME_SIMON2) { /* simon 2 dos / talkie */
- playVoc(_game_file, _effects_offsets, sound, &_effects_sound, SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- } else { /* simon 1 dos */
- warning("playEffects(%d)", sound);
- }
-}
-
-void SimonState::playAmbient(uint sound)
-{
- if (_effects_offsets == NULL)
- return;
-
- if (_ambient_paused)
- return;
-
- if (sound == _ambient_playing)
- return;
-
- _ambient_playing = sound;
-
- if (_ambient_sound)
- _mixer->stop(_ambient_index);
-
- if (_game & GAME_WIN) {
- _ambient_index = playWav(_game_file, _effects_offsets, sound, &_ambient_sound,
- SoundMixer::FLAG_LOOP|SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- } else {
- _ambient_index = playVoc(_game_file, _effects_offsets, sound, &_ambient_sound,
- SoundMixer::FLAG_LOOP|SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE);
- }
-}
-
void SimonState::playMusic(uint music)
{
/* TODO */
diff --git a/simon/simon.h b/simon/simon.h
index 3d1034d21c..6ed283ea8b 100644
--- a/simon/simon.h
+++ b/simon/simon.h
@@ -26,6 +26,7 @@
#include "common/engine.h"
#include "simon/midi.h"
#include "sound/mixer.h"
+#include "simon/simonsound.h"
/* Various other settings */
//#define DRAW_IMAGES_DEBUG
@@ -332,11 +333,7 @@ public:
int _num_screen_updates;
int _vga_tick_counter;
- PlayingSoundHandle _effects_sound;
- PlayingSoundHandle _voice_sound;
- PlayingSoundHandle _ambient_sound;
- int _ambient_index;
- uint _ambient_playing;
+ SimonSound *_sound;
bool _effects_paused;
bool _ambient_paused;
@@ -522,8 +519,6 @@ public:
File *openTablesFile_gme(const char *filename);
void closeTablesFile_gme(File *in);
- void readSfxFile(const char *filename);
-
void invokeTimeEvent(TimeEvent *te);
bool kickoffTimeEvents();
@@ -773,15 +768,6 @@ public:
void video_putchar_newline(FillOrCopyStruct *fcs);
void video_putchar_drawchar(FillOrCopyStruct *fcs, uint x, uint y, byte chr);
- void initSound();
- void playVoice(uint voice);
- void playEffects(uint sound);
- void playAmbient(uint sound);
-
- int playVoc(File *sound_file, uint32 *offsets, uint sound, PlayingSoundHandle *sound_handle, byte flags);
- int playWav(File *sound_file, uint32 *offsets, uint sound, PlayingSoundHandle *sound_handle, byte flags);
- int playMP3(File *sound_file, uint32 *offsets, uint sound, PlayingSoundHandle *sound_handle, byte flags);
-
void playMusic(uint music);
void checkTimerCallback();
void delay(uint delay);
diff --git a/simon/simonsound.cpp b/simon/simonsound.cpp
new file mode 100644
index 0000000000..e687c880ed
--- /dev/null
+++ b/simon/simonsound.cpp
@@ -0,0 +1,434 @@
+#include "simon/simonsound.h"
+#include "common/file.h"
+#include "common/engine.h"
+
+enum {
+ GAME_SIMON2 = 1,
+ GAME_WIN = 2,
+ GAME_TALKIE = 4,
+ GAME_DEMO = 8,
+
+ GAME_SIMON1DOS = 0,
+ GAME_SIMON2DOS = GAME_SIMON2,
+ GAME_SIMON1TALKIE = GAME_TALKIE,
+ GAME_SIMON2TALKIE = GAME_SIMON2 + GAME_TALKIE,
+ GAME_SIMON1WIN = GAME_WIN + GAME_TALKIE,
+ GAME_SIMON2WIN = GAME_SIMON2 + GAME_WIN + GAME_TALKIE,
+ GAME_SIMON1DEMO = GAME_DEMO,
+};
+
+SimonSound::SimonSound(const byte game, const GameSpecificSettings *gss, const char *gameDataPath, SoundMixer *mixer)
+{
+ _game = game;
+ _mixer = mixer;
+
+ _effects_paused = false;
+ _ambient_paused = false;
+
+ _voice_handle = 0;
+ _effects_handle = 0;
+ _ambient_handle = 0;
+
+ _ambient_playing = 0;
+
+ File *file = new File();
+ File *file2 = new File();
+ const char *s;
+
+#ifdef USE_MAD
+ file->open(gss->mp3_filename, gameDataPath);
+ if (file->isOpen() == false) {
+#endif
+ if (_game & GAME_WIN) {
+ s = gss->wav_filename;
+ file->open(s, gameDataPath);
+ if (file->isOpen() == false) {
+ warning("Cannot open voice file %s", s);
+ } else {
+ _voice = new WavSound(_mixer, file, gss->NUM_VOICE_RESOURCES);
+ }
+ } else if (_game & GAME_TALKIE) {
+ s = gss->voc_filename;
+ file->open(s, gameDataPath);
+ if (file->isOpen() == false) {
+ warning("Cannot open voice file %s", s);
+ } else {
+ _voice = new VocSound(_mixer, file, gss->NUM_VOICE_RESOURCES);
+ }
+ }
+#ifdef USE_MAD
+ } else {
+ _voice = new MP3Sound(_mixer, file, gss->NUM_VOICE_RESOURCES);
+ }
+#endif
+
+ if (_game == GAME_SIMON1TALKIE) {
+#ifdef USE_MAD
+ file2->open(gss->mp3_effects_filename, gameDataPath);
+ if (file2->isOpen() == false) {
+#endif
+ s = gss->voc_effects_filename;
+ file2->open(s, gameDataPath);
+ if (file2->isOpen() == false) {
+ warning("Cannot open effects file %s", s);
+ } else {
+ _effects = new VocSound(_mixer, file2, gss->NUM_VOICE_RESOURCES);
+ }
+#ifdef USE_MAD
+ } else {
+ _effects = new MP3Sound(_mixer, file2, gss->NUM_VOICE_RESOURCES);
+ }
+#endif
+ }
+}
+
+void SimonSound::readSfxFile(const char *filename, const char *gameDataPath)
+{
+ stopAll();
+
+ File *file = new File();
+ file->open(filename, gameDataPath);
+
+ if (file->isOpen() == false) {
+ warning("readSfxFile: Cannot load sfx file %s", filename);
+ return;
+ }
+
+ _effects = new WavSound(_mixer, file);
+}
+
+void SimonSound::loadSfxTable(File *gameFile, uint32 offs, int set)
+{
+ if (!set)
+ return;
+
+ stopAll();
+
+ if (_game & GAME_WIN)
+ _effects = new WavSound(_mixer, gameFile, offs, set);
+ else
+ _effects = new VocSound(_mixer, gameFile, offs, set);
+}
+
+void SimonSound::playVoice(uint sound)
+{
+ if (!_voice)
+ return;
+
+ _voice->playSound(sound, &_voice_handle, 0);
+}
+
+void SimonSound::playEffects(uint sound)
+{
+ if (!_effects)
+ return;
+
+ if (_effects_paused)
+ return;
+
+ _effects->playSound(sound, &_effects_handle, 0);
+}
+
+void SimonSound::playAmbient(uint sound)
+{
+ if (!_effects)
+ return;
+
+ if (sound == _ambient_playing)
+ return;
+
+ _ambient_playing = sound;
+
+ if (_ambient_paused)
+ return;
+
+ if (_ambient_handle)
+ _mixer->stop(_ambient_index);
+
+ _ambient_index = _effects->playSound(sound, &_ambient_handle, SoundMixer::FLAG_LOOP);
+}
+
+void SimonSound::stopAll()
+{
+ _mixer->stopAll();
+ _ambient_playing = 0;
+}
+
+void SimonSound::effectsPause(bool b)
+{
+ _effects_paused = b;
+}
+
+void SimonSound::ambientPause(bool b)
+{
+ _ambient_paused = b;
+
+ if (_ambient_paused && _ambient_playing) {
+ _mixer->stop(_ambient_index);
+ } else if (_ambient_playing) {
+ uint tmp = _ambient_playing;
+ _ambient_playing = 0;
+ playAmbient(tmp);
+ }
+}
+
+/******************************************************************************/
+
+SimonSound::WavSound::WavSound(SoundMixer *mixer, File *file, uint resources)
+{
+ _mixer = mixer;
+ _file = file;
+ loadOffsets(resources);
+}
+
+SimonSound::WavSound::WavSound(SoundMixer *mixer, File *file) /* only used in simon1win */
+{
+ _mixer = mixer;
+ _file = file;
+ loadOffsets();
+}
+
+SimonSound::WavSound::WavSound(SoundMixer *mixer, File *file, uint32 offs, int set) /* only used in simon2 */
+{
+ _mixer = mixer;
+ _file = file;
+ loadOffsets(offs, set);
+}
+
+SimonSound::VocSound::VocSound(SoundMixer *mixer, File *file, uint resources)
+{
+ _mixer = mixer;
+ _file = file;
+ loadOffsets(resources);
+}
+
+SimonSound::VocSound::VocSound(SoundMixer *mixer, File *file, uint32 offs, int set) /* only used in simon2 */
+{
+ _mixer = mixer;
+ _file = file;
+ loadOffsets(offs, set);
+}
+
+#ifdef USE_MAD
+SimonSound::MP3Sound::MP3Sound(SoundMixer *mixer, File *file, uint resources)
+{
+ _mixer = mixer;
+ _file = file;
+
+ _offsets = (uint32 *)malloc((resources + 1) * sizeof(uint32));
+
+ if (_offsets == NULL)
+ error("Out of memory for voice offsets");
+
+ if (_file->read(_offsets, resources * sizeof(uint32)) != resources * sizeof(uint32))
+ error("Cannot read offsets");
+
+#ifdef SCUMM_BIG_ENDIAN
+ for (uint i = 0; i < resources; i++)
+ _offsets[i] = FROM_LE_32(_offsets[i]);
+#endif
+ _file->seek(0, SEEK_END);
+ _offsets[resources] = _file->pos();
+}
+#endif
+
+/******************************************************************************/
+
+void SimonSound::Sound::loadOffsets(uint resources)
+{
+ _offsets = (uint32 *)malloc(resources * sizeof(uint32));
+
+ if (_offsets == NULL)
+ error("Out of memory for offsets");
+
+ if (_file->read(_offsets, resources * sizeof(uint32)) != resources * sizeof(uint32))
+ error("Cannot read offsets");
+
+#ifdef SCUMM_BIG_ENDIAN
+ for (uint i = 0; i < resources; i++)
+ _offsets[i] = FROM_LE_32(_offsets[i]);
+#endif
+}
+
+void SimonSound::Sound::loadOffsets()
+{
+ uint num = 0;
+
+ uint32 size;
+
+ _file->seek(4, SEEK_SET);
+ size = _file->readUint32LE();
+
+ num = size / sizeof(uint32);
+
+ _offsets = (uint32 *)malloc(size);
+
+ _file->seek(0, SEEK_SET);
+ _file->read(_offsets, size);
+
+#if defined(SCUMM_BIG_ENDIAN)
+ for (uint r = 0; r < num; r++)
+ _offsets[r] = FROM_LE_32(_offsets[r]);
+#endif
+}
+
+void SimonSound::Sound::loadOffsets(uint32 offs, int set)
+{
+ int num_per_set[] = {0, 188, 223, 217, 209, 179, 187, 189, 116, 174, 203,
+ 173, 176, 38, 205, 134, 213, 212, 167, 141};
+
+ uint num;
+ uint i;
+
+ num = num_per_set[set];
+
+ if (num == 0)
+ return;
+
+ _offsets = (uint32 *)malloc(num * sizeof(uint32));
+
+ _file->seek(offs, SEEK_SET);
+ _file->read(_offsets, num * sizeof(uint32));
+
+ for (i = 0; i < num; i++) {
+#if defined(SCUMM_BIG_ENDIAN)
+ _offsets[i] = FROM_LE_32(_offsets[i]);
+#endif
+ _offsets[i] += offs;
+ }
+}
+
+/******************************************************************************/
+
+#if !defined(__GNUC__)
+#pragma START_PACK_STRUCTS
+#endif
+
+struct WaveHeader {
+ uint32 riff;
+ uint32 unk;
+ uint32 wave;
+ uint32 fmt;
+
+ uint32 size;
+
+ uint16 format_tag;
+ uint16 channels;
+ uint32 samples_per_sec;
+ uint32 avg_bytes;
+
+ uint16 block_align;
+ uint16 bits_per_sample;
+} GCC_PACK;
+
+struct VocHeader {
+ uint8 desc[20];
+ uint16 datablock_offset;
+ uint16 version;
+ uint16 id;
+} GCC_PACK;
+
+struct VocBlockHeader {
+ uint8 blocktype;
+ uint8 size[3];
+ uint8 sr;
+ uint8 pack;
+} GCC_PACK;
+
+#if !defined(__GNUC__)
+#pragma END_PACK_STRUCTS
+#endif
+
+#ifdef USE_MAD
+int SimonSound::MP3Sound::playSound(uint sound, PlayingSoundHandle *handle, byte flags)
+{
+ if (_offsets == NULL)
+ return 0;
+
+ flags |= SoundMixer::FLAG_AUTOFREE;
+
+ _file->seek(_offsets[sound], SEEK_SET);
+
+ uint32 size = _offsets[sound+1] - _offsets[sound];
+
+ byte *buffer = (byte *)malloc(size);
+ _file->read(buffer, size);
+
+ return _mixer->playMP3(handle, buffer, size, flags);
+}
+#endif
+
+int SimonSound::VocSound::playSound(uint sound, PlayingSoundHandle *handle, byte flags)
+{
+ if (_offsets == NULL)
+ return 0;
+
+ VocHeader voc_hdr;
+ VocBlockHeader voc_block_hdr;
+ uint32 size;
+
+ flags |= SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE;
+
+ _file->seek(_offsets[sound], SEEK_SET);
+
+ if (_file->read(&voc_hdr, sizeof(voc_hdr)) != sizeof(voc_hdr) ||
+ strncmp((char *)voc_hdr.desc, "Creative Voice File\x1A", 10) != 0) {
+ error("playVoc(%d): cannot read voc header", sound);
+ }
+
+ _file->read(&voc_block_hdr, sizeof(voc_block_hdr));
+
+ size = voc_block_hdr.size[0] + (voc_block_hdr.size[1] << 8) + (voc_block_hdr.size[2] << 16) - 2;
+ uint32 samples_per_sec;
+
+ /* workaround for voc weakness */
+ if (voc_block_hdr.sr == 0xa6) {
+ samples_per_sec = 11025;
+ } else if (voc_block_hdr.sr == 0xd2) {
+ samples_per_sec = 22050;
+ } else {
+ samples_per_sec = 1000000L / (256L - (long)voc_block_hdr.sr);
+ warning("inexact sample rate used: %i", samples_per_sec);
+ }
+
+ byte *buffer = (byte *)malloc(size);
+ _file->read(buffer, size);
+
+ return _mixer->playRaw(handle, buffer, size, samples_per_sec, flags);
+}
+
+int SimonSound::WavSound::playSound(uint sound, PlayingSoundHandle *handle, byte flags)
+{
+ if (_offsets == NULL)
+ return 0;
+
+ WaveHeader wave_hdr;
+ uint32 data[2];
+
+ flags |= SoundMixer::FLAG_UNSIGNED|SoundMixer::FLAG_AUTOFREE;
+
+ _file->seek(_offsets[sound], SEEK_SET);
+
+ if (_file->read(&wave_hdr, sizeof(wave_hdr)) != sizeof(wave_hdr) ||
+ wave_hdr.riff != MKID('RIFF') || wave_hdr.wave != MKID('WAVE')
+ || wave_hdr.fmt != MKID('fmt ') || READ_LE_UINT16(&wave_hdr.format_tag) != 1
+ || READ_LE_UINT16(&wave_hdr.channels) != 1
+ || READ_LE_UINT16(&wave_hdr.bits_per_sample) != 8) {
+ error("playWav(%d): cannot read RIFF header", sound);
+ }
+
+ _file->seek(FROM_LE_32(wave_hdr.size) - sizeof(wave_hdr) + 20, SEEK_CUR);
+
+ data[0] = _file->readUint32LE();
+ data[1] = _file->readUint32LE();
+ if (//fread(data, sizeof(data), 1, sound_file) != 1 ||
+ data[0] != 'atad') {
+ error("playWav(%d): cannot read data header", sound);
+ }
+
+ byte *buffer = (byte *)malloc(data[1]);
+ _file->read(buffer, data[1]);
+
+ return _mixer->playRaw(handle, buffer, data[1], FROM_LE_32(wave_hdr.samples_per_sec), flags);
+}
+
diff --git a/simon/simonsound.h b/simon/simonsound.h
new file mode 100644
index 0000000000..22935ac9eb
--- /dev/null
+++ b/simon/simonsound.h
@@ -0,0 +1,74 @@
+#include "sound/mixer.h"
+#include "simon/intern.h"
+
+class SimonSound {
+private:
+ class Sound {
+ protected:
+ File *_file;
+ uint32 *_offsets;
+ SoundMixer *_mixer;
+
+ void loadOffsets(uint resources);
+ void loadOffsets();
+ void loadOffsets(uint32 offs, int set);
+
+ public:
+ virtual int playSound(uint sound, PlayingSoundHandle *handle, byte flags) = 0;
+ };
+
+
+ class WavSound : public Sound {
+ public:
+ WavSound(SoundMixer *mixer, File *file, uint resources);
+ WavSound(SoundMixer *mixer, File *file);
+ WavSound(SoundMixer *mixer, File *file, uint32 offs, int set);
+
+ int playSound(uint sound, PlayingSoundHandle *handle, byte flags);
+ };
+
+ class VocSound : public Sound {
+ public:
+ VocSound(SoundMixer *mixer, File *file, uint resources);
+ VocSound(SoundMixer *mixer, File *file, uint32 offs, int set);
+
+ int playSound(uint sound, PlayingSoundHandle *handle, byte flags);
+ };
+
+ class MP3Sound : public Sound {
+ public:
+ MP3Sound(SoundMixer *mixer, File *file, uint resources);
+ int playSound(uint sound, PlayingSoundHandle *handle, byte flags);
+ };
+
+ byte _game;
+ int _ambient_index;
+ SoundMixer *_mixer;
+
+ Sound *_voice;
+ Sound *_effects;
+
+ bool _effects_paused;
+ bool _ambient_paused;
+
+public:
+ PlayingSoundHandle _voice_handle;
+ PlayingSoundHandle _effects_handle;
+ PlayingSoundHandle _ambient_handle;
+
+ uint _ambient_playing;
+
+ SimonSound(const byte game, const GameSpecificSettings *gss, const char *gameDataPath, SoundMixer *mixer);
+
+ void readSfxFile(const char *filename, const char *gameDataPath);
+ void loadSfxTable(File *gameFile, uint32 offs, int set);
+
+ void playVoice(uint sound);
+ void playEffects(uint sound);
+ void playAmbient(uint sound);
+
+ void stopAll();
+ void effectsPause(bool b);
+ void ambientPause(bool b);
+};
+
diff --git a/simon/vga.cpp b/simon/vga.cpp
index d687820f35..100b51e1b4 100644
--- a/simon/vga.cpp
+++ b/simon/vga.cpp
@@ -1343,8 +1343,7 @@ void SimonState::vc_28()
void SimonState::vc_29_stop_all_sounds()
{
- _mixer->stopAll();
- _ambient_playing = 0;
+ _sound->stopAll();
}
void SimonState::vc_30_set_base_delay()
@@ -1604,13 +1603,13 @@ void SimonState::vc_52()
uint16 a = vc_read_next_word();
if (!(_game & GAME_SIMON2)) {
- playEffects(a);
+ _sound->playEffects(a);
} else {
if (a >= 0x8000) {
a = -a;
- playAmbient(a);
+ _sound->playAmbient(a);
} else {
- playEffects(a);
+ _sound->playEffects(a);
}
}
}
@@ -1790,14 +1789,12 @@ void SimonState::vc_62()
vc_29_stop_all_sounds();
- if (!_video_var_3) {
- warning("vc_62: music stuff?");
- }
-
+// if (!_video_var_3) {
_video_var_3 = true;
_video_num_pal_colors = 256;
if (_video_palette_mode == 4)
_video_num_pal_colors = 208;
+// }
memcpy(_video_buf_1, _palette_backup, _video_num_pal_colors * sizeof(uint32));
for (i = NUM_PALETTE_FADEOUT; i != 0; --i) {
@@ -1864,14 +1861,6 @@ void SimonState::vc_64()
void SimonState::vc_65()
{ // Simon2
warning("vc_65 unimplemented");
- //_palette_color_count = 0x270;
- //_video_num_pal_colors = 0x0D0;
- //if (_video_palette_mode != 4) {
- //_palette_color_count = 0x300;
- //_video_num_pal_colors = 0x100;
- //}
- //_palette_color_count |= 0x8000;
- //_video_var_3 = false;
}
void SimonState::vc_66()