[Scummvm-cvs-logs] SF.net SVN: scummvm:[51645] scummvm/trunk

athrxx at users.sourceforge.net athrxx at users.sourceforge.net
Mon Aug 2 20:30:26 CEST 2010


Revision: 51645
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51645&view=rev
Author:   athrxx
Date:     2010-08-02 18:30:25 +0000 (Mon, 02 Aug 2010)

Log Message:
-----------
KYRA: FM-Towns audio driver rewrite

- FM-Towns euphony driver completely rewritten based on KYRA FM-Towns and LOOM towns disasm.

- Split all the emu and driver code from sound_towns.cpp into different files to make things a bit less confusing.

- Move the driver code to common space since the exact same euphony driver is used by LOOM which means we could get rid of the outdated and incomplete ym2612 driver/emu implementation (which doesn't even do things like instrument loading, pan position, etc). I haven't tried to add this to the Scumm engine yet, since I am not  familiar with it and my priority was to get the driver finished first. But from the look of disasm it shouldn't be difficult to do.

- Introduce a generic FM-Towns audio interface based on FM-Towns system file disasm which was necessary for the euphony driver rewrite. Every FM-Towns game I have seen so far seems to access the audio hardware via these system functions. This interface implementation will also allow reasonably simple creation of new FM-Towns audio drivers (e.g. this could be used for Kings Quest 5 FM-Towns or others).

- Move the PC98 driver to common space, too, since I have a strong feeling that this driver is also used in the PC98 version of Future Wars

- This also improves KYRA FM-Towns music quality, sound effects accuracy and music fading.

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/resource.h
    scummvm/trunk/engines/kyra/sound_intern.h
    scummvm/trunk/engines/kyra/sound_towns.cpp
    scummvm/trunk/engines/kyra/staticres.cpp
    scummvm/trunk/sound/module.mk
    scummvm/trunk/tools/create_kyradat/create_kyradat.cpp
    scummvm/trunk/tools/create_kyradat/create_kyradat.h
    scummvm/trunk/tools/create_kyradat/games.cpp
    scummvm/trunk/tools/create_kyradat/tables.cpp

Added Paths:
-----------
    scummvm/trunk/sound/softsynth/fmtowns_pc98/
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_audio.cpp
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_audio.h
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_euphony.cpp
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_euphony.h
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_pc98_driver.h
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
    scummvm/trunk/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h

Modified: scummvm/trunk/engines/kyra/resource.h
===================================================================
--- scummvm/trunk/engines/kyra/resource.h	2010-08-02 18:25:48 UTC (rev 51644)
+++ scummvm/trunk/engines/kyra/resource.h	2010-08-02 18:30:25 UTC (rev 51645)
@@ -209,6 +209,7 @@
 
 	k1CreditsStrings,
 
+	k1TownsMusicFadeTable,
 	k1TownsSFXwdTable,
 	k1TownsSFXbtTable,
 	k1TownsCDATable,

Modified: scummvm/trunk/engines/kyra/sound_intern.h
===================================================================
--- scummvm/trunk/engines/kyra/sound_intern.h	2010-08-02 18:25:48 UTC (rev 51644)
+++ scummvm/trunk/engines/kyra/sound_intern.h	2010-08-02 18:30:25 UTC (rev 51645)
@@ -31,7 +31,9 @@
 
 #include "common/mutex.h"
 
-#include "sound/softsynth/ym2612.h"
+#include "sound/softsynth/fmtowns_pc98/towns_pc98_driver.h"
+#include "sound/softsynth/fmtowns_pc98/towns_euphony.h"
+
 #include "sound/softsynth/emumidi.h"
 #include "sound/midiparser.h"
 
@@ -99,10 +101,7 @@
 	Common::Mutex _mutex;
 };
 
-class Towns_EuphonyDriver;
-class TownsPC98_OpnDriver;
-
-class SoundTowns : public MidiDriver, public Sound {
+class SoundTowns : public Sound {
 public:
 	SoundTowns(KyraEngine_v1 *vm, Audio::Mixer *mixer);
 	~SoundTowns();
@@ -119,43 +118,33 @@
 	void haltTrack();
 
 	void playSoundEffect(uint8);
+	void stopAllSoundEffects();
 
 	void beginFadeOut();
 
-	//MidiDriver interface implementation
-	int open();
-	void close();
-	void send(uint32 b);
-	void metaEvent(byte type, byte *data, uint16 length) {}
-
-	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
-	uint32 getBaseTempo();
-
-	//Channel allocation functions
-	MidiChannel *allocateChannel()      { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
-
-	static float calculatePhaseStep(int8 semiTone, int8 semiToneRootkey,
-	    uint32 sampleRate, uint32 outputRate, int32 pitchWheel);
-
 private:
 	bool loadInstruments();
 	void playEuphonyTrack(uint32 offset, int loop);
 
-	static void onTimer(void *data);
+	void fadeOutSoundEffects();
 
 	int _lastTrack;
 	Audio::AudioStream *_currentSFX;
 	Audio::SoundHandle _sfxHandle;
 
+	uint8 *_musicTrackData;
+
 	uint _sfxFileIndex;
 	uint8 *_sfxFileData;
+	uint8 _sfxChannel;
 
-	Towns_EuphonyDriver * _driver;
-	MidiParser * _parser;
-
+	TownsEuphonyDriver *_driver;
+	
 	Common::Mutex _mutex;
 
+	bool _cdaPlaying;
+
+	const uint8 *_musicFadeTable;
 	const uint8 *_sfxBTTable;
 	const uint8 *_sfxWDTable;
 };
@@ -186,7 +175,7 @@
 	int _lastTrack;
 	uint8 *_musicTrackData;
 	uint8 *_sfxTrackData;
-	TownsPC98_OpnDriver *_driver;
+	TownsPC98_AudioDriver *_driver;
 };
 
 class SoundTownsPC98_v2 : public Sound {
@@ -218,7 +207,7 @@
 
 	uint8 *_musicTrackData;
 	uint8 *_sfxTrackData;
-	TownsPC98_OpnDriver *_driver;
+	TownsPC98_AudioDriver *_driver;
 };
 
 // PC Speaker MIDI driver

Modified: scummvm/trunk/engines/kyra/sound_towns.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sound_towns.cpp	2010-08-02 18:25:48 UTC (rev 51644)
+++ scummvm/trunk/engines/kyra/sound_towns.cpp	2010-08-02 18:30:25 UTC (rev 51645)
@@ -36,3889 +36,37 @@
 
 #include "common/util.h"
 
-#define EUPHONY_FADEOUT_TICKS 600
-
 namespace Kyra {
 
-enum EnvelopeState { s_ready, s_attacking, s_decaying, s_sustaining, s_releasing };
-
-class Towns_EuphonyChannel : public MidiChannel {
-public:
-	Towns_EuphonyChannel() {}
-	virtual ~Towns_EuphonyChannel() {}
-
-	virtual void nextTick(int32 *outbuf, int buflen) = 0;
-	virtual void rate(uint16 r) = 0;
-
-protected:
-	uint16 _rate;
-};
-
-class Towns_EuphonyFmChannel : public Towns_EuphonyChannel {
-public:
-	Towns_EuphonyFmChannel();
-	virtual ~Towns_EuphonyFmChannel();
-
-	void nextTick(int32 *outbuf, int buflen);
-	void rate(uint16 r);
-
-	// MidiChannel interface
-	MidiDriver *device() { return 0; }
-	byte getNumber() { return 0; }
-	void release() { }
-	void send(uint32) { }
-	void noteOff(byte note);
-	void noteOn(byte note, byte onVelo);
-	void programChange(byte) {}
-	void pitchBend(int16 value);
-	void controlChange(byte control, byte value);
-	void pitchBendFactor(byte) { }
-	void sysEx_customInstrument(uint32 unused, const byte *instr);
-
-protected:
-	Voice2612 *_voice;
-};
-
-class Towns_EuphonyPcmChannel : public Towns_EuphonyChannel {
-public:
-	void nextTick(int32 *outbuf, int buflen);
-	void rate(uint16 r);
-
-	Towns_EuphonyPcmChannel();
-	virtual ~Towns_EuphonyPcmChannel();
-
-	// MidiChannel interface
-	MidiDriver *device() { return 0; }
-	byte getNumber() { return 0; }
-	void release() { }
-	void send(uint32 b) { }
-	void noteOff(byte note);
-	void noteOn(byte note, byte onVelo);
-	void programChange(byte program) {}
-	void pitchBend(int16 value);
-	void controlChange(byte control, byte value);
-	void pitchBendFactor(byte value) { }
-	void sysEx_customInstrument(uint32 type, const byte *instr);
-
-protected:
-	void velocity(int velo);
-	void panPosition(int8 pan);
-	void evpNextTick();
-
-	int _ctrl7_volume;
-	int16 _velocity;
-	int16 _note;
-	int32 _frequencyOffs;
-	float _phase;
-	int8 _current;
-
-	struct Voice {
-		char name[9];
-		uint16 split[8];
-		uint32 id[8];
-		struct Snd {
-			char name[9];
-			int32 id;
-			int32 numSamples;
-			int32 loopStart;
-			int32 loopLength;
-			int32 samplingRate;
-			int32 keyOffset;
-			int32 keyNote;
-			const int8 *_samples;
-		} *_snd[8];
-		struct Env {
-			EnvelopeState state;
-			int32 currentLevel;
-			int32 rate;
-			int32 tickCount;
-			int32 totalLevel;
-			int32 attackRate;
-			int32 decayRate;
-			int32 sustainLevel;
-			int32 sustainRate;
-			int32 releaseLevel;
-			int32 releaseRate;
-			int32 rootKeyOffset;
-			int32 size;
-		} *_env[8];
-	} *_voice;
-};
-
-class Towns_EuphonyTrackQueue {
-public:
-	Towns_EuphonyTrackQueue(Towns_EuphonyDriver *driver, Towns_EuphonyTrackQueue *last);
-	~Towns_EuphonyTrackQueue() {}
-
-	Towns_EuphonyTrackQueue *release();
-	void initDriver();
-	void loadDataToCurrentPosition(uint8 *trackdata, uint32 size, bool loop = 0);
-	void loadDataToEndOfQueue(uint8 *trackdata, uint32 size, bool loop = 0);
-	void setPlayBackStatus(bool playing);
-	bool isPlaying() const {return _playing; }
-	uint8 *trackData() {return _trackData; }
-
-	bool _loop;
-	Towns_EuphonyTrackQueue *_next;
-
-private:
-	uint8 *_trackData;
-	uint8 *_used;
-	uint8 *_fchan;
-	uint8 *_wchan;
-	bool _playing;
-	Towns_EuphonyDriver *_driver;
-	Towns_EuphonyTrackQueue *_last;
-};
-
-class Towns_EuphonyParser : public MidiParser {
-public:
-	Towns_EuphonyParser(Towns_EuphonyTrackQueue * queue);
-	bool loadMusic (byte *data, uint32 size);
-	int32 calculateTempo(int16 val);
-
-protected:
-	void parseNextEvent (EventInfo &info);
-	void resetTracking();
-	void setup();
-
-	byte *_enable;
-	byte *_mode;
-	byte *_channel;
-	byte *_adjVelo;
-	int8 *_adjNote;
-
-	uint8 _firstBaseTickStep;
-	uint8 _nextBaseTickStep;
-	uint32 _initialTempo;
-	uint32 _baseTick;
-
-	byte _tempo[3];
-	Towns_EuphonyTrackQueue *_queue;
-};
-
-class Towns_EuphonyDriver : public MidiDriver_Emulated {
-public:
-	Towns_EuphonyDriver(Audio::Mixer *mixer);
-	virtual ~Towns_EuphonyDriver();
-
-	int open();
-	void close();
-	void send(uint32 b);
-	void send(byte channel, uint32 b);
-	uint32 property(int prop, uint32 param) { return 0; }
-
-	void setPitchBendRange(byte channel, uint range) { }
-	void loadFmInstruments(const byte *instr);
-	void loadWaveInstruments(const byte *instr);
-
-	Towns_EuphonyTrackQueue *queue() { return _queue; }
-
-	MidiChannel *allocateChannel() { return 0; }
-	MidiChannel *getPercussionChannel() { return 0; }
-
-	void assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber);
-	void assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber);
-	void removeChannel(uint8 midiChannelNumber);
-
-	void setVolume(int val = -1) { if (val >= 0) _volume = val; }
-	int getVolume(int val = -1) { return _volume; }
-
-	// AudioStream API
-	bool isStereo() const { return true; }
-	int getRate() const { return _mixer->getOutputRate(); }
-
-	void fading(bool status = true);
-
-protected:
-	void nextTick(int16 *buf1, int buflen);
-	void rate(uint16 r);
-
-	void generateSamples(int16 *buf, int len);
-
-	Towns_EuphonyFmChannel *_fChannel[6];
-	Towns_EuphonyPcmChannel *_wChannel[8];
-	Towns_EuphonyChannel *_channel[16];
-	Towns_EuphonyTrackQueue *_queue;
-
-	int _volume;
-	bool _fading;
-	int16 _fadestate;
-
-	uint8 *_fmInstruments;
-	uint8 *_waveInstruments;
-	int8 * _waveSounds[10];
-};
-
-Towns_EuphonyFmChannel::Towns_EuphonyFmChannel() {
-	_voice = new Voice2612;
-}
-
-Towns_EuphonyFmChannel::~Towns_EuphonyFmChannel() {
-	delete _voice;
-}
-
-void Towns_EuphonyFmChannel::noteOn(byte note, byte onVelo) {
-	_voice->noteOn(note, onVelo);
-}
-
-void Towns_EuphonyFmChannel::noteOff(byte note) {
-	_voice->noteOff(note);
-}
-
-void Towns_EuphonyFmChannel::controlChange(byte control, byte value) {
-	if (control == 121) {
-		// Reset controller
-		delete _voice;
-		_voice = new Voice2612;
-	} else if (control == 10) {
-		// pan position
-	} else {
-		_voice->setControlParameter(control, value);
-	}
-}
-
-void Towns_EuphonyFmChannel::sysEx_customInstrument(uint32, const byte *fmInst) {
-	_voice->_rate = _rate;
-	_voice->setInstrument(fmInst);
-}
-
-void Towns_EuphonyFmChannel::pitchBend(int16 value) {
-	_voice->pitchBend(value);
-}
-
-void Towns_EuphonyFmChannel::nextTick(int32 *outbuf, int buflen) {
-	_voice->nextTick((int *)outbuf, buflen);
-}
-
-void Towns_EuphonyFmChannel::rate(uint16 r) {
-	_rate = r;
-	_voice->_rate = r;
-}
-
-Towns_EuphonyPcmChannel::Towns_EuphonyPcmChannel() {
-	_voice = new Voice;
-	for (uint8 i = 0; i < 8; i++) {
-		_voice->_env[i] = new Voice::Env;
-		_voice->_snd[i] = 0;
-	}
-
-	_ctrl7_volume = 127;
-	velocity(0);
-	_frequencyOffs = 0x2000;
-	_current = -1;
-}
-
-Towns_EuphonyPcmChannel::~Towns_EuphonyPcmChannel() {
-	for (uint8 i = 0; i < 8; i++) {
-		if (_voice->_snd[i])
-			delete _voice->_snd[i];
-		delete _voice->_env[i];
-	}
-	delete _voice;
-}
-
-void Towns_EuphonyPcmChannel::noteOn(byte note, byte onVelo) {
-	_note = note;
-	velocity(onVelo);
-	_phase = 0;
-
-	for (_current = 0; _current < 7; _current++) {
-		if (note <=	_voice->split[_current])
-			break;
-	}
-
-	_voice->_env[_current]->state = s_attacking;
-	_voice->_env[_current]->currentLevel = 0;
-	_voice->_env[_current]->rate = _rate;
-	_voice->_env[_current]->tickCount = 0;
-}
-
-void Towns_EuphonyPcmChannel::noteOff(byte note) {
-    if (_current == -1)
-		return;
-	if (_voice->_env[_current]->state == s_ready)
-		return;
-
-	_voice->_env[_current]->state = s_releasing;
-	_voice->_env[_current]->releaseLevel = _voice->_env[_current]->currentLevel;
-	_voice->_env[_current]->tickCount = 0;
-}
-
-void Towns_EuphonyPcmChannel::controlChange(byte control, byte value) {
-	switch (control) {
-	case 0x07:
-		// volume
-		_ctrl7_volume = value;
-		break;
-	case 0x0A:
-		// pan position
-		break;
-	case 0x79:
-		// Reset controller
-		for (uint8 i = 0; i < 8; i++) {
-			if (_voice->_snd[i])
-				delete _voice->_snd[i];
-			delete _voice->_env[i];
-		}
-		delete _voice;
-		_voice = new Voice;
-		for (uint8 i = 0; i < 8; i++) {
-			_voice->_env[i] = new Voice::Env;
-			_voice->_snd[i] = 0;
-		}
-		break;
-	case 0x7B:
-		noteOff(_note);
-		break;
-	default:
-		break;
-	}
-}
-
-void Towns_EuphonyPcmChannel::sysEx_customInstrument(uint32 type, const byte *fmInst) {
-	if (type == 0x80) {
-		for (uint8 i = 0; i < 8; i++) {
-			const byte * const *pos = (const byte * const *)fmInst;
-			for (uint8 ii = 0; ii < 10; ii++) {
-				if (_voice->id[i] == *(pos[ii] + 8)) {
-					if (!_voice->_snd[i])
-						_voice->_snd[i] = new Voice::Snd;
-					memset(_voice->_snd[i]->name, 0, 9);
-					memcpy(_voice->_snd[i]->name, (const char *)pos[ii], 8);
-					_voice->_snd[i]->id = READ_LE_UINT32(pos[ii] + 8);
-					_voice->_snd[i]->numSamples = READ_LE_UINT32(pos[ii] + 12);
-					_voice->_snd[i]->loopStart = READ_LE_UINT32(pos[ii] + 16);
-					_voice->_snd[i]->loopLength = READ_LE_UINT32(pos[ii] + 20);
-					_voice->_snd[i]->samplingRate = READ_LE_UINT16(pos[ii] + 24);
-					_voice->_snd[i]->keyOffset = READ_LE_UINT16(pos[ii] + 26);
-					_voice->_snd[i]->keyNote = *(const uint8 *)(pos[ii] + 28);
-					_voice->_snd[i]->_samples = (const int8 *)(pos[ii] + 32);
-				}
-			}
-		}
-	} else {
-		memset(_voice->name, 0, 9);
-		memcpy(_voice->name, (const char *)fmInst, 8);
-
-		for (uint8 i = 0; i < 8; i++) {
-			_voice->split[i] = READ_LE_UINT16(fmInst + 16 + 2 * i);
-			_voice->id[i] = READ_LE_UINT32(fmInst + 32 + 4 * i);
-			_voice->_snd[i] = 0;
-			_voice->_env[i]->state = s_ready;
-			_voice->_env[i]->currentLevel = 0;
-			_voice->_env[i]->totalLevel = *(fmInst + 64 + 8 * i);
-			_voice->_env[i]->attackRate = *(fmInst + 65 + 8 * i) * 10;
-			_voice->_env[i]->decayRate = *(fmInst + 66 + 8 * i) * 10;
-			_voice->_env[i]->sustainLevel = *(fmInst + 67 + 8 * i);
-			_voice->_env[i]->sustainRate = *(fmInst + 68 + 8 * i) * 20;
-			_voice->_env[i]->releaseRate = *(fmInst + 69 + 8 * i) * 10;
-			_voice->_env[i]->rootKeyOffset = *(fmInst + 70 + 8 * i);
-		}
-	}
-}
-
-void Towns_EuphonyPcmChannel::pitchBend(int16 value) {
-	_frequencyOffs = value;
-}
-
-void Towns_EuphonyPcmChannel::nextTick(int32 *outbuf, int buflen) {
-	if (_current == -1 || !_voice->_snd[_current] || !_voice->_env[_current]->state || !_velocity) {
-		velocity(0);
-		_current = -1;
-		return;
-	}
-
-	float phaseStep = SoundTowns::calculatePhaseStep(_note, _voice->_snd[_current]->keyNote -
-		_voice->_env[_current]->rootKeyOffset, _voice->_snd[_current]->samplingRate, _rate, _frequencyOffs);
-
-	int32 looplength = _voice->_snd[_current]->loopLength;
-	int32 numsamples = _voice->_snd[_current]->numSamples;
-	const int8 * samples = _voice->_snd[_current]->_samples;
-
-	for (int i = 0; i < buflen; i++) {
-		if (looplength > 0) {
-			while (_phase >= numsamples)
-				_phase -= looplength;
-		} else {
-			if (_phase >= numsamples) {
-				velocity(0);
-				_current = -1;
-				break;
-			}
-		}
-
-		int32 output;
-
-		int32 phase0 = int32(_phase);
-		int32 phase1 = int32(_phase + 1);
-		if (phase1 >= numsamples)
-			phase1 -= looplength;
-		float weight0 = _phase - phase0;
-		float weight1 = phase1 - _phase;
-		output = int32(samples[phase0] * weight0 + samples[phase1] * weight1);
-
-		output *= _velocity;
-		output <<= 1;
-
-		evpNextTick();
-		output *= _voice->_env[_current]->currentLevel;
-		output >>= 7;
-		output *= _ctrl7_volume;
-		output >>= 7;
-
-		output *= 185;
-		output >>= 8;
-		outbuf[i] += output;
-		_phase += phaseStep;
-	}
-}
-
-void Towns_EuphonyPcmChannel::evpNextTick() {
-	switch (_voice->_env[_current]->state) {
-	case s_ready:
-		_voice->_env[_current]->currentLevel = 0;
-		return;
-
-	case s_attacking:
-		if (_voice->_env[_current]->attackRate == 0)
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
-		else if (_voice->_env[_current]->attackRate >= 1270)
-			_voice->_env[_current]->currentLevel = 0;
-		else
-			_voice->_env[_current]->currentLevel = (_voice->_env[_current]->totalLevel *
-				_voice->_env[_current]->tickCount++ * 1000) /
-					(_voice->_env[_current]->attackRate * _voice->_env[_current]->rate);
-
-		if (_voice->_env[_current]->currentLevel >= _voice->_env[_current]->totalLevel) {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
-			_voice->_env[_current]->state = s_decaying;
-			_voice->_env[_current]->tickCount = 0;
-		}
-		break;
-
-	case s_decaying:
-		if (_voice->_env[_current]->decayRate == 0) {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
-		} else if (_voice->_env[_current]->decayRate >= 1270) {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
-		} else {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->totalLevel;
-			_voice->_env[_current]->currentLevel -= ((_voice->_env[_current]->totalLevel -
-				_voice->_env[_current]->sustainLevel) * _voice->_env[_current]->tickCount++ * 1000) /
-					(_voice->_env[_current]->decayRate * _voice->_env[_current]->rate);
-		}
-
-		if (_voice->_env[_current]->currentLevel <= _voice->_env[_current]->sustainLevel) {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
-			_voice->_env[_current]->state = s_sustaining;
-			_voice->_env[_current]->tickCount = 0;
-		}
-		break;
-
-	case s_sustaining:
-		if (_voice->_env[_current]->sustainRate == 0) {
-			_voice->_env[_current]->currentLevel = 0;
-		} else if (_voice->_env[_current]->sustainRate >= 2540) {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
-		} else {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->sustainLevel;
-			_voice->_env[_current]->currentLevel -= (_voice->_env[_current]->sustainLevel *
-				_voice->_env[_current]->tickCount++ * 1000) / (_voice->_env[_current]->sustainRate *
-					_voice->_env[_current]->rate);
-		}
-
-		if (_voice->_env[_current]->currentLevel <= 0) {
-			_voice->_env[_current]->currentLevel = 0;
-			_voice->_env[_current]->state = s_ready;
-			_voice->_env[_current]->tickCount = 0;
-		}
-		break;
-
-	case s_releasing:
-		if (_voice->_env[_current]->releaseRate == 0) {
-			_voice->_env[_current]->currentLevel = 0;
-		} else if (_voice->_env[_current]->releaseRate >= 1270) {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->releaseLevel;
-		} else {
-			_voice->_env[_current]->currentLevel = _voice->_env[_current]->releaseLevel;
-			_voice->_env[_current]->currentLevel -= (_voice->_env[_current]->releaseLevel *
-				_voice->_env[_current]->tickCount++ * 1000) / (_voice->_env[_current]->releaseRate *
-					_voice->_env[_current]->rate);
-		}
-
-		if (_voice->_env[_current]->currentLevel <= 0) {
-			_voice->_env[_current]->currentLevel = 0;
-			_voice->_env[_current]->state = s_ready;
-		}
-		break;
-
-	default:
-		break;
-	}
-}
-
-void Towns_EuphonyPcmChannel::rate(uint16 r) {
-	_rate = r;
-}
-
-void Towns_EuphonyPcmChannel::velocity(int velo) {
-	_velocity = velo;
-}
-
-Towns_EuphonyDriver::Towns_EuphonyDriver(Audio::Mixer *mixer)
-	: MidiDriver_Emulated(mixer) {
-	_volume = 255;
-	_fadestate = EUPHONY_FADEOUT_TICKS;
-	_queue = 0;
-
-	MidiDriver_YM2612::createLookupTables();
-
-	for (uint8 i = 0; i < 6; i++)
-		_channel[i] = _fChannel[i] = new Towns_EuphonyFmChannel;
-	for (uint8 i = 0; i < 8; i++)
-		_channel[i + 6] = _wChannel[i] = new Towns_EuphonyPcmChannel;
-	_channel[14] = _channel[15] = 0;
-
-	_fmInstruments = _waveInstruments = 0;
-	memset(_waveSounds, 0, sizeof(uint8 *)* 10);
-
-	rate(getRate());
-	fading(0);
-
-	_queue = new Towns_EuphonyTrackQueue(this, 0);
-}
-
-Towns_EuphonyDriver::~Towns_EuphonyDriver() {
-	for (int i = 0; i < 6; i++)
-		delete _fChannel[i];
-	for (int i = 0; i < 8; i++)
-		delete _wChannel[i];
-
-	MidiDriver_YM2612::removeLookupTables();
-
-	delete[] _fmInstruments;
-	_fmInstruments = 0;
-
-	delete[] _waveInstruments;
-	_waveInstruments = 0;
-
-	for (int i = 0; i < 10; i++) {
-		delete[] _waveSounds[i];
-		_waveSounds[i] = 0;
-	}
-
-	if (_queue) {
-		_queue->release();
-		delete _queue;
-		_queue = 0;
-	}
-}
-
-int Towns_EuphonyDriver::open() {
-	if (_isOpen)
-		return MERR_ALREADY_OPEN;
-	MidiDriver_Emulated::open();
-
-	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle,
-		this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
-	return 0;
-}
-
-void Towns_EuphonyDriver::close() {
-	if (!_isOpen)
-		return;
-	_isOpen = false;
-	_mixer->stopHandle(_mixerSoundHandle);
-}
-
-void Towns_EuphonyDriver::send(uint32 b) {
-	send(b & 0xF, b & 0xFFFFFFF0);
-}
-
-void Towns_EuphonyDriver::send(byte chan, uint32 b) {
-	byte param2 = (byte) ((b >> 16) & 0xFF);
-	byte param1 = (byte) ((b >>  8) & 0xFF);
-	byte cmd    = (byte) (b & 0xF0);
-	if (chan > ARRAYSIZE(_channel))
-		return;
-
-	switch (cmd) {
-	case 0x80:// Note Off
-		if (_channel[chan])
-			_channel[chan]->noteOff(param1);
-		break;
-	case 0x90: // Note On
-		if (_channel[chan])
-			_channel[chan]->noteOn(param1, param2);
-		break;
-	case 0xA0: // Aftertouch
-		break; // Not supported.
-	case 0xB0: // Control Change
-		if (param1 == 0x79) {
-			fading(0);
-			for (int i = 0; i < 15; i++) {
-				if (_channel[i]) {
-					_channel[i]->controlChange(param1, param2);
-					_channel[i]->programChange(0);
-				}
-			}
-		} else if (param1 == 0x7B) {
-			for (int i = 0; i < 15; i++) {
-				if (_channel[i])
-					_channel[i]->controlChange(param1, param2);
-			}
-		} else {
-			if (_channel[chan])
-				_channel[chan]->controlChange(param1, param2);
-		}
-		break;
-	case 0xC0: // Program Change
-        for (int i = 0; i < 6; i++) {
-			if (_channel[chan] == _fChannel[i]) {
-				_channel[chan]->sysEx_customInstrument(0, _fmInstruments + param1 * 0x30);
-				break;
-			}
-		}
-		for (int i = 0; i < 8; i++) {
-			if (_channel[chan] == _wChannel[i]) {
-				_channel[chan]->sysEx_customInstrument(0, _waveInstruments + param1 * 0x80);
-				_channel[chan]->sysEx_customInstrument(0x80, (const byte *)_waveSounds);
-				break;
-			}
-		}
-		break;
-	case 0xD0: // Channel Pressure
-		break; // Not supported.
-	case 0xE0: // Pitch Bend
-		if (_channel[chan])
-			_channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
-		break;
-	default:
-		warning("Towns_EuphonyDriver: Unknown send() command 0x%02X", cmd);
-	}
-}
-
-void Towns_EuphonyDriver::loadFmInstruments(const byte *instr) {
-	delete[] _fmInstruments;
-	_fmInstruments = new uint8[0x1800];
-	memcpy(_fmInstruments, instr, 0x1800);
-}
-
-void Towns_EuphonyDriver::loadWaveInstruments(const byte *instr) {
-	delete[] _waveInstruments;
-	_waveInstruments = new uint8[0x1000];
-	memcpy(_waveInstruments, instr, 0x1000);
-
-	const uint8 *pos = (const uint8 *)(instr + 0x1000);
-
-	for (uint8 i = 0; i < 10; i++) {
-		delete[] _waveSounds[i];
-		uint32 numsamples = READ_LE_UINT32(pos + 0x0C);
-		_waveSounds[i] = new int8[numsamples + 0x20];
-        memcpy(_waveSounds[i], pos, 0x20);
-		pos += 0x20;
-		for (uint32 ii = 0; ii < numsamples; ii++) {
-			uint8 s = *(pos + ii);
-			s = (s < 0x80) ? 0x80 - s : s;
-			_waveSounds[i][ii + 0x20] = s ^ 0x80;
-		}
-		pos += numsamples;
-	}
-}
-
-
-void Towns_EuphonyDriver::assignFmChannel(uint8 midiChannelNumber, uint8 fmChannelNumber) {
-	_channel[midiChannelNumber] = _fChannel[fmChannelNumber];
-}
-
-void Towns_EuphonyDriver::assignWaveChannel(uint8 midiChannelNumber, uint8 waveChannelNumber) {
-	_channel[midiChannelNumber] = _wChannel[waveChannelNumber];
-}
-
-void Towns_EuphonyDriver::removeChannel(uint8 midiChannelNumber) {
-	_channel[midiChannelNumber] = 0;
-}
-
-void Towns_EuphonyDriver::generateSamples(int16 *data, int len) {
-	memset(data, 0, 2 * sizeof(int16) * len);
-	nextTick(data, len);
-}
-
-void Towns_EuphonyDriver::nextTick(int16 *buf1, int buflen) {
-	int32 *buf0 = (int32 *)buf1;
-
-	for (int i = 0; i < ARRAYSIZE(_channel); i++) {
-		if (_channel[i])
-			_channel[i]->nextTick(buf0, buflen);
-	}
-
-	for (int i = 0; i < buflen; ++i) {
-		int s = int( float(buf0[i] * _volume) * float((float)_fadestate / EUPHONY_FADEOUT_TICKS) );
-		buf1[i*2] = buf1[i*2+1] = (s >> 9) & 0xffff;
-	}
-
-	if (_fading) {
-		if (_fadestate) {
-			_fadestate--;
-		} else {
-			_fading = false;
-			_queue->setPlayBackStatus(false);
-		}
-	}
-}
-
-void Towns_EuphonyDriver::rate(uint16 r) {
-	for (uint8 i = 0; i < 16; i++) {
-		if (_channel[i])
-			_channel[i]->rate(r);
-	}
-}
-
-void Towns_EuphonyDriver::fading(bool status) {
-	_fading = status;
-	if (!_fading)
-		_fadestate = EUPHONY_FADEOUT_TICKS;
-}
-
-Towns_EuphonyParser::Towns_EuphonyParser(Towns_EuphonyTrackQueue * queue) : MidiParser(),
-	_firstBaseTickStep(0x33), _nextBaseTickStep(0x33) {
-		_initialTempo = calculateTempo(0x5a);
-		_queue = queue;
-}
-
-void Towns_EuphonyParser::parseNextEvent(EventInfo &info) {
-	byte *pos = _position._play_pos;
-
-	if (_queue->_next) {
-		if (info.ext.type == 0x2F) {
-			unloadMusic();
-			memset(&info, 0, sizeof(EventInfo));
-			pos = _position._play_pos = _tracks[0] = _queue->trackData() + 0x806;
-		} else if (_active_track == 255) {
-			_queue = _queue->_next;
-			setup();
-			setTrack(0);
-			_queue->setPlayBackStatus(true);
-			return;
-		} else if (!_queue->isPlaying()) {
-			unloadMusic();
-			_queue = _queue->_next;
-			setup();
-			setTrack(0);
-			_queue->setPlayBackStatus(true);
-			return;
-		}
-	}
-
-	bool loop = true;
-	while (loop) {
-		byte cmd = *pos;
-		byte evt = (cmd & 0xF0);
-
-		if (evt == 0x90) {
-			byte chan = pos[1];
-
-			if (_enable[chan]) {
-				uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
-				info.start = pos + 6;
-				uint32 last = _position._last_event_tick;
-				info.delta = (tick < last) ? 0 : (tick - last);
-
-				info.event = 0x90 | _channel[chan];
-				info.length = pos[7] | (pos[8] << 4) | (pos[9] << 8) | (pos[10] << 12);
-
-				int8 note = (int8) pos[4];
-				if (_adjNote[chan]) {
-					note = (note & 0x7f) & _adjNote[chan];
-					if (note > 0x7c)
-						note -= 0x0c;
-					else if (note < 0)
-						note += 0x0c;
-				}
-				info.basic.param1 = (byte) note;
-
-				uint8 onVelo = (pos[5] & 0x7f) + _adjVelo[chan];
-				if (onVelo > 0x7f)
-					onVelo = 0x7f;
-				if (onVelo < 1)
-					onVelo = 1;
-				info.basic.param2 = onVelo;
-
-				pos += 12;
-				loop = false;
-			} else {
-				pos += 6;
-			}
-		} else if (evt == 0xB0 || evt == 0xC0 || evt == 0xe0) {
-			byte chan = pos[1];
-
-			if (_enable[chan]) {
-				info.start = pos;
-				uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
-				uint32 last = _position._last_event_tick;
-				info.delta = (tick < last) ? 0 : (tick - last);
-				info.event = evt | _channel[chan];
-				info.length = 0;
-				info.basic.param1 = pos[4];
-				info.basic.param2 = pos[5];
-				pos += 6;
-				loop = false;
-			} else {
-				pos += 6;
-			}
-		} else if (cmd == 0xF2) {
-			static const uint16 tickTable[] = { 0x180, 0xC0, 0x80, 0x60, 0x40, 0x30, 0x20, 0x18 };
-			_baseTick += tickTable[_nextBaseTickStep >> 4] * ((_nextBaseTickStep & 0x0f) + 1);
-			_nextBaseTickStep = pos[1];
-			pos += 6;
-		} else if (cmd == 0xF8) {
-			int32 tempo = calculateTempo(pos[4] | (pos[5] << 7));
-			info.event = 0xff;
-			info.length = 3;
-			info.ext.type = 0x51;
-			_tempo[0] = (tempo >> 16) & 0xff;
-			_tempo[1] = (tempo >> 8) & 0xff;
-			_tempo[2] = tempo & 0xff;
-			info.ext.data = (byte *)_tempo;
-			pos += 6;
-			loop = false;
-		} else if (cmd == 0xFD || cmd == 0xFE) {
-			// End of track.
-			if (_autoLoop) {
-				unloadMusic();
-				_queue->setPlayBackStatus(true);
-				pos = info.start = _tracks[0];
-			} else {
-				info.start = pos;
-			}
-
-			uint32 last = _position._last_event_tick;
-			uint16 tick = (pos[2] | ((uint16) pos[3] << 7)) + _baseTick;
-			info.delta = (tick < last) ? 0 : (tick - last);
-			info.event = 0xFF;
-			info.ext.type = 0x2F;
-			info.ext.data = pos;
-			loop = false;
-		} else {
-			warning("Unknown Euphony music event 0x%02X", (int)cmd);
-			memset(&info, 0, sizeof(info));
-			pos = 0;
-			loop = false;
-		}
-	}
-	_position._play_pos = pos;
-}
-
-bool Towns_EuphonyParser::loadMusic(byte *data, uint32 size) {
-	bool loop = _autoLoop;
-
-	if (_queue->isPlaying() && !_queue->_loop) {
-		_queue->loadDataToEndOfQueue(data, size, loop);
-	} else {
-		unloadMusic();
-		_queue = _queue->release();
-		_queue->loadDataToCurrentPosition(data, size, loop);
-		setup();
-		setTrack(0);
-		_queue->setPlayBackStatus(true);
-	}
-	return true;
-}
-
-int32 Towns_EuphonyParser::calculateTempo(int16 val) {
-	int32 tempo = val;
-
-	if (tempo < 0)
-		tempo = 0;
-	if (tempo > 0x1F4)
-		tempo = 0x1F4;
-
-	tempo = 0x4C4B4 / (tempo + 0x1E);
-	while (tempo < 0x451)
-		tempo <<= 1;
-	tempo <<= 8;
-
-	return tempo;
-}
-
-void Towns_EuphonyParser::resetTracking() {
-	MidiParser::resetTracking();
-
-	_nextBaseTickStep = _firstBaseTickStep;
-	_baseTick = 0;
-	setTempo(_initialTempo);
-	_queue->setPlayBackStatus(false);
-}
-
-void Towns_EuphonyParser::setup() {
-	uint8 *data = _queue->trackData();
-	if (!data)
-		return;
-	_queue->initDriver();
-
-	_enable = data + 0x354;
-	_mode = data + 0x374;
-	_channel = data + 0x394;
-	_adjVelo = data + 0x3B4;
-	_adjNote = (int8 *)data + 0x3D4;
-
-	_nextBaseTickStep = _firstBaseTickStep = data[0x804];
-	_initialTempo = calculateTempo((data[0x805] > 0xfc) ? 0x5a : data[0x805]);
-
-	property(MidiParser::mpAutoLoop, _queue->_loop);
-
-	_num_tracks = 1;
-	_ppqn = 120;
-	_tracks[0] = data + 0x806;
-}
-
-Towns_EuphonyTrackQueue::Towns_EuphonyTrackQueue(Towns_EuphonyDriver * driver, Towns_EuphonyTrackQueue * last) {
-	_trackData = 0;
-	_next = 0;
-	_driver = driver;
-	_last = last;
-	_used = _fchan = _wchan = 0;
-	_playing = _loop = false;
-}
-
-void Towns_EuphonyTrackQueue::setPlayBackStatus(bool playing) {
-	Towns_EuphonyTrackQueue *i = this;
-	do {
-		i->_playing = playing;
-		i = i->_next;
-	} while (i);
-}
-
-void Towns_EuphonyTrackQueue::loadDataToCurrentPosition(uint8 * trackdata, uint32 size, bool loop) {
-	delete[] _trackData;
-	_trackData = new uint8[0xC58A];
-	memset(_trackData, 0, 0xC58A);
-	Screen::decodeFrame4(trackdata, _trackData, size);
-
-	_used = _trackData + 0x374;
-	_fchan = _trackData + 0x6d4;
-	_wchan = _trackData + 0x6dA;
-	_loop = loop;
-	_playing = false;
-}
-
-void Towns_EuphonyTrackQueue::loadDataToEndOfQueue(uint8 * trackdata, uint32 size, bool loop) {
-	if (!_trackData) {
-		loadDataToCurrentPosition(trackdata, size, loop);
-		return;
-	}
-
-	Towns_EuphonyTrackQueue *i = this;
-	while (i->_next)
-		i = i->_next;
-
-	i = i->_next = new Towns_EuphonyTrackQueue(_driver, i);
-	i->_trackData = new uint8[0xC58A];
-	memset(i->_trackData, 0, 0xC58A);
-	Screen::decodeFrame4(trackdata, i->_trackData, size);
-
-	i->_used = i->_trackData + 0x374;
-	i->_fchan = i->_trackData + 0x6d4;
-	i->_wchan = i->_trackData + 0x6dA;
-	i->_loop = loop;
-	i->_playing = _playing;
-}
-
-Towns_EuphonyTrackQueue *Towns_EuphonyTrackQueue::release() {
-	Towns_EuphonyTrackQueue *i = this;
-	while (i->_next)
-		i = i->_next;
-
-	Towns_EuphonyTrackQueue *res = i;
-
-	while (i) {
-		i->_playing = false;
-		i->_used = i->_fchan = i->_wchan = 0;
-		delete[] i->_trackData;
-		i->_trackData = 0;
-		i = i->_last;
-		if (i) {
-			res = i;
-			delete i->_next;
-			i->_next = 0;
-		}
-	}
-
-	delete[] res->_trackData;
-	res->_trackData = 0;
-
-	return res;
-}
-
-void Towns_EuphonyTrackQueue::initDriver() {
-	for (uint8 i = 0; i < 6; i++) {
-		if (_used[_fchan[i]])
-			_driver->assignFmChannel(_fchan[i], i);
-	}
-
-	for (uint8 i = 0; i < 8; i++) {
-		if (_used[_wchan[i]])
-			_driver->assignWaveChannel(_wchan[i], i);
-	}
-
-	for (uint8 i = 0; i < 16; i++) {
-		if (!_used[i])
-			_driver->removeChannel(i);
-	}
-	_driver->send(0x79B0);
-}
-
-class TownsPC98_OpnOperator {
-public:
-	TownsPC98_OpnOperator(const uint32 timerbase, const uint8 *rateTable,
-		const uint8 *shiftTable, const uint8 *attackDecayTable, const uint32 *frqTable,
-		const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable);
-	~TownsPC98_OpnOperator() {}
-
-	void keyOn();
-	void keyOff();
-	void frequency(int freq);
-	void updatePhaseIncrement();
-	void recalculateRates();
-	void generateOutput(int32 phasebuf, int32 *feedbuf, int32 &out);
-
-	void feedbackLevel(int32 level) {_feedbackLevel = level ? level + 6 : 0; }
-	void detune(int value) { _detn = &_detnTbl[value << 5]; }
-	void multiple(uint32 value) { _multiple = value ? (value << 1) : 1;	}
-	void attackRate(uint32 value) { _specifiedAttackRate = value; }
-	bool scaleRate(uint8 value);
-	void decayRate(uint32 value) { _specifiedDecayRate = value;	recalculateRates();	}
-	void sustainRate(uint32 value) { _specifiedSustainRate = value;	recalculateRates();	}
-	void sustainLevel(uint32 value) { _sustainLevel = (value == 0x0f) ? 0x3e0 : value << 5; }
-	void releaseRate(uint32 value) { _specifiedReleaseRate = value;	recalculateRates();	}
-	void totalLevel(uint32 value) { _totalLevel = value << 3; }
-	void reset();
-
-protected:
-	EnvelopeState _state;
-	bool _playing;
-	uint32 _feedbackLevel;
-	uint32 _multiple;
-	uint32 _totalLevel;
-	uint8 _keyScale1;
-	uint8 _keyScale2;
-	uint32 _specifiedAttackRate;
-	uint32 _specifiedDecayRate;
-	uint32 _specifiedSustainRate;
-	uint32 _specifiedReleaseRate;
-	uint32 _tickCount;
-	uint32 _sustainLevel;
-
-	uint32 _frequency;
-	uint8 _kcode;
-	uint32 _phase;
-	uint32 _phaseIncrement;
-	const int32 *_detn;
-
-	const uint8 *_rateTbl;
-	const uint8 *_rshiftTbl;
-	const uint8 *_adTbl;
-	const uint32 *_fTbl;
-	const uint32 *_sinTbl;
-	const int32 *_tLvlTbl;
-	const int32 *_detnTbl;
-
-	const uint32 _tickLength;
-	uint32 _timer;
-	int32 _currentLevel;
-
-	struct EvpState {
-		uint8 rate;
-		uint8 shift;
-	} fs_a, fs_d, fs_s, fs_r;
-};
-
-TownsPC98_OpnOperator::TownsPC98_OpnOperator(const uint32 timerbase, const uint8 *rateTable,
-	const uint8 *shiftTable, const uint8 *attackDecayTable,	const uint32 *frqTable,
-	const uint32 *sineTable, const int32 *tlevelOut, const int32 *detuneTable) :
-	_rateTbl(rateTable), _rshiftTbl(shiftTable), _adTbl(attackDecayTable), _fTbl(frqTable),
-	_sinTbl(sineTable), _tLvlTbl(tlevelOut), _detnTbl(detuneTable), _tickLength(timerbase * 2),
-	_specifiedAttackRate(0), _specifiedDecayRate(0), _specifiedReleaseRate(0), _specifiedSustainRate(0),
-	_phase(0), _state(s_ready),	_playing(false), _timer(0), _keyScale1(0), _keyScale2(0), _currentLevel(1023),
-	_tickCount(0) {
-
-	fs_a.rate = fs_a.shift = fs_d.rate = fs_d.shift = fs_s.rate = fs_s.shift = fs_r.rate = fs_r.shift = 0;
-
-	reset();
-}
-
-void TownsPC98_OpnOperator::keyOn() {
-	if (_playing)
-		return;
-
-	_playing = true;
-	_state = s_attacking;
-	_phase = 0;
-}
-
-void TownsPC98_OpnOperator::keyOff() {
-	if (!_playing)
-		return;
-
-	_playing = false;
-	if (_state != s_ready)
-		_state = s_releasing;
-}
-
-void TownsPC98_OpnOperator::frequency(int freq) {
-	uint8 block = (freq >> 11);
-	uint16 pos = (freq & 0x7ff);
-	uint8 c = pos >> 7;
-
-	_kcode = (block << 2) | ((c < 7) ? 0 : ((c > 8) ? 3 : c - 6 ));
-	_frequency = _fTbl[pos << 1] >> (7 - block);
-}
-
-void TownsPC98_OpnOperator::updatePhaseIncrement() {
-	_phaseIncrement = ((_frequency + _detn[_kcode]) * _multiple) >> 1;
-	uint8 keyscale = _kcode >> _keyScale1;
-	if (_keyScale2 != keyscale) {
-		_keyScale2 = keyscale;
-		recalculateRates();
-	}
-}
-
-void TownsPC98_OpnOperator::recalculateRates() {
-	int k = _keyScale2;
-	int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
-	fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
-	fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
-
-	r = _specifiedDecayRate ? (_specifiedDecayRate << 1) + 0x20 : 0;
-	fs_d.rate = _rateTbl[r + k];
-	fs_d.shift = _rshiftTbl[r + k];
-
-	r = _specifiedSustainRate ? (_specifiedSustainRate << 1) + 0x20 : 0;
-	fs_s.rate = _rateTbl[r + k];
-	fs_s.shift = _rshiftTbl[r + k];
-
-	r = (_specifiedReleaseRate << 2) + 0x22;
-	fs_r.rate = _rateTbl[r + k];
-	fs_r.shift = _rshiftTbl[r + k];
-}
-
-void TownsPC98_OpnOperator::generateOutput(int32 phasebuf, int32 *feed, int32 &out) {
-	if (_state == s_ready)
-		return;
-
-	_timer += _tickLength;
-	while (_timer > 0x5B8D80) {
-		_timer -= 0x5B8D80;
-		++_tickCount;
-
-		int32 levelIncrement = 0;
-		uint32 targetTime = 0;
-		int32 targetLevel = 0;
-		EnvelopeState nextState = s_ready;
-
-		switch (_state) {
-		case s_ready:
-			return;
-		case s_attacking:
-			targetLevel = 0;
-			nextState = s_decaying;
-			if ((_specifiedAttackRate << 1) + _keyScale2 < 64) {
-				targetTime = (1 << fs_a.shift) - 1;
-				levelIncrement = (~_currentLevel * _adTbl[fs_a.rate + ((_tickCount >> fs_a.shift) & 7)]) >> 4;
-				break;
-			} else {
-				_currentLevel = targetLevel;
-				_state = nextState;
-			}
-			// Fall through
-		case s_decaying:
-			targetTime = (1 << fs_d.shift) - 1;
-			nextState = s_sustaining;
-			targetLevel = _sustainLevel;
-			levelIncrement = _adTbl[fs_d.rate + ((_tickCount >> fs_d.shift) & 7)];
-			break;
-		case s_sustaining:
-			targetTime = (1 << fs_s.shift) - 1;
-			nextState = s_sustaining;
-			targetLevel = 1023;
-			levelIncrement = _adTbl[fs_s.rate + ((_tickCount >> fs_s.shift) & 7)];
-			break;
-		case s_releasing:
-			targetTime = (1 << fs_r.shift) - 1;
-			nextState = s_ready;
-			targetLevel = 1023;
-			levelIncrement = _adTbl[fs_r.rate + ((_tickCount >> fs_r.shift) & 7)];
-			break;
-		}
-
-		if (!(_tickCount & targetTime)) {
-			_currentLevel += levelIncrement;
-			if ((_state == s_attacking && _currentLevel <= targetLevel) || (_state != s_attacking && _currentLevel >= targetLevel)) {
-				if (_state != s_decaying)
-					_currentLevel = targetLevel;
-				_state = nextState;
-			}
-		}
-	}
-
-	uint32 lvlout = _totalLevel + (uint32) _currentLevel;
-
-
-	int32 outp = 0;
-	int32 *i = &outp, *o = &outp;
-	int phaseShift = 0;
-
-	if (feed) {
-		o = &feed[0];
-		i = &feed[1];
-		phaseShift = _feedbackLevel ? ((*o + *i) << _feedbackLevel) : 0;
-		*o = *i;
-	} else {
-		phaseShift = phasebuf << 15;
-	}
-
-	if (lvlout < 832) {
-		uint32 index = (lvlout << 3) + _sinTbl[(((int32)((_phase & 0xffff0000)
-			+ phaseShift)) >> 16) & 0x3ff];
-		*i = ((index < 6656) ? _tLvlTbl[index] : 0);
-	} else {
-		*i = 0;
-	}
-
-	_phase += _phaseIncrement;
-	out += *o;
-}
-
-void TownsPC98_OpnOperator::reset(){
-	keyOff();
-	_timer = 0;
-	_keyScale2 = 0;
-	_currentLevel = 1023;
-
-	frequency(0);
-	detune(0);
-	scaleRate(0);
-	multiple(0);
-	updatePhaseIncrement();
-	attackRate(0);
-	decayRate(0);
-	releaseRate(0);
-	sustainRate(0);
-	feedbackLevel(0);
-	totalLevel(127);
-}
-
-bool TownsPC98_OpnOperator::scaleRate(uint8 value) {
-	value = 3 - value;
-	if (_keyScale1 != value) {
-		_keyScale1 = value;
-		return true;
-	}
-
-	int k = _keyScale2;
-	int r = _specifiedAttackRate ? (_specifiedAttackRate << 1) + 0x20 : 0;
-	fs_a.rate = ((r + k) < 94) ? _rateTbl[r + k] : 136;
-	fs_a.shift = ((r + k) < 94) ? _rshiftTbl[r + k] : 0;
-	return false;
-}
-
-class TownsPC98_OpnDriver;
-class TownsPC98_OpnChannel {
-public:
-	TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
-		uint8 key, uint8 prt, uint8 id);
-	virtual ~TownsPC98_OpnChannel();
-	virtual void init();
-
-	typedef enum channelState {
-		CHS_RECALCFREQ		=	0x01,
-		CHS_KEYOFF			=	0x02,
-		CHS_SSGOFF			=	0x04,
-		CHS_VBROFF			=	0x08,
-		CHS_ALLOFF			=	0x0f,
-		CHS_PROTECT			=	0x40,
-		CHS_EOT				=	0x80
-	} ChannelState;
-
-	virtual void loadData(uint8 *data);
-	virtual void processEvents();
-	virtual void processFrequency();
-	virtual bool processControlEvent(uint8 cmd);
-
-	virtual void keyOn();
-	void keyOff();
-
-	void setOutputLevel();
-	virtual void fadeStep();
-	virtual void reset();
-
-	const uint8 _idFlag;
-
-protected:
-	void setupVibrato();
-	bool processVibrato();
-
-	bool control_dummy(uint8 para);
-	bool control_f0_setPatch(uint8 para);
-	bool control_f1_presetOutputLevel(uint8 para);
-	bool control_f2_setKeyOffTime(uint8 para);
-	bool control_f3_setFreqLSB(uint8 para);
-	bool control_f4_setOutputLevel(uint8 para);
-	bool control_f5_setTempo(uint8 para);
-	bool control_f6_repeatSection(uint8 para);
-	bool control_f7_setupVibrato(uint8 para);
-	bool control_f8_toggleVibrato(uint8 para);
-	bool control_fa_writeReg(uint8 para);
-	virtual bool control_fb_incOutLevel(uint8 para);
-	virtual bool control_fc_decOutLevel(uint8 para);
-	bool control_fd_jump(uint8 para);
-	virtual bool control_ff_endOfTrack(uint8 para);
-
-	uint8 _ticksLeft;
-	uint8 _algorithm;
-	uint8 _instr;
-	uint8 _totalLevel;
-	uint8 _frqBlockMSB;
-	int8 _frqLSB;
-	uint8 _keyOffTime;
-	bool _hold;
-	uint8 *_dataPtr;
-	uint8 _vbrInitDelayHi;
-	uint8 _vbrInitDelayLo;
-	int16 _vbrModInitVal;
-	uint8 _vbrDuration;
-	uint8 _vbrCurDelay;
-	int16 _vbrModCurVal;
-	uint8 _vbrDurLeft;
-	uint16 _frequency;
-	uint8 _block;
-	uint8 _regOffset;
-	uint8 _flags;
-	uint8 _ssgTl;
-	uint8 _ssgStep;
-	uint8 _ssgTicksLeft;
-	uint8 _ssgTargetLvl;
-	uint8 _ssgStartLvl;
-
-	const uint8 _chanNum;
-	const uint8 _keyNum;
-	const uint8 _part;
-
-	TownsPC98_OpnDriver *_drv;
-
-	typedef bool (TownsPC98_OpnChannel::*ControlEventFunc)(uint8 para);
-	const ControlEventFunc *controlEvents;
-};
-
-class TownsPC98_OpnChannelSSG : public TownsPC98_OpnChannel {
-public:
-	TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs,
-		uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
-	virtual ~TownsPC98_OpnChannelSSG() {}
-	void init();
-
-	virtual void loadData(uint8 *data);
-	void processEvents();
-	void processFrequency();
-	bool processControlEvent(uint8 cmd);
-
-	void keyOn();
-	void nextShape();
-
-	void protect();
-	void restore();
-	virtual void reset();
-
-	void fadeStep();
-
-protected:
-	void setOutputLevel(uint8 lvl);
-
-	bool control_f0_setPatch(uint8 para);
-	bool control_f1_setTotalLevel(uint8 para);
-	bool control_f4_setAlgorithm(uint8 para);
-	bool control_f9_loadCustomPatch(uint8 para);
-	bool control_fb_incOutLevel(uint8 para);
-	bool control_fc_decOutLevel(uint8 para);
-	bool control_ff_endOfTrack(uint8 para);
-
-	typedef bool (TownsPC98_OpnChannelSSG::*ControlEventFunc)(uint8 para);
-	const ControlEventFunc *controlEvents;
-};
-
-class TownsPC98_OpnSfxChannel : public TownsPC98_OpnChannelSSG {
-public:
-	TownsPC98_OpnSfxChannel(TownsPC98_OpnDriver *driver, uint8 regOffs,
-		uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
-		TownsPC98_OpnChannelSSG(driver, regOffs, flgs, num, key, prt, id) {}
-	~TownsPC98_OpnSfxChannel() {}
-
-	void loadData(uint8 *data);
-	void reset();
-};
-
-class TownsPC98_OpnChannelPCM : public TownsPC98_OpnChannel {
-public:
-	TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs,
-		uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id);
-	~TownsPC98_OpnChannelPCM() {}
-	void init();
-
-	void loadData(uint8 *data);
-	void processEvents();
-	bool processControlEvent(uint8 cmd);
-
-private:
-	bool control_f1_prcStart(uint8 para);
-	bool control_ff_endOfTrack(uint8 para);
-
-	typedef bool (TownsPC98_OpnChannelPCM::*ControlEventFunc)(uint8 para);
-	const ControlEventFunc *controlEvents;
-};
-
-class TownsPC98_OpnSquareSineSource {
-public:
-	TownsPC98_OpnSquareSineSource(const uint32 timerbase);
-	~TownsPC98_OpnSquareSineSource();
-
-	void init(const int *rsTable, const int *rseTable);
-	void reset();
-	void writeReg(uint8 address, uint8 value, bool force = false);
-
-	void nextTick(int32 *buffer, uint32 bufferSize);
-
-	void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; }
-	void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; }
-
-	uint8 chanEnable() const { return _chanEnable; }
-private:
-	void updateRegs();
-
-	uint8 _updateRequestBuf[64];
-	int _updateRequest;
-	int _rand;
-
-	int8 _evpTimer;
-	uint32 _pReslt;
-	uint8 _attack;
-
-	bool _evpUpdate, _cont;
-
-	int _evpUpdateCnt;
-	uint8 _outN;
-	int _nTick;
-
-	int32 *_tlTable;
-	int32 *_tleTable;
-
-	const uint32 _tickLength;
-	uint32 _timer;
-
-	struct Channel {
-		int tick;
-		uint8 smp;
-		uint8 out;
-
-		uint8 frqL;
-		uint8 frqH;
-		uint8 vol;
-	} _channels[3];
-
-	uint8 _noiseGenerator;
-	uint8 _chanEnable;
-
-	uint8 **_reg;
-
-	uint16 _volumeA;
-	uint16 _volumeB;
-	int _volMaskA;
-	int _volMaskB;
-
-	bool _ready;
-};
-
-class TownsPC98_OpnPercussionSource {
-public:
-	TownsPC98_OpnPercussionSource(const uint32 timerbase);
-	~TownsPC98_OpnPercussionSource() { delete[] _reg; }
-
-	void init(const uint8 *instrData = 0);
-	void reset();
-	void writeReg(uint8 address, uint8 value);
-
-	void nextTick(int32 *buffer, uint32 bufferSize);
-
-	void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; }
-	void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; }
-
-private:
-	struct RhtChannel {
-		const uint8 *data;
-
-		const uint8 *start;
-		const uint8 *end;
-		const uint8 *pos;
-		uint32 size;
-		bool active;
-		uint8 level;
-
-		int8 decState;
-		uint8 decStep;
-
-		int16 samples[2];
-		int out;
-
-		uint8 startPosH;
-		uint8 startPosL;
-		uint8 endPosH;
-		uint8 endPosL;
-	};
-
-	void recalcOuput(RhtChannel *ins);
-	void advanceInput(RhtChannel *ins);
-
-	RhtChannel _rhChan[6];
-
-	uint8 _totalLevel;
-
-	const uint32 _tickLength;
-	uint32 _timer;
-
-	uint8 **_reg;
-
-	uint16 _volumeA;
-	uint16 _volumeB;
-	int _volMaskA;
-	int _volMaskB;
-
-	bool _ready;
-};
-
-class TownsPC98_OpnCore : public Audio::AudioStream {
-public:
-	enum OpnType {
-		OD_TOWNS,
-		OD_TYPE26,
-		OD_TYPE86
-	};
-
-	TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type);
-	virtual ~TownsPC98_OpnCore();
-
-	virtual bool init();
-	virtual void reset();
-
-	void writeReg(uint8 part, uint8 regAddress, uint8 value);
-
-	// AudioStream interface
-	int readBuffer(int16 *buffer, const int numSamples);
-	bool isStereo() const { return true; }
-	bool endOfData() const { return false; }
-	int getRate() const { return _mixer->getOutputRate(); }
-
-protected:
-	void toggleRegProtection(bool prot) { _regProtectionFlag = prot; }
-	uint8 readSSGStatus() { return _ssg->chanEnable(); }
-
-	virtual void timerCallbackA() = 0;
-	virtual void timerCallbackB() = 0;
-
-	// The audio driver can store and apply two different audio settings
-	// (usually for music and sound effects). The channel mask will determine
-	// which channels get effected by the setting. The first bits will be
-	// the normal opn channels, the next bits the ssg channels and the final
-	// bit the rhythm channel.
-	void setVolumeIntern(int volA, int volB);
-	void setVolumeChannelMasks(int channelMaskA, int channelMaskB);
-
-	const int _numChan;
-	const int _numSSG;
-	const bool _hasPercussion;
-
-	Common::Mutex _mutex;
-private:
-	void generateTables();
-	void nextTick(int32 *buffer, uint32 bufferSize);
-	void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed);
-
-	struct ChanInternal {
-		ChanInternal() {
-			memset(this, 0, sizeof(ChanInternal));
-		}
-
-		~ChanInternal() {
-			for (uint i = 0; i < ARRAYSIZE(opr); ++i)
-				delete opr[i];
-		}
-
-		uint16 frqTemp;
-		bool enableLeft;
-		bool enableRight;
-		bool updateEnvelopeParameters;
-		int32 feedbuf[3];
-		uint8 algorithm;
-		TownsPC98_OpnOperator *opr[4];
-	};
-
-	TownsPC98_OpnSquareSineSource *_ssg;
-	TownsPC98_OpnPercussionSource *_prc;
-	ChanInternal *_chanInternal;
-
-	uint8 *_oprRates;
-	uint8 *_oprRateshift;
-	uint8 *_oprAttackDecay;
-	uint32 *_oprFrq;
-	uint32 *_oprSinTbl;
-	int32 *_oprLevelOut;
-	int32 *_oprDetune;
-
-	bool _regProtectionFlag;
-
-	typedef void (TownsPC98_OpnCore::*OpnTimerProc)();
-
-	struct OpnTimer {
-		bool enabled;
-		uint16 value;
-
-		int32 smpTillCb;
-		uint32 smpTillCbRem;
-		int32 smpPerCb;
-		uint32 smpPerCbRem;
-
-		OpnTimerProc cb;
-	};
-
-	OpnTimer _timers[2];
-
-	int _volMaskA, _volMaskB;
-	uint16 _volumeA, _volumeB;
-
-	const float _baserate;
-	uint32 _timerbase;
-
-	Audio::Mixer *_mixer;
-	Audio::SoundHandle _soundHandle;
-
-	static const uint8 _percussionData[];
-	static const uint32 _adtStat[];
-	static const uint8 _detSrc[];
-	static const int _ssgTables[];
-
-	bool _ready;
-};
-
-class TownsPC98_OpnDriver : public TownsPC98_OpnCore {
-friend class TownsPC98_OpnChannel;
-friend class TownsPC98_OpnChannelSSG;
-friend class TownsPC98_OpnSfxChannel;
-friend class TownsPC98_OpnChannelPCM;
-public:
-	TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type);
-	~TownsPC98_OpnDriver();
-
-	void loadMusicData(uint8 *data, bool loadPaused = false);
-	void loadSoundEffectData(uint8 *data, uint8 trackNum);
-	bool init();
-	void reset();
-
-	void fadeStep();
-
-	void pause() { _musicPlaying = false; }
-	void cont() { _musicPlaying = true; }
-
-	void timerCallbackB();
-	void timerCallbackA();
-
-	bool looping() { return _looping == _updateChannelsFlag ? true : false; }
-	bool musicPlaying() { return _musicPlaying; }
-
-	void setMusicVolume(int volume) { _musicVolume = volume; setVolumeIntern(_musicVolume, _sfxVolume); }
-	void setSoundEffectVolume(int volume) { _sfxVolume = volume; setVolumeIntern(_musicVolume, _sfxVolume); }
-
-protected:
-	void startSoundEffect();
-
-	void setMusicTempo(uint8 tempo);
-	void setSfxTempo(uint16 tempo);
-
-	TownsPC98_OpnChannel **_channels;
-	TownsPC98_OpnChannelSSG **_ssgChannels;
-	TownsPC98_OpnSfxChannel **_sfxChannels;
-	TownsPC98_OpnChannelPCM *_rhythmChannel;
-
-	const uint8 *_opnCarrier;
-	const uint8 *_opnFreqTable;
-	const uint8 *_opnFreqTableSSG;
-	const uint8 *_opnFxCmdLen;
-	const uint8 *_opnLvlPresets;
-
-	uint8 *_musicBuffer;
-	uint8 *_sfxBuffer;
-	uint8 *_trackPtr;
-	uint8 *_patches;
-	uint8 *_ssgPatches;
-
-	uint8 _updateChannelsFlag;
-	uint8 _updateSSGFlag;
-	uint8 _updateRhythmFlag;
-	uint8 _updateSfxFlag;
-	uint8 _finishedChannelsFlag;
-	uint8 _finishedSSGFlag;
-	uint8 _finishedRhythmFlag;
-	uint8 _finishedSfxFlag;
-
-	bool _musicPlaying;
-	bool _sfxPlaying;
-	uint8 _fading;
-	uint8 _looping;
-	uint32 _musicTickCounter;
-
-	int _sfxOffs;
-	uint8 *_sfxData;
-	uint16 _sfxOffsets[2];
-
-	uint16 _musicVolume;
-	uint16 _sfxVolume;
-
-	static const uint8 _drvTables[];
-
-	bool _ready;
-};
-
-TownsPC98_OpnChannel::TownsPC98_OpnChannel(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num,
-	uint8 key, uint8 prt, uint8 id) : _drv(driver), _regOffset(regOffs), _flags(flgs), _chanNum(num), _keyNum(key),
-	_part(prt), _idFlag(id), controlEvents(0) {
-
-	_ticksLeft = _algorithm = _instr = _totalLevel = _frqBlockMSB = _keyOffTime = 0;
-	_ssgStartLvl = _ssgTl = _ssgStep = _ssgTicksLeft = _ssgTargetLvl = _block = 0;
-	_vbrInitDelayHi = _vbrInitDelayLo = _vbrDuration = _vbrCurDelay = _vbrDurLeft = 0;
-	_frqLSB = 0;
-	_hold = false;
-	_dataPtr = 0;
-	_vbrModInitVal = _vbrModCurVal = 0;
-	_frequency = 0;
-}
-
-TownsPC98_OpnChannel::~TownsPC98_OpnChannel() {
-}
-
-void TownsPC98_OpnChannel::init() {
-	#define Control(x)	&TownsPC98_OpnChannel::control_##x
-	static const ControlEventFunc ctrlEvents[] = {
-		Control(f0_setPatch),
-		Control(f1_presetOutputLevel),
-		Control(f2_setKeyOffTime),
-		Control(f3_setFreqLSB),
-		Control(f4_setOutputLevel),
-		Control(f5_setTempo),
-		Control(f6_repeatSection),
-		Control(f7_setupVibrato),
-		Control(f8_toggleVibrato),
-		Control(dummy),
-		Control(fa_writeReg),
-		Control(fb_incOutLevel),
-		Control(fc_decOutLevel),
-		Control(fd_jump),
-		Control(dummy),
-		Control(ff_endOfTrack)
-	};
-	#undef Control
-
-	controlEvents = ctrlEvents;
-}
-
-void TownsPC98_OpnChannel::keyOff() {
-	// all operators off
-	uint8 value = _keyNum & 0x0f;
-	if (_part)
-		value |= 4;
-	uint8 regAddress = 0x28;
-	_drv->writeReg(0, regAddress, value);
-	_flags |= CHS_KEYOFF;
-}
-
-void TownsPC98_OpnChannel::keyOn() {
-	// all operators on
-	uint8 value = _keyNum | 0xf0;
-	if (_part)
-		value |= 4;
-	uint8 regAddress = 0x28;
-	_drv->writeReg(0, regAddress, value);
-}
-
-void TownsPC98_OpnChannel::loadData(uint8 *data) {
-	_flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
-	_ticksLeft = 1;
-	_dataPtr = data;
-	_totalLevel = 0x7F;
-
-	uint8 *tmp = _dataPtr;
-	for (bool loop = true; loop; ) {
-		uint8 cmd = *tmp++;
-		if (cmd < 0xf0) {
-			tmp++;
-		} else if (cmd == 0xff) {
-			if (READ_LE_UINT16(tmp)) {
-				_drv->_looping |= _idFlag;
-				tmp += _drv->_opnFxCmdLen[cmd - 240];
-			} else
-				loop = false;
-		} else if (cmd == 0xf6) {
-			// reset repeat section countdown
-			tmp[0] = tmp[1];
-			tmp += 4;
-		} else {
-			tmp += _drv->_opnFxCmdLen[cmd - 240];
-		}
-	}
-}
-
-void TownsPC98_OpnChannel::processEvents() {
-	if (_flags & CHS_EOT)
-		return;
-
-	if (!_hold && _ticksLeft == _keyOffTime)
-		keyOff();
-
-	if (--_ticksLeft)
-		return;
-
-	if (!_hold)
-		keyOff();
-
-	uint8 cmd = 0;
-	bool loop = true;
-
-	while (loop) {
-		cmd = *_dataPtr++;
-		if (cmd < 0xf0)
-			loop = false;
-		else if (!processControlEvent(cmd))
-			return;
-	}
-
-	uint8 para = *_dataPtr++;
-
-	if (cmd == 0x80) {
-		keyOff();
-		_hold = false;
-	} else {
-		keyOn();
-
-		if (_hold == false || cmd != _frqBlockMSB)
-			_flags |= CHS_RECALCFREQ;
-
-		_hold = (para & 0x80) ? true : false;
-		_frqBlockMSB = cmd;
-	}
-
-	_ticksLeft = para & 0x7f;
-}
-
-void TownsPC98_OpnChannel::processFrequency() {
-	if (_flags & CHS_RECALCFREQ) {
-
-		_frequency = (((const uint16 *)_drv->_opnFreqTable)[_frqBlockMSB & 0x0f] + _frqLSB) | (((_frqBlockMSB & 0x70) >> 1) << 8);
-
-		_drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
-		_drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
-
-		setupVibrato();
-	}
-
-	if (!(_flags & CHS_VBROFF)) {
-		if (!processVibrato())
-			return;
-
-		_drv->writeReg(_part, _regOffset + 0xa4, (_frequency >> 8));
-		_drv->writeReg(_part, _regOffset + 0xa0, (_frequency & 0xff));
-	}
-}
-
-void TownsPC98_OpnChannel::setupVibrato() {
-	_vbrCurDelay = _vbrInitDelayHi;
-	if (_flags & CHS_KEYOFF) {
-		_vbrModCurVal = _vbrModInitVal;
-		_vbrCurDelay += _vbrInitDelayLo;
-	}
-	_vbrDurLeft = (_vbrDuration >> 1);
-	_flags &= ~(CHS_KEYOFF | CHS_RECALCFREQ);
-}
-
-bool TownsPC98_OpnChannel::processVibrato() {
-	if (--_vbrCurDelay)
-		return false;
-
-	_vbrCurDelay = _vbrInitDelayHi;
-	_frequency += _vbrModCurVal;
-
-	if (!--_vbrDurLeft) {
-		_vbrDurLeft = _vbrDuration;
-		_vbrModCurVal = -_vbrModCurVal;
-	}
-
-	return true;
-}
-
-bool TownsPC98_OpnChannel::processControlEvent(uint8 cmd) {
-	uint8 para = *_dataPtr++;
-	return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-void TownsPC98_OpnChannel::setOutputLevel() {
-	uint8 outopr = _drv->_opnCarrier[_algorithm];
-	uint8 reg = 0x40 + _regOffset;
-
-	for (int i = 0; i < 4; i++) {
-		if (outopr & 1)
-			_drv->writeReg(_part, reg, _totalLevel);
-		outopr >>= 1;
-		reg += 4;
-	}
-}
-
-void TownsPC98_OpnChannel::fadeStep() {
-	_totalLevel += 3;
-	if (_totalLevel > 0x7f)
-		_totalLevel = 0x7f;
-	setOutputLevel();
-}
-
-void TownsPC98_OpnChannel::reset() {
-	_hold = false;
-	_keyOffTime = 0;
-	_ticksLeft = 1;
-
-	_flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
-
-	_totalLevel = 0;
-	_algorithm = 0;
-	_flags = CHS_EOT;
-	_algorithm = 0;
-
-	_block = 0;
-	_frequency = 0;
-	_frqBlockMSB = 0;
-	_frqLSB = 0;
-
-	_ssgTl = 0;
-	_ssgStartLvl = 0;
-	_ssgTargetLvl = 0;
-	_ssgStep = 0;
-	_ssgTicksLeft = 0;
-
-	_vbrInitDelayHi = 0;
-	_vbrInitDelayLo = 0;
-	_vbrModInitVal = 0;
-	_vbrDuration = 0;
-	_vbrCurDelay = 0;
-	_vbrModCurVal = 0;
-	_vbrDurLeft = 0;
-}
-
-bool TownsPC98_OpnChannel::control_f0_setPatch(uint8 para) {
-	_instr = para;
-	uint8 reg = _regOffset + 0x80;
-
-	for (int i = 0; i < 4; i++) {
-		// set release rate for each operator
-		_drv->writeReg(_part, reg, 0x0f);
-		reg += 4;
-	}
-
-	const uint8 *tptr = _drv->_patches + ((uint32)_instr << 5);
-	reg = _regOffset + 0x30;
-
-	// write registers 0x30 to 0x8f
-	for (int i = 0; i < 6; i++) {
-		_drv->writeReg(_part, reg, tptr[0]);
-		reg += 4;
-		_drv->writeReg(_part, reg, tptr[2]);
-		reg += 4;
-		_drv->writeReg(_part, reg, tptr[1]);
-		reg += 4;
-		_drv->writeReg(_part, reg, tptr[3]);
-		reg += 4;
-		tptr += 4;
-	}
-
-	reg = _regOffset + 0xB0;
-	_algorithm = tptr[0] & 7;
-	// set feedback and algorithm
-	_drv->writeReg(_part, reg, tptr[0]);
-
-	setOutputLevel();
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f1_presetOutputLevel(uint8 para) {
-	if (_drv->_fading)
-		return true;
-
-	_totalLevel = _drv->_opnLvlPresets[para];
-	setOutputLevel();
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f2_setKeyOffTime(uint8 para) {
-	_keyOffTime = para;
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f3_setFreqLSB(uint8 para) {
-	_frqLSB = (int8) para;
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f4_setOutputLevel(uint8 para) {
-	if (_drv->_fading)
-		return true;
-
-	_totalLevel = para;
-	setOutputLevel();
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f5_setTempo(uint8 para) {
-	_drv->setMusicTempo(para);
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f6_repeatSection(uint8 para) {
-	_dataPtr--;
-	_dataPtr[0]--;
-
-	if (*_dataPtr) {
-		// repeat section until counter has reached zero
-		_dataPtr = _drv->_trackPtr + READ_LE_UINT16(_dataPtr + 2);
-	} else {
-		// reset counter, advance to next section
-		_dataPtr[0] = _dataPtr[1];
-		_dataPtr += 4;
-	}
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f7_setupVibrato(uint8 para) {
-	_vbrInitDelayHi = _dataPtr[0];
-	_vbrInitDelayLo = para;
-	_vbrModInitVal = (int16) READ_LE_UINT16(_dataPtr + 1);
-	_vbrDuration = _dataPtr[3];
-	_dataPtr += 4;
-	_flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF | CHS_RECALCFREQ;
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_f8_toggleVibrato(uint8 para) {
-	if (para == 0x10) {
-		if (*_dataPtr++) {
-			_flags = (_flags & ~CHS_VBROFF) | CHS_KEYOFF;
-		} else {
-			_flags |= CHS_VBROFF;
-		}
-	} else {
-		/* NOT IMPLEMENTED
-		uint8 skipChannels = para / 36;
-		uint8 entry = para % 36;
-		TownsPC98_OpnDriver::TownsPC98_OpnChannel *t = &chan[skipChannels];
-
-		t->unnamedEntries[entry] = *_dataPtr++;*/
-	}
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_fa_writeReg(uint8 para) {
-	_drv->writeReg(_part, para, *_dataPtr++);
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_fb_incOutLevel(uint8 para) {
-	_dataPtr--;
-	if (_drv->_fading)
-		return true;
-
-	uint8 val = (_totalLevel + 3);
-	if (val > 0x7f)
-		val = 0x7f;
-
-	_totalLevel = val;
-	setOutputLevel();
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_fc_decOutLevel(uint8 para) {
-	_dataPtr--;
-	if (_drv->_fading)
-		return true;
-
-	int8 val = (int8) (_totalLevel - 3);
-	if (val < 0)
-		val = 0;
-
-	_totalLevel = (uint8) val;
-	setOutputLevel();
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_fd_jump(uint8 para) {
-	uint8 *tmp = _drv->_trackPtr + READ_LE_UINT16(_dataPtr - 1);
-	_dataPtr = (tmp[1] == 1) ? tmp : (_dataPtr + 1);
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_dummy(uint8 para) {
-	_dataPtr--;
-	return true;
-}
-
-bool TownsPC98_OpnChannel::control_ff_endOfTrack(uint8 para) {
-	uint16 val = READ_LE_UINT16(--_dataPtr);
-	if (val) {
-		// loop
-		_dataPtr = _drv->_trackPtr + val;
-		return true;
-	} else {
-		// quit parsing for active channel
-		--_dataPtr;
-		_flags |= CHS_EOT;
-		_drv->_finishedChannelsFlag |= _idFlag;
-		keyOff();
-		return false;
-	}
-}
-
-TownsPC98_OpnChannelSSG::TownsPC98_OpnChannelSSG(TownsPC98_OpnDriver *driver, uint8 regOffs,
-		uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
-		TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) {
-}
-
-void TownsPC98_OpnChannelSSG::init() {
-	_algorithm = 0x80;
-
-	#define Control(x)	&TownsPC98_OpnChannelSSG::control_##x
-	static const ControlEventFunc ctrlEventsSSG[] = {
-		Control(f0_setPatch),
-		Control(f1_setTotalLevel),
-		Control(f2_setKeyOffTime),
-		Control(f3_setFreqLSB),
-		Control(f4_setAlgorithm),
-		Control(f5_setTempo),
-		Control(f6_repeatSection),
-		Control(f7_setupVibrato),
-		Control(f8_toggleVibrato),
-		Control(f9_loadCustomPatch),
-		Control(fa_writeReg),
-		Control(fb_incOutLevel),
-		Control(fc_decOutLevel),
-		Control(fd_jump),
-		Control(dummy),
-		Control(ff_endOfTrack)
-	};
-	#undef Control
-
-	controlEvents = ctrlEventsSSG;
-}
-
-void TownsPC98_OpnChannelSSG::processEvents() {
-	if (_flags & CHS_EOT)
-		return;
-
-	_drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
-
-	if (!_hold && _ticksLeft == _keyOffTime)
-		nextShape();
-
-	if (!--_ticksLeft) {
-
-		uint8 cmd = 0;
-		bool loop = true;
-
-		while (loop) {
-			cmd = *_dataPtr++;
-			if (cmd < 0xf0)
-				loop = false;
-			else if (!processControlEvent(cmd))
-				return;
-		}
-
-		uint8 para = *_dataPtr++;
-
-		if (cmd == 0x80) {
-			nextShape();
-			_hold = false;
-		} else {
-			if (!_hold) {
-				_instr &= 0xf0;
-				_ssgStep = _drv->_ssgPatches[_instr];
-				_ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
-				_ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
-				_ssgStartLvl = _drv->_ssgPatches[_instr + 3];
-				_flags = (_flags & ~CHS_SSGOFF) | CHS_KEYOFF;
-			}
-
-			keyOn();
-
-			if (_hold == false || cmd != _frqBlockMSB)
-				_flags |= CHS_RECALCFREQ;
-
-			_hold = (para & 0x80) ? true : false;
-			_frqBlockMSB = cmd;
-		}
-
-		_ticksLeft = para & 0x7f;
-	}
-
-	if (!(_flags & CHS_SSGOFF)) {
-		if (--_ssgTicksLeft) {
-			if (!_drv->_fading)
-				setOutputLevel(_ssgStartLvl);
-			return;
-		}
-
-		_ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
-
-		if (_drv->_ssgPatches[_instr + 1] & 0x80) {
-			uint8 t = _ssgStartLvl - _ssgStep;
-
-			if (_ssgStep <= _ssgStartLvl && _ssgTargetLvl < t) {
-				if (!_drv->_fading)
-					setOutputLevel(t);
-				return;
-			}
-		} else {
-			int t = _ssgStartLvl + _ssgStep;
-			uint8 p = (uint8) (t & 0xff);
-
-			if (t < 256 && _ssgTargetLvl > p) {
-				if (!_drv->_fading)
-					setOutputLevel(p);
-				return;
-			}
-		}
-
-		setOutputLevel(_ssgTargetLvl);
-		if (_ssgStartLvl && !(_instr & 8)){
-			_instr += 4;
-			_ssgStep = _drv->_ssgPatches[_instr];
-			_ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
-			_ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
-		} else {
-			_flags |= CHS_SSGOFF;
-			setOutputLevel(0);
-		}
-	}
-}
-
-void TownsPC98_OpnChannelSSG::processFrequency() {
-	if (_algorithm & 0x40)
-		return;
-
-	if (_flags & CHS_RECALCFREQ) {
-		_block = _frqBlockMSB >> 4;
-		_frequency = ((const uint16 *)_drv->_opnFreqTableSSG)[_frqBlockMSB & 0x0f] + _frqLSB;
-
-		uint16 f = _frequency >> _block;
-		_drv->writeReg(_part, _regOffset << 1, f & 0xff);
-		_drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
-
-		setupVibrato();
-	}
-
-	if (!(_flags & (CHS_EOT | CHS_VBROFF | CHS_SSGOFF))) {
-		if (!processVibrato())
-			return;
-
-		uint16 f = _frequency >> _block;
-		_drv->writeReg(_part, _regOffset << 1, f & 0xff);
-		_drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
-	}
-}
-
-bool TownsPC98_OpnChannelSSG::processControlEvent(uint8 cmd) {
-	uint8 para = *_dataPtr++;
-	return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-void TownsPC98_OpnChannelSSG::nextShape() {
-	_instr = (_instr & 0xf0) + 0x0c;
-	_ssgStep = _drv->_ssgPatches[_instr];
-	_ssgTicksLeft = _drv->_ssgPatches[_instr + 1] & 0x7f;
-	_ssgTargetLvl = _drv->_ssgPatches[_instr + 2];
-}
-
-void TownsPC98_OpnChannelSSG::keyOn() {
-	uint8 c = 0x7b;
-	uint8 t = (_algorithm & 0xC0) << 1;
-	if (_algorithm & 0x80)
-		t |= 4;
-
-	c = (c << (_regOffset + 1)) | (c >> (7 - _regOffset));
-	t = (t << (_regOffset + 1)) | (t >> (7 - _regOffset));
-
-	if (!(_algorithm & 0x80))
-		_drv->writeReg(_part, 6, _algorithm & 0x7f);
-
-	uint8 e = (_drv->readSSGStatus() & c) | t;
-	_drv->writeReg(_part, 7, e);
-}
-
-void TownsPC98_OpnChannelSSG::protect() {
-	_flags |= CHS_PROTECT;
-}
-
-void TownsPC98_OpnChannelSSG::restore() {
-	_flags &= ~CHS_PROTECT;
-	keyOn();
-	_drv->writeReg(_part, 8 + _regOffset, _ssgTl);
-	uint16 f = _frequency >> _block;
-	_drv->writeReg(_part, _regOffset << 1, f & 0xff);
-	_drv->writeReg(_part, (_regOffset << 1) + 1, f >> 8);
-}
-
-void TownsPC98_OpnChannelSSG::loadData(uint8 *data) {
-	_drv->toggleRegProtection(_flags & CHS_PROTECT ? true : false);
-	TownsPC98_OpnChannel::loadData(data);
-	setOutputLevel(0);
-	_algorithm = 0x80;
-}
-
-void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) {
-	_ssgStartLvl = lvl;
-	uint16 newTl = (((uint16)_totalLevel + 1) * (uint16)lvl) >> 8;
-	if (newTl == _ssgTl)
-		return;
-	_ssgTl = newTl;
-	_drv->writeReg(_part, 8 + _regOffset, _ssgTl);
-}
-
-void TownsPC98_OpnChannelSSG::reset() {
-	TownsPC98_OpnChannel::reset();
-
-	// Unlike the original we restore the default patch data. This fixes a bug
-	// where certain sound effects would bring each other out of tune (e.g. the
-	// dragon's fire in Darm's house in Kyra 1 would sound different each time
-	// you triggered another sfx by dropping an item etc.)
-	uint8 i = (10 + _regOffset) << 4;
-	const uint8 *src = &_drv->_drvTables[156];
-	_drv->_ssgPatches[i] = src[i];
-	_drv->_ssgPatches[i + 3] = src[i + 3];
-	_drv->_ssgPatches[i + 4] = src[i + 4];
-	_drv->_ssgPatches[i + 6] = src[i + 6];
-	_drv->_ssgPatches[i + 8] = src[i + 8];
-	_drv->_ssgPatches[i + 12] = src[i + 12];
-}
-
-void TownsPC98_OpnChannelSSG::fadeStep() {
-	_totalLevel--;
-	if ((int8)_totalLevel < 0)
-		_totalLevel = 0;
-	setOutputLevel(_ssgStartLvl);
-}
-
-bool TownsPC98_OpnChannelSSG::control_f0_setPatch(uint8 para) {
-	_instr = para << 4;
-	para = (para >> 3) & 0x1e;
-	if (para)
-		return control_f4_setAlgorithm(para | 0x40);
-	return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_f1_setTotalLevel(uint8 para) {
-	if (!_drv->_fading)
-		_totalLevel = para;
-	return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_f4_setAlgorithm(uint8 para) {
-	_algorithm = para;
-	return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_f9_loadCustomPatch(uint8 para) {
-	_instr = (_drv->_sfxOffs + 10 + _regOffset) << 4;
-	_drv->_ssgPatches[_instr] = *_dataPtr++;
-	_drv->_ssgPatches[_instr + 3] = para;
-	_drv->_ssgPatches[_instr + 4] = *_dataPtr++;
-	_drv->_ssgPatches[_instr + 6] = *_dataPtr++;
-	_drv->_ssgPatches[_instr + 8] = *_dataPtr++;
-	_drv->_ssgPatches[_instr + 12] = *_dataPtr++;
-	return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_fb_incOutLevel(uint8 para) {
-	_dataPtr--;
-	if (_drv->_fading)
-		return true;
-
-	_totalLevel--;
-	if ((int8)_totalLevel < 0)
-		_totalLevel = 0;
-
-	return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_fc_decOutLevel(uint8 para) {
-	_dataPtr--;
-	if (_drv->_fading)
-		return true;
-
-	if (_totalLevel + 1 < 0x10)
-		_totalLevel++;
-
-	return true;
-}
-
-bool TownsPC98_OpnChannelSSG::control_ff_endOfTrack(uint8 para) {
-	if (!_drv->_sfxOffs) {
-		uint16 val = READ_LE_UINT16(--_dataPtr);
-		if (val) {
-			// loop
-			_dataPtr = _drv->_trackPtr + val;
-			return true;
-		} else {
-			// stop parsing
-			if (!_drv->_fading)
-				setOutputLevel(0);
-			--_dataPtr;
-			_flags |= CHS_EOT;
-			_drv->_finishedSSGFlag |= _idFlag;
-		}
-	} else {
-		// end of sfx track - restore ssg music channel
-		_flags |= CHS_EOT;
-		_drv->_finishedSfxFlag |= _idFlag;
-		_drv->_ssgChannels[_chanNum]->restore();
-	}
-
-	return false;
-}
-
-void TownsPC98_OpnSfxChannel::loadData(uint8 *data) {
-	_flags = CHS_ALLOFF;
-	_ticksLeft = 1;
-	_dataPtr = data;
-	_ssgTl = 0xff;
-	_algorithm = 0x80;
-
-	uint8 *tmp = _dataPtr;
-	for (bool loop = true; loop; ) {
-		uint8 cmd = *tmp++;
-		if (cmd < 0xf0) {
-			tmp++;
-		} else if (cmd == 0xff) {
-			loop = false;
-		} else if (cmd == 0xf6) {
-			// reset repeat section countdown
-			tmp[0] = tmp[1];
-			tmp += 4;
-		} else {
-			tmp += _drv->_opnFxCmdLen[cmd - 240];
-		}
-	}
-}
-
-void TownsPC98_OpnSfxChannel::reset() {
-	TownsPC98_OpnChannel::reset();
-
-	// Unlike the original we restore the default patch data. This fixes a bug
-	// where certain sound effects would bring each other out of tune (e.g. the
-	// dragon's fire in Darm's house in Kyra 1 would sound different each time
-	// you triggered another sfx by dropping an item etc.)
-	uint8 i = (13 + _regOffset) << 4;
-	const uint8 *src = &_drv->_drvTables[156];
-	_drv->_ssgPatches[i] = src[i];
-	_drv->_ssgPatches[i + 3] = src[i + 3];
-	_drv->_ssgPatches[i + 4] = src[i + 4];
-	_drv->_ssgPatches[i + 6] = src[i + 6];
-	_drv->_ssgPatches[i + 8] = src[i + 8];
-	_drv->_ssgPatches[i + 12] = src[i + 12];
-}
-
-TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs,
-		uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) :
-		TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) {
-}
-
-void TownsPC98_OpnChannelPCM::init() {
-	_algorithm = 0x80;
-
-	#define Control(x)	&TownsPC98_OpnChannelPCM::control_##x
-	static const ControlEventFunc ctrlEventsPCM[] = {
-		Control(dummy),
-		Control(f1_prcStart),
-		Control(dummy),
-		Control(dummy),
-		Control(dummy),
-		Control(dummy),
-		Control(f6_repeatSection),
-		Control(dummy),
-		Control(dummy),
-		Control(dummy),
-		Control(fa_writeReg),
-		Control(dummy),
-		Control(dummy),
-		Control(dummy),
-		Control(dummy),
-		Control(ff_endOfTrack)
-	};
-	#undef Control
-
-	controlEvents = ctrlEventsPCM;
-}
-
-void TownsPC98_OpnChannelPCM::loadData(uint8 *data) {
-	_flags = (_flags & ~CHS_EOT) | CHS_ALLOFF;
-	_ticksLeft = 1;
-	_dataPtr = data;
-	_totalLevel = 0x7F;
-}
-
-void TownsPC98_OpnChannelPCM::processEvents()  {
-	if (_flags & CHS_EOT)
-		return;
-
-	if (--_ticksLeft)
-		return;
-
-	uint8 cmd = 0;
-	bool loop = true;
-
-	while (loop) {
-		cmd = *_dataPtr++;
-		if (cmd == 0x80) {
-			loop = false;
-		} else if (cmd < 0xf0) {
-			_drv->writeReg(_part, 0x10, cmd);
-		} else if (!processControlEvent(cmd)) {
-			return;
-		}
-	}
-
-	_ticksLeft = *_dataPtr++;
-}
-
-bool TownsPC98_OpnChannelPCM::processControlEvent(uint8 cmd) {
-	uint8 para = *_dataPtr++;
-	return (this->*controlEvents[cmd & 0x0f])(para);
-}
-
-bool TownsPC98_OpnChannelPCM::control_f1_prcStart(uint8 para) {
-	_totalLevel = para;
-	_drv->writeReg(_part, 0x11, para);
-	return true;
-}
-
-bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) {
-	uint16 val = READ_LE_UINT16(--_dataPtr);
-	if (val) {
-		// loop
-		_dataPtr = _drv->_trackPtr + val;
-		return true;
-	} else {
-		// quit parsing for active channel
-		--_dataPtr;
-		_flags |= CHS_EOT;
-		_drv->_finishedRhythmFlag |= _idFlag;
-		return false;
-	}
-}
-
-TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0),
-	_tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1),
-	_nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true),
-	_timer(0), _noiseGenerator(0), _chanEnable(0),
-	_volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
-
-	memset(_channels, 0, sizeof(_channels));
-	memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf));
-	_reg = new uint8 *[11];
-
-	_reg[0] = &_channels[0].frqL;
-	_reg[1] = &_channels[0].frqH;
-	_reg[2] = &_channels[1].frqL;
-	_reg[3] = &_channels[1].frqH;
-	_reg[4] = &_channels[2].frqL;
-	_reg[5] = &_channels[2].frqH;
-	_reg[6] = &_noiseGenerator;
-	_reg[7] = &_chanEnable;
-	_reg[8] = &_channels[0].vol;
-	_reg[9] = &_channels[1].vol;
-	_reg[10] = &_channels[2].vol;
-
-	reset();
-}
-
-TownsPC98_OpnSquareSineSource::~TownsPC98_OpnSquareSineSource() {
-	delete[] _tlTable;
-	delete[] _tleTable;
-	delete[] _reg;
-}
-
-void TownsPC98_OpnSquareSineSource::init(const int *rsTable, const int *rseTable) {
-	if (_ready) {
-		reset();
-		return;
-	}
-
-	delete[] _tlTable;
-	delete[] _tleTable;
-	_tlTable = new int32[16];
-	_tleTable = new int32[32];
-	float a, b, d;
-	d = 801.0f;
-
-	for (int i = 0; i < 16; i++) {
-		b = 1.0f / rsTable[i];
-		a = 1.0f / d + b + 1.0f / 1000.0f;
-		float v = (b / a) * 32767.0f;
-		_tlTable[i] = (int32) v;
-
-		b = 1.0f / rseTable[i];
-		a = 1.0f / d + b + 1.0f / 1000.0f;
-		v = (b / a) * 32767.0f;
-		_tleTable[i] = (int32) v;
-	}
-
-	for (int i = 16; i < 32; i++) {
-		b = 1.0f / rseTable[i];
-		a = 1.0f / d + b + 1.0f / 1000.0f;
-		float v = (b / a) * 32767.0f;
-		_tleTable[i] = (int32) v;
-	}
-
-	_ready = true;
-}
-
-void TownsPC98_OpnSquareSineSource::reset() {
-	_rand = 1;
-	_outN = 1;
-	_updateRequest = -1;
-	_nTick = _evpUpdateCnt = 0;
-	_evpTimer = 0x1f;
-	_pReslt = 0x1f;
-	_attack = 0;
-	_cont = false;
-	_evpUpdate = true;
-	_timer = 0;
-
-	for (int i = 0; i < 3; i++) {
-		_channels[i].tick = 0;
-		_channels[i].smp = _channels[i].out = 0;
-	}
-
-	for (int i = 0; i < 14; i++)
-		writeReg(i, 0, true);
-
-	writeReg(7, 0xbf, true);
-}
-
-void TownsPC98_OpnSquareSineSource::writeReg(uint8 address, uint8 value, bool force) {
-	if (!_ready)
-		return;
-
-	if (address > 10 || *_reg[address] == value) {
-		if ((address == 11 || address == 12 || address == 13) && value)
-			warning("TownsPC98_OpnSquareSineSource: unsupported reg address: %d", address);
-		return;
-	}
-
-	if (!force) {
-		if (_updateRequest >= 63) {
-			warning("TownsPC98_OpnSquareSineSource: event buffer overflow");
-			_updateRequest = -1;
-		}
-		_updateRequestBuf[++_updateRequest] = value;
-		_updateRequestBuf[++_updateRequest] = address;
-		return;
-	}
-
-	*_reg[address] = value;
-}
-
-void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
-	if (!_ready)
-		return;
-
-	for (uint32 i = 0; i < bufferSize; i++) {
-		_timer += _tickLength;
-		while (_timer > 0x5B8D80) {
-			_timer -= 0x5B8D80;
-
-			if (++_nTick >= (_noiseGenerator & 0x1f)) {
-				if ((_rand + 1) & 2)
-					_outN ^= 1;
-
-				_rand = (((_rand & 1) ^ ((_rand >> 3) & 1)) << 16) | (_rand >> 1);
-				_nTick = 0;
-			}
-
-			for (int ii = 0; ii < 3; ii++) {
-				if (++_channels[ii].tick >= (((_channels[ii].frqH & 0x0f) << 8) | _channels[ii].frqL)) {
-					_channels[ii].tick = 0;
-					_channels[ii].smp ^= 1;
-				}
-				_channels[ii].out = (_channels[ii].smp | ((_chanEnable >> ii) & 1)) & (_outN | ((_chanEnable >> (ii + 3)) & 1));
-			}
-
-			if (_evpUpdate) {
-				if (++_evpUpdateCnt >= 0) {
-					_evpUpdateCnt = 0;
-
-					if (--_evpTimer < 0) {
-						if (_cont) {
-							_evpTimer &= 0x1f;
-						} else {
-							_evpUpdate = false;
-							_evpTimer = 0;
-						}
-					}
-				}
-			}
-			_pReslt = _evpTimer ^ _attack;
-			updateRegs();
-		}
-
-		int32 finOut = 0;
-		for (int ii = 0; ii < 3; ii++) {
-			int32 finOutTemp = ((_channels[ii].vol >> 4) & 1) ? _tleTable[_channels[ii].out ? _pReslt : 0] : _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
-
-			if ((1 << ii) & _volMaskA)
-				finOutTemp = (finOutTemp * _volumeA) / Audio::Mixer::kMaxMixerVolume;
-
-			if ((1 << ii) & _volMaskB)
-				finOutTemp = (finOutTemp * _volumeB) / Audio::Mixer::kMaxMixerVolume;
-
-			finOut += finOutTemp;
-		}
-
-		finOut /= 3;
-
-		buffer[i << 1] += finOut;
-		buffer[(i << 1) + 1] += finOut;
-	}
-}
-
-void TownsPC98_OpnSquareSineSource::updateRegs() {
-	for (int i = 0; i < _updateRequest;) {
-		uint8 b = _updateRequestBuf[i++];
-		uint8 a = _updateRequestBuf[i++];
-		writeReg(a, b, true);
-	}
-	_updateRequest = -1;
-}
-
-TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) :
-	_tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
-
-	memset(_rhChan, 0, sizeof(RhtChannel) * 6);
-	_reg = new uint8 *[40];
-
-	_reg[0] = _reg[1] = _reg[2] = _reg[3] = _reg[4] = _reg[5] = _reg[6] = _reg[7] = _reg[8] = _reg[9] = _reg[10] = _reg[11] = _reg[12] = _reg[13] = _reg[14] = _reg[15] = 0;
-	_reg[16] = &_rhChan[0].startPosL;
-	_reg[17] = &_rhChan[1].startPosL;
-	_reg[18] = &_rhChan[2].startPosL;
-	_reg[19] = &_rhChan[3].startPosL;
-	_reg[20] = &_rhChan[4].startPosL;
-	_reg[21] = &_rhChan[5].startPosL;
-	_reg[22] = &_rhChan[0].startPosH;
-	_reg[23] = &_rhChan[1].startPosH;
-	_reg[24] = &_rhChan[2].startPosH;
-	_reg[25] = &_rhChan[3].startPosH;
-	_reg[26] = &_rhChan[4].startPosH;
-	_reg[27] = &_rhChan[5].startPosH;
-	_reg[28] = &_rhChan[0].endPosL;
-	_reg[29] = &_rhChan[1].endPosL;
-	_reg[30] = &_rhChan[2].endPosL;
-	_reg[31] = &_rhChan[3].endPosL;
-	_reg[32] = &_rhChan[4].endPosL;
-	_reg[33] = &_rhChan[5].endPosL;
-	_reg[34] = &_rhChan[0].endPosH;
-	_reg[35] = &_rhChan[1].endPosH;
-	_reg[36] = &_rhChan[2].endPosH;
-	_reg[37] = &_rhChan[3].endPosH;
-	_reg[38] = &_rhChan[4].endPosH;
-	_reg[39] = &_rhChan[5].endPosH;
-}
-
-void TownsPC98_OpnPercussionSource::init(const uint8 *instrData) {
-	if (_ready) {
-		reset();
-		return;
-	}
-
-	const uint8 *start = instrData;
-	const uint8 *pos = start;
-
-	if (instrData) {
-		for (int i = 0; i < 6; i++) {
-			_rhChan[i].data = start + READ_BE_UINT16(pos);
-			pos += 2;
-			_rhChan[i].size = READ_BE_UINT16(pos);
-			pos += 2;
-		}
-		reset();
-		_ready = true;
-	} else {
-		memset(_rhChan, 0, sizeof(RhtChannel) * 6);
-		_ready = false;
-	}
-}
-
-void TownsPC98_OpnPercussionSource::reset() {
-	_timer = 0;
-	_totalLevel = 63;
-
-	for (int i = 0; i < 6; i++) {
-		RhtChannel *s = &_rhChan[i];
-		s->pos = s->start = s->data;
-		s->end = s->data + s->size;
-		s->active = false;
-		s->level = 0;
-		s->out = 0;
-		s->decStep = 1;
-		s->decState = 0;
-		s->samples[0] = s->samples[1] = 0;
-		s->startPosH = s->startPosL = s->endPosH = s->endPosL = 0;
-	}
-}
-
-void TownsPC98_OpnPercussionSource::writeReg(uint8 address, uint8 value) {
-	if (!_ready)
-		return;
-
-	 uint8 h = address >> 4;
-	 uint8 l = address & 15;
-
-	if (address > 15)
-		*_reg[address] = value;
-
-	if (address == 0) {
-		if (value & 0x80) {
-			//key off
-			for (int i = 0; i < 6; i++) {
-				if ((value >> i) & 1)
-					_rhChan[i].active = false;
-			}
-		} else {
-			//key on
-			for (int i = 0; i < 6; i++) {
-				if ((value >> i) & 1) {
-					RhtChannel *s = &_rhChan[i];
-					s->pos = s->start;
-					s->active = true;
-					s->out = 0;
-					s->samples[0] = s->samples[1] = 0;
-					s->decStep = 1;
-					s->decState = 0;
-				}
-			}
-		}
-	} else if (address == 1) {
-		// total level
-		_totalLevel = (value & 63) ^ 63;
-		for (int i = 0; i < 6; i++)
-			recalcOuput(&_rhChan[i]);
-	} else if (!h && l & 8) {
-		// instrument level
-		l &= 7;
-		_rhChan[l].level = (value & 0x1f) ^ 0x1f;
-		recalcOuput(&_rhChan[l]);
-	} else if (h & 3) {
-		l &= 7;
-		if (h == 1) {
-			// set start offset
-			_rhChan[l].start  = _rhChan[l].data + ((_rhChan[l].startPosH << 8 | _rhChan[l].startPosL) << 8);
-		} else if (h == 2) {
-			// set end offset
-			_rhChan[l].end = _rhChan[l].data + ((_rhChan[l].endPosH << 8 | _rhChan[l].endPosL) << 8) + 255;
-		}
-	}
-}
-
-void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
-	if (!_ready)
-		return;
-
-	for (uint32 i = 0; i < bufferSize; i++) {
-		_timer += _tickLength;
-		while (_timer > 0x5B8D80) {
-			_timer -= 0x5B8D80;
-
-			for (int ii = 0; ii < 6; ii++) {
-				RhtChannel *s = &_rhChan[ii];
-				if (s->active) {
-					recalcOuput(s);
-					if (s->decStep) {
-						advanceInput(s);
-						if (s->pos == s->end)
-							s->active = false;
-					}
-					s->decStep ^= 1;
-				}
-			}
-		}
-
-		int32 finOut = 0;
-
-		for (int ii = 0; ii < 6; ii++) {
-			if (_rhChan[ii].active)
-				finOut += _rhChan[ii].out;
-		}
-
-		finOut <<= 1;
-
-		if (1 & _volMaskA)
-			finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
-
-		if (1 & _volMaskB)
-			finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
-
-		buffer[i << 1] += finOut;
-		buffer[(i << 1) + 1] += finOut;
-	}
-}
-
-void TownsPC98_OpnPercussionSource::recalcOuput(RhtChannel *ins) {
-	uint32 s = _totalLevel + ins->level;
-	uint32 x = s > 62 ? 0 : (1 + (s >> 3));
-	int32 y = s > 62 ? 0 : (15 - (s & 7));
-	ins->out = ((ins->samples[ins->decStep] * y) >> x) & ~3;
-}
-
-void TownsPC98_OpnPercussionSource::advanceInput(RhtChannel *ins) {
-	static const int8 adjustIndex[] = {-1, -1, -1, -1, 2, 5, 7, 9 };
-
-	static const int16 stepTable[] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55,
-		60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337,
-		371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
-	};
-
-	uint8 cur = (int8) *ins->pos++;
-
-	for (int i = 0; i < 2; i++) {
-		int b = (2 * (cur & 7) + 1) * stepTable[ins->decState] / 8;
-		ins->samples[i] = CLIP<int16>(ins->samples[i ^ 1] + (cur & 8 ? b : -b), -2048, 2047);
-		ins->decState = CLIP<int8>(ins->decState + adjustIndex[cur & 7], 0, 48);
-		cur >>= 4;
-	}
-}
-
-TownsPC98_OpnCore::TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type) :
-	_mixer(mixer),
-	_chanInternal(0), _ssg(0), _prc(0),
-	_numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPercussion(type == OD_TYPE86 ? true : false),
-	_oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
-	_baserate(55125.0f / (float)mixer->getOutputRate()),
-	_volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
-	_regProtectionFlag(false), _ready(false) {
-
-	memset(&_timers[0], 0, sizeof(OpnTimer));
-	memset(&_timers[1], 0, sizeof(OpnTimer));
-	_timers[0].cb = &TownsPC98_OpnCore::timerCallbackA;
-	_timers[1].cb = &TownsPC98_OpnCore::timerCallbackB;
-	_timerbase = (uint32)(_baserate * 1000000.0f);
-}
-
-TownsPC98_OpnCore::~TownsPC98_OpnCore() {
-	Common::StackLock lock(_mutex);
-	_mixer->stopHandle(_soundHandle);
-	delete _ssg;
-	delete _prc;
-	delete[] _chanInternal;
-
-	delete[] _oprRates;
-	delete[] _oprRateshift;
-	delete[] _oprFrq;
-	delete[] _oprAttackDecay;
-	delete[] _oprSinTbl;
-	delete[] _oprLevelOut;
-	delete[] _oprDetune;
-}
-
-bool TownsPC98_OpnCore::init() {
-	if (_ready) {
-		reset();
-		return true;
-	}
-
-	generateTables();
-
-	_chanInternal = new ChanInternal[_numChan];
-	for (int i = 0; i < _numChan; i++) {
-		memset(&_chanInternal[i], 0, sizeof(ChanInternal));
-		for (int j = 0; j < 4; ++j)
-			_chanInternal[i].opr[j] = new TownsPC98_OpnOperator(_timerbase, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune);
-	}
-
-	if (_numSSG) {
-		_ssg = new TownsPC98_OpnSquareSineSource(_timerbase);
-		_ssg->init(&_ssgTables[0], &_ssgTables[16]);
-	}
-
-	if (_hasPercussion) {
-		_prc = new TownsPC98_OpnPercussionSource(_timerbase);
-		_prc->init(_percussionData);
-	}
-
-	_mixer->playStream(Audio::Mixer::kPlainSoundType,
-		&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
-	_ready = true;
-
-	return true;
-}
-
-void TownsPC98_OpnCore::reset() {
-	for (int i = 0; i < _numChan; i++) {
-		for (int ii = 0; ii < 4; ii++)
-			_chanInternal[i].opr[ii]->reset();
-		memset(_chanInternal[i].feedbuf, 0, 3);
-		_chanInternal[i].algorithm = 0;
-		_chanInternal[i].frqTemp = 0;
-		_chanInternal[i].enableLeft = _chanInternal[i].enableRight = true;
-		_chanInternal[i].updateEnvelopeParameters = false;
-	}
-
-	writeReg(0, 0x27, 0x33);
-
-	if (_ssg)
-		_ssg->reset();
-
-	if (_prc)
-		_prc->reset();
-}
-
-void TownsPC98_OpnCore::writeReg(uint8 part, uint8 regAddress, uint8 value) {
-	if (_regProtectionFlag || !_ready)
-		return;
-
-	static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
-
-	uint8 h = regAddress & 0xf0;
-	uint8 l = (regAddress & 0x0f);
-
-	ChanInternal *c = 0;
-	TownsPC98_OpnOperator **co = 0;
-	TownsPC98_OpnOperator *o = 0;
-
-	if (regAddress > 0x2F) {
-		c = &_chanInternal[(l & 3) + 3 * part];
-		co = c->opr;
-		o = c->opr[oprOrdr[(l - (l & 3)) >> 2]];
-	} else if (regAddress == 0x28) {
-		c = &_chanInternal[(value & 3) + ((value & 4) ? 3 : 0)];
-		co = c->opr;
-	}
-
-	switch (h) {
-	case 0x00:
-		// ssg
-		if (_ssg)
-			_ssg->writeReg(l, value);
-		break;
-	case 0x10:
-		// pcm rhythm channel
-		if (_prc)
-			_prc->writeReg(l, value);
-		break;
-	case 0x20:
-		if (l == 8) {
-			// Key on/off
-			for (int i = 0; i < 4; i++) {
-				if ((value >> (4 + i)) & 1)
-					co[oprOrdr[i]]->keyOn();
-				else
-					co[oprOrdr[i]]->keyOff();
-			}
-		} else if (l == 4) {
-			// Timer A
-			_timers[0].value = (_timers[0].value & 0xff00) | value;
-		} else if (l == 5) {
-			// Timer A
-			_timers[0].value = (_timers[0].value & 0xff) | (value << 8);
-		} else if (l == 6) {
-			// Timer B
-			_timers[1].value = value & 0xff;
-		} else if (l == 7) {
-			_timers[0].enabled = (value & 1) ? 1 : 0;
-			_timers[1].enabled = (value & 2) ? 1 : 0;
-
-			float spc = (float)(0x400 - _timers[0].value) / _baserate;
-			_timers[0].smpPerCb = (int32) spc;
-			_timers[0].smpPerCbRem = (uint32) ((spc - (float)_timers[0].smpPerCb) * 1000000.0f);
-
-			spc = (float)(0x100 - _timers[1].value) * 16.0f / _baserate;
-			_timers[1].smpPerCb = (int32) spc;
-			_timers[1].smpPerCbRem = (uint32) ((spc - (float)_timers[1].smpPerCb) * 1000000.0f);
-
-			if (value & 10) {
-				_timers[0].smpTillCb = _timers[0].smpPerCb;
-				_timers[0].smpTillCbRem = _timers[0].smpTillCbRem;
-			}
-
-			if (value & 20) {
-				_timers[1].smpTillCb = _timers[1].smpPerCb;
-				_timers[1].smpTillCbRem = _timers[1].smpTillCbRem;
-			}
-		} else if (l == 2) {
-			// LFO
-			warning("TownsPC98_OpnDriver: TRYING TO USE LFO (NOT SUPPORTED)");
-		} else if (l == 10 || l == 11) {
-			// DAC
-			warning("TownsPC98_OpnDriver: TRYING TO USE DAC (NOT SUPPORTED)");
-		}
-		break;
-
-	case 0x30:
-		// detune, multiple
-		o->detune((value >> 4) & 7);
-		o->multiple(value & 0x0f);
-		c->updateEnvelopeParameters = true;
-		break;
-
-	case 0x40:
-		// total level
-		o->totalLevel(value & 0x7f);
-		break;
-
-	case 0x50:
-		// rate scaling, attack rate
-		o->attackRate(value & 0x1f);
-		if (o->scaleRate(value >> 6))
-			c->updateEnvelopeParameters = true;
-		break;
-
-	case 0x60:
-		// first decay rate, amplitude modulation
-		o->decayRate(value & 0x1f);
-		if (value & 0x80)
-			warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION (NOT SUPPORTED)");
-		break;
-
-	case 0x70:
-		// secondary decay rate
-		o->sustainRate(value & 0x1f);
-		break;
-
-	case 0x80:
-		// secondary amplitude, release rate;
-		o->sustainLevel(value >> 4);
-		o->releaseRate(value & 0x0f);
-		break;
-
-	case 0x90:
-		warning("TownsPC98_OpnDriver: TRYING TO SSG ENVELOPE SHAPES (NOT SUPPORTED)");
-		break;
-
-	case 0xa0:
-		// frequency
-		l &= ~3;
-		if (l == 0) {
-			c->frqTemp = (c->frqTemp & 0xff00) | value;
-			c->updateEnvelopeParameters = true;
-			for (int i = 0; i < 4; i++)
-				co[i]->frequency(c->frqTemp);
-		} else if (l == 4) {
-			c->frqTemp = (c->frqTemp & 0xff) | (value << 8);
-		} else if (l == 8) {
-			// Ch 3/6 special mode frq
-			warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
-		} else if (l == 12) {
-			// Ch 3/6 special mode frq
-			warning("TownsPC98_OpnDriver: TRYING TO USE CH 3/6 SPECIAL MODE FREQ (NOT SUPPORTED)");
-		}
-		break;
-
-	case 0xb0:
-		l &= ~3;
-		if (l == 0) {
-			// feedback, _algorithm
-			co[0]->feedbackLevel((value >> 3) & 7);
-			c->algorithm = value & 7;
-		} else if (l == 4) {
-			// stereo, LFO sensitivity
-			c->enableLeft = value & 0x80 ? true : false;
-			c->enableRight = value & 0x40 ? true : false;
-			uint8 ams = (value & 0x3F) >> 3;
-			if (ams)
-				warning("TownsPC98_OpnDriver: TRYING TO USE AMP MODULATION SENSITIVITY (NOT SUPPORTED)");
-			uint8 fms = value & 3;
-			if (fms)
-				warning("TownsPC98_OpnDriver: TRYING TO USE FREQ MODULATION SENSITIVITY (NOT SUPPORTED)");
-		}
-		break;
-
-	default:
-		warning("TownsPC98_OpnDriver: UNKNOWN ADDRESS %d", regAddress);
-	}
-}
-
-int TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) {
-	Common::StackLock lock(_mutex);
-
-	memset(buffer, 0, sizeof(int16) * numSamples);
-	int32 *tmp = new int32[numSamples];
-	int32 *tmpStart = tmp;
-	memset(tmp, 0, sizeof(int32) * numSamples);
-	int32 samplesLeft = numSamples >> 1;
-
-	while (samplesLeft) {
-		int32 render = samplesLeft;
-
-		for (int i = 0; i < 2; i++) {
-			if (_timers[i].enabled && _timers[i].cb) {
-				if (!_timers[i].smpTillCb) {
-					(this->*_timers[i].cb)();
-					_timers[i].smpTillCb = _timers[i].smpPerCb;
-
-					_timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
-					if (_timers[i].smpTillCbRem >= _timerbase) {
-						_timers[i].smpTillCb++;
-						_timers[i].smpTillCbRem -= _timerbase;
-					}
-				}
-				render = MIN(render, _timers[i].smpTillCb);
-			}
-		}
-
-		samplesLeft -= render;
-
-		for (int i = 0; i < 2; i++) {
-			if (_timers[i].enabled && _timers[i].cb) {
-				_timers[i].smpTillCb -= render;
-			}
-		}
-
-		nextTick(tmp, render);
-
-		if (_ssg)
-			_ssg->nextTick(tmp, render);
-		if (_prc)
-			_prc->nextTick(tmp, render);
-
-		for (int i = 0; i < render; ++i) {
-			int32 l = CLIP<int32>(tmp[i << 1], -32767, 32767);
-			buffer[i << 1] = (int16) l;
-			int32 r = CLIP<int32>(tmp[(i << 1) + 1], -32767, 32767);
-			buffer[(i << 1) + 1] = (int16) r;
-		}
-
-		buffer += (render << 1);
-		tmp += (render << 1);
-	}
-
-	delete[] tmpStart;
-	return numSamples;
-}
-
-void TownsPC98_OpnCore::setVolumeIntern(int volA, int volB) {
-	Common::StackLock lock(_mutex);
-	_volumeA = volA;
-	_volumeB = volB;
-	if (_ssg)
-		_ssg->setVolumeIntern(volA, volB);
-	if (_prc)
-		_prc->setVolumeIntern(volA, volB);
-}
-
-void TownsPC98_OpnCore::setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
-	Common::StackLock lock(_mutex);
-	_volMaskA = channelMaskA;
-	_volMaskB = channelMaskB;
-	if (_ssg)
-		_ssg->setVolumeChannelMasks(_volMaskA >> _numChan, _volMaskB >> _numChan);
-	if (_prc)
-		_prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG));
-}
-
-void TownsPC98_OpnCore::generateTables() {
-	delete[] _oprRates;
-	_oprRates = new uint8[128];
-
-	WRITE_BE_UINT32(_oprRates + 32, _numChan == 6 ? 0x90900000 : 0x00081018);
-	WRITE_BE_UINT32(_oprRates + 36, _numChan == 6 ? 0x00001010 : 0x00081018);
-	memset(_oprRates, 0x90, 32);
-	memset(_oprRates + 96, 0x80, 32);
-	uint8 *dst = (uint8 *)_oprRates + 40;
-	for (int i = 0; i < 40; i += 4)
-		WRITE_BE_UINT32(dst + i, 0x00081018);
-	for (int i = 0; i < 48; i += 4)
-		WRITE_BE_UINT32(dst + i, 0x00081018);
-	dst += 40;
-	for (uint8 i = 0; i < 16; i ++) {
-		uint8 v = (i < 12) ? i : 12;
-		*dst++ = ((4 + v) << 3);
-	}
-
-	delete[] _oprRateshift;
-	_oprRateshift = new uint8[128];
-	memset(_oprRateshift, 0, 128);
-	dst = (uint8 *)_oprRateshift + 32;
-	for (int i = 11; i; i--) {
-		memset(dst, i, 4);
-		dst += 4;
-	}
-
-	delete[] _oprFrq;
-	_oprFrq = new uint32[0x1000];
-	for (uint32 i = 0; i < 0x1000; i++)
-		_oprFrq[i] = (uint32)(_baserate * (float)(i << 11));
-
-	delete[] _oprAttackDecay;
-	_oprAttackDecay = new uint8[152];
-	memset(_oprAttackDecay, 0, 152);
-	for (int i = 0; i < 36; i++)
-		WRITE_BE_UINT32(_oprAttackDecay + (i << 2), _adtStat[i]);
-
-	delete[] _oprSinTbl;
-	_oprSinTbl = new uint32[1024];
-	for (int i = 0; i < 1024; i++) {
-		double val = sin((double) (((i << 1) + 1) * PI / 1024.0));
-		double d_dcb = log(1.0 / (double)ABS(val)) / log(2.0) * 256.0;
-		int32 i_dcb = (int32)(2.0 * d_dcb);
-		i_dcb = (i_dcb & 1) ? (i_dcb >> 1) + 1 : (i_dcb >> 1);
-		_oprSinTbl[i] = (i_dcb << 1) + (val >= 0.0 ? 0 : 1);
-	}
-
-	delete[] _oprLevelOut;
-	_oprLevelOut = new int32[0x1a00];
-	for (int i = 0; i < 256; i++) {
-		double val = floor(65536.0 / pow(2.0, 0.00390625 * (double)(1 + i)));
-		int32 val_int = ((int32) val) >> 4;
-		_oprLevelOut[i << 1] = (val_int & 1) ? ((val_int >> 1) + 1) << 2 : (val_int >> 1) << 2;
-		_oprLevelOut[(i << 1) + 1] = -_oprLevelOut[i << 1];
-		for (int ii = 1; ii < 13; ii++) {
-			_oprLevelOut[(i << 1) + (ii << 9)] =  _oprLevelOut[i << 1] >> ii;
-			_oprLevelOut[(i << 1) + (ii << 9) + 1] = -_oprLevelOut[(i << 1) + (ii << 9)];
-		}
-	}
-
-	uint8 *dtt = new uint8[128];
-	memset(dtt, 0, 36);
-	memset(dtt + 36, 1, 8);
-	memcpy(dtt + 44, _detSrc, 84);
-
-	delete[] _oprDetune;
-	_oprDetune = new int32[256];
-	for (int i = 0; i < 128; i++) {
-		_oprDetune[i] = (int32)	((float)dtt[i] * _baserate * 64.0);
-		_oprDetune[i + 128] = -_oprDetune[i];
-	}
-
-	delete[] dtt;
-}
-
-void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) {
-	if (!_ready)
-		return;
-
-	for (int i = 0; i < _numChan; i++) {
-		TownsPC98_OpnOperator **o = _chanInternal[i].opr;
-
-		if (_chanInternal[i].updateEnvelopeParameters) {
-			_chanInternal[i].updateEnvelopeParameters = false;
-			for (int ii = 0; ii < 4 ; ii++)
-				o[ii]->updatePhaseIncrement();
-		}
-
-		for (uint32 ii = 0; ii < bufferSize ; ii++) {
-			int32 phbuf1, phbuf2, output;
-			phbuf1 = phbuf2 = output = 0;
-
-			int32 *leftSample = &buffer[ii * 2];
-			int32 *rightSample = &buffer[ii * 2 + 1];
-			int32 *del = &_chanInternal[i].feedbuf[2];
-			int32 *feed = _chanInternal[i].feedbuf;
-
-			switch (_chanInternal[i].algorithm) {
-			case 0:
-				o[0]->generateOutput(0, feed, phbuf1);
-				o[2]->generateOutput(*del, 0, phbuf2);
-				*del = 0;
-				o[1]->generateOutput(phbuf1, 0, *del);
-				o[3]->generateOutput(phbuf2, 0, output);
-				break;
-			case 1:
-				o[0]->generateOutput(0, feed, phbuf1);
-				o[2]->generateOutput(*del, 0, phbuf2);
-				o[1]->generateOutput(0, 0, phbuf1);
-				o[3]->generateOutput(phbuf2, 0, output);
-				*del = phbuf1;
-				break;
-			case 2:
-				o[0]->generateOutput(0, feed, phbuf2);
-				o[2]->generateOutput(*del, 0, phbuf2);
-				o[1]->generateOutput(0, 0, phbuf1);
-				o[3]->generateOutput(phbuf2, 0, output);
-				*del = phbuf1;
-				break;
-			case 3:
-				o[0]->generateOutput(0, feed, phbuf2);
-				o[2]->generateOutput(0, 0, *del);
-				o[1]->generateOutput(phbuf2, 0, phbuf1);
-				o[3]->generateOutput(*del, 0, output);
-				*del = phbuf1;
-				break;
-			case 4:
-				o[0]->generateOutput(0, feed, phbuf1);
-				o[2]->generateOutput(0, 0, phbuf2);
-				o[1]->generateOutput(phbuf1, 0, output);
-				o[3]->generateOutput(phbuf2, 0, output);
-				*del = 0;
-				break;
-			case 5:
-				o[0]->generateOutput(0, feed, phbuf1);
-				o[2]->generateOutput(*del, 0, output);
-				o[1]->generateOutput(phbuf1, 0, output);
-				o[3]->generateOutput(phbuf1, 0, output);
-				*del = phbuf1;
-				break;
-			case 6:
-				o[0]->generateOutput(0, feed, phbuf1);
-				o[2]->generateOutput(0, 0, output);
-				o[1]->generateOutput(phbuf1, 0, output);
-				o[3]->generateOutput(0, 0, output);
-				*del = 0;
-				break;
-			case 7:
-				o[0]->generateOutput(0, feed, output);
-				o[2]->generateOutput(0, 0, output);
-				o[1]->generateOutput(0, 0, output);
-				o[3]->generateOutput(0, 0, output);
-				*del = 0;
-				break;
-			};
-
-			int32 finOut = (output << 2) / ((_numChan + _numSSG - 3) / 3);
-
-			if ((1 << i) & _volMaskA)
-				finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
-
-			if ((1 << i) & _volMaskB)
-				finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
-
-			if (_chanInternal[i].enableLeft)
-				*leftSample += finOut;
-
-			if (_chanInternal[i].enableRight)
-				*rightSample += finOut;
-		}
-	}
-}
-
-TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : TownsPC98_OpnCore(mixer, type),
-	_channels(0), _ssgChannels(0), _sfxChannels(0), _rhythmChannel(0),
-	_trackPtr(0), _sfxData(0), _sfxOffs(0), _ssgPatches(0),
-	_patches(0), _sfxBuffer(0), _musicBuffer(0),
-
-	_opnCarrier(_drvTables + 76), _opnFreqTable(_drvTables + 108), _opnFreqTableSSG(_drvTables + 132),
-	_opnFxCmdLen(_drvTables + 36), _opnLvlPresets(_drvTables + (type == OD_TOWNS ? 52 : 84)),
-
-	_updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0),
-	_updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0),
-	_updateRhythmFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedRhythmFlag(0),
-	_updateSfxFlag(0), _finishedSfxFlag(0),
-
-	_musicTickCounter(0),
-
-	_musicVolume(255), _sfxVolume(255),
-
-	_musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) {
-
-	_sfxOffsets[0] = _sfxOffsets[1] = 0;
-}
-
-TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
-	reset();
-
-	if (_channels) {
-		for (int i = 0; i < _numChan; i++)
-			delete _channels[i];
-		delete[] _channels;
-	}
-
-	if (_ssgChannels) {
-		for (int i = 0; i < _numSSG; i++)
-			delete _ssgChannels[i];
-		delete[] _ssgChannels;
-	}
-
-	if (_sfxChannels) {
-		for (int i = 0; i < 2; i++)
-			delete _sfxChannels[i];
-		delete[] _sfxChannels;
-	}
-
-	delete _rhythmChannel;
-
-	delete[] _ssgPatches;
-}
-
-bool TownsPC98_OpnDriver::init() {
-	if (_ready) {
-		reset();
-		return true;
-	}
-
-	TownsPC98_OpnCore::init();
-
-	setVolumeChannelMasks(-1, 0);
-
-	_channels = new TownsPC98_OpnChannel *[_numChan];
-	for (int i = 0; i < _numChan; i++) {
-		int ii = i * 6;
-		_channels[i] = new TownsPC98_OpnChannel(this, _drvTables[ii], _drvTables[ii + 1],
-			_drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
-		_channels[i]->init();
-	}
-
-	if (_numSSG) {
-		_ssgPatches = new uint8[256];
-		memcpy(_ssgPatches, _drvTables + 156, 256);
-
-		_ssgChannels = new TownsPC98_OpnChannelSSG *[_numSSG];
-		for (int i = 0; i < _numSSG; i++) {
-			int ii = i * 6;
-			_ssgChannels[i] = new TownsPC98_OpnChannelSSG(this, _drvTables[ii], _drvTables[ii + 1],
-				_drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
-			_ssgChannels[i]->init();
-		}
-
-		_sfxChannels = new TownsPC98_OpnSfxChannel *[2];
-		for (int i = 0; i < 2; i++) {
-			int ii = (i + 1) * 6;
-			_sfxChannels[i] = new TownsPC98_OpnSfxChannel(this, _drvTables[ii], _drvTables[ii + 1],
-				_drvTables[ii + 2], _drvTables[ii + 3], _drvTables[ii + 4], _drvTables[ii + 5]);
-			_sfxChannels[i]->init();
-		}
-	}
-
-	if (_hasPercussion) {
-		_rhythmChannel = new TownsPC98_OpnChannelPCM(this, 0, 0, 0, 0, 0, 1);
-		_rhythmChannel->init();
-	}
-
-	setMusicTempo(84);
-	setSfxTempo(654);
-
-	_ready = true;
-
-	return true;
-}
-
-void TownsPC98_OpnDriver::loadMusicData(uint8 *data, bool loadPaused) {
-	if (!_ready) {
-		warning("TownsPC98_OpnDriver: Driver must be initialized before loading data");
-		return;
-	}
-
-	if (!data) {
-		warning("TownsPC98_OpnDriver: Invalid music file data");
-		return;
-	}
-
-	reset();
-
-	Common::StackLock lock(_mutex);
-	uint8 *src_a = _trackPtr = _musicBuffer = data;
-
-	for (uint8 i = 0; i < 3; i++) {
-		_channels[i]->loadData(data + READ_LE_UINT16(src_a));
-		src_a += 2;
-	}
-
-	for (int i = 0; i < _numSSG; i++) {
-		_ssgChannels[i]->loadData(data + READ_LE_UINT16(src_a));
-		src_a += 2;
-	}
-
-	for (uint8 i = 3; i < _numChan; i++) {
-		_channels[i]->loadData(data + READ_LE_UINT16(src_a));
-		src_a += 2;
-	}
-
-	if (_hasPercussion) {
-		_rhythmChannel->loadData(data + READ_LE_UINT16(src_a));
-		src_a += 2;
-	}
-
-	toggleRegProtection(false);
-
-	_patches = src_a + 4;
-	_finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0;
-
-	_musicPlaying = (loadPaused ? false : true);
-}
-
-void TownsPC98_OpnDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
-	if (!_ready) {
-		warning("TownsPC98_OpnDriver: Driver must be initialized before loading data");
-		return;
-	}
-
-	if (!_sfxChannels) {
-		warning("TownsPC98_OpnDriver: Sound effects not supported by this configuration");
-		return;
-	}
-
-	if (!data) {
-		warning("TownsPC98_OpnDriver: Invalid sound effects file data");
-		return;
-	}
-
-	Common::StackLock lock(_mutex);
-	_sfxData = _sfxBuffer = data;
-	_sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);
-	_sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);
-	_sfxPlaying = true;
-	_finishedSfxFlag = 0;
-}
-
-void TownsPC98_OpnDriver::reset() {
-	Common::StackLock lock(_mutex);
-
-	_musicPlaying = false;
-	_sfxPlaying = false;
-	_fading = false;
-	_looping = 0;
-	_musicTickCounter = 0;
-	_sfxData = 0;
-
-	TownsPC98_OpnCore::reset();
-
-	for (int i = 0; i < _numChan; i++)
-		_channels[i]->reset();
-	for (int i = 0; i < _numSSG; i++)
-		_ssgChannels[i]->reset();
-
-	if (_numSSG) {
-		for (int i = 0; i < 2; i++)
-			_sfxChannels[i]->reset();
-
-		memcpy(_ssgPatches, _drvTables + 156, 256);
-	}
-
-	if (_rhythmChannel)
-		_rhythmChannel->reset();
-}
-
-void TownsPC98_OpnDriver::fadeStep() {
-	if (!_musicPlaying)
-		return;
-
-	Common::StackLock lock(_mutex);
-	for (int j = 0; j < _numChan; j++) {
-		if (_updateChannelsFlag & _channels[j]->_idFlag)
-			_channels[j]->fadeStep();
-	}
-
-	for (int j = 0; j < _numSSG; j++) {
-		if (_updateSSGFlag & _ssgChannels[j]->_idFlag)
-			_ssgChannels[j]->fadeStep();
-	}
-
-	if (!_fading) {
-		_fading = 19;
-		if (_hasPercussion) {
-			if (_updateRhythmFlag & _rhythmChannel->_idFlag)
-				_rhythmChannel->reset();
-		}
-	} else {
-		if (!--_fading)
-			reset();
-	}
-}
-
-void TownsPC98_OpnDriver::timerCallbackB() {
-	_sfxOffs = 0;
-
-	if (_musicPlaying) {
-		_musicTickCounter++;
-
-		for (int i = 0; i < _numChan; i++) {
-			if (_updateChannelsFlag & _channels[i]->_idFlag) {
-				_channels[i]->processEvents();
-				_channels[i]->processFrequency();
-			}
-		}
-
-		for (int i = 0; i < _numSSG; i++) {
-			if (_updateSSGFlag & _ssgChannels[i]->_idFlag) {
-				_ssgChannels[i]->processEvents();
-				_ssgChannels[i]->processFrequency();
-			}
-		}
-
-		if (_hasPercussion)
-			if (_updateRhythmFlag & _rhythmChannel->_idFlag)
-				_rhythmChannel->processEvents();
-	}
-
-	toggleRegProtection(false);
-
-	if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag)
-		_musicPlaying = false;
-}
-
-void TownsPC98_OpnDriver::timerCallbackA() {
-	if (_sfxChannels && _sfxPlaying) {
-		if (_sfxData)
-			startSoundEffect();
-
-		_sfxOffs = 3;
-		_trackPtr = _sfxBuffer;
-
-		for (int i = 0; i < 2; i++) {
-			if (_updateSfxFlag & _sfxChannels[i]->_idFlag) {
-				_sfxChannels[i]->processEvents();
-				_sfxChannels[i]->processFrequency();
-			}
-		}
-
-		_trackPtr = _musicBuffer;
-	}
-
-	if (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) {
-		_sfxPlaying = false;
-		_updateSfxFlag = 0;
-		setVolumeChannelMasks(-1, 0);
-	}
-}
-
-void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) {
-	writeReg(0, 0x26, tempo);
-	writeReg(0, 0x27, 0x33);
-}
-
-void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) {
-	writeReg(0, 0x24, tempo & 0xff);
-	writeReg(0, 0x25, tempo >> 8);
-	writeReg(0, 0x27, 0x33);
-}
-
-void TownsPC98_OpnDriver::startSoundEffect() {
-	int volFlags = 0;
-
-	for (int i = 0; i < 2; i++) {
-		if (_sfxOffsets[i]) {
-			_ssgChannels[i + 1]->protect();
-			_sfxChannels[i]->reset();
-			_sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]);
-			_updateSfxFlag |= _sfxChannels[i]->_idFlag;
-			volFlags |= (_sfxChannels[i]->_idFlag << _numChan);
-		} else {
-			_ssgChannels[i + 1]->restore();
-			_updateSfxFlag &= ~_sfxChannels[i]->_idFlag;
-		}
-	}
-
-	setVolumeChannelMasks(~volFlags, volFlags);
-	_sfxData = 0;
-}
-
-const uint8 TownsPC98_OpnDriver::_drvTables[] = {
-	//	channel presets
-	0x00, 0x80, 0x00, 0x00, 0x00, 0x01,
-	0x01, 0x80, 0x01, 0x01, 0x00, 0x02,
-	0x02, 0x80, 0x02, 0x02, 0x00, 0x04,
-	0x00, 0x80, 0x03, 0x04, 0x01, 0x08,
-	0x01, 0x80, 0x04, 0x05, 0x01, 0x10,
-	0x02, 0x80, 0x05, 0x06, 0x01, 0x20,
-
-	//	control event size
-	0x01, 0x01, 0x01, 0x01,	0x01, 0x01, 0x04, 0x05,
-	0x02, 0x06, 0x02, 0x00, 0x00, 0x02, 0x00, 0x02,
-
-	//	fmt level presets
-	0x54, 0x50,	0x4C, 0x48,	0x44, 0x40, 0x3C, 0x38,
-	0x34, 0x30, 0x2C, 0x28, 0x24, 0x20, 0x1C, 0x18,
-	0x14, 0x10, 0x0C, 0x08,	0x04, 0x90, 0x90, 0x90,
-
-	//	carriers
-	0x08, 0x08, 0x08, 0x08,	0x0C, 0x0E, 0x0E, 0x0F,
-
-	//	pc98 level presets
-	0x40, 0x3B, 0x38, 0x34, 0x30, 0x2A, 0x28, 0x25,
-	0x22, 0x20, 0x1D, 0x1A, 0x18, 0x15, 0x12, 0x10,
-	0x0D, 0x0A, 0x08, 0x05, 0x02, 0x90, 0x90, 0x90,
-
-	//	frequencies
-	0x6A, 0x02, 0x8F, 0x02, 0xB6, 0x02, 0xDF, 0x02,
-	0x0B, 0x03, 0x39, 0x03, 0x6A, 0x03, 0x9E, 0x03,
-	0xD5, 0x03, 0x10, 0x04, 0x4E, 0x04, 0x8F, 0x04,
-
-	//	ssg frequencies
-	0xE8, 0x0E, 0x12, 0x0E, 0x48, 0x0D, 0x89, 0x0C,
-	0xD5, 0x0B, 0x2B, 0x0B, 0x8A, 0x0A, 0xF3, 0x09,
-	0x64, 0x09, 0xDD, 0x08, 0x5E, 0x08, 0xE6, 0x07,
-
-	// ssg patch data
-	0x00, 0x00, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0x37, 0x81, 0xC8, 0x00,
-	0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
-	0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
-	0x04, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xBE, 0x00,
-	0x0A, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0x01, 0x00,
-	0xFF, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,
-	0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x00,
-	0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x64, 0x01, 0xFF, 0x64, 0xFF, 0x81, 0xFF, 0x00,
-	0x01, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-
-	0x02, 0x01, 0xFF, 0x28, 0xFF, 0x81, 0xF0, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0x0A, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xC8, 0x00,
-	0x01, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0x78, 0x5F, 0x81, 0xA0, 0x00,
-	0x05, 0x81, 0x00, 0x00, 0x28, 0x81, 0x00, 0x00,
-	0x00, 0x01, 0xFF, 0xFF, 0x00, 0x81, 0x00, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0xFF, 0x81, 0x00, 0x00,

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list