aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/parallaction/callables.cpp5
-rw-r--r--engines/parallaction/disk.cpp166
-rw-r--r--engines/parallaction/disk.h7
-rw-r--r--engines/parallaction/location.cpp11
-rw-r--r--engines/parallaction/music.cpp49
-rw-r--r--engines/parallaction/music.h20
-rw-r--r--engines/parallaction/zone.cpp7
-rw-r--r--engines/parallaction/zone.h4
-rw-r--r--engines/saga/scene.cpp10
9 files changed, 165 insertions, 114 deletions
diff --git a/engines/parallaction/callables.cpp b/engines/parallaction/callables.cpp
index 1946737488..1c81534ed6 100644
--- a/engines/parallaction/callables.cpp
+++ b/engines/parallaction/callables.cpp
@@ -449,7 +449,10 @@ void _c_testResult(void *parm) {
}
void _c_offSound(void*) {
- // TODO: to be implemented
+ _vm->_soundMan->stopSfx(0);
+ _vm->_soundMan->stopSfx(1);
+ _vm->_soundMan->stopSfx(2);
+ _vm->_soundMan->stopSfx(3);
}
void _c_startMusic(void*) {
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp
index cbedb17e85..d1f237773a 100644
--- a/engines/parallaction/disk.cpp
+++ b/engines/parallaction/disk.cpp
@@ -22,101 +22,19 @@
#include "common/stdafx.h"
+#include "graphics/iff.h"
+
#include "parallaction/defs.h"
#include "parallaction/graphics.h"
#include "parallaction/parallaction.h"
#include "parallaction/disk.h"
#include "parallaction/walk.h"
-#include "graphics/ilbm.h"
-
-namespace Parallaction {
-
-class RLEStream : public Common::ReadStream {
-
- Common::ReadStream *_input;
-
- byte _rembuf[257];
- int32 _wpos;
- int32 _rpos;
-
- int32 _toBeRead;
- byte* _dst;
- int32 _read;
-
- void store(byte b) {
- if (_toBeRead > 0) {
- *_dst++ = b;
- _read++;
- _wpos = 0;
- _rpos = 0;
- } else {
- assert(_wpos < 257);
- _rembuf[_wpos++] = b;
- _rpos = 0;
- }
-
- _toBeRead--;
- }
-
- void feed() {
- int32 len = MIN(_wpos - _rpos, _toBeRead);
- if (len == 0) return;
-
- memcpy(_dst, _rembuf + _rpos, len);
-
- _rpos += len;
- _read += len;
- _toBeRead -= len;
- }
-
- void unpack() {
- byte byteRun;
- byte idx;
-
- uint32 i, j;
-
- while (_toBeRead > 0 && !_input->eos()) {
- byteRun = _input->readByte();
- if (byteRun <= 127) {
- i = byteRun + 1;
- for (j = 0; j < i; j++) {
- idx = _input->readByte();
- store(idx);
- }
- } else if (byteRun != 128) {
- i = (256 - byteRun) + 1;
- idx = _input->readByte();
- for (j = 0; j < i; j++) {
- store(idx);
- }
- }
- }
-
- }
-
-public:
- RLEStream(Common::ReadStream *input) : _input(input), _wpos(0), _rpos(0) {
- }
-
- ~RLEStream() {
- }
-
- bool eos() const {
- return _input->eos() & (_rpos == _wpos);
- }
-
- uint32 read(void *dataPtr, uint32 dataSize) {
- _toBeRead = (int32)dataSize;
- _dst = (byte*)dataPtr;
- _read = 0;
- feed();
- unpack();
- return _read;
- }
-
-};
+namespace Audio {
+ AudioStream *make8SVXStream(Common::ReadStream &input);
+}
+namespace Parallaction {
/*
This stream class is just a wrapper around Archive, so
@@ -290,7 +208,7 @@ Cnv* DosDisk::loadCnv(const char *filename) {
uint32 decsize = numFrames * width * height;
byte *data = (byte*)malloc(decsize);
- RLEStream decoder(&_resArchive);
+ Graphics::PackBitsReadStream decoder(_resArchive);
decoder.read(data, decsize);
return new Cnv(numFrames, width, height, data);
@@ -416,7 +334,7 @@ StaticCnv* DosDisk::loadStatic(const char* name) {
uint16 size = cnv->_width*cnv->_height;
cnv->_data0 = (byte*)malloc(size);
- RLEStream decoder(&_resArchive);
+ Graphics::PackBitsReadStream decoder(_resArchive);
decoder.read(cnv->_data0, size);
return cnv;
@@ -489,7 +407,7 @@ void DosDisk::loadBackground(const char *filename) {
byte *path = (byte*)calloc(1, SCREENPATH_WIDTH*SCREEN_HEIGHT);
- RLEStream stream(&_resArchive);
+ Graphics::PackBitsReadStream stream(_resArchive);
unpackBackground(&stream, bg, mask, path);
_vm->_gfx->setBackground(bg);
@@ -580,6 +498,16 @@ Common::ReadStream* DosDisk::loadMusic(const char* name) {
return stream;
}
+
+Common::ReadStream* DosDisk::loadSound(const char* name) {
+ return NULL;
+}
+
+
+
+
+
+
#pragma mark -
@@ -746,7 +674,6 @@ public:
-
AmigaDisk::AmigaDisk(Parallaction *vm) : Disk(vm) {
}
@@ -1020,18 +947,42 @@ class BackgroundDecoder : public Graphics::ILBMDecoder {
uint32 _i;
protected:
- void readCRNG() {
- _range[_i]._timer = _chunk.readUint16();
- _range[_i]._step = _chunk.readUint16();
- _range[_i]._flags = _chunk.readUint16();
- _range[_i]._first = _chunk.readByte();
- _range[_i]._last = _chunk.readByte();
+ void readCRNG(Common::IFFChunk &chunk) {
+ _range[_i]._timer = chunk.readUint16BE();
+ _range[_i]._step = chunk.readUint16BE();
+ _range[_i]._flags = chunk.readUint16BE();
+ _range[_i]._first = chunk.readByte();
+ _range[_i]._last = chunk.readByte();
_i++;
}
public:
- BackgroundDecoder(Common::ReadStream &input, PaletteFxRange *range) : ILBMDecoder(input), _range(range), _i(0) {
+ BackgroundDecoder(Common::ReadStream &input, Graphics::Surface &surface, byte *&colors, PaletteFxRange *range) :
+ Graphics::ILBMDecoder(input, surface, colors), _range(range), _i(0) {
+ }
+
+ void decode() {
+ Common::IFFChunk *chunk;
+ while ((chunk = nextChunk()) != 0) {
+ switch (chunk->id) {
+ case ID_BMHD:
+ readBMHD(*chunk);
+ break;
+
+ case ID_CMAP:
+ readCMAP(*chunk);
+ break;
+
+ case ID_BODY:
+ readBODY(*chunk);
+ break;
+
+ case ID_CRNG:
+ readCRNG(*chunk);
+ break;
+ }
+ }
}
uint32 getNumRanges() {
@@ -1043,12 +994,12 @@ public:
void AmigaDisk::loadBackground(const char *name) {
Common::SeekableReadStream *s = openArchivedFile(name, true);
- BackgroundDecoder decoder(*s, _vm->_gfx->_palettefx);
Graphics::Surface surf;
byte *pal;
+ BackgroundDecoder decoder(*s, surf, pal, _vm->_gfx->_palettefx);
+ decoder.decode();
- decoder.decode(surf, pal);
for (uint32 i = 0; i < BASE_PALETTE_COLORS * 3; i++)
_vm->_gfx->_palette[i] = pal[i] >> 2;
free(pal);
@@ -1082,7 +1033,7 @@ void AmigaDisk::loadMask(const char *name) {
s->seek(0x126, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
- RLEStream stream(s);
+ Graphics::PackBitsReadStream stream(*s);
byte *buf = (byte*)malloc(SCREENMASK_WIDTH*SCREEN_HEIGHT);
stream.read(buf, SCREENMASK_WIDTH*SCREEN_HEIGHT);
@@ -1106,7 +1057,7 @@ void AmigaDisk::loadPath(const char *name) {
s->seek(0x120, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
- RLEStream stream(s);
+ Graphics::PackBitsReadStream stream(*s);
byte *buf = (byte*)malloc(SCREENPATH_WIDTH*SCREEN_HEIGHT);
stream.read(buf, SCREENPATH_WIDTH*SCREEN_HEIGHT);
setPath(buf);
@@ -1171,5 +1122,14 @@ Common::ReadStream* AmigaDisk::loadMusic(const char* name) {
return openArchivedFile(name);
}
+Common::ReadStream* AmigaDisk::loadSound(const char* name) {
+ char path[PATH_LEN];
+ sprintf(path, "%s.snd", name);
+
+ openArchivedFile(path);
+
+ return new DummyArchiveStream(_resArchive);
+}
+
} // namespace Parallaction
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index ea3ad6523f..14c671b02b 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -26,6 +26,10 @@
#include "parallaction/defs.h"
#include "common/file.h"
+namespace Audio {
+ class AudioStream;
+}
+
namespace Parallaction {
//------------------------------------------------------
@@ -112,6 +116,7 @@ public:
virtual void loadScenery(const char* background, const char* mask) = 0;
virtual Table* loadTable(const char* name) = 0;
virtual Common::ReadStream* loadMusic(const char* name) = 0;
+ virtual Common::ReadStream* loadSound(const char* name) = 0;
};
class DosDisk : public Disk {
@@ -147,6 +152,7 @@ public:
void loadScenery(const char* background, const char* mask);
Table* loadTable(const char* name);
Common::ReadStream* loadMusic(const char* name);
+ Common::ReadStream* loadSound(const char* name);
};
class AmigaDisk : public Disk {
@@ -178,6 +184,7 @@ public:
void loadScenery(const char* background, const char* mask);
Table* loadTable(const char* name);
Common::ReadStream* loadMusic(const char* name);
+ Common::ReadStream* loadSound(const char* name);
};
} // namespace Parallaction
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
index c0c2d8cad5..3c76021097 100644
--- a/engines/parallaction/location.cpp
+++ b/engines/parallaction/location.cpp
@@ -154,6 +154,10 @@ void Parallaction::parseLocation(const char *filename) {
if (getPlatform() == Common::kPlatformAmiga)
_soundMan->setMusicFile(_tokens[1]);
}
+ if (!scumm_stricmp(_tokens[0], "SOUND")) {
+// if (getPlatform() == Common::kPlatformAmiga)
+// _soundMan->loadSfx(_tokens[1], atoi(_tokens[2]));
+ }
fillBuffers(*_locationScript, true);
}
@@ -181,6 +185,11 @@ void Parallaction::resolveLocationForwards() {
void Parallaction::freeLocation() {
debugC(7, kDebugLocation, "freeLocation");
+ _soundMan->stopSfx(0);
+ _soundMan->stopSfx(1);
+ _soundMan->stopSfx(2);
+ _soundMan->stopSfx(3);
+
if (_localFlagNames)
delete _localFlagNames;
_localFlagNames = new Table(120);
@@ -413,6 +422,8 @@ void Parallaction::changeLocation(char *location) {
debugC(1, kDebugLocation, "changeLocation: location acommands run");
}
+// _soundMan->playSfx(0);
+
debugC(1, kDebugLocation, "changeLocation completed");
return;
diff --git a/engines/parallaction/music.cpp b/engines/parallaction/music.cpp
index e637e84569..8398bd7729 100644
--- a/engines/parallaction/music.cpp
+++ b/engines/parallaction/music.cpp
@@ -307,6 +307,53 @@ AmigaSoundMan::~AmigaSoundMan() {
stopMusic();
}
+void AmigaSoundMan::playSfx(const char *filename, uint channel, bool looping, int volume, int rate) {
+ if (channel < 0 || channel >= NUM_AMIGA_CHANNELS) {
+ warning("unknown sfx channel");
+ return;
+ }
+
+ Channel *ch = &_channels[channel];
+ Common::ReadStream *stream = _vm->_disk->loadSound(filename);
+ Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize);
+ decoder.decode();
+ delete stream;
+
+ uint32 loopStart, loopEnd, flags;
+ if (looping) {
+ // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
+ // repeatHiSamples fields, but Nippon Safes handles loops according to flags
+ // set in its location scripts and always operates on the whole data.
+ loopStart = 0;
+ loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
+ flags = Audio::Mixer::FLAG_LOOP;
+ } else {
+ loopStart = loopEnd = 0;
+ flags = 0;
+ }
+
+ if (volume == -1) {
+ volume = ch->header.volume;
+ }
+
+ if (rate == -1) {
+ rate = ch->header.samplesPerSec;
+ }
+
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize, rate, flags, -1, volume, 0, loopStart, loopEnd);
+}
+
+void AmigaSoundMan::stopSfx(uint channel) {
+ if (channel < 0 || channel >= NUM_AMIGA_CHANNELS) {
+ warning("unknown sfx channel");
+ return;
+ }
+
+ _mixer->stopHandle(_channels[channel].handle);
+ free(_channels[channel].data);
+ _channels[channel].data = 0;
+}
+
void AmigaSoundMan::playMusic() {
stopMusic();
@@ -314,7 +361,7 @@ void AmigaSoundMan::playMusic() {
_musicStream = Audio::makeProtrackerStream(stream);
delete stream;
- _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, _musicStream, -1, 255, 0, false, true);
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, _musicStream, -1, 255, 0, false, false);
}
void AmigaSoundMan::stopMusic() {
diff --git a/engines/parallaction/music.h b/engines/parallaction/music.h
index bfb74fa38f..ae2f9c8716 100644
--- a/engines/parallaction/music.h
+++ b/engines/parallaction/music.h
@@ -27,6 +27,7 @@
#include "common/mutex.h"
#include "sound/audiostream.h"
+#include "sound/iff.h"
#include "sound/mixer.h"
#include "sound/mididrv.h"
@@ -50,14 +51,14 @@ public:
SoundMan(Parallaction *vm);
virtual ~SoundMan() {}
- void setMusicFile(const char *filename);
+ virtual void playSfx(const char *filename, uint channel, bool looping, int volume = -1, int rate = -1) { }
+ virtual void stopSfx(uint channel) { }
+ void setMusicFile(const char *filename);
virtual void playMusic() = 0;
virtual void stopMusic() = 0;
-
virtual void playCharacterMusic(const char *character) = 0;
virtual void playLocationMusic(const char *location) = 0;
-
void setMusicVolume(int value);
};
@@ -76,17 +77,30 @@ public:
void playLocationMusic(const char *location);
};
+#define NUM_AMIGA_CHANNELS 4
+
class AmigaSoundMan : public SoundMan {
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle;
+ struct Channel {
+ Audio::Voice8Header header;
+ byte *data;
+ uint32 dataSize;
+ Audio::SoundHandle handle;
+ uint32 flags;
+ } _channels[NUM_AMIGA_CHANNELS];
+
public:
AmigaSoundMan(Parallaction *vm);
~AmigaSoundMan();
void playMusic();
void stopMusic();
+ void playSfx(const char *filename, uint channel, bool looping, int volume, int rate);
+ void stopSfx(uint channel);
+
void playCharacterMusic(const char *character);
void playLocationMusic(const char *location);
};
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
index f3cb12f7ca..03ac70fe7d 100644
--- a/engines/parallaction/zone.cpp
+++ b/engines/parallaction/zone.cpp
@@ -26,6 +26,7 @@
#include "parallaction/graphics.h"
#include "parallaction/inventory.h"
#include "parallaction/zone.h"
+#include "parallaction/music.h"
namespace Parallaction {
@@ -271,6 +272,10 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
case kZoneHear: // hear Zone init
if (!scumm_stricmp(_tokens[0], "sound")) {
strcpy(u->hear->_name, _tokens[1]);
+ z->u.hear->_channel = atoi(_tokens[2]);
+ }
+ if (!scumm_stricmp(_tokens[0], "freq")) {
+ z->u.hear->_freq = atoi(_tokens[1]);
}
break;
@@ -400,7 +405,7 @@ uint16 Parallaction::runZone(Zone *z) {
break;
case kZoneHear:
- strcpy(_soundFile, z->u.hear->_name);
+ _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
break;
case kZoneSpeak:
diff --git a/engines/parallaction/zone.h b/engines/parallaction/zone.h
index 559eedb0fe..707f24f7f2 100644
--- a/engines/parallaction/zone.h
+++ b/engines/parallaction/zone.h
@@ -147,8 +147,12 @@ struct DoorData { // size = 28
};
struct HearData { // size = 20
char _name[20];
+ int _channel;
+ int _freq;
HearData() {
+ _channel = -1;
+ _freq = -1;
_name[0] = '\0';
}
};
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 8311308018..bbe6b92c2b 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -45,7 +45,7 @@
#include "saga/rscfile.h"
#include "saga/sagaresnames.h"
-#include "graphics/ilbm.h"
+#include "graphics/iff.h"
#include "common/util.h"
namespace Saga {
@@ -594,7 +594,7 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
Event event;
Event *q_event;
static PalEntry current_pal[PAL_ENTRIES];
-
+
if ((_vm->getGameType() == GType_IHNM) && (loadSceneParams->chapter != NO_CHAPTER_CHANGE)) {
if (loadSceneParams->loadFlag != kLoadBySceneNumber) {
error("loadScene wrong usage");
@@ -680,7 +680,7 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_vm->_resource->loadResource(_sceneContext, _resourceList[i].resourceId,
_resourceList[i].buffer, _resourceList[i].size);
-
+
if (_resourceList[i].size >= 6) {
if (!memcmp(_resourceList[i].buffer, "DUMMY!", 6)) {
_resourceList[i].invalid = true;
@@ -897,7 +897,7 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
void Scene::loadSceneDescriptor(uint32 resourceId) {
byte *sceneDescriptorData;
size_t sceneDescriptorDataLength;
-
+
memset(&_sceneDescription, 0, sizeof(_sceneDescription));
if (resourceId == 0) {
@@ -970,7 +970,7 @@ void Scene::processSceneResources() {
SAGAResourceTypes resType;
getResourceTypes(types, typesCount);
-
+
// Process the scene resource list
for (i = 0; i < _resourceListCount; i++) {
if (_resourceList[i].invalid) {