aboutsummaryrefslogtreecommitdiff
path: root/sound/mods/rjp1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sound/mods/rjp1.cpp')
-rw-r--r--sound/mods/rjp1.cpp582
1 files changed, 0 insertions, 582 deletions
diff --git a/sound/mods/rjp1.cpp b/sound/mods/rjp1.cpp
deleted file mode 100644
index be376d61a4..0000000000
--- a/sound/mods/rjp1.cpp
+++ /dev/null
@@ -1,582 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/debug.h"
-#include "common/endian.h"
-
-#include "sound/mods/paula.h"
-#include "sound/mods/rjp1.h"
-#include "sound/audiostream.h"
-
-namespace Audio {
-
-struct Rjp1Channel {
- const int8 *waveData;
- const int8 *modulatePeriodData;
- const int8 *modulateVolumeData;
- const int8 *envelopeData;
- uint16 volumeScale;
- int16 volume;
- uint16 modulatePeriodBase;
- uint32 modulatePeriodLimit;
- uint32 modulatePeriodIndex;
- uint16 modulateVolumeBase;
- uint32 modulateVolumeLimit;
- uint32 modulateVolumeIndex;
- uint8 freqStep;
- uint32 freqInc;
- uint32 freqInit;
- const uint8 *noteData;
- const uint8 *sequenceOffsets;
- const uint8 *sequenceData;
- uint8 loopSeqCount;
- uint8 loopSeqCur;
- uint8 loopSeq2Count;
- uint8 loopSeq2Cur;
- bool active;
- int16 modulatePeriodInit;
- int16 modulatePeriodNext;
- bool setupNewNote;
- int8 envelopeMode;
- int8 envelopeScale;
- int8 envelopeEnd1;
- int8 envelopeEnd2;
- int8 envelopeStart;
- int8 envelopeVolume;
- uint8 currentInstrument;
- const int8 *data;
- uint16 pos;
- uint16 len;
- uint16 repeatPos;
- uint16 repeatLen;
- bool isSfx;
-};
-
-class Rjp1 : public Paula {
-public:
-
- struct Vars {
- int8 *instData;
- uint8 *songData[7];
- uint8 activeChannelsMask;
- uint8 currentChannel;
- int subsongsCount;
- int instrumentsCount;
- };
-
- Rjp1(int rate, bool stereo);
- virtual ~Rjp1();
-
- bool load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData);
- void unload();
-
- void startPattern(int ch, int pat);
- void startSong(int song);
-
-protected:
-
- void startSequence(uint8 channelNum, uint8 seqNum);
- void turnOffChannel(Rjp1Channel *channel);
- void playChannel(Rjp1Channel *channel);
- void turnOnChannel(Rjp1Channel *channel);
- bool executeSfxSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p);
- bool executeSongSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p);
- void playSongSequence(Rjp1Channel *channel);
- void modulateVolume(Rjp1Channel *channel);
- void modulatePeriod(Rjp1Channel *channel);
- void setupNote(Rjp1Channel *channel, int16 freq);
- void setupInstrument(Rjp1Channel *channel, uint8 num);
- void setRelease(Rjp1Channel *channel);
- void modulateVolumeEnvelope(Rjp1Channel *channel);
- void setSustain(Rjp1Channel *channel);
- void setDecay(Rjp1Channel *channel);
- void modulateVolumeWaveform(Rjp1Channel *channel);
- void setVolume(Rjp1Channel *channel);
-
- void stopPaulaChannel(uint8 channel);
- void setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen);
-
- virtual void interrupt();
-
- Vars _vars;
- Rjp1Channel _channelsTable[4];
-
- static const int16 _periodsTable[];
- static const int _periodsCount;
-};
-
-Rjp1::Rjp1(int rate, bool stereo)
- : Paula(stereo, rate, rate / 50) {
- memset(&_vars, 0, sizeof(_vars));
- memset(_channelsTable, 0, sizeof(_channelsTable));
-}
-
-Rjp1::~Rjp1() {
- unload();
-}
-
-bool Rjp1::load(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData) {
- if (songData->readUint32BE() == MKID_BE('RJP1') && songData->readUint32BE() == MKID_BE('SMOD')) {
- for (int i = 0; i < 7; ++i) {
- uint32 size = songData->readUint32BE();
- _vars.songData[i] = (uint8 *)malloc(size);
- if (!_vars.songData[i])
- return false;
-
- songData->read(_vars.songData[i], size);
- switch (i) {
- case 0:
- _vars.instrumentsCount = size / 32;
- break;
- case 1:
- break;
- case 2:
- // sequence index to offsets, 1 per channel
- _vars.subsongsCount = size / 4;
- break;
- case 3:
- case 4:
- // sequence offsets
- break;
- case 5:
- case 6:
- // sequence data
- break;
- }
- }
-
- if (instrumentsData->readUint32BE() == MKID_BE('RJP1')) {
- uint32 size = instrumentsData->size() - 4;
- _vars.instData = (int8 *)malloc(size);
- if (!_vars.instData)
- return false;
-
- instrumentsData->read(_vars.instData, size);
-
- }
- }
-
- debug(5, "Rjp1::load() _instrumentsCount = %d _subsongsCount = %d", _vars.instrumentsCount, _vars.subsongsCount);
- return true;
-}
-
-void Rjp1::unload() {
- for (int i = 0; i < 7; ++i) {
- free(_vars.songData[i]);
- }
- free(_vars.instData);
- memset(&_vars, 0, sizeof(_vars));
- memset(_channelsTable, 0, sizeof(_channelsTable));
-}
-
-void Rjp1::startPattern(int ch, int pat) {
- Rjp1Channel *channel = &_channelsTable[ch];
- _vars.activeChannelsMask |= 1 << ch;
- channel->sequenceData = READ_BE_UINT32(_vars.songData[4] + pat * 4) + _vars.songData[6];
- channel->loopSeqCount = 6;
- channel->loopSeqCur = channel->loopSeq2Cur = 1;
- channel->active = true;
- channel->isSfx = true;
- // "start" Paula audiostream
- startPaula();
-}
-
-void Rjp1::startSong(int song) {
- if (song == 0 || song >= _vars.subsongsCount) {
- warning("Invalid subsong number %d, defaulting to 1", song);
- song = 1;
- }
- const uint8 *p = _vars.songData[2] + (song & 0x3F) * 4;
- for (int i = 0; i < 4; ++i) {
- uint8 seq = *p++;
- if (seq) {
- startSequence(i, seq);
- }
- }
- // "start" Paula audiostream
- startPaula();
-}
-
-void Rjp1::startSequence(uint8 channelNum, uint8 seqNum) {
- Rjp1Channel *channel = &_channelsTable[channelNum];
- _vars.activeChannelsMask |= 1 << channelNum;
- if (seqNum != 0) {
- const uint8 *p = READ_BE_UINT32(_vars.songData[3] + seqNum * 4) + _vars.songData[5];
- uint8 seq = *p++;
- channel->sequenceOffsets = p;
- channel->sequenceData = READ_BE_UINT32(_vars.songData[4] + seq * 4) + _vars.songData[6];
- channel->loopSeqCount = 6;
- channel->loopSeqCur = channel->loopSeq2Cur = 1;
- channel->active = true;
- } else {
- channel->active = false;
- turnOffChannel(channel);
- }
-}
-
-void Rjp1::turnOffChannel(Rjp1Channel *channel) {
- stopPaulaChannel(channel - _channelsTable);
-}
-
-void Rjp1::playChannel(Rjp1Channel *channel) {
- if (channel->active) {
- turnOnChannel(channel);
- if (channel->sequenceData) {
- playSongSequence(channel);
- }
- modulateVolume(channel);
- modulatePeriod(channel);
- }
-}
-
-void Rjp1::turnOnChannel(Rjp1Channel *channel) {
- if (channel->setupNewNote) {
- channel->setupNewNote = false;
- setupPaulaChannel(channel - _channelsTable, channel->data, channel->pos, channel->len, channel->repeatPos, channel->repeatLen);
- }
-}
-
-bool Rjp1::executeSfxSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p) {
- bool loop = true;
- switch (code & 7) {
- case 0:
- _vars.activeChannelsMask &= ~(1 << _vars.currentChannel);
- loop = false;
- stopPaula();
- break;
- case 1:
- setRelease(channel);
- loop = false;
- break;
- case 2:
- channel->loopSeqCount = *p++;
- break;
- case 3:
- channel->loopSeq2Count = *p++;
- break;
- case 4:
- code = *p++;
- if (code != 0) {
- setupInstrument(channel, code);
- }
- break;
- case 7:
- loop = false;
- break;
- }
- return loop;
-}
-
-bool Rjp1::executeSongSequenceOp(Rjp1Channel *channel, uint8 code, const uint8 *&p) {
- bool loop = true;
- const uint8 *offs;
- switch (code & 7) {
- case 0:
- offs = channel->sequenceOffsets;
- channel->loopSeq2Count = 1;
- while (1) {
- code = *offs++;
- if (code != 0) {
- channel->sequenceOffsets = offs;
- p = READ_BE_UINT32(_vars.songData[4] + code * 4) + _vars.songData[6];
- break;
- } else {
- code = offs[0];
- if (code == 0) {
- p = 0;
- channel->active = false;
- _vars.activeChannelsMask &= ~(1 << _vars.currentChannel);
- loop = false;
- break;
- } else if (code & 0x80) {
- code = offs[1];
- offs = READ_BE_UINT32(_vars.songData[3] + code * 4) + _vars.songData[5];
- } else {
- offs -= code;
- }
- }
- }
- break;
- case 1:
- setRelease(channel);
- loop = false;
- break;
- case 2:
- channel->loopSeqCount = *p++;
- break;
- case 3:
- channel->loopSeq2Count = *p++;
- break;
- case 4:
- code = *p++;
- if (code != 0) {
- setupInstrument(channel, code);
- }
- break;
- case 5:
- channel->volumeScale = *p++;
- break;
- case 6:
- channel->freqStep = *p++;
- channel->freqInc = READ_BE_UINT32(p); p += 4;
- channel->freqInit = 0;
- break;
- case 7:
- loop = false;
- break;
- }
- return loop;
-}
-
-void Rjp1::playSongSequence(Rjp1Channel *channel) {
- const uint8 *p = channel->sequenceData;
- --channel->loopSeqCur;
- if (channel->loopSeqCur == 0) {
- --channel->loopSeq2Cur;
- if (channel->loopSeq2Cur == 0) {
- bool loop = true;
- do {
- uint8 code = *p++;
- if (code & 0x80) {
- if (channel->isSfx) {
- loop = executeSfxSequenceOp(channel, code, p);
- } else {
- loop = executeSongSequenceOp(channel, code, p);
- }
- } else {
- code >>= 1;
- if (code < _periodsCount) {
- setupNote(channel, _periodsTable[code]);
- }
- loop = false;
- }
- } while (loop);
- channel->sequenceData = p;
- channel->loopSeq2Cur = channel->loopSeq2Count;
- }
- channel->loopSeqCur = channel->loopSeqCount;
- }
-}
-
-void Rjp1::modulateVolume(Rjp1Channel *channel) {
- modulateVolumeEnvelope(channel);
- modulateVolumeWaveform(channel);
- setVolume(channel);
-}
-
-void Rjp1::modulatePeriod(Rjp1Channel *channel) {
- if (channel->modulatePeriodData) {
- uint32 per = channel->modulatePeriodIndex;
- int period = (channel->modulatePeriodData[per] * channel->modulatePeriodInit) / 128;
- period = -period;
- if (period < 0) {
- period /= 2;
- }
- channel->modulatePeriodNext = period + channel->modulatePeriodInit;
- ++per;
- if (per == channel->modulatePeriodLimit) {
- per = channel->modulatePeriodBase * 2;
- }
- channel->modulatePeriodIndex = per;
- }
- if (channel->freqStep != 0) {
- channel->freqInit += channel->freqInc;
- --channel->freqStep;
- }
- setChannelPeriod(channel - _channelsTable, channel->freqInit + channel->modulatePeriodNext);
-}
-
-void Rjp1::setupNote(Rjp1Channel *channel, int16 period) {
- const uint8 *note = channel->noteData;
- if (note) {
- channel->modulatePeriodInit = channel->modulatePeriodNext = period;
- channel->freqInit = 0;
- const int8 *e = (const int8 *)_vars.songData[1] + READ_BE_UINT16(note + 12);
- channel->envelopeData = e;
- channel->envelopeStart = e[1];
- channel->envelopeScale = e[1] - e[0];
- channel->envelopeEnd2 = e[2];
- channel->envelopeEnd1 = e[2];
- channel->envelopeMode = 4;
- channel->data = channel->waveData;
- channel->pos = READ_BE_UINT16(note + 16);
- channel->len = channel->pos + READ_BE_UINT16(note + 18);
- channel->setupNewNote = true;
- }
-}
-
-void Rjp1::setupInstrument(Rjp1Channel *channel, uint8 num) {
- if (channel->currentInstrument != num) {
- channel->currentInstrument = num;
- const uint8 *p = _vars.songData[0] + num * 32;
- channel->noteData = p;
- channel->repeatPos = READ_BE_UINT16(p + 20);
- channel->repeatLen = READ_BE_UINT16(p + 22);
- channel->volumeScale = READ_BE_UINT16(p + 14);
- channel->modulatePeriodBase = READ_BE_UINT16(p + 24);
- channel->modulatePeriodIndex = 0;
- channel->modulatePeriodLimit = READ_BE_UINT16(p + 26) * 2;
- channel->modulateVolumeBase = READ_BE_UINT16(p + 28);
- channel->modulateVolumeIndex = 0;
- channel->modulateVolumeLimit = READ_BE_UINT16(p + 30) * 2;
- channel->waveData = _vars.instData + READ_BE_UINT32(p);
- uint32 off = READ_BE_UINT32(p + 4);
- if (off) {
- channel->modulatePeriodData = _vars.instData + off;
- }
- off = READ_BE_UINT32(p + 8);
- if (off) {
- channel->modulateVolumeData = _vars.instData + off;
- }
- }
-}
-
-void Rjp1::setRelease(Rjp1Channel *channel) {
- const int8 *e = channel->envelopeData;
- if (e) {
- channel->envelopeStart = 0;
- channel->envelopeScale = -channel->envelopeVolume;
- channel->envelopeEnd2 = e[5];
- channel->envelopeEnd1 = e[5];
- channel->envelopeMode = -1;
- }
-}
-
-void Rjp1::modulateVolumeEnvelope(Rjp1Channel *channel) {
- if (channel->envelopeMode) {
- int16 es = channel->envelopeScale;
- if (es) {
- int8 m = channel->envelopeEnd1;
- if (m == 0) {
- es = 0;
- } else {
- es *= m;
- m = channel->envelopeEnd2;
- if (m == 0) {
- es = 0;
- } else {
- es /= m;
- }
- }
- }
- channel->envelopeVolume = channel->envelopeStart - es;
- --channel->envelopeEnd1;
- if (channel->envelopeEnd1 == -1) {
- switch (channel->envelopeMode) {
- case 0:
- break;
- case 2:
- setSustain(channel);
- break;
- case 4:
- setDecay(channel);
- break;
- case -1:
- setSustain(channel);
- break;
- default:
- error("Unhandled envelope mode %d", channel->envelopeMode);
- break;
- }
- return;
- }
- }
- channel->volume = channel->envelopeVolume;
-}
-
-void Rjp1::setSustain(Rjp1Channel *channel) {
- channel->envelopeMode = 0;
-}
-
-void Rjp1::setDecay(Rjp1Channel *channel) {
- const int8 *e = channel->envelopeData;
- if (e) {
- channel->envelopeStart = e[3];
- channel->envelopeScale = e[3] - e[1];
- channel->envelopeEnd2 = e[4];
- channel->envelopeEnd1 = e[4];
- channel->envelopeMode = 2;
- }
-}
-
-void Rjp1::modulateVolumeWaveform(Rjp1Channel *channel) {
- if (channel->modulateVolumeData) {
- uint32 i = channel->modulateVolumeIndex;
- channel->volume += channel->modulateVolumeData[i] * channel->volume / 128;
- ++i;
- if (i == channel->modulateVolumeLimit) {
- i = channel->modulateVolumeBase * 2;
- }
- channel->modulateVolumeIndex = i;
- }
-}
-
-void Rjp1::setVolume(Rjp1Channel *channel) {
- channel->volume = (channel->volume * channel->volumeScale) / 64;
- channel->volume = CLIP<int16>(channel->volume, 0, 64);
- setChannelVolume(channel - _channelsTable, channel->volume);
-}
-
-void Rjp1::stopPaulaChannel(uint8 channel) {
- clearVoice(channel);
-}
-
-void Rjp1::setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen) {
- if (waveData) {
- setChannelData(channel, waveData, waveData + repeatPos * 2, len * 2, repeatLen * 2, offset * 2);
- }
-}
-
-void Rjp1::interrupt() {
- for (int i = 0; i < 4; ++i) {
- _vars.currentChannel = i;
- playChannel(&_channelsTable[i]);
- }
-}
-
-const int16 Rjp1::_periodsTable[] = {
- 0x01C5, 0x01E0, 0x01FC, 0x021A, 0x023A, 0x025C, 0x0280, 0x02A6, 0x02D0,
- 0x02FA, 0x0328, 0x0358, 0x00E2, 0x00F0, 0x00FE, 0x010D, 0x011D, 0x012E,
- 0x0140, 0x0153, 0x0168, 0x017D, 0x0194, 0x01AC, 0x0071, 0x0078, 0x007F,
- 0x0087, 0x008F, 0x0097, 0x00A0, 0x00AA, 0x00B4, 0x00BE, 0x00CA, 0x00D6
-};
-
-const int Rjp1::_periodsCount = ARRAYSIZE(_periodsTable);
-
-AudioStream *makeRjp1Stream(Common::SeekableReadStream *songData, Common::SeekableReadStream *instrumentsData, int num, int rate, bool stereo) {
- Rjp1 *stream = new Rjp1(rate, stereo);
- if (stream->load(songData, instrumentsData)) {
- if (num < 0) {
- stream->startPattern(3, -num);
- } else {
- stream->startSong(num);
- }
- return stream;
- }
- delete stream;
- return 0;
-}
-
-} // End of namespace Audio