diff options
Diffstat (limited to 'simon')
-rw-r--r-- | simon/items.cpp | 2 | ||||
-rw-r--r-- | simon/module.mk | 3 | ||||
-rw-r--r-- | simon/simon.cpp | 424 | ||||
-rw-r--r-- | simon/simon.h | 18 | ||||
-rw-r--r-- | simon/simonsound.cpp | 434 | ||||
-rw-r--r-- | simon/simonsound.h | 74 | ||||
-rw-r--r-- | simon/vga.cpp | 23 |
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() |