aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/sound.cpp9
-rw-r--r--engines/agi/sound.h2
-rw-r--r--engines/agi/sound_pcjr.cpp103
-rw-r--r--engines/agi/sound_pcjr.h5
4 files changed, 118 insertions, 1 deletions
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index f2d7af32da..f44b34c70d 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -41,6 +41,10 @@ AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, S
return NULL;
uint16 type = READ_LE_UINT16(data);
+ // For V1 sound resources
+ if ((type & 0xFF) == 0x01)
+ return new PCjrSound(data, len, resnum, manager);
+
switch (type) { // Create a sound object based on the type
case AGI_SOUND_SAMPLE:
return new IIgsSample(data, len, resnum, manager);
@@ -62,6 +66,11 @@ PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A
_data = data; // Save the resource pointer
_len = len; // Save the resource's length
_type = READ_LE_UINT16(data); // Read sound resource's type
+
+ // Detect V1 sound resources
+ if ((_type & 0xFF) == 0x01)
+ _type = AGI_SOUND_4CHN;
+
_isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2);
if (!_isValid) // Check for errors
diff --git a/engines/agi/sound.h b/engines/agi/sound.h
index 0ee19878c4..bd175d3c24 100644
--- a/engines/agi/sound.h
+++ b/engines/agi/sound.h
@@ -122,6 +122,8 @@ public:
~PCjrSound() { free(_data); }
virtual uint16 type() { return _type; }
const uint8 *getVoicePointer(uint voiceNum);
+ uint8 *getData() { return _data; }
+ uint32 getLength() { return _len; }
protected:
uint8 *_data; ///< Raw sound resource data
uint32 _len; ///< Length of the raw sound resource
diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp
index fdebf16b1a..f5cb5e7e1b 100644
--- a/engines/agi/sound_pcjr.cpp
+++ b/engines/agi/sound_pcjr.cpp
@@ -153,6 +153,9 @@ void SoundGenPCJr::play(int resnum) {
_tchannel[i].genType = kGenTone;
_tchannel[i].genTypePrev = -1;
}
+
+ _v1data = pcjrSound->getData() + 1;
+ _v1size = pcjrSound->getLength() - 1;
}
void SoundGenPCJr::stop(void) {
@@ -214,11 +217,22 @@ int SoundGenPCJr::volumeCalc(SndGenChan *chan) {
return attenuation;
}
+int SoundGenPCJr::getNextNote(int ch, Tone *tone)
+{
+ if (_vm->getVersion() > 0x2001)
+ return getNextNote_v2(ch, tone);
+ else
+ return getNextNote_v1(ch, tone);
+
+ return -1;
+}
+
// read the next channel data.. fill it in *tone
// if tone isn't touched.. it should be inited so it just plays silence
// return 0 if it's passing more data
// return -1 if it's passing nothing (end of data)
-int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
+
+int SoundGenPCJr::getNextNote_v2(int ch, Tone *tone) {
ToneChan *tpcm;
SndGenChan *chan;
const byte *data;
@@ -305,6 +319,89 @@ int SoundGenPCJr::getNextNote(int ch, Tone *tone) {
return 0;
}
+int SoundGenPCJr::getNextNote_v1(int ch, Tone *tone)
+{
+ static bool fetched[4] = { false, false, false, false };
+ static int duration = 0;
+
+ // Get previously fetched data if possible
+ if (fetched[ch]) {
+ fetched[ch] = false;
+
+ tone->freqCount = _channel[ch].freqCount;
+ tone->atten = _channel[ch].attenuation;
+ tone->type = _channel[ch].genType;
+
+ return 0;
+ }
+
+ // In the V1 player the default duration for a row is 2 ticks
+ if (duration > 0) {
+ duration--;
+
+ tone->freqCount = _channel[ch].freqCount;
+ tone->atten = _channel[ch].attenuation;
+ tone->type = _channel[ch].genType;
+
+ return 0;
+ }
+ duration = 2 * CHAN_MAX;
+
+ // Otherwise fetch a row of data for all channels
+ byte *data = _v1data;
+ uint32 len = _v1size;
+ int reg = 0;
+
+ if (len <= 0 || data == NULL)
+ return -1;
+
+ fetched[0] = fetched[1] = fetched[2] = fetched[3] = true;
+
+ while (*data) {
+ if ((*data & 0x90) == 0x90) {
+ reg = (*data >> 5) & 0x3;
+ _channel[reg].attenuation = *data & 0xF;
+ } else if ((*data & 0xF0) == 0xE0) {
+ _channel[3].genType = (data[3] & 0x4) ? kGenWhite : kGenPeriod;
+ int noiseFreq = data[3] & 0x03;
+ switch (noiseFreq) {
+ case 0:
+ _channel[3].freqCount = 32;
+ break;
+ case 1:
+ _channel[3].freqCount = 64;
+ break;
+ case 2:
+ _channel[3].freqCount = 128;
+ break;
+ case 3:
+ _channel[3].freqCount = _channel[2].freqCount * 2;
+ break;
+ }
+ } else if (*data & 0x80) {
+ reg = (*data >> 5) & 0x3;
+ _channel[reg].freqCount = *data & 0xF;
+ _channel[reg].genType = kGenTone;
+ } else {
+ _channel[reg].freqCount |= (*data & 0x3F) << 4;
+ }
+
+ data++;
+ len--;
+ }
+ data++;
+ len--;
+
+ _v1data = data;
+ _v1size = len;
+
+ tone->freqCount = _channel[ch].freqCount;
+ tone->atten = _channel[ch].attenuation;
+ tone->type = _channel[ch].genType;
+
+ return 0;
+}
+
// Formulas for noise generator
// bit0 = output
@@ -348,9 +445,13 @@ int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) {
retVal = -1;
+ debugC(5, kDebugLevelSound, "chanGen()");
+
while (len > 0) {
if (tpcm->noteCount <= 0) {
// get new tone data
+ tpcm->avail=1;
+ debugC(5, kDebugLevelSound, "new note data (avail=%d)", tpcm->avail);
toneNew.freqCount = 0;
toneNew.atten = 0xF;
toneNew.type = kGenTone;
diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h
index 4317e86516..d9ced4ac80 100644
--- a/engines/agi/sound_pcjr.h
+++ b/engines/agi/sound_pcjr.h
@@ -103,6 +103,8 @@ public:
private:
int getNextNote(int ch, Tone *tone);
+ int getNextNote_v2(int ch, Tone *tone);
+ int getNextNote_v1(int ch, Tone *tone);
int volumeCalc(SndGenChan *chan);
int chanGen(int chan, int16 *stream, int len);
@@ -117,6 +119,9 @@ private:
int _chanAllocated;
int _dissolveMethod;
+
+ uint8 *_v1data;
+ uint32 _v1size;
};
} // End of namespace Agi