aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kiewitz2016-01-18 21:52:48 +0100
committerMartin Kiewitz2016-01-18 21:52:48 +0100
commit1084c22a786f1d8a0215c1bb3e676f05f948162c (patch)
tree2b275384c674723288f5152c011d64c2fbfa06a8
parent84eca2f5b0884414f8fb422c3919fca1a5683ee9 (diff)
downloadscummvm-rg350-1084c22a786f1d8a0215c1bb3e676f05f948162c.tar.gz
scummvm-rg350-1084c22a786f1d8a0215c1bb3e676f05f948162c.tar.bz2
scummvm-rg350-1084c22a786f1d8a0215c1bb3e676f05f948162c.zip
AGI: fix Apple IIgs sound code + cleanup
fixes several crash possibilities including uninitialized .chn
-rw-r--r--engines/agi/sound_2gs.cpp71
-rw-r--r--engines/agi/sound_2gs.h6
2 files changed, 43 insertions, 34 deletions
diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp
index b221afbc23..e054c16c12 100644
--- a/engines/agi/sound_2gs.cpp
+++ b/engines/agi/sound_2gs.cpp
@@ -95,8 +95,6 @@ int SoundGen2GS::readBuffer(int16 *buffer, const int numSamples) {
void SoundGen2GS::play(int resnum) {
AgiSoundEmuType type;
- _playingSound = resnum;
-
type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type();
assert (type == AGI_SOUND_SAMPLE || type == AGI_SOUND_MIDI);
@@ -105,11 +103,12 @@ void SoundGen2GS::play(int resnum) {
return;
}
+ // FIXME: all sorts of things in here are not thread-safe
haltGenerators();
switch (type) {
case AGI_SOUND_SAMPLE: {
- IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound];
+ IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[resnum];
const IIgsSampleHeader &header = sampleRes->getHeader();
_channels[kSfxMidiChannel].setInstrument(&header.instrument);
_channels[kSfxMidiChannel].setVolume(header.volume);
@@ -117,18 +116,20 @@ void SoundGen2GS::play(int resnum) {
break;
}
case AGI_SOUND_MIDI:
- ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind();
+ ((IIgsMidi *) _vm->_game.sounds[resnum])->rewind();
_ticks = 0;
break;
default:
break;
}
+
+ _playingSound = resnum;
}
void SoundGen2GS::stop() {
haltGenerators();
_playingSound = -1;
- _playing = 0;
+ _playing = false;
}
/**
@@ -182,10 +183,10 @@ uint SoundGen2GS::generateOutput() {
if ((uint)fracToInt(g->osc[0].p) >= g->osc[0].size) {
g->osc[0].p -= intToFrac(g->osc[0].size);
if (!g->osc[0].loop)
- g->osc[0].halt = 1;
+ g->osc[0].halt = true;
if (g->osc[0].swap) {
- g->osc[0].halt = 1;
- g->osc[1].halt = 0;
+ g->osc[0].halt = true;
+ g->osc[1].halt = false;
}
}
}
@@ -195,10 +196,10 @@ uint SoundGen2GS::generateOutput() {
if ((uint)fracToInt(g->osc[1].p) >= g->osc[1].size) {
g->osc[1].p -= intToFrac(g->osc[1].size);
if (!g->osc[1].loop)
- g->osc[1].halt = 1;
+ g->osc[1].halt = true;
if (g->osc[1].swap) {
- g->osc[0].halt = 0;
- g->osc[1].halt = 1;
+ g->osc[0].halt = false;
+ g->osc[1].halt = true;
}
}
}
@@ -430,6 +431,9 @@ double SoundGen2GS::midiKeyToFreq(int key, double finetune) {
void SoundGen2GS::haltGenerators() {
for (int i = 0; i < MAX_GENERATORS; i++) {
+ // Reset instrument pointer especially for samples, because samples are deleted on unload/room changes
+ // and not resetting them here would cause those invalidated samples get accessed during generateOutput()
+ _generators[i].ins = nullptr;
_generators[i].osc[0].halt = true;
_generators[i].osc[1].halt = true;
}
@@ -525,29 +529,30 @@ bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreA
waveCount[0] = stream.readByte();
waveCount[1] = stream.readByte();
- for (int i = 0; i < 2; i++)
- for (int k = 0; k < waveCount[i]; k++) {
- wave[i][k].key = stream.readByte();
- wave[i][k].offset = stream.readByte() << 8;
- wave[i][k].size = 0x100 << (stream.readByte() & 7);
- uint8 b = stream.readByte();
- wave[i][k].tune = stream.readUint16LE();
-
- // For sample resources we ignore the address.
- if (ignoreAddr)
- wave[i][k].offset = 0;
-
- // Check for samples that extend out of the wavetable.
- if (wave[i][k].offset + wave[i][k].size >= SIERRASTANDARD_SIZE) {
- warning("Invalid data detected in the instrument set of Apple IIGS AGI. Continuing anyway...");
- wave[i][k].size = SIERRASTANDARD_SIZE - wave[i][k].offset;
- }
+ for (int i = 0; i < 2; i++) {
+ for (int k = 0; k < waveCount[i]; k++) {
+ wave[i][k].key = stream.readByte();
+ wave[i][k].offset = stream.readByte() << 8;
+ wave[i][k].size = 0x100 << (stream.readByte() & 7);
+ uint8 b = stream.readByte();
+ wave[i][k].tune = stream.readUint16LE();
+
+ // For sample resources we ignore the address.
+ if (ignoreAddr)
+ wave[i][k].offset = 0;
+
+ // Check for samples that extend out of the wavetable.
+ if (wave[i][k].offset + wave[i][k].size >= SIERRASTANDARD_SIZE) {
+ warning("Invalid data detected in the instrument set of Apple IIGS AGI. Continuing anyway...");
+ wave[i][k].size = SIERRASTANDARD_SIZE - wave[i][k].offset;
+ }
- // Parse the generator mode byte to separate fields.
- wave[i][k].halt = b & 0x1; // Bit 0 = HALT
- wave[i][k].loop = !(b & 0x2); // Bit 1 =!LOOP
- wave[i][k].swap = (b & 0x6) == 0x6; // Bit 1&2 = SWAP
- wave[k][k].chn = (b >> 4) > 0; // Output channel (left or right)
+ // Parse the generator mode byte to separate fields.
+ wave[i][k].halt = b & 0x1; // Bit 0 = HALT
+ wave[i][k].loop = !(b & 0x2); // Bit 1 =!LOOP
+ wave[i][k].swap = (b & 0x6) == 0x6; // Bit 1&2 = SWAP
+ wave[i][k].chn = (b >> 4) > 0; // Output channel (left or right)
+ }
}
return !(stream.eos() || stream.err());
diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h
index 8a1999c8eb..4eaba528cc 100644
--- a/engines/agi/sound_2gs.h
+++ b/engines/agi/sound_2gs.h
@@ -122,7 +122,11 @@ struct IIgsSampleHeader {
class IIgsGenerator {
public:
- IIgsGenerator() : ins(NULL), key(-1), chn(-1) {}
+ IIgsGenerator() : ins(NULL), key(-1), chn(-1) {
+ memset(&osc, 0, sizeof(osc));
+ seg = 0;
+ a = 0;
+ }
const IIgsInstrumentHeader *ins; ///< Currently used instrument
int key; ///< MIDI key