From de0dd94c9cbf44f5dae72c69467fb7d24872eca5 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Fri, 14 Apr 2006 04:22:49 +0000 Subject: Add support for sound effects in Amiga version of FF and cleanup svn-id: r21870 --- engines/simon/res.cpp | 297 ++++++++++++++++++++++++++++++++++++++++++++++++ engines/simon/simon.cpp | 268 ------------------------------------------- engines/simon/simon.h | 2 + engines/simon/sound.cpp | 1 - engines/simon/vga.cpp | 4 +- 5 files changed, 300 insertions(+), 272 deletions(-) (limited to 'engines') diff --git a/engines/simon/res.cpp b/engines/simon/res.cpp index 7f307bee86..c9ddd6a27b 100644 --- a/engines/simon/res.cpp +++ b/engines/simon/res.cpp @@ -22,9 +22,19 @@ // Resource file routines for Simon1/Simon2 #include "common/stdafx.h" + #include "common/file.h" + #include "simon/simon.h" #include "simon/intern.h" +#include "simon/sound.h" + + +#ifdef USE_ZLIB +#include +#endif + +using Common::File; namespace Simon { @@ -135,6 +145,35 @@ uint32 SimonEngine::readUint32Wrapper(const void *src) { return READ_BE_UINT32(src); } +void SimonEngine::decompressData(const char *srcName, byte *dst, uint32 offset, uint32 srcSize, uint32 dstSize) { +#ifdef USE_ZLIB + File in; + in.open(srcName); + if (in.isOpen() == false) + error("decompressData: can't open %s", srcName); + + in.seek(offset, SEEK_SET); + if (srcSize != dstSize) { + byte *srcBuffer = (byte *)malloc(srcSize); + + if (in.read(srcBuffer, srcSize) != srcSize) + error("decompressData: read failed"); + + unsigned long decompressedSize = dstSize; + int result = uncompress(dst, &decompressedSize, srcBuffer, srcSize); + if (result != Z_OK) + error("decompressData() Zlib uncompress error"); + free(srcBuffer); + } else { + if (in.read(dst, dstSize) != dstSize) + error("decompressData: read failed"); + } + in.close(); +#else + error("Zlib support is required for Amiga and Macintosh versions"); +#endif +} + void SimonEngine::loadOffsets(const char *filename, int number, uint32 &file, uint32 &offset, uint32 &srcSize, uint32 &dstSize) { Common::File in; @@ -409,4 +448,262 @@ byte *SimonEngine::readSingleOpcode(Common::File *in, byte *ptr) { } } +// Thanks to Stuart Caie for providing the original +// C conversion upon which this decruncher is based. + +#define SD_GETBIT(var) do { \ + if (!bits--) { \ + s -= 4; \ + if (s < src) \ + return false; \ + bb = READ_BE_UINT32(s); \ + bits = 31; \ + } \ + (var) = bb & 1; \ + bb >>= 1; \ +}while (0) + +#define SD_GETBITS(var, nbits) do { \ + bc = (nbits); \ + (var) = 0; \ + while (bc--) { \ + (var) <<= 1; \ + SD_GETBIT(bit); \ + (var) |= bit; \ + } \ +}while (0) + +#define SD_TYPE_LITERAL (0) +#define SD_TYPE_MATCH (1) + +static bool decrunchFile(byte *src, byte *dst, uint32 size) { + byte *s = src + size - 4; + uint32 destlen = READ_BE_UINT32 (s); + uint32 bb, x, y; + byte *d = dst + destlen; + byte bc, bit, bits, type; + + // Initialize bit buffer. + s -= 4; + bb = x = READ_BE_UINT32 (s); + bits = 0; + do { + x >>= 1; + bits++; + } while (x); + bits--; + + while (d > dst) { + SD_GETBIT(x); + if (x) { + SD_GETBITS(x, 2); + switch (x) { + case 0: + type = SD_TYPE_MATCH; + x = 9; + y = 2; + break; + + case 1: + type = SD_TYPE_MATCH; + x = 10; + y = 3; + break; + + case 2: + type = SD_TYPE_MATCH; + x = 12; + SD_GETBITS(y, 8); + break; + + default: + type = SD_TYPE_LITERAL; + x = 8; + y = 8; + } + } else { + SD_GETBIT(x); + if (x) { + type = SD_TYPE_MATCH; + x = 8; + y = 1; + } else { + type = SD_TYPE_LITERAL; + x = 3; + y = 0; + } + } + + if (type == SD_TYPE_LITERAL) { + SD_GETBITS(x, x); + y += x; + if ((int)(y + 1) > (d - dst)) + return false; // Overflow? + do { + SD_GETBITS(x, 8); + *--d = x; + } while (y-- > 0); + } else { + if ((int)(y + 1) > (d - dst)) + return false; // Overflow? + SD_GETBITS(x, x); + if ((d + x) > (dst + destlen)) + return false; // Offset overflow? + do { + d--; + *d = d[x]; + } while (y-- > 0); + } + } + + // Successful decrunch. + return true; +} + +#undef SD_GETBIT +#undef SD_GETBITS +#undef SD_TYPE_LITERAL +#undef SD_TYPE_MATCH + +void SimonEngine::read_vga_from_datfile_1(uint vga_id) { + if (getFeatures() & GF_OLD_BUNDLE) { + File in; + char filename[15]; + uint32 size; + if (vga_id == 23) + vga_id = 112; + if (vga_id == 328) + vga_id = 119; + + if (getPlatform() == Common::kPlatformAmiga) { + if (getFeatures() & GF_TALKIE) + sprintf(filename, "0%d.out", vga_id); + else + sprintf(filename, "0%d.pkd", vga_id); + } else { + sprintf(filename, "0%d.VGA", vga_id); + } + + in.open(filename); + if (in.isOpen() == false) + error("read_vga_from_datfile_1: can't open %s", filename); + size = in.size(); + + if (getFeatures() & GF_CRUNCHED) { + byte *buffer = new byte[size]; + if (in.read(buffer, size) != size) + error("read_vga_from_datfile_1: read failed"); + decrunchFile(buffer, _vgaBufferPointers[11].vgaFile2, size); + delete [] buffer; + } else { + if (in.read(_vgaBufferPointers[11].vgaFile2, size) != size) + error("read_vga_from_datfile_1: read failed"); + } + in.close(); + } else { + uint32 offs_a = _gameOffsetsPtr[vga_id]; + uint32 size = _gameOffsetsPtr[vga_id + 1] - offs_a; + + resfile_read(_vgaBufferPointers[11].vgaFile2, offs_a, size); + } +} + +byte *SimonEngine::read_vga_from_datfile_2(uint id, uint type) { + File in; + char filename[15]; + byte *dst = NULL; + + // !!! HACK !!! + // allocate more space for text to cope with foreign languages that use + // up more space than english. I hope 6400 bytes are enough. This number + // is base on: 2 (lines) * 320 (screen width) * 10 (textheight) -- olki + int extraBuffer = (id == 5 ? 6400 : 0); + + if (getFeatures() & GF_ZLIBCOMP) { + uint32 file, offset, srcSize, dstSize; + if (getPlatform() == Common::kPlatformAmiga) { + loadOffsets((const char*)"gfxindex.dat", id / 2 * 3 + type, file, offset, srcSize, dstSize); + } else { + loadOffsets((const char*)"graphics.vga", id / 2 * 3 + type, file, offset, srcSize, dstSize); + } + + if (getPlatform() == Common::kPlatformAmiga) + sprintf(filename, "GFX%d.VGA", file); + else + sprintf(filename, "graphics.vga"); + + dst = allocBlock(dstSize); + decompressData(filename, dst, offset, srcSize, dstSize); + return dst; + } else if (getFeatures() & GF_OLD_BUNDLE) { + uint32 size; + if (getPlatform() == Common::kPlatformAmiga) { + if (getFeatures() & GF_TALKIE) + sprintf(filename, "%.3d%d.out", id / 2, type); + else + sprintf(filename, "%.3d%d.pkd", id / 2, type); + } else { + sprintf(filename, "%.3d%d.VGA", id / 2, type); + } + + in.open(filename); + if (in.isOpen() == false) { + if (type == 3) + return NULL; + else + error("read_vga_from_datfile_2: can't open %s", filename); + } + size = in.size(); + + if (getFeatures() & GF_CRUNCHED) { + byte *buffer = new byte[size]; + if (in.read(buffer, size) != size) + error("read_vga_from_datfile_2: read failed"); + dst = allocBlock (READ_BE_UINT32(buffer + size - 4) + extraBuffer); + decrunchFile(buffer, dst, size); + delete[] buffer; + } else { + dst = allocBlock(size + extraBuffer); + if (in.read(dst, size) != size) + error("read_vga_from_datfile_2: read failed"); + } + in.close(); + + return dst; + } else { + uint32 offs_a = _gameOffsetsPtr[id]; + uint32 size = _gameOffsetsPtr[id + 1] - offs_a; + + dst = allocBlock(size + extraBuffer); + resfile_read(dst, offs_a, size); + + return dst; + } +} + +void SimonEngine::loadSound(uint sound, uint pan, uint vol, bool ambient) { + if (getFeatures() & GF_ZLIBCOMP) { + char filename[15]; + + uint32 file, offset, srcSize, dstSize; + if (getPlatform() == Common::kPlatformAmiga) { + loadOffsets((const char*)"sfxindex.dat", _zoneNumber * 22 + sound, file, offset, srcSize, dstSize); + } else { + loadOffsets((const char*)"effects.wav", _zoneNumber * 22 + sound, file, offset, srcSize, dstSize); + } + + if (getPlatform() == Common::kPlatformAmiga) + sprintf(filename, "sfx%d.wav", file); + else + sprintf(filename, "effects.wav"); + + byte *dst = (byte *)malloc(dstSize); + decompressData(filename, dst, offset, srcSize, dstSize); + _sound->playSoundData(dst, sound, pan, vol, ambient); + } else { + int offs = READ_LE_UINT32(_curSfxFile + sound * 4); + _sound->playSoundData(_curSfxFile + offs, sound, pan, vol, ambient); + } +} + } // End of namespace Simon diff --git a/engines/simon/simon.cpp b/engines/simon/simon.cpp index 25a93935bd..d2fbfa94dd 100644 --- a/engines/simon/simon.cpp +++ b/engines/simon/simon.cpp @@ -48,10 +48,6 @@ extern bool isSmartphone(void); #include "globals.h" #endif -#ifdef USE_ZLIB -#include -#endif - using Common::File; namespace Simon { @@ -3275,270 +3271,6 @@ void SimonEngine::playSpeech(uint speech_id, uint vgaSpriteId) { } } -// Thanks to Stuart Caie for providing the original -// C conversion upon which this decruncher is based. - -#define SD_GETBIT(var) do { \ - if (!bits--) { \ - s -= 4; \ - if (s < src) \ - return false; \ - bb = READ_BE_UINT32(s); \ - bits = 31; \ - } \ - (var) = bb & 1; \ - bb >>= 1; \ -}while (0) - -#define SD_GETBITS(var, nbits) do { \ - bc = (nbits); \ - (var) = 0; \ - while (bc--) { \ - (var) <<= 1; \ - SD_GETBIT(bit); \ - (var) |= bit; \ - } \ -}while (0) - -#define SD_TYPE_LITERAL (0) -#define SD_TYPE_MATCH (1) - -static bool decrunchFile(byte *src, byte *dst, uint32 size) { - byte *s = src + size - 4; - uint32 destlen = READ_BE_UINT32 (s); - uint32 bb, x, y; - byte *d = dst + destlen; - byte bc, bit, bits, type; - - // Initialize bit buffer. - s -= 4; - bb = x = READ_BE_UINT32 (s); - bits = 0; - do { - x >>= 1; - bits++; - } while (x); - bits--; - - while (d > dst) { - SD_GETBIT(x); - if (x) { - SD_GETBITS(x, 2); - switch (x) { - case 0: - type = SD_TYPE_MATCH; - x = 9; - y = 2; - break; - - case 1: - type = SD_TYPE_MATCH; - x = 10; - y = 3; - break; - - case 2: - type = SD_TYPE_MATCH; - x = 12; - SD_GETBITS(y, 8); - break; - - default: - type = SD_TYPE_LITERAL; - x = 8; - y = 8; - } - } else { - SD_GETBIT(x); - if (x) { - type = SD_TYPE_MATCH; - x = 8; - y = 1; - } else { - type = SD_TYPE_LITERAL; - x = 3; - y = 0; - } - } - - if (type == SD_TYPE_LITERAL) { - SD_GETBITS(x, x); - y += x; - if ((int)(y + 1) > (d - dst)) - return false; // Overflow? - do { - SD_GETBITS(x, 8); - *--d = x; - } while (y-- > 0); - } else { - if ((int)(y + 1) > (d - dst)) - return false; // Overflow? - SD_GETBITS(x, x); - if ((d + x) > (dst + destlen)) - return false; // Offset overflow? - do { - d--; - *d = d[x]; - } while (y-- > 0); - } - } - - // Successful decrunch. - return true; -} - -#undef SD_GETBIT -#undef SD_GETBITS -#undef SD_TYPE_LITERAL -#undef SD_TYPE_MATCH - -void SimonEngine::read_vga_from_datfile_1(uint vga_id) { - if (getFeatures() & GF_OLD_BUNDLE) { - File in; - char buf[15]; - uint32 size; - if (vga_id == 23) - vga_id = 112; - if (vga_id == 328) - vga_id = 119; - - if (getPlatform() == Common::kPlatformAmiga) { - if (getFeatures() & GF_TALKIE) - sprintf(buf, "0%d.out", vga_id); - else - sprintf(buf, "0%d.pkd", vga_id); - } else { - sprintf(buf, "0%d.VGA", vga_id); - } - - in.open(buf); - if (in.isOpen() == false) - error("read_vga_from_datfile_1: can't open %s", buf); - size = in.size(); - - if (getFeatures() & GF_CRUNCHED) { - byte *buffer = new byte[size]; - if (in.read(buffer, size) != size) - error("read_vga_from_datfile_1: read failed"); - decrunchFile(buffer, _vgaBufferPointers[11].vgaFile2, size); - delete [] buffer; - } else { - if (in.read(_vgaBufferPointers[11].vgaFile2, size) != size) - error("read_vga_from_datfile_1: read failed"); - } - in.close(); - } else { - uint32 offs_a = _gameOffsetsPtr[vga_id]; - uint32 size = _gameOffsetsPtr[vga_id + 1] - offs_a; - - resfile_read(_vgaBufferPointers[11].vgaFile2, offs_a, size); - } -} - -byte *SimonEngine::read_vga_from_datfile_2(uint id, uint type) { - // !!! HACK !!! - // allocate more space for text to cope with foreign languages that use - // up more space than english. I hope 6400 bytes are enough. This number - // is base on: 2 (lines) * 320 (screen width) * 10 (textheight) -- olki - int extraBuffer = (id == 5 ? 6400 : 0); - - if (getGameType() == GType_FF && getPlatform() != Common::kPlatformWindows) { -#ifdef USE_ZLIB - File in; - char buf[15]; - byte *dst = NULL; - - uint32 file, offset, srcSize, dstSize; - if (getPlatform() == Common::kPlatformAmiga) { - loadOffsets((const char*)"gfxindex.dat", id / 2 * 3 + type, file, offset, srcSize, dstSize); - } else { - loadOffsets((const char*)"graphics.vga", id / 2 * 3 + type, file, offset, srcSize, dstSize); - } - - if (getPlatform() == Common::kPlatformAmiga) - sprintf(buf, "GFX%d.VGA", file); - else - sprintf(buf, "graphics.vga"); - - in.open(buf); - if (in.isOpen() == false) - error("read_vga_from_datfile_2: can't open %s", buf); - - dst = allocBlock(dstSize); - - in.seek(offset, SEEK_SET); - if (srcSize != dstSize) { - byte *srcBuffer = (byte *)malloc(srcSize); - - if (in.read(srcBuffer, srcSize) != srcSize) - error("read_vga_from_datfile_2: read failed"); - - unsigned long decompressedSize = dstSize; - int result = uncompress(dst, &decompressedSize, srcBuffer, srcSize); - if (result != Z_OK) - error("read_vga_from_datfile_2() Zlib uncompress error"); - free(srcBuffer); - } else { - if (in.read(dst, dstSize) != dstSize) - error("read_vga_from_datfile_2: read failed"); - } - in.close(); - return dst; -#else - error("Zlib support is required for Amiga and Macintosh versions"); - return NULL; -#endif - } else if (getFeatures() & GF_OLD_BUNDLE) { - File in; - char buf[15]; - uint32 size; - byte *dst = NULL; - - if (getPlatform() == Common::kPlatformAmiga) { - if (getFeatures() & GF_TALKIE) - sprintf(buf, "%.3d%d.out", id / 2, type); - else - sprintf(buf, "%.3d%d.pkd", id / 2, type); - } else { - sprintf(buf, "%.3d%d.VGA", id / 2, type); - } - - in.open(buf); - if (in.isOpen() == false) { - if (type == 3) - return NULL; - else - error("read_vga_from_datfile_2: can't open %s", buf); - } - size = in.size(); - - if (getFeatures() & GF_CRUNCHED) { - byte *buffer = new byte[size]; - if (in.read(buffer, size) != size) - error("read_vga_from_datfile_2: read failed"); - dst = allocBlock (READ_BE_UINT32(buffer + size - 4) + extraBuffer); - decrunchFile(buffer, dst, size); - delete[] buffer; - } else { - dst = allocBlock(size + extraBuffer); - if (in.read(dst, size) != size) - error("read_vga_from_datfile_2: read failed"); - } - in.close(); - - return dst; - } else { - uint32 offs_a = _gameOffsetsPtr[id]; - uint32 size = _gameOffsetsPtr[id + 1] - offs_a; - byte *dst; - - dst = allocBlock(size + extraBuffer); - resfile_read(dst, offs_a, size); - - return dst; - } -} - void SimonEngine::resfile_read(void *dst, uint32 offs, uint32 size) { _gameFile->seek(offs, SEEK_SET); if (_gameFile->read(dst, size) != size) diff --git a/engines/simon/simon.h b/engines/simon/simon.h index f067a716f8..17025aa856 100644 --- a/engines/simon/simon.h +++ b/engines/simon/simon.h @@ -480,7 +480,9 @@ protected: void readItemChildren(Common::File *in, Item *item, uint tmp); void readItemFromGamePc(Common::File *in, Item *item); void loadGamePcFile(const char *filename); + void decompressData(const char *srcName, byte *dst, uint32 offset, uint32 srcSize, uint32 dstSize); void loadOffsets(const char *filename, int number, uint32 &file, uint32 &offset, uint32 &compressedSize, uint32 &size); + void loadSound(uint sound, uint pan, uint vol, bool ambient); void palette_fadeout(uint32 *pal_values, uint num); diff --git a/engines/simon/sound.cpp b/engines/simon/sound.cpp index b3a7b54502..88cc32b969 100644 --- a/engines/simon/sound.cpp +++ b/engines/simon/sound.cpp @@ -477,7 +477,6 @@ void Sound::playSoundData(byte *soundData, uint sound, uint pan, uint vol, bool return; } - soundData += READ_LE_UINT32(soundData + sound * 4); int size = READ_LE_UINT32(soundData + 4); Common::MemoryReadStream stream(soundData, size); if (!loadWAVFromStream(stream, size, rate, flags)) { diff --git a/engines/simon/vga.cpp b/engines/simon/vga.cpp index 940b0ce319..93ab4ebee9 100644 --- a/engines/simon/vga.cpp +++ b/engines/simon/vga.cpp @@ -1958,9 +1958,7 @@ void SimonEngine::vc52_playSound() { if (getGameType() == GType_FF) { uint16 pan = vcReadNextWord(); uint16 vol = vcReadNextWord(); - - if (_curSfxFile != NULL) - _sound->playSoundData(_curSfxFile, sound, pan, vol, ambient); + loadSound(sound, pan, vol, ambient); } else if (getGameType() == GType_SIMON2) { if (ambient) { _sound->playAmbient(sound); -- cgit v1.2.3