shithub: choc

Download patch

ref: 36f721637c5e5ac85671eb438ab9e6831933138c
parent: 77a480fcbf908bd39192b64af00487b6831a2d7b
parent: e3954613bd4365cac43dd6f7b89ef73e82c56936
author: Simon Howard <[email protected]>
date: Sun Feb 28 08:27:56 EST 2016

Merge remote-tracking branch 'origin/master' into sdl2-branch

--- a/msvc/libopl.vcproj
+++ b/msvc/libopl.vcproj
@@ -159,10 +159,6 @@
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
 			<File
-				RelativePath="..\opl\dbopl.c"
-				>
-			</File>
-			<File
 				RelativePath="..\opl\ioperm_sys.c"
 				>
 			</File>
@@ -194,6 +190,10 @@
 				RelativePath="..\opl\opl_win32.c"
 				>
 			</File>
+			<File
+				RelativePath="..\opl\opl3.c"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Header Files"
@@ -222,6 +222,10 @@
 			</File>
 			<File
 				RelativePath="..\opl\opl_timer.h"
+				>
+			</File>
+			<File
+				RelativePath="..\opl\opl3.h"
 				>
 			</File>
 		</Filter>
--- a/opl/Makefile.am
+++ b/opl/Makefile.am
@@ -15,5 +15,5 @@
         opl_timer.c         opl_timer.h           \
         opl_win32.c                               \
         ioperm_sys.c        ioperm_sys.h          \
-        dbopl.c             dbopl.h
+        opl3.c              opl3.h
 
--- a/opl/dbopl.c
+++ /dev/null
@@ -1,1638 +1,0 @@
-/*
- *  Copyright (C) 2002-2010  The DOSBox Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- */
-
-//
-// Chocolate Doom-related discussion:
-//
-// This is the DosBox OPL emulator code (src/hardware/dbopl.cpp) r3635,
-// converted to C.  The bulk of the work was done using the minus-minus
-// script in the Chocolate Doom SVN repository, then the result tweaked
-// by hand until working.
-//
-
-
-/*
-	DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator.
-	Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2
-	Except for the table generation it's all integer math
-	Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms
-	The generation was based on the MAME implementation but tried to have it use less memory and be faster in general
-	MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times
-
-	//TODO Don't delay first operator 1 sample in opl3 mode
-	//TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter
-	//TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though?
-	//TODO Check if having the same accuracy in all frequency multipliers sounds better or not
-
-	//DUNNO Keyon in 4op, switch to 2op without keyoff.
-*/
-
-/* $Id: dbopl.cpp,v 1.10 2009-06-10 19:54:51 harekiet Exp $ */
-
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-//#include "dosbox.h"
-#include "dbopl.h"
-
-
-#define GCC_UNLIKELY(x) x
-
-#define TRUE 1
-#define FALSE 0
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-#define OPLRATE		((double)(14318180.0 / 288.0))
-#define TREMOLO_TABLE 52
-
-//Try to use most precision for frequencies
-//Else try to keep different waves in synch
-//#define WAVE_PRECISION	1
-#ifndef WAVE_PRECISION
-//Wave bits available in the top of the 32bit range
-//Original adlib uses 10.10, we use 10.22
-#define WAVE_BITS	10
-#else
-//Need some extra bits at the top to have room for octaves and frequency multiplier
-//We support to 8 times lower rate
-//128 * 15 * 8 = 15350, 2^13.9, so need 14 bits
-#define WAVE_BITS	14
-#endif
-#define WAVE_SH		( 32 - WAVE_BITS )
-#define WAVE_MASK	( ( 1 << WAVE_SH ) - 1 )
-
-//Use the same accuracy as the waves
-#define LFO_SH ( WAVE_SH - 10 )
-//LFO is controlled by our tremolo 256 sample limit
-#define LFO_MAX ( 256 << ( LFO_SH ) )
-
-
-//Maximum amount of attenuation bits
-//Envelope goes to 511, 9 bits
-#if (DBOPL_WAVE == WAVE_TABLEMUL )
-//Uses the value directly
-#define ENV_BITS	( 9 )
-#else
-//Add 3 bits here for more accuracy and would have to be shifted up either way
-#define ENV_BITS	( 9 )
-#endif
-//Limits of the envelope with those bits and when the envelope goes silent
-#define ENV_MIN		0
-#define ENV_EXTRA	( ENV_BITS - 9 )
-#define ENV_MAX		( 511 << ENV_EXTRA )
-#define ENV_LIMIT	( ( 12 * 256) >> ( 3 - ENV_EXTRA ) )
-#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT )
-
-//Attack/decay/release rate counter shift
-#define RATE_SH		24
-#define RATE_MASK	( ( 1 << RATE_SH ) - 1 )
-//Has to fit within 16bit lookuptable
-#define MUL_SH		16
-
-//Check some ranges
-#if ENV_EXTRA > 3
-#error Too many envelope bits
-#endif
-
-static inline void Operator__SetState(Operator *self, Bit8u s );
-static inline Bit32u Chip__ForwardNoise(Chip *self);
-
-// C++'s template<> sure is useful sometimes.
-
-static Channel* Channel__BlockTemplate(Channel *self, Chip* chip,
-                                Bit32u samples, Bit32s* output,
-                                SynthMode mode );
-#define BLOCK_TEMPLATE(mode) \
-    static Channel* Channel__BlockTemplate_ ## mode(Channel *self, Chip* chip, \
-                                             Bit32u samples, Bit32s* output) \
-    { \
-       return Channel__BlockTemplate(self, chip, samples, output, mode); \
-    }
-
-BLOCK_TEMPLATE(sm2AM)
-BLOCK_TEMPLATE(sm2FM)
-BLOCK_TEMPLATE(sm3AM)
-BLOCK_TEMPLATE(sm3FM)
-BLOCK_TEMPLATE(sm3FMFM)
-BLOCK_TEMPLATE(sm3AMFM)
-BLOCK_TEMPLATE(sm3FMAM)
-BLOCK_TEMPLATE(sm3AMAM)
-BLOCK_TEMPLATE(sm2Percussion)
-BLOCK_TEMPLATE(sm3Percussion)
-
-//How much to substract from the base value for the final attenuation
-static const Bit8u KslCreateTable[16] = {
-	//0 will always be be lower than 7 * 8
-	64, 32, 24, 19, 
-	16, 12, 11, 10, 
-	 8,  6,  5,  4,
-	 3,  2,  1,  0,
-};
-
-#define M(_X_) ((Bit8u)( (_X_) * 2))
-static const Bit8u FreqCreateTable[16] = {
-	M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ),
-	M(8  ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15)
-};
-#undef M
-
-//We're not including the highest attack rate, that gets a special value
-static const Bit8u AttackSamplesTable[13] = {
-	69, 55, 46, 40,
-	35, 29, 23, 20,
-	19, 15, 11, 10,
-	9
-};
-//On a real opl these values take 8 samples to reach and are based upon larger tables
-static const Bit8u EnvelopeIncreaseTable[13] = {
-	4,  5,  6,  7,
-	8, 10, 12, 14,
-	16, 20, 24, 28,
-	32, 
-};
-
-#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
-static Bit16u ExpTable[ 256 ];
-#endif
-
-#if ( DBOPL_WAVE == WAVE_HANDLER )
-//PI table used by WAVEHANDLER
-static Bit16u SinTable[ 512 ];
-#endif
-
-#if ( DBOPL_WAVE > WAVE_HANDLER )
-//Layout of the waveform table in 512 entry intervals
-//With overlapping waves we reduce the table to half it's size
-
-//	|    |//\\|____|WAV7|//__|/\  |____|/\/\|
-//	|\\//|    |    |WAV7|    |  \/|    |    |
-//	|06  |0126|17  |7   |3   |4   |4 5 |5   |
-
-//6 is just 0 shifted and masked
-
-static Bit16s WaveTable[ 8 * 512 ];
-//Distance into WaveTable the wave starts
-static const Bit16u WaveBaseTable[8] = {
-	0x000, 0x200, 0x200, 0x800,
-	0xa00, 0xc00, 0x100, 0x400,
-
-};
-//Mask the counter with this
-static const Bit16u WaveMaskTable[8] = {
-	1023, 1023, 511, 511,
-	1023, 1023, 512, 1023,
-};
-
-//Where to start the counter on at keyon
-static const Bit16u WaveStartTable[8] = {
-	512, 0, 0, 0,
-	0, 512, 512, 256,
-};
-#endif
-
-#if ( DBOPL_WAVE == WAVE_TABLEMUL )
-static Bit16u MulTable[ 384 ];
-#endif
-
-static Bit8u KslTable[ 8 * 16 ];
-static Bit8u TremoloTable[ TREMOLO_TABLE ];
-//Start of a channel behind the chip struct start
-static Bit16u ChanOffsetTable[32];
-//Start of an operator behind the chip struct start
-static Bit16u OpOffsetTable[64];
-
-//The lower bits are the shift of the operator vibrato value
-//The highest bit is right shifted to generate -1 or 0 for negation
-//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0
-static const Bit8s VibratoTable[ 8 ] = {	
-	1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00, 
-	1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80 
-};
-
-//Shift strength for the ksl value determined by ksl strength
-static const Bit8u KslShiftTable[4] = {
-	31,1,2,0
-};
-
-//Generate a table index and table shift value using input value from a selected rate
-static void EnvelopeSelect( Bit8u val, Bit8u *index, Bit8u *shift ) {
-	if ( val < 13 * 4 ) {				//Rate 0 - 12
-		*shift = 12 - ( val >> 2 );
-		*index = val & 3;
-	} else if ( val < 15 * 4 ) {		//rate 13 - 14
-		*shift = 0;
-		*index = val - 12 * 4;
-	} else {							//rate 15 and up
-		*shift = 0;
-		*index = 12;
-	}
-}
-
-#if ( DBOPL_WAVE == WAVE_HANDLER )
-/*
-	Generate the different waveforms out of the sine/exponetial table using handlers
-*/
-static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
-	Bitu total = wave + volume;
-	Bitu index = total & 0xff;
-	Bitu sig = ExpTable[ index ];
-	Bitu exp = total >> 8;
-#if 0
-	//Check if we overflow the 31 shift limit
-	if ( exp >= 32 ) {
-		LOG_MSG( "WTF %d %d", total, exp );
-	}
-#endif
-	return (sig >> exp);
-};
-
-static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
-	Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
-	Bitu wave = SinTable[i & 511];
-	return (MakeVolume( wave, volume ) ^ neg) - neg;
-}
-static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) {
-	Bit32u wave = SinTable[i & 511];
-	wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
-	return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) {
-	Bitu wave = SinTable[i & 511];
-	return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) {
-	Bitu wave = SinTable[i & 255];
-	wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 );
-	return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) {
-	//Twice as fast
-	i <<= 1;
-	Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
-	Bitu wave = SinTable[i & 511];
-	wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
-	return (MakeVolume( wave, volume ) ^ neg) - neg;
-}
-static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) {
-	//Twice as fast
-	i <<= 1;
-	Bitu wave = SinTable[i & 511];
-	wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
-	return MakeVolume( wave, volume );
-}
-static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) {
-	Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
-	return (MakeVolume( 0, volume ) ^ neg) - neg;
-}
-static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) {
-	//Negative is reversed here
-	Bits neg = (( i >> 9) & 1) - 1;
-	Bitu wave = (i << 3);
-	//When negative the volume also runs backwards
-	wave = ((wave ^ neg) - neg) & 4095;
-	return (MakeVolume( wave, volume ) ^ neg) - neg;
-}
-
-static const WaveHandler WaveHandlerTable[8] = {
-	WaveForm0, WaveForm1, WaveForm2, WaveForm3,
-	WaveForm4, WaveForm5, WaveForm6, WaveForm7
-};
-
-#endif
-
-/*
-	Operator
-*/
-
-//We zero out when rate == 0
-static inline void Operator__UpdateAttack(Operator *self, const Chip* chip ) {
-	Bit8u rate = self->reg60 >> 4;
-	if ( rate ) {
-		Bit8u val = (rate << 2) + self->ksr;
-		self->attackAdd = chip->attackRates[ val ];
-		self->rateZero &= ~(1 << ATTACK);
-	} else {
-		self->attackAdd = 0;
-		self->rateZero |= (1 << ATTACK);
-	}
-}
-static inline void Operator__UpdateDecay(Operator *self, const Chip* chip ) {
-	Bit8u rate = self->reg60 & 0xf;
-	if ( rate ) {
-		Bit8u val = (rate << 2) + self->ksr;
-		self->decayAdd = chip->linearRates[ val ];
-		self->rateZero &= ~(1 << DECAY);
-	} else {
-		self->decayAdd = 0;
-		self->rateZero |= (1 << DECAY);
-	}
-}
-static inline void Operator__UpdateRelease(Operator *self, const Chip* chip ) {
-	Bit8u rate = self->reg80 & 0xf;
-	if ( rate ) {
-		Bit8u val = (rate << 2) + self->ksr;
-		self->releaseAdd = chip->linearRates[ val ];
-		self->rateZero &= ~(1 << RELEASE);
-		if ( !(self->reg20 & MASK_SUSTAIN ) ) {
-			self->rateZero &= ~( 1 << SUSTAIN );
-		}	
-	} else {
-		self->rateZero |= (1 << RELEASE);
-		self->releaseAdd = 0;
-		if ( !(self->reg20 & MASK_SUSTAIN ) ) {
-			self->rateZero |= ( 1 << SUSTAIN );
-		}	
-	}
-}
-
-static inline void Operator__UpdateAttenuation(Operator *self) {
-	Bit8u kslBase = (Bit8u)((self->chanData >> SHIFT_KSLBASE) & 0xff);
-	Bit32u tl = self->reg40 & 0x3f;
-	Bit8u kslShift = KslShiftTable[ self->reg40 >> 6 ];
-	//Make sure the attenuation goes to the right bits
-	self->totalLevel = tl << ( ENV_BITS - 7 );	//Total level goes 2 bits below max
-	self->totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift;
-}
-
-static void Operator__UpdateFrequency(Operator *self) {
-	Bit32u freq = self->chanData & (( 1 << 10 ) - 1);
-	Bit32u block = (self->chanData >> 10) & 0xff;
-#ifdef WAVE_PRECISION
-	block = 7 - block;
-	self->waveAdd = ( freq * self->freqMul ) >> block;
-#else
-	self->waveAdd = ( freq << block ) * self->freqMul;
-#endif
-	if ( self->reg20 & MASK_VIBRATO ) {
-		self->vibStrength = (Bit8u)(freq >> 7);
-
-#ifdef WAVE_PRECISION
-		self->vibrato = ( self->vibStrength * self->freqMul ) >> block;
-#else
-		self->vibrato = ( self->vibStrength << block ) * self->freqMul;
-#endif
-	} else {
-		self->vibStrength = 0;
-		self->vibrato = 0;
-	}
-}
-
-static void Operator__UpdateRates(Operator *self, const Chip* chip ) {
-	//Mame seems to reverse this where enabling ksr actually lowers
-	//the rate, but pdf manuals says otherwise?
-	Bit8u newKsr = (Bit8u)((self->chanData >> SHIFT_KEYCODE) & 0xff);
-	if ( !( self->reg20 & MASK_KSR ) ) {
-		newKsr >>= 2;
-	}
-	if ( self->ksr == newKsr )
-		return;
-	self->ksr = newKsr;
-	Operator__UpdateAttack( self, chip );
-	Operator__UpdateDecay( self, chip );
-	Operator__UpdateRelease( self, chip );
-}
-
-static inline Bit32s Operator__RateForward(Operator *self, Bit32u add ) {
-	Bit32s ret; // haleyjd: GNUisms out!
-	self->rateIndex += add;
-	ret = self->rateIndex >> RATE_SH;
-	self->rateIndex = self->rateIndex & RATE_MASK;
-	return ret;
-}
-
-static Bits Operator__TemplateVolume(Operator *self, OperatorState yes) {
-	Bit32s vol = self->volume;
-	Bit32s change;
-	switch ( yes ) {
-	case OFF:
-		return ENV_MAX;
-	case ATTACK:
-		change = Operator__RateForward( self, self->attackAdd );
-		if ( !change )
-			return vol;
-		vol += ( (~vol) * change ) >> 3;
-		if ( vol < ENV_MIN ) {
-			self->volume = ENV_MIN;
-			self->rateIndex = 0;
-			Operator__SetState( self, DECAY );
-			return ENV_MIN;
-		}
-		break;
-	case DECAY:
-		vol += Operator__RateForward( self, self->decayAdd );
-		if ( GCC_UNLIKELY(vol >= self->sustainLevel) ) {
-			//Check if we didn't overshoot max attenuation, then just go off
-			if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
-				self->volume = ENV_MAX;
-				Operator__SetState( self, OFF );
-				return ENV_MAX;
-			}
-			//Continue as sustain
-			self->rateIndex = 0;
-			Operator__SetState( self, SUSTAIN );
-		}
-		break;
-	case SUSTAIN:
-		if ( self->reg20 & MASK_SUSTAIN ) {
-			return vol;
-		}
-		//In sustain phase, but not sustaining, do regular release
-	case RELEASE: 
-		vol += Operator__RateForward( self, self->releaseAdd );;
-		if ( GCC_UNLIKELY(vol >= ENV_MAX) ) {
-			self->volume = ENV_MAX;
-			Operator__SetState( self, OFF );
-			return ENV_MAX;
-		}
-		break;
-	}
-	self->volume = vol;
-	return vol;
-}
-
-#define TEMPLATE_VOLUME(mode) \
-    static Bits Operator__TemplateVolume ## mode(Operator *self) \
-    { \
-        return Operator__TemplateVolume(self, mode); \
-    }
-
-TEMPLATE_VOLUME(OFF)
-TEMPLATE_VOLUME(RELEASE)
-TEMPLATE_VOLUME(SUSTAIN)
-TEMPLATE_VOLUME(ATTACK)
-TEMPLATE_VOLUME(DECAY)
-
-static const VolumeHandler VolumeHandlerTable[5] = {
-        &Operator__TemplateVolumeOFF,
-        &Operator__TemplateVolumeRELEASE,
-        &Operator__TemplateVolumeSUSTAIN,
-        &Operator__TemplateVolumeDECAY,
-        &Operator__TemplateVolumeATTACK,
-};
-
-static inline Bitu Operator__ForwardVolume(Operator *self) {
-	return self->currentLevel + (self->volHandler)(self);
-}
-
-
-static inline Bitu Operator__ForwardWave(Operator *self) {
-	self->waveIndex += self->waveCurrent;	
-	return self->waveIndex >> WAVE_SH;
-}
-
-static void Operator__Write20(Operator *self, const Chip* chip, Bit8u val ) {
-	Bit8u change = (self->reg20 ^ val );
-	if ( !change ) 
-		return;
-	self->reg20 = val;
-	//Shift the tremolo bit over the entire register, saved a branch, YES!
-	self->tremoloMask = (Bit8s)(val) >> 7;
-	self->tremoloMask &= ~(( 1 << ENV_EXTRA ) -1);
-	//Update specific features based on changes
-	if ( change & MASK_KSR ) {
-		Operator__UpdateRates( self, chip );
-	}
-	//With sustain enable the volume doesn't change
-	if ( self->reg20 & MASK_SUSTAIN || ( !self->releaseAdd ) ) {
-		self->rateZero |= ( 1 << SUSTAIN );
-	} else {
-		self->rateZero &= ~( 1 << SUSTAIN );
-	}
-	//Frequency multiplier or vibrato changed
-	if ( change & (0xf | MASK_VIBRATO) ) {
-		self->freqMul = chip->freqMul[ val & 0xf ];
-		Operator__UpdateFrequency(self);
-	}
-}
-
-static void Operator__Write40(Operator *self, const Chip *chip, Bit8u val ) {
-	if (!(self->reg40 ^ val )) 
-		return;
-	self->reg40 = val;
-	Operator__UpdateAttenuation( self );
-}
-
-static void Operator__Write60(Operator *self, const Chip* chip, Bit8u val ) {
-	Bit8u change = self->reg60 ^ val;
-	self->reg60 = val;
-	if ( change & 0x0f ) {
-		Operator__UpdateDecay( self, chip );
-	}
-	if ( change & 0xf0 ) {
-		Operator__UpdateAttack( self, chip );
-	}
-}
-
-static void Operator__Write80(Operator *self, const Chip* chip, Bit8u val ) {
-	Bit8u change = (self->reg80 ^ val );
-	Bit8u sustain; // haleyjd 09/09/10: GNUisms out!
-	if ( !change ) 
-		return;
-	self->reg80 = val;
-	sustain = val >> 4;
-	//Turn 0xf into 0x1f
-	sustain |= ( sustain + 1) & 0x10;
-	self->sustainLevel = sustain << ( ENV_BITS - 5 );
-	if ( change & 0x0f ) {
-		Operator__UpdateRelease( self, chip );
-	}
-}
-
-static void Operator__WriteE0(Operator *self, const Chip* chip, Bit8u val ) {
-	Bit8u waveForm; // haleyjd 09/09/10: GNUisms out!
-	if ( !(self->regE0 ^ val) ) 
-		return;
-	//in opl3 mode you can always selet 7 waveforms regardless of waveformselect
-	waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
-	self->regE0 = val;
-#if( DBOPL_WAVE == WAVE_HANDLER )
-	self->waveHandler = WaveHandlerTable[ waveForm ];
-#else
-	self->waveBase = WaveTable + WaveBaseTable[ waveForm ];
-	self->waveStart = WaveStartTable[ waveForm ] << WAVE_SH;
-	self->waveMask = WaveMaskTable[ waveForm ];
-#endif
-}
-
-static inline void Operator__SetState(Operator *self, Bit8u s ) {
-	self->state = s;
-	self->volHandler = VolumeHandlerTable[ s ];
-}
-
-static inline int Operator__Silent(Operator *self) {
-	if ( !ENV_SILENT( self->totalLevel + self->volume ) )
-		return FALSE;
-	if ( !(self->rateZero & ( 1 << self->state ) ) )
-		return FALSE;
-	return TRUE;
-}
-
-static inline void Operator__Prepare(Operator *self, const Chip* chip )  {
-	self->currentLevel = self->totalLevel + (chip->tremoloValue & self->tremoloMask);
-	self->waveCurrent = self->waveAdd;
-	if ( self->vibStrength >> chip->vibratoShift ) {
-		Bit32s add = self->vibrato >> chip->vibratoShift;
-		//Sign extend over the shift value
-		Bit32s neg = chip->vibratoSign;
-		//Negate the add with -1 or 0
-		add = ( add ^ neg ) - neg; 
-		self->waveCurrent += add;
-	}
-}
-
-static void Operator__KeyOn(Operator *self, Bit8u mask ) {
-	if ( !self->keyOn ) {
-		//Restart the frequency generator
-#if( DBOPL_WAVE > WAVE_HANDLER )
-		self->waveIndex = self->waveStart;
-#else
-		self->waveIndex = 0;
-#endif
-		self->rateIndex = 0;
-		Operator__SetState( self, ATTACK );
-	}
-	self->keyOn |= mask;
-}
-
-static void Operator__KeyOff(Operator *self, Bit8u mask ) {
-	self->keyOn &= ~mask;
-	if ( !self->keyOn ) {
-		if ( self->state != OFF ) {
-			Operator__SetState( self, RELEASE );
-		}
-	}
-}
-
-static inline Bits Operator__GetWave(Operator *self, Bitu index, Bitu vol ) {
-#if( DBOPL_WAVE == WAVE_HANDLER )
-	return self->waveHandler( index, vol << ( 3 - ENV_EXTRA ) );
-#elif( DBOPL_WAVE == WAVE_TABLEMUL )
-	return(self->waveBase[ index & self->waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
-#elif( DBOPL_WAVE == WAVE_TABLELOG )
-	Bit32s wave = self->waveBase[ index & self->waveMask ];
-	Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA );
-	Bit32s sig = ExpTable[ total & 0xff ];
-	Bit32u exp = total >> 8;
-	Bit32s neg = wave >> 16;
-	return((sig ^ neg) - neg) >> exp;
-#else
-#error "No valid wave routine"
-#endif
-}
-
-static inline Bits Operator__GetSample(Operator *self, Bits modulation ) {
-	Bitu vol = Operator__ForwardVolume(self);
-	if ( ENV_SILENT( vol ) ) {
-		//Simply forward the wave
-		self->waveIndex += self->waveCurrent;
-		return 0;
-	} else {
-		Bitu index = Operator__ForwardWave(self);
-		index += modulation;
-		return Operator__GetWave( self, index, vol );
-	}
-}
-
-static void Operator__Operator(Operator *self) {
-	self->chanData = 0;
-	self->freqMul = 0;
-	self->waveIndex = 0;
-	self->waveAdd = 0;
-	self->waveCurrent = 0;
-	self->keyOn = 0;
-	self->ksr = 0;
-	self->reg20 = 0;
-	self->reg40 = 0;
-	self->reg60 = 0;
-	self->reg80 = 0;
-	self->regE0 = 0;
-	Operator__SetState( self, OFF );
-	self->rateZero = (1 << OFF);
-	self->sustainLevel = ENV_MAX;
-	self->currentLevel = ENV_MAX;
-	self->totalLevel = ENV_MAX;
-	self->volume = ENV_MAX;
-	self->releaseAdd = 0;
-}
-
-/*
-	Channel
-*/
-
-static void Channel__Channel(Channel *self) {
-        Operator__Operator(&self->op[0]);
-        Operator__Operator(&self->op[1]);
-	self->old[0] = self->old[1] = 0;
-	self->chanData = 0;
-	self->regB0 = 0;
-	self->regC0 = 0;
-	self->maskLeft = -1;
-	self->maskRight = -1;
-	self->feedback = 31;
-	self->fourMask = 0;
-	self->synthHandler = Channel__BlockTemplate_sm2FM;
-};
-
-static inline Operator* Channel__Op( Channel *self, Bitu index ) {
-        return &( ( self + (index >> 1) )->op[ index & 1 ]);
-}
-
-static void Channel__SetChanData(Channel *self, const Chip* chip, Bit32u data ) {
-	Bit32u change = self->chanData ^ data;
-	self->chanData = data;
-	Channel__Op( self, 0 )->chanData = data;
-	Channel__Op( self, 1 )->chanData = data;
-	//Since a frequency update triggered this, always update frequency
-        Operator__UpdateFrequency(Channel__Op( self, 0 ));
-        Operator__UpdateFrequency(Channel__Op( self, 1 ));
-	if ( change & ( 0xff << SHIFT_KSLBASE ) ) {
-                Operator__UpdateAttenuation(Channel__Op( self, 0 ));
-                Operator__UpdateAttenuation(Channel__Op( self, 1 ));
-	}
-	if ( change & ( 0xff << SHIFT_KEYCODE ) ) {
-                Operator__UpdateRates(Channel__Op( self, 0 ), chip);
-                Operator__UpdateRates(Channel__Op( self, 1 ), chip);
-	}
-}
-
-static void Channel__UpdateFrequency(Channel *self, const Chip* chip, Bit8u fourOp ) {
-	//Extrace the frequency bits
-	Bit32u data = self->chanData & 0xffff;
-	Bit32u kslBase = KslTable[ data >> 6 ];
-	Bit32u keyCode = ( data & 0x1c00) >> 9;
-	if ( chip->reg08 & 0x40 ) {
-		keyCode |= ( data & 0x100)>>8;	/* notesel == 1 */
-	} else {
-		keyCode |= ( data & 0x200)>>9;	/* notesel == 0 */
-	}
-	//Add the keycode and ksl into the highest bits of chanData
-	data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE );
-        Channel__SetChanData( self + 0, chip, data );
-	if ( fourOp & 0x3f ) {
-                Channel__SetChanData( self + 1, chip, data );
-	}
-}
-
-static void Channel__WriteA0(Channel *self, const Chip* chip, Bit8u val ) {
-	Bit8u fourOp = chip->reg104 & chip->opl3Active & self->fourMask;
-	Bit32u change; // haleyjd 09/09/10: GNUisms out!
-	//Don't handle writes to silent fourop channels
-	if ( fourOp > 0x80 )
-		return;
-	change = (self->chanData ^ val ) & 0xff;
-	if ( change ) {
-		self->chanData ^= change;
-		Channel__UpdateFrequency( self, chip, fourOp );
-	}
-}
-
-static void Channel__WriteB0(Channel *self, const Chip* chip, Bit8u val ) {
-	Bit8u fourOp = chip->reg104 & chip->opl3Active & self->fourMask;
-	Bitu change; // haleyjd 09/09/10: GNUisms out!
-	//Don't handle writes to silent fourop channels
-	if ( fourOp > 0x80 )
-		return;
-	change = (self->chanData ^ ( val << 8 ) ) & 0x1f00;
-	if ( change ) {
-		self->chanData ^= change;
-		Channel__UpdateFrequency( self, chip, fourOp );
-	}
-	//Check for a change in the keyon/off state
-	if ( !(( val ^ self->regB0) & 0x20))
-		return;
-	self->regB0 = val;
-	if ( val & 0x20 ) {
-                Operator__KeyOn( Channel__Op(self, 0), 0x1 );
-                Operator__KeyOn( Channel__Op(self, 1), 0x1 );
-		if ( fourOp & 0x3f ) {
-                        Operator__KeyOn( Channel__Op(self + 1, 0), 1 );
-                        Operator__KeyOn( Channel__Op(self + 1, 1), 1 );
-		}
-	} else {
-                Operator__KeyOff( Channel__Op(self, 0), 0x1 );
-                Operator__KeyOff( Channel__Op(self, 1), 0x1 );
-		if ( fourOp & 0x3f ) {
-                        Operator__KeyOff( Channel__Op(self + 1, 0), 1 );
-                        Operator__KeyOff( Channel__Op(self + 1, 1), 1 );
-		}
-	}
-}
-
-static void Channel__WriteC0(Channel *self, const Chip* chip, Bit8u val ) {
-	Bit8u change = val ^ self->regC0;
-	if ( !change )
-		return;
-	self->regC0 = val;
-	self->feedback = ( val >> 1 ) & 7;
-	if ( self->feedback ) {
-		//We shift the input to the right 10 bit wave index value
-		self->feedback = 9 - self->feedback;
-	} else {
-		self->feedback = 31;
-	}
-	//Select the new synth mode
-	if ( chip->opl3Active ) {
-		//4-op mode enabled for this channel
-		if ( (chip->reg104 & self->fourMask) & 0x3f ) {
-			Channel* chan0, *chan1;
-			Bit8u synth; // haleyjd 09/09/10: GNUisms out!
-			//Check if it's the 2nd channel in a 4-op
-			if ( !(self->fourMask & 0x80 ) ) {
-				chan0 = self;
-				chan1 = self + 1;
-			} else {
-				chan0 = self - 1;
-				chan1 = self;
-			}
-
-			synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
-			switch ( synth ) {
-			case 0:
-				chan0->synthHandler = Channel__BlockTemplate_sm3FMFM;
-				break;
-			case 1:
-				chan0->synthHandler = Channel__BlockTemplate_sm3AMFM;
-				break;
-			case 2:
-				chan0->synthHandler = Channel__BlockTemplate_sm3FMAM ;
-				break;
-			case 3:
-				chan0->synthHandler = Channel__BlockTemplate_sm3AMAM ;
-				break;
-			}
-		//Disable updating percussion channels
-		} else if ((self->fourMask & 0x40) && ( chip->regBD & 0x20) ) {
-
-		//Regular dual op, am or fm
-		} else if ( val & 1 ) {
-			self->synthHandler = Channel__BlockTemplate_sm3AM;
-		} else {
-			self->synthHandler = Channel__BlockTemplate_sm3FM;
-		}
-		self->maskLeft = ( val & 0x10 ) ? -1 : 0;
-		self->maskRight = ( val & 0x20 ) ? -1 : 0;
-	//opl2 active
-	} else { 
-		//Disable updating percussion channels
-		if ( (self->fourMask & 0x40) && ( chip->regBD & 0x20 ) ) {
-
-		//Regular dual op, am or fm
-		} else if ( val & 1 ) {
-			self->synthHandler = Channel__BlockTemplate_sm2AM;
-		} else {
-			self->synthHandler = Channel__BlockTemplate_sm2FM;
-		}
-	}
-}
-
-static void Channel__ResetC0(Channel *self, const Chip* chip ) {
-	Bit8u val = self->regC0;
-	self->regC0 ^= 0xff;
-	Channel__WriteC0( self, chip, val );
-};
-
-static inline void Channel__GeneratePercussion(Channel *self, Chip* chip,
-                                               Bit32s* output, int opl3Mode ) {
-	Channel* chan = self;
-
-	//BassDrum
-	Bit32s mod = (Bit32u)((self->old[0] + self->old[1])) >> self->feedback;
-	Bit32s sample; // haleyjd 09/09/10
-	Bit32u noiseBit;
-	Bit32u c2;
-	Bit32u c5;
-	Bit32u phaseBit;
-	Bit32u hhVol;
-	Bit32u sdVol;
-	Bit32u tcVol;
-
-	self->old[0] = self->old[1];
-	self->old[1] = Operator__GetSample( Channel__Op(self, 0), mod ); 
-
-	//When bassdrum is in AM mode first operator is ignoed
-	if ( chan->regC0 & 1 ) {
-		mod = 0;
-	} else {
-		mod = self->old[0];
-	}
-	sample = Operator__GetSample( Channel__Op(self, 1), mod ); 
-
-	//Precalculate stuff used by other outputs
-	noiseBit = Chip__ForwardNoise(chip) & 0x1;
-	c2 = Operator__ForwardWave(Channel__Op(self, 2));
-	c5 = Operator__ForwardWave(Channel__Op(self, 5));
-	phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00;
-
-	//Hi-Hat
-	hhVol = Operator__ForwardVolume(Channel__Op(self, 2));
-	if ( !ENV_SILENT( hhVol ) ) {
-		Bit32u hhIndex = (phaseBit<<8) | (0x34 << ( phaseBit ^ (noiseBit << 1 )));
-		sample += Operator__GetWave( Channel__Op(self, 2), hhIndex, hhVol );
-	}
-	//Snare Drum
-	sdVol = Operator__ForwardVolume( Channel__Op(self, 3) );
-	if ( !ENV_SILENT( sdVol ) ) {
-		Bit32u sdIndex = ( 0x100 + (c2 & 0x100) ) ^ ( noiseBit << 8 );
-		sample += Operator__GetWave( Channel__Op(self, 3), sdIndex, sdVol );
-	}
-	//Tom-tom
-	sample += Operator__GetSample( Channel__Op(self, 4), 0 );
-
-	//Top-Cymbal
-	tcVol = Operator__ForwardVolume(Channel__Op(self, 5));
-	if ( !ENV_SILENT( tcVol ) ) {
-		Bit32u tcIndex = (1 + phaseBit) << 8;
-		sample += Operator__GetWave( Channel__Op(self, 5), tcIndex, tcVol );
-	}
-	sample <<= 1;
-	if ( opl3Mode ) {
-		output[0] += sample;
-		output[1] += sample;
-	} else {
-		output[0] += sample;
-	}
-}
-
-Channel* Channel__BlockTemplate(Channel *self, Chip* chip,
-                                Bit32u samples, Bit32s* output,
-                                SynthMode mode ) {
-        Bitu i;
-
-	switch( mode ) {
-	case sm2AM:
-	case sm3AM:
-		if ( Operator__Silent(Channel__Op(self, 0))
-                 && Operator__Silent(Channel__Op(self, 1))) {
-			self->old[0] = self->old[1] = 0;
-			return(self + 1);
-		}
-		break;
-	case sm2FM:
-	case sm3FM:
-		if ( Operator__Silent(Channel__Op(self, 1))) {
-			self->old[0] = self->old[1] = 0;
-			return (self + 1);
-		}
-		break;
-	case sm3FMFM:
-		if ( Operator__Silent(Channel__Op(self, 3))) {
-			self->old[0] = self->old[1] = 0;
-			return (self + 2);
-		}
-		break;
-	case sm3AMFM:
-		if ( Operator__Silent( Channel__Op(self, 0) )
-                 && Operator__Silent( Channel__Op(self, 3) )) {
-			self->old[0] = self->old[1] = 0;
-			return (self + 2);
-		}
-		break;
-	case sm3FMAM:
-		if ( Operator__Silent( Channel__Op(self, 1))
-                 && Operator__Silent( Channel__Op(self, 3))) {
-			self->old[0] = self->old[1] = 0;
-			return (self + 2);
-		}
-		break;
-	case sm3AMAM:
-		if ( Operator__Silent( Channel__Op(self, 0) )
-                 && Operator__Silent( Channel__Op(self, 2) )
-                 && Operator__Silent( Channel__Op(self, 3) )) {
-			self->old[0] = self->old[1] = 0;
-			return (self + 2);
-		}
-		break;
-
-        default:
-                abort();
-	}
-	//Init the operators with the the current vibrato and tremolo values
-        Operator__Prepare( Channel__Op( self, 0 ), chip );
-        Operator__Prepare( Channel__Op( self, 1 ), chip );
-	if ( mode > sm4Start ) {
-                Operator__Prepare( Channel__Op( self, 2 ), chip );
-                Operator__Prepare( Channel__Op( self, 3 ), chip );
-	}
-	if ( mode > sm6Start ) {
-                Operator__Prepare( Channel__Op( self, 4 ), chip );
-                Operator__Prepare( Channel__Op( self, 5 ), chip );
-	}
-	for ( i = 0; i < samples; i++ ) {
-		Bit32s mod; // haleyjd 09/09/10: GNUisms out!
-		Bit32s sample;
-		Bit32s out0;
-
-		//Early out for percussion handlers
-		if ( mode == sm2Percussion ) {
-			Channel__GeneratePercussion( self, chip, output + i, FALSE );
-			continue;	//Prevent some unitialized value bitching
-		} else if ( mode == sm3Percussion ) {
-			Channel__GeneratePercussion( self, chip, output + i * 2, TRUE );
-			continue;	//Prevent some unitialized value bitching
-		}
-
-		//Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
-		mod = (Bit32u)((self->old[0] + self->old[1])) >> self->feedback;
-		self->old[0] = self->old[1];
-		self->old[1] = Operator__GetSample( Channel__Op(self, 0), mod );
-		sample = 0;
-		out0 = self->old[0];
-		if ( mode == sm2AM || mode == sm3AM ) {
-			sample = out0 + Operator__GetSample( Channel__Op(self, 1), 0 );
-		} else if ( mode == sm2FM || mode == sm3FM ) {
-			sample = Operator__GetSample( Channel__Op(self, 1), out0 );
-		} else if ( mode == sm3FMFM ) {
-			Bits next = Operator__GetSample( Channel__Op(self, 1), out0 );
-			next = Operator__GetSample( Channel__Op(self, 2), next );
-			sample = Operator__GetSample( Channel__Op(self, 3), next );
-		} else if ( mode == sm3AMFM ) {
-			Bits next; // haleyjd 09/09/10: GNUisms out!
-			sample = out0;
-			next = Operator__GetSample( Channel__Op(self, 1), 0 );
-			next = Operator__GetSample( Channel__Op(self, 2), next );
-			sample += Operator__GetSample( Channel__Op(self, 3), next );
-		} else if ( mode == sm3FMAM ) {
-			Bits next; // haleyjd 09/09/10: GNUisms out!
-			sample = Operator__GetSample( Channel__Op(self, 1), out0 );
-			next = Operator__GetSample( Channel__Op(self, 2), 0 );
-			sample += Operator__GetSample( Channel__Op(self, 3), next );
-		} else if ( mode == sm3AMAM ) {
-			Bits next; // haleyjd 09/09/10: GNUisms out!
-			sample = out0;
-			next = Operator__GetSample( Channel__Op(self, 1), 0 );
-			sample += Operator__GetSample( Channel__Op(self, 2), next );
-			sample += Operator__GetSample( Channel__Op(self, 3), 0 );
-		}
-		switch( mode ) {
-		case sm2AM:
-		case sm2FM:
-			output[ i ] += sample;
-			break;
-		case sm3AM:
-		case sm3FM:
-		case sm3FMFM:
-		case sm3AMFM:
-		case sm3FMAM:
-		case sm3AMAM:
-			output[ i * 2 + 0 ] += sample & self->maskLeft;
-			output[ i * 2 + 1 ] += sample & self->maskRight;
-			break;
-                default:
-                        abort();
-		}
-	}
-	switch( mode ) {
-	case sm2AM:
-	case sm2FM:
-	case sm3AM:
-	case sm3FM:
-		return ( self + 1 );
-	case sm3FMFM:
-	case sm3AMFM:
-	case sm3FMAM:
-	case sm3AMAM:
-		return ( self + 2 );
-	case sm2Percussion:
-	case sm3Percussion:
-		return( self + 3 );
-        default:
-                abort();
-	}
-	return 0;
-}
-
-/*
-	Chip
-*/
-
-void Chip__Chip(Chip *self) {
-        int i;
-
-        for (i=0; i<18; ++i) {
-                Channel__Channel(&self->chan[i]);
-        }
-
-	self->reg08 = 0;
-	self->reg04 = 0;
-	self->regBD = 0;
-	self->reg104 = 0;
-	self->opl3Active = 0;
-}
-
-static inline Bit32u Chip__ForwardNoise(Chip *self) {
-	Bitu count;
-	self->noiseCounter += self->noiseAdd;
-	count = self->noiseCounter >> LFO_SH;
-	self->noiseCounter &= WAVE_MASK;
-	for ( ; count > 0; --count ) {
-		//Noise calculation from mame
-		self->noiseValue ^= ( 0x800302 ) & ( 0 - (self->noiseValue & 1 ) );
-		self->noiseValue >>= 1;
-	}
-	return self->noiseValue;
-}
-
-static inline Bit32u Chip__ForwardLFO(Chip *self, Bit32u samples ) {
-	Bit32u todo; // haleyjd 09/09/10: GNUisms out!!!!!!
-	Bit32u count;
-
-	//Current vibrato value, runs 4x slower than tremolo
-	self->vibratoSign = ( VibratoTable[ self->vibratoIndex >> 2] ) >> 7;
-	self->vibratoShift = ( VibratoTable[ self->vibratoIndex >> 2] & 7) + self->vibratoStrength; 
-	self->tremoloValue = TremoloTable[ self->tremoloIndex ] >> self->tremoloStrength;
-
-	//Check hom many samples there can be done before the value changes
-	todo = LFO_MAX - self->lfoCounter;
-	count = (todo + self->lfoAdd - 1) / self->lfoAdd;
-	if ( count > samples ) {
-		count = samples;
-		self->lfoCounter += count * self->lfoAdd;
-	} else {
-		self->lfoCounter += count * self->lfoAdd;
-		self->lfoCounter &= (LFO_MAX - 1);
-		//Maximum of 7 vibrato value * 4
-		self->vibratoIndex = ( self->vibratoIndex + 1 ) & 31;
-		//Clip tremolo to the the table size
-		if ( self->tremoloIndex + 1 < TREMOLO_TABLE  )
-			++self->tremoloIndex;
-		else
-			self->tremoloIndex = 0;
-	}
-	return count;
-}
-
-
-static void Chip__WriteBD(Chip *self, Bit8u val ) {
-	Bit8u change = self->regBD ^ val;
-	if ( !change )
-		return;
-	self->regBD = val;
-	//TODO could do this with shift and xor?
-	self->vibratoStrength = (val & 0x40) ? 0x00 : 0x01;
-	self->tremoloStrength = (val & 0x80) ? 0x00 : 0x02;
-	if ( val & 0x20 ) {
-		//Drum was just enabled, make sure channel 6 has the right synth
-		if ( change & 0x20 ) {
-			if ( self->opl3Active ) {
-				self->chan[6].synthHandler
-                                    = Channel__BlockTemplate_sm3Percussion; 
-			} else {
-				self->chan[6].synthHandler
-                                    = Channel__BlockTemplate_sm2Percussion;
-			}
-		}
-		//Bass Drum
-		if ( val & 0x10 ) {
-                        Operator__KeyOn( &self->chan[6].op[0], 0x2 );
-                        Operator__KeyOn( &self->chan[6].op[1], 0x2 );
-		} else {
-                        Operator__KeyOff( &self->chan[6].op[0], 0x2 );
-                        Operator__KeyOff( &self->chan[6].op[1], 0x2 );
-		}
-		//Hi-Hat
-		if ( val & 0x1 ) {
-                        Operator__KeyOn( &self->chan[7].op[0], 0x2 );
-		} else {
-                        Operator__KeyOff( &self->chan[7].op[0], 0x2 );
-		}
-		//Snare
-		if ( val & 0x8 ) {
-                        Operator__KeyOn( &self->chan[7].op[1], 0x2 );
-		} else {
-                        Operator__KeyOff( &self->chan[7].op[1], 0x2 );
-		}
-		//Tom-Tom
-		if ( val & 0x4 ) {
-                        Operator__KeyOn( &self->chan[8].op[0], 0x2 );
-		} else {
-                        Operator__KeyOff( &self->chan[8].op[0], 0x2 );
-		}
-		//Top Cymbal
-		if ( val & 0x2 ) {
-                        Operator__KeyOn( &self->chan[8].op[1], 0x2 );
-		} else {
-                        Operator__KeyOff( &self->chan[8].op[1], 0x2 );
-		}
-	//Toggle keyoffs when we turn off the percussion
-	} else if ( change & 0x20 ) {
-		//Trigger a reset to setup the original synth handler
-                Channel__ResetC0( &self->chan[6], self );
-                Operator__KeyOff( &self->chan[6].op[0], 0x2 );
-                Operator__KeyOff( &self->chan[6].op[1], 0x2 );
-                Operator__KeyOff( &self->chan[7].op[0], 0x2 );
-                Operator__KeyOff( &self->chan[7].op[1], 0x2 );
-                Operator__KeyOff( &self->chan[8].op[0], 0x2 );
-                Operator__KeyOff( &self->chan[8].op[1], 0x2 );
-	}
-}
-
-
-#define REGOP( _FUNC_ )															\
-	index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f );								\
-	if ( OpOffsetTable[ index ] ) {													\
-		Operator* regOp = (Operator*)( ((char *)self ) + OpOffsetTable[ index ] );	\
-                Operator__ ## _FUNC_ (regOp, self, val); \
-	}
-
-#define REGCHAN( _FUNC_ )																\
-	index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf );										\
-	if ( ChanOffsetTable[ index ] ) {													\
-		Channel* regChan = (Channel*)( ((char *)self ) + ChanOffsetTable[ index ] );	\
-                Channel__ ## _FUNC_ (regChan, self, val); \
-	}
-
-void Chip__WriteReg(Chip *self, Bit32u reg, Bit8u val ) {
-	Bitu index;
-	switch ( (reg & 0xf0) >> 4 ) {
-	case 0x00 >> 4:
-		if ( reg == 0x01 ) {
-			self->waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0; 
-		} else if ( reg == 0x104 ) {
-			//Only detect changes in lowest 6 bits
-			if ( !((self->reg104 ^ val) & 0x3f) )
-				return;
-			//Always keep the highest bit enabled, for checking > 0x80
-			self->reg104 = 0x80 | ( val & 0x3f );
-		} else if ( reg == 0x105 ) {
-                        int i;
-
-			//MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
-			if ( !((self->opl3Active ^ val) & 1 ) )
-				return;
-			self->opl3Active = ( val & 1 ) ? 0xff : 0;
-			//Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
-			for ( i = 0; i < 18;i++ ) {
-                                Channel__ResetC0( &self->chan[i], self );
-			}
-		} else if ( reg == 0x08 ) {
-			self->reg08 = val;
-		}
-	case 0x10 >> 4:
-		break;
-	case 0x20 >> 4:
-	case 0x30 >> 4:
-		REGOP( Write20 );
-		break;
-	case 0x40 >> 4:
-	case 0x50 >> 4:
-		REGOP( Write40 );
-		break;
-	case 0x60 >> 4:
-	case 0x70 >> 4:
-		REGOP( Write60 );
-		break;
-	case 0x80 >> 4:
-	case 0x90 >> 4:
-		REGOP( Write80 );
-		break;
-	case 0xa0 >> 4:
-		REGCHAN( WriteA0 );
-		break;
-	case 0xb0 >> 4:
-		if ( reg == 0xbd ) {
-			Chip__WriteBD( self, val );
-		} else {
-			REGCHAN( WriteB0 );
-		}
-		break;
-	case 0xc0 >> 4:
-		REGCHAN( WriteC0 );
-	case 0xd0 >> 4:
-		break;
-	case 0xe0 >> 4:
-	case 0xf0 >> 4:
-		REGOP( WriteE0 );
-		break;
-	}
-}
-
-Bit32u Chip__WriteAddr(Chip *self, Bit32u port, Bit8u val ) {
-	switch ( port & 3 ) {
-	case 0:
-		return val;
-	case 2:
-		if ( self->opl3Active || (val == 0x05) )
-			return 0x100 | val;
-		else
-			return val;
-	}
-	return 0;
-}
-
-void Chip__GenerateBlock2(Chip *self, Bitu total, Bit32s* output ) {
-	while ( total > 0 ) {
-                Channel *ch;
-		int count;
-
-		Bit32u samples = Chip__ForwardLFO( self, total );
-		memset(output, 0, sizeof(Bit32s) * samples);
-		count = 0;
-		for ( ch = self->chan; ch < self->chan + 9; ) {
-			count++;
-			ch = (ch->synthHandler)( ch, self, samples, output );
-		}
-		total -= samples;
-		output += samples;
-	}
-}
-
-void Chip__GenerateBlock3(Chip *self, Bitu total, Bit32s* output  ) {
-	while ( total > 0 ) {
-                int count;
-                Channel *ch;
-
-		Bit32u samples = Chip__ForwardLFO( self, total );
-		memset(output, 0, sizeof(Bit32s) * samples *2);
-		count = 0;
-		for ( ch = self->chan; ch < self->chan + 18; ) {
-			count++;
-			ch = (ch->synthHandler)( ch, self, samples, output );
-		}
-		total -= samples;
-		output += samples * 2;
-	}
-}
-
-void Chip__Setup(Chip *self, Bit32u rate ) {
-	double original = OPLRATE;
-	Bit32u i;
-	Bit32u freqScale; // haleyjd 09/09/10: GNUisms out!
-//	double original = rate;
-	double scale = original / (double)rate;
-
-	//Noise counter is run at the same precision as general waves
-	self->noiseAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
-	self->noiseCounter = 0;
-	self->noiseValue = 1;	//Make sure it triggers the noise xor the first time
-	//The low frequency oscillation counter
-	//Every time his overflows vibrato and tremoloindex are increased
-	self->lfoAdd = (Bit32u)( 0.5 + scale * ( 1 << LFO_SH ) );
-	self->lfoCounter = 0;
-	self->vibratoIndex = 0;
-	self->tremoloIndex = 0;
-
-	//With higher octave this gets shifted up
-	//-1 since the freqCreateTable = *2
-#ifdef WAVE_PRECISION
-	double freqScale = ( 1 << 7 ) * scale * ( 1 << ( WAVE_SH - 1 - 10));
-	for ( i = 0; i < 16; i++ ) {
-		self->freqMul[i] = (Bit32u)( 0.5 + freqScale * FreqCreateTable[ i ] );
-	}
-#else
-	freqScale = (Bit32u)( 0.5 + scale * ( 1 << ( WAVE_SH - 1 - 10)));
-	for ( i = 0; i < 16; i++ ) {
-		self->freqMul[i] = freqScale * FreqCreateTable[ i ];
-	}
-#endif
-
-	//-3 since the real envelope takes 8 steps to reach the single value we supply
-	for ( i = 0; i < 76; i++ ) {
-		Bit8u index, shift;
-		EnvelopeSelect( i, &index, &shift );
-		self->linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
-	}
-	//Generate the best matching attack rate
-	for ( i = 0; i < 62; i++ ) {
-		Bit8u index, shift;
-		Bit32s original; // haleyjd 09/09/10: GNUisms out!
-		Bit32s guessAdd;
-		Bit32s bestAdd;
-		Bit32u bestDiff;
-		Bit32u passes;
-		EnvelopeSelect( i, &index, &shift );
-		//Original amount of samples the attack would take
-		original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
-		 
-		guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
-		bestAdd = guessAdd;
-		bestDiff = 1 << 30;
-
-		for ( passes = 0; passes < 16; passes ++ ) {
-			Bit32s volume = ENV_MAX;
-			Bit32s samples = 0;
-			Bit32u count = 0;
-			Bit32s diff;
-			Bit32u lDiff;
-			while ( volume > 0 && samples < original * 2 ) {
-				Bit32s change; // haleyjd 09/09/10
-				count += guessAdd;
-				change = count >> RATE_SH;
-				count &= RATE_MASK;
-				if ( GCC_UNLIKELY(change) ) { // less than 1 % 
-					volume += ( ~volume * change ) >> 3;
-				}
-				samples++;
-
-			}
-			diff = original - samples;
-			lDiff = labs( diff );
-			//Init last on first pass
-			if ( lDiff < bestDiff ) {
-				bestDiff = lDiff;
-				bestAdd = guessAdd;
-				if ( !bestDiff )
-					break;
-			}
-			//Below our target
-			if ( diff < 0 ) {
-				//Better than the last time
-				Bit32s mul = ((original - diff) << 12) / original;
-				guessAdd = ((guessAdd * mul) >> 12);
-				guessAdd++;
-			} else if ( diff > 0 ) {
-				Bit32s mul = ((original - diff) << 12) / original;
-				guessAdd = (guessAdd * mul) >> 12;
-				guessAdd--;
-			}
-		}
-		self->attackRates[i] = bestAdd;
-	}
-	for ( i = 62; i < 76; i++ ) {
-		//This should provide instant volume maximizing
-		self->attackRates[i] = 8 << RATE_SH;
-	}
-	//Setup the channels with the correct four op flags
-	//Channels are accessed through a table so they appear linear here
-	self->chan[ 0].fourMask = 0x00 | ( 1 << 0 );
-	self->chan[ 1].fourMask = 0x80 | ( 1 << 0 );
-	self->chan[ 2].fourMask = 0x00 | ( 1 << 1 );
-	self->chan[ 3].fourMask = 0x80 | ( 1 << 1 );
-	self->chan[ 4].fourMask = 0x00 | ( 1 << 2 );
-	self->chan[ 5].fourMask = 0x80 | ( 1 << 2 );
-
-	self->chan[ 9].fourMask = 0x00 | ( 1 << 3 );
-	self->chan[10].fourMask = 0x80 | ( 1 << 3 );
-	self->chan[11].fourMask = 0x00 | ( 1 << 4 );
-	self->chan[12].fourMask = 0x80 | ( 1 << 4 );
-	self->chan[13].fourMask = 0x00 | ( 1 << 5 );
-	self->chan[14].fourMask = 0x80 | ( 1 << 5 );
-
-	//mark the percussion channels
-	self->chan[ 6].fourMask = 0x40;
-	self->chan[ 7].fourMask = 0x40;
-	self->chan[ 8].fourMask = 0x40;
-
-	//Clear Everything in opl3 mode
-	Chip__WriteReg( self, 0x105, 0x1 );
-	for ( i = 0; i < 512; i++ ) {
-		if ( i == 0x105 )
-			continue;
-		Chip__WriteReg( self, i, 0xff );
-		Chip__WriteReg( self, i, 0x0 );
-	}
-	Chip__WriteReg( self, 0x105, 0x0 );
-	//Clear everything in opl2 mode
-	for ( i = 0; i < 255; i++ ) {
-		Chip__WriteReg( self, i, 0xff );
-		Chip__WriteReg( self, i, 0x0 );
-	}
-}
-
-static int doneTables = FALSE;
-void DBOPL_InitTables( void ) {
-        int i, oct;
-
-	if ( doneTables )
-		return;
-	doneTables = TRUE;
-#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
-	//Exponential volume table, same as the real adlib
-	for ( i = 0; i < 256; i++ ) {
-		//Save them in reverse
-		ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 );
-		ExpTable[i] += 1024; //or remove the -1 oh well :)
-		//Preshift to the left once so the final volume can shift to the right
-		ExpTable[i] *= 2;
-	}
-#endif
-#if ( DBOPL_WAVE == WAVE_HANDLER )
-	//Add 0.5 for the trunc rounding of the integer cast
-	//Do a PI sinetable instead of the original 0.5 PI
-	for ( i = 0; i < 512; i++ ) {
-		SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
-	}
-#endif
-#if ( DBOPL_WAVE == WAVE_TABLEMUL )
-	//Multiplication based tables
-	for ( i = 0; i < 384; i++ ) {
-		int s = i * 8;
-		//TODO maybe keep some of the precision errors of the original table?
-		double val = ( 0.5 + ( pow(2.0, -1.0 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH ));
-		MulTable[i] = (Bit16u)(val);
-	}
-
-	//Sine Wave Base
-	for ( i = 0; i < 512; i++ ) {
-		WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
-		WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
-	}
-	//Exponential wave
-	for ( i = 0; i < 256; i++ ) {
-		WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2.0, -1.0 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
-		WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
-	}
-#endif
-#if ( DBOPL_WAVE == WAVE_TABLELOG )
-	//Sine Wave Base
-	for ( i = 0; i < 512; i++ ) {
-		WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
-		WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
-	}
-	//Exponential wave
-	for ( i = 0; i < 256; i++ ) {
-		WaveTable[ 0x700 + i ] = i * 8;
-		WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
-	} 
-#endif
-
-	//	|    |//\\|____|WAV7|//__|/\  |____|/\/\|
-	//	|\\//|    |    |WAV7|    |  \/|    |    |
-	//	|06  |0126|27  |7   |3   |4   |4 5 |5   |
-
-#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
-	for ( i = 0; i < 256; i++ ) {
-		//Fill silence gaps
-		WaveTable[ 0x400 + i ] = WaveTable[0];
-		WaveTable[ 0x500 + i ] = WaveTable[0];
-		WaveTable[ 0x900 + i ] = WaveTable[0];
-		WaveTable[ 0xc00 + i ] = WaveTable[0];
-		WaveTable[ 0xd00 + i ] = WaveTable[0];
-		//Replicate sines in other pieces
-		WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ];
-		//double speed sines
-		WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ];
-		WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ];
-		WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ];
-		WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ];
-	} 
-#endif
-
-	//Create the ksl table
-	for ( oct = 0; oct < 8; oct++ ) {
-		int base = oct * 8;
-		for ( i = 0; i < 16; i++ ) {
-			int val = base - KslCreateTable[i];
-			if ( val < 0 )
-				val = 0;
-			//*4 for the final range to match attenuation range
-			KslTable[ oct * 16 + i ] = val * 4;
-		}
-	}
-	//Create the Tremolo table, just increase and decrease a triangle wave
-	for ( i = 0; i < TREMOLO_TABLE / 2; i++ ) {
-		Bit8u val = i << ENV_EXTRA;
-		TremoloTable[i] = val;
-		TremoloTable[TREMOLO_TABLE - 1 - i] = val;
-	}
-	//Create a table with offsets of the channels from the start of the chip
-	{ // haleyjd 09/09/10: Driving me #$%^@ insane
-		Chip *chip = NULL;
-		for ( i = 0; i < 32; i++ ) {
-			Bitu index = i & 0xf;
-			Bitu blah; // haleyjd 09/09/10
-			if ( index >= 9 ) {
-				ChanOffsetTable[i] = 0;
-				continue;
-			}
-			//Make sure the four op channels follow eachother
-			if ( index < 6 ) {
-				index = (index % 3) * 2 + ( index / 3 );
-			}
-			//Add back the bits for highest ones
-			if ( i >= 16 )
-				index += 9;
-			blah = (Bitu) ( &(chip->chan[ index ]) );
-			ChanOffsetTable[i] = blah;
-		}
-		//Same for operators
-		for ( i = 0; i < 64; i++ ) {
-			Bitu chNum; // haleyjd 09/09/10
-			Bitu opNum;
-			Bitu blah;
-			Channel* chan = NULL;
-			if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
-				OpOffsetTable[i] = 0;
-				continue;
-			}
-			chNum = (i / 8) * 3 + (i % 8) % 3;
-			//Make sure we use 16 and up for the 2nd range to match the chanoffset gap
-			if ( chNum >= 12 )
-				chNum += 16 - 12;
-			opNum = ( i % 8 ) / 3;
-			blah = (Bitu) ( &(chan->op[opNum]) );
-			OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah;
-		}
-#if 0
-		//Stupid checks if table's are correct
-		for ( Bitu i = 0; i < 18; i++ ) {
-			Bit32u find = (Bit16u)( &(chip->chan[ i ]) );
-			for ( Bitu c = 0; c < 32; c++ ) {
-				if ( ChanOffsetTable[c] == find ) {
-					find = 0;
-					break;
-				}
-			}
-			if ( find ) {
-				find = find;
-			}
-		}
-		for ( Bitu i = 0; i < 36; i++ ) {
-			Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) );
-			for ( Bitu c = 0; c < 64; c++ ) {
-				if ( OpOffsetTable[c] == find ) {
-					find = 0;
-					break;
-				}
-			}
-			if ( find ) {
-				find = find;
-			}
-		}
-#endif
-	}
-}
-
-/*
-
-Bit32u Handler::WriteAddr( Bit32u port, Bit8u val ) {
-	return chip.WriteAddr( port, val );
-
-}
-void Handler::WriteReg( Bit32u addr, Bit8u val ) {
-	chip.WriteReg( addr, val );
-}
-
-void Handler::Generate( MixerChannel* chan, Bitu samples ) {
-	Bit32s buffer[ 512 * 2 ];
-	if ( GCC_UNLIKELY(samples > 512) )
-		samples = 512;
-	if ( !chip.opl3Active ) {
-		chip.GenerateBlock2( samples, buffer );
-		chan->AddSamples_m32( samples, buffer );
-	} else {
-		chip.GenerateBlock3( samples, buffer );
-		chan->AddSamples_s32( samples, buffer );
-	}
-}
-
-void Handler::Init( Bitu rate ) {
-	InitTables();
-	chip.Setup( rate );
-}
-*/
-
--- a/opl/dbopl.h
+++ /dev/null
@@ -1,203 +1,0 @@
-/*
- *  Copyright (C) 2002-2010  The DOSBox Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- */
-
-#include <inttypes.h>
-
-//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
-#define WAVE_HANDLER	10
-//Use a logarithmic wavetable with an exponential table for volume
-#define WAVE_TABLELOG	11
-//Use a linear wavetable with a multiply table for volume
-#define WAVE_TABLEMUL	12
-
-//Select the type of wave generator routine
-#define DBOPL_WAVE WAVE_TABLEMUL
-
-typedef struct _Chip Chip;
-typedef struct _Operator Operator;
-typedef struct _Channel Channel;
-
-typedef uintptr_t       Bitu;
-typedef intptr_t        Bits;
-typedef uint32_t        Bit32u;
-typedef int32_t         Bit32s;
-typedef uint16_t        Bit16u;
-typedef int16_t         Bit16s;
-typedef uint8_t         Bit8u;
-typedef int8_t          Bit8s;
-
-#if (DBOPL_WAVE == WAVE_HANDLER)
-typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
-#endif
-
-#define DB_FASTCALL
-
-typedef Bits (*VolumeHandler)(Operator *self);
-typedef Channel* (*SynthHandler)(Channel *self, Chip* chip, Bit32u samples, Bit32s* output );
-
-//Different synth modes that can generate blocks of data
-typedef enum {
-	sm2AM,
-	sm2FM,
-	sm3AM,
-	sm3FM,
-	sm4Start,
-	sm3FMFM,
-	sm3AMFM,
-	sm3FMAM,
-	sm3AMAM,
-	sm6Start,
-	sm2Percussion,
-	sm3Percussion,
-} SynthMode;
-
-//Shifts for the values contained in chandata variable
-enum {
-	SHIFT_KSLBASE = 16,
-	SHIFT_KEYCODE = 24,
-};
-
-//Masks for operator 20 values
-enum {
-        MASK_KSR = 0x10,
-        MASK_SUSTAIN = 0x20,
-        MASK_VIBRATO = 0x40,
-        MASK_TREMOLO = 0x80,
-};
-
-typedef enum {
-        OFF,
-        RELEASE,
-        SUSTAIN,
-        DECAY,
-        ATTACK,
-} OperatorState;
-
-struct _Operator {
-	VolumeHandler volHandler;
-
-#if (DBOPL_WAVE == WAVE_HANDLER)
-	WaveHandler waveHandler;	//Routine that generate a wave 
-#else
-	Bit16s* waveBase;
-	Bit32u waveMask;
-	Bit32u waveStart;
-#endif
-	Bit32u waveIndex;			//WAVE_BITS shifted counter of the frequency index
-	Bit32u waveAdd;				//The base frequency without vibrato
-	Bit32u waveCurrent;			//waveAdd + vibratao
-
-	Bit32u chanData;			//Frequency/octave and derived data coming from whatever channel controls this
-	Bit32u freqMul;				//Scale channel frequency with this, TODO maybe remove?
-	Bit32u vibrato;				//Scaled up vibrato strength
-	Bit32s sustainLevel;		//When stopping at sustain level stop here
-	Bit32s totalLevel;			//totalLevel is added to every generated volume
-	Bit32u currentLevel;		//totalLevel + tremolo
-	Bit32s volume;				//The currently active volume
-	
-	Bit32u attackAdd;			//Timers for the different states of the envelope
-	Bit32u decayAdd;
-	Bit32u releaseAdd;
-	Bit32u rateIndex;			//Current position of the evenlope
-
-	Bit8u rateZero;				//Bits for the different states of the envelope having no changes
-	Bit8u keyOn;				//Bitmask of different values that can generate keyon
-	//Registers, also used to check for changes
-	Bit8u reg20, reg40, reg60, reg80, regE0;
-	//Active part of the envelope we're in
-	Bit8u state;
-	//0xff when tremolo is enabled
-	Bit8u tremoloMask;
-	//Strength of the vibrato
-	Bit8u vibStrength;
-	//Keep track of the calculated KSR so we can check for changes
-	Bit8u ksr;
-};
-
-struct _Channel {
-	Operator op[2];
-	SynthHandler synthHandler;
-	Bit32u chanData;		//Frequency/octave and derived values
-	Bit32s old[2];			//Old data for feedback
-
-	Bit8u feedback;			//Feedback shift
-	Bit8u regB0;			//Register values to check for changes
-	Bit8u regC0;
-	//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
-	Bit8u fourMask;
-	Bit8s maskLeft;		//Sign extended values for both channel's panning
-	Bit8s maskRight;
-
-};
-
-struct _Chip {
-	//This is used as the base counter for vibrato and tremolo
-	Bit32u lfoCounter;
-	Bit32u lfoAdd;
-	
-
-	Bit32u noiseCounter;
-	Bit32u noiseAdd;
-	Bit32u noiseValue;
-
-	//Frequency scales for the different multiplications
-	Bit32u freqMul[16];
-	//Rates for decay and release for rate of this chip
-	Bit32u linearRates[76];
-	//Best match attack rates for the rate of this chip
-	Bit32u attackRates[76];
-
-	//18 channels with 2 operators each
-	Channel chan[18];
-
-	Bit8u reg104;
-	Bit8u reg08;
-	Bit8u reg04;
-	Bit8u regBD;
-	Bit8u vibratoIndex;
-	Bit8u tremoloIndex;
-	Bit8s vibratoSign;
-	Bit8u vibratoShift;
-	Bit8u tremoloValue;
-	Bit8u vibratoStrength;
-	Bit8u tremoloStrength;
-	//Mask for allowed wave forms
-	Bit8u waveFormMask;
-	//0 or -1 when enabled
-	Bit8s opl3Active;
-
-};
-
-/*
-struct Handler : public Adlib::Handler {
-	DBOPL::Chip chip;
-	virtual Bit32u WriteAddr( Bit32u port, Bit8u val );
-	virtual void WriteReg( Bit32u addr, Bit8u val );
-	virtual void Generate( MixerChannel* chan, Bitu samples );
-	virtual void Init( Bitu rate );
-};
-*/
-
-
-void Chip__Setup(Chip *self, Bit32u rate );
-void DBOPL_InitTables( void );
-void Chip__Chip(Chip *self);
-void Chip__WriteReg(Chip *self, Bit32u reg, Bit8u val );
-void Chip__GenerateBlock2(Chip *self, Bitu total, Bit32s* output );
-void Chip__GenerateBlock3(Chip *self, Bitu total, Bit32s* output );
-
-// haleyjd 09/09/10: Not standard C.
-#ifdef _MSC_VER
-#define inline __inline
-#endif
--- /dev/null
+++ b/opl/opl3.c
@@ -1,0 +1,1430 @@
+//
+// Copyright (C) 2013-2016 Alexey Khokholov (Nuke.YKT)
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//
+//  Nuked OPL3 emulator.
+//  Thanks:
+//      MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
+//          Feedback and Rhythm part calculation information.
+//      forums.submarine.org.uk(carbon14, opl3):
+//          Tremolo and phase generator calculation information.
+//      OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
+//          OPL2 ROMs.
+//
+// version: 1.7
+//
+//  Changelog:
+//
+//  v1.1:
+//      Vibrato's sign fix.
+//  v1.2:
+//      Operator key fix.
+//      Corrected 4-operator mode.
+//      Corrected rhythm mode.
+//      Some small fixes.
+//  v1.2.1:
+//      Small envelope generator fix.
+//      Removed EX_Get function(not used)
+//  v1.3:
+//      Complete rewrite.
+//  v1.4:
+//      New envelope and waveform generator.
+//      Some small fixes.
+//  v1.4.1:
+//      Envelope generator rate calculation fix.
+//  v1.4.2:
+//      Version for ZDoom.
+//  v1.5:
+//      Optimizations.
+//  v1.6:
+//      Improved emulation output.
+//  v1.6.1:
+//      Simple YMF289(OPL3-L) emulation.
+//  v1.7:
+//      Version for Chocolate Doom.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "opl3.h"
+
+#define RSM_FRAC    10
+
+// Channel types
+
+enum {
+    ch_2op = 0,
+    ch_4op = 1,
+    ch_4op2 = 2,
+    ch_drum = 3
+};
+
+// Envelope key types
+
+enum {
+    egk_norm = 0x01,
+    egk_drum = 0x02
+};
+
+
+//
+// logsin table
+//
+
+static const Bit16u logsinrom[256] = {
+    0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,
+    0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
+    0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,
+    0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
+    0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,
+    0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
+    0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,
+    0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
+    0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,
+    0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
+    0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,
+    0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
+    0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,
+    0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
+    0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,
+    0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
+    0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,
+    0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
+    0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,
+    0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
+    0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,
+    0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
+    0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,
+    0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
+    0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,
+    0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
+    0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,
+    0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
+    0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,
+    0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
+    0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
+    0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
+};
+
+//
+// exp table
+//
+
+static const Bit16u exprom[256] = {
+    0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014,
+    0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a,
+    0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042,
+    0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a,
+    0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072,
+    0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b,
+    0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4,
+    0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be,
+    0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9,
+    0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4,
+    0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110,
+    0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c,
+    0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149,
+    0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167,
+    0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185,
+    0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4,
+    0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4,
+    0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4,
+    0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205,
+    0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227,
+    0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249,
+    0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d,
+    0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291,
+    0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5,
+    0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db,
+    0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302,
+    0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329,
+    0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351,
+    0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a,
+    0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4,
+    0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf,
+    0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa
+};
+
+// 
+// freq mult table multiplied by 2
+//
+// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15
+//
+
+static const Bit8u mt[16] = {
+    1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30
+};
+
+//
+// ksl table
+//
+
+static const Bit8u kslrom[16] = {
+    0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64
+};
+
+static const Bit8u kslshift[4] = {
+    8, 1, 2, 0
+};
+
+//
+// envelope generator constants
+//
+
+static const Bit8u eg_incstep[3][4][8] = {
+    {
+        { 0, 0, 0, 0, 0, 0, 0, 0 },
+        { 0, 0, 0, 0, 0, 0, 0, 0 },
+        { 0, 0, 0, 0, 0, 0, 0, 0 },
+        { 0, 0, 0, 0, 0, 0, 0, 0 }
+    },
+    {
+        { 0, 1, 0, 1, 0, 1, 0, 1 },
+        { 0, 1, 0, 1, 1, 1, 0, 1 },
+        { 0, 1, 1, 1, 0, 1, 1, 1 },
+        { 0, 1, 1, 1, 1, 1, 1, 1 }
+    },
+    {
+        { 1, 1, 1, 1, 1, 1, 1, 1 },
+        { 2, 2, 1, 1, 1, 1, 1, 1 },
+        { 2, 2, 1, 1, 2, 2, 1, 1 },
+        { 2, 2, 2, 2, 2, 2, 1, 1 }
+    }
+};
+
+static const Bit8u eg_incdesc[16] = {
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2
+};
+
+static const Bit8s eg_incsh[16] = {
+    0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2
+};
+
+//
+// address decoding
+//
+
+static const Bit8s ad_slot[0x20] = {
+    0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1,
+    12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static const Bit8u ch_slot[18] = {
+    0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32
+};
+
+//
+// Envelope generator
+//
+
+typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope);
+typedef void(*envelope_genfunc)(opl3_slot *slott);
+
+static Bit16s OPL3_EnvelopeCalcExp(Bit32u level)
+{
+    if (level > 0x1fff)
+    {
+        level = 0x1fff;
+    }
+    return ((exprom[(level & 0xff) ^ 0xff] | 0x400) << 1) >> (level >> 8);
+}
+
+static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    Bit16u neg = 0;
+    phase &= 0x3ff;
+    if (phase & 0x200)
+    {
+        neg = ~0;
+    }
+    if (phase & 0x100)
+    {
+        out = logsinrom[(phase & 0xff) ^ 0xff];
+    }
+    else
+    {
+        out = logsinrom[phase & 0xff];
+    }
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg;
+}
+
+static Bit16s OPL3_EnvelopeCalcSin1(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    phase &= 0x3ff;
+    if (phase & 0x200)
+    {
+        out = 0x1000;
+    }
+    else if (phase & 0x100)
+    {
+        out = logsinrom[(phase & 0xff) ^ 0xff];
+    }
+    else
+    {
+        out = logsinrom[phase & 0xff];
+    }
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin2(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    phase &= 0x3ff;
+    if (phase & 0x100)
+    {
+        out = logsinrom[(phase & 0xff) ^ 0xff];
+    }
+    else
+    {
+        out = logsinrom[phase & 0xff];
+    }
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin3(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    phase &= 0x3ff;
+    if (phase & 0x100)
+    {
+        out = 0x1000;
+    }
+    else
+    {
+        out = logsinrom[phase & 0xff];
+    }
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    Bit16u neg = 0;
+    phase &= 0x3ff;
+    if ((phase & 0x300) == 0x100)
+    {
+        neg = ~0;
+    }
+    if (phase & 0x200)
+    {
+        out = 0x1000;
+    }
+    else if (phase & 0x80)
+    {
+        out = logsinrom[((phase ^ 0xff) << 1) & 0xff];
+    }
+    else
+    {
+        out = logsinrom[(phase << 1) & 0xff];
+    }
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg;
+}
+
+static Bit16s OPL3_EnvelopeCalcSin5(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    phase &= 0x3ff;
+    if (phase & 0x200)
+    {
+        out = 0x1000;
+    }
+    else if (phase & 0x80)
+    {
+        out = logsinrom[((phase ^ 0xff) << 1) & 0xff];
+    }
+    else
+    {
+        out = logsinrom[(phase << 1) & 0xff];
+    }
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope)
+{
+    Bit16u neg = 0;
+    phase &= 0x3ff;
+    if (phase & 0x200)
+    {
+        neg = ~0;
+    }
+    return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg;
+}
+
+static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope)
+{
+    Bit16u out = 0;
+    Bit16u neg = 0;
+    phase &= 0x3ff;
+    if (phase & 0x200)
+    {
+        neg = ~0;
+        phase = (phase & 0x1ff) ^ 0x1ff;
+    }
+    out = phase << 3;
+    return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg;
+}
+
+static const envelope_sinfunc envelope_sin[8] = {
+    OPL3_EnvelopeCalcSin0,
+    OPL3_EnvelopeCalcSin1,
+    OPL3_EnvelopeCalcSin2,
+    OPL3_EnvelopeCalcSin3,
+    OPL3_EnvelopeCalcSin4,
+    OPL3_EnvelopeCalcSin5,
+    OPL3_EnvelopeCalcSin6,
+    OPL3_EnvelopeCalcSin7
+};
+
+static void OPL3_EnvelopeGenOff(opl3_slot *slot);
+static void OPL3_EnvelopeGenAttack(opl3_slot *slot);
+static void OPL3_EnvelopeGenDecay(opl3_slot *slot);
+static void OPL3_EnvelopeGenSustain(opl3_slot *slot);
+static void OPL3_EnvelopeGenRelease(opl3_slot *slot);
+
+envelope_genfunc envelope_gen[5] = {
+    OPL3_EnvelopeGenOff,
+    OPL3_EnvelopeGenAttack,
+    OPL3_EnvelopeGenDecay,
+    OPL3_EnvelopeGenSustain,
+    OPL3_EnvelopeGenRelease
+};
+
+enum envelope_gen_num
+{
+    envelope_gen_num_off = 0,
+    envelope_gen_num_attack = 1,
+    envelope_gen_num_decay = 2,
+    envelope_gen_num_sustain = 3,
+    envelope_gen_num_release = 4
+};
+
+static Bit8u OPL3_EnvelopeCalcRate(opl3_slot *slot, Bit8u reg_rate)
+{
+    Bit8u rate;
+    if (reg_rate == 0x00)
+    {
+        return 0x00;
+    }
+    rate = (reg_rate << 2)
+         + (slot->reg_ksr ? slot->channel->ksv : (slot->channel->ksv >> 2));
+    if (rate > 0x3c)
+    {
+        rate = 0x3c;
+    }
+    return rate;
+}
+
+static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot)
+{
+    Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2)
+               - ((0x08 - slot->channel->block) << 5);
+    if (ksl < 0)
+    {
+        ksl = 0;
+    }
+    slot->eg_ksl = (Bit8u)ksl;
+}
+
+static void OPL3_EnvelopeUpdateRate(opl3_slot *slot)
+{
+    switch (slot->eg_gen)
+    {
+    case envelope_gen_num_off:
+    case envelope_gen_num_attack:
+        slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_ar);
+        break;
+    case envelope_gen_num_decay:
+        slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_dr);
+        break;
+    case envelope_gen_num_sustain:
+    case envelope_gen_num_release:
+        slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_rr);
+        break;
+    }
+}
+
+static void OPL3_EnvelopeGenOff(opl3_slot *slot)
+{
+    slot->eg_rout = 0x1ff;
+}
+
+static void OPL3_EnvelopeGenAttack(opl3_slot *slot)
+{
+    if (slot->eg_rout == 0x00)
+    {
+        slot->eg_gen = envelope_gen_num_decay;
+        OPL3_EnvelopeUpdateRate(slot);
+        return;
+    }
+    slot->eg_rout += ((~slot->eg_rout) * slot->eg_inc) >> 3;
+    if (slot->eg_rout < 0x00)
+    {
+        slot->eg_rout = 0x00;
+    }
+}
+
+static void OPL3_EnvelopeGenDecay(opl3_slot *slot)
+{
+    if (slot->eg_rout >= slot->reg_sl << 4)
+    {
+        slot->eg_gen = envelope_gen_num_sustain;
+        OPL3_EnvelopeUpdateRate(slot);
+        return;
+    }
+    slot->eg_rout += slot->eg_inc;
+}
+
+static void OPL3_EnvelopeGenSustain(opl3_slot *slot)
+{
+    if (!slot->reg_type)
+    {
+        OPL3_EnvelopeGenRelease(slot);
+    }
+}
+
+static void OPL3_EnvelopeGenRelease(opl3_slot *slot)
+{
+    if (slot->eg_rout >= 0x1ff)
+    {
+        slot->eg_gen = envelope_gen_num_off;
+        slot->eg_rout = 0x1ff;
+        OPL3_EnvelopeUpdateRate(slot);
+        return;
+    }
+    slot->eg_rout += slot->eg_inc;
+}
+
+static void OPL3_EnvelopeCalc(opl3_slot *slot)
+{
+    Bit8u rate_h, rate_l;
+    Bit8u inc = 0;
+    rate_h = slot->eg_rate >> 2;
+    rate_l = slot->eg_rate & 3;
+    if (eg_incsh[rate_h] > 0)
+    {
+        if ((slot->chip->timer & ((1 << eg_incsh[rate_h]) - 1)) == 0)
+        {
+            inc = eg_incstep[eg_incdesc[rate_h]][rate_l]
+                            [((slot->chip->timer)>> eg_incsh[rate_h]) & 0x07];
+        }
+    }
+    else
+    {
+        inc = eg_incstep[eg_incdesc[rate_h]][rate_l]
+                        [slot->chip->timer & 0x07] << (-eg_incsh[rate_h]);
+    }
+    slot->eg_inc = inc;
+    slot->eg_out = slot->eg_rout + (slot->reg_tl << 2)
+                 + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem;
+    envelope_gen[slot->eg_gen](slot);
+}
+
+static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type)
+{
+    if (!slot->key)
+    {
+        slot->eg_gen = envelope_gen_num_attack;
+        if ((slot->eg_rate >> 2) != 0x0f)
+        {
+            slot->eg_gen = envelope_gen_num_attack;
+        }
+        else
+        {
+            slot->eg_gen = envelope_gen_num_decay;
+            slot->eg_rout = 0x00;
+        }
+        OPL3_EnvelopeUpdateRate(slot);
+        slot->pg_phase = 0x00;
+    }
+    slot->key |= type;
+}
+
+static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type)
+{
+    if (slot->key)
+    {
+        slot->key &= (~type);
+        if (!slot->key)
+        {
+            slot->eg_gen = envelope_gen_num_release;
+            OPL3_EnvelopeUpdateRate(slot);
+        }
+    }
+}
+
+//
+// Phase Generator
+//
+
+static void OPL3_PhaseGenerate(opl3_slot *slot)
+{
+    Bit16u f_num;
+    Bit32u basefreq;
+
+    f_num = slot->channel->f_num;
+    if (slot->reg_vib)
+    {
+        Bit8s range;
+        Bit8u vibpos;
+
+        range = (f_num >> 7) & 7;
+        vibpos = slot->chip->vibpos;
+
+        if (!(vibpos & 3))
+        {
+            range = 0;
+        }
+        else if (vibpos & 1)
+        {
+            range >>= 1;
+        }
+        range >>= slot->chip->vibshift;
+
+        if (vibpos & 4)
+        {
+            range = -range;
+        }
+        f_num += range;
+    }
+    basefreq = (f_num << slot->channel->block) >> 1;
+    slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1;
+}
+
+//
+// Noise Generator
+//
+
+static void OPL3_NoiseGenerate(opl3_chip *chip)
+{
+    if (chip->noise & 0x01)
+    {
+        chip->noise ^= 0x800302;
+    }
+    chip->noise >>= 1;
+}
+
+//
+// Slot
+//
+
+static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data)
+{
+    if ((data >> 7) & 0x01)
+    {
+        slot->trem = &slot->chip->tremolo;
+    }
+    else
+    {
+        slot->trem = (Bit8u*)&slot->chip->zeromod;
+    }
+    slot->reg_vib = (data >> 6) & 0x01;
+    slot->reg_type = (data >> 5) & 0x01;
+    slot->reg_ksr = (data >> 4) & 0x01;
+    slot->reg_mult = data & 0x0f;
+    OPL3_EnvelopeUpdateRate(slot);
+}
+
+static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data)
+{
+    slot->reg_ksl = (data >> 6) & 0x03;
+    slot->reg_tl = data & 0x3f;
+    OPL3_EnvelopeUpdateKSL(slot);
+}
+
+static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data)
+{
+    slot->reg_ar = (data >> 4) & 0x0f;
+    slot->reg_dr = data & 0x0f;
+    OPL3_EnvelopeUpdateRate(slot);
+}
+
+static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data)
+{
+    slot->reg_sl = (data >> 4) & 0x0f;
+    if (slot->reg_sl == 0x0f)
+    {
+        slot->reg_sl = 0x1f;
+    }
+    slot->reg_rr = data & 0x0f;
+    OPL3_EnvelopeUpdateRate(slot);
+}
+
+static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data)
+{
+    slot->reg_wf = data & 0x07;
+    if (slot->chip->newm == 0x00)
+    {
+        slot->reg_wf &= 0x03;
+    }
+}
+
+static void OPL3_SlotGeneratePhase(opl3_slot *slot, Bit16u phase)
+{
+    slot->out = envelope_sin[slot->reg_wf](phase, slot->eg_out);
+}
+
+static void OPL3_SlotGenerate(opl3_slot *slot)
+{
+    OPL3_SlotGeneratePhase(slot, (Bit16u)(slot->pg_phase >> 9) + *slot->mod);
+}
+
+static void OPL3_SlotGenerateZM(opl3_slot *slot)
+{
+    OPL3_SlotGeneratePhase(slot, 0);
+}
+
+static void OPL3_SlotCalcFB(opl3_slot *slot)
+{
+    if (slot->channel->fb != 0x00)
+    {
+        slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb);
+    }
+    else
+    {
+        slot->fbmod = 0;
+    }
+    slot->prout = slot->out;
+}
+
+//
+// Channel
+//
+
+static void OPL3_ChannelSetupAlg(opl3_channel *channel);
+
+static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data)
+{
+    opl3_channel *channel6;
+    opl3_channel *channel7;
+    opl3_channel *channel8;
+    Bit8u chnum;
+
+    chip->rhy = data & 0x3f;
+    if (chip->rhy & 0x20)
+    {
+        channel6 = &chip->channel[6];
+        channel7 = &chip->channel[7];
+        channel8 = &chip->channel[8];
+        channel6->out[0] = &channel6->slots[1]->out;
+        channel6->out[1] = &channel6->slots[1]->out;
+        channel6->out[2] = &chip->zeromod;
+        channel6->out[3] = &chip->zeromod;
+        channel7->out[0] = &channel7->slots[0]->out;
+        channel7->out[1] = &channel7->slots[0]->out;
+        channel7->out[2] = &channel7->slots[1]->out;
+        channel7->out[3] = &channel7->slots[1]->out;
+        channel8->out[0] = &channel8->slots[0]->out;
+        channel8->out[1] = &channel8->slots[0]->out;
+        channel8->out[2] = &channel8->slots[1]->out;
+        channel8->out[3] = &channel8->slots[1]->out;
+        for (chnum = 6; chnum < 9; chnum++)
+        {
+            chip->channel[chnum].chtype = ch_drum;
+        }
+        OPL3_ChannelSetupAlg(channel6);
+        //hh
+        if (chip->rhy & 0x01)
+        {
+            OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum);
+        }
+        else
+        {
+            OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum);
+        }
+        //tc
+        if (chip->rhy & 0x02)
+        {
+            OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum);
+        }
+        else
+        {
+            OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum);
+        }
+        //tom
+        if (chip->rhy & 0x04)
+        {
+            OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum);
+        }
+        else
+        {
+            OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum);
+        }
+        //sd
+        if (chip->rhy & 0x08)
+        {
+            OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum);
+        }
+        else
+        {
+            OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum);
+        }
+        //bd
+        if (chip->rhy & 0x10)
+        {
+            OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum);
+            OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum);
+        }
+        else
+        {
+            OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum);
+            OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum);
+        }
+    }
+    else
+    {
+        for (chnum = 6; chnum < 9; chnum++)
+        {
+            chip->channel[chnum].chtype = ch_2op;
+            OPL3_ChannelSetupAlg(&chip->channel[chnum]);
+        }
+    }
+}
+
+static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data)
+{
+    if (channel->chip->newm && channel->chtype == ch_4op2)
+    {
+        return;
+    }
+    channel->f_num = (channel->f_num & 0x300) | data;
+    channel->ksv = (channel->block << 1)
+                 | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01);
+    OPL3_EnvelopeUpdateKSL(channel->slots[0]);
+    OPL3_EnvelopeUpdateKSL(channel->slots[1]);
+    OPL3_EnvelopeUpdateRate(channel->slots[0]);
+    OPL3_EnvelopeUpdateRate(channel->slots[1]);
+    if (channel->chip->newm && channel->chtype == ch_4op)
+    {
+        channel->pair->f_num = channel->f_num;
+        channel->pair->ksv = channel->ksv;
+        OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]);
+        OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]);
+        OPL3_EnvelopeUpdateRate(channel->pair->slots[0]);
+        OPL3_EnvelopeUpdateRate(channel->pair->slots[1]);
+    }
+}
+
+static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data)
+{
+    if (channel->chip->newm && channel->chtype == ch_4op2)
+    {
+        return;
+    }
+    channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8);
+    channel->block = (data >> 2) & 0x07;
+    channel->ksv = (channel->block << 1)
+                 | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01);
+    OPL3_EnvelopeUpdateKSL(channel->slots[0]);
+    OPL3_EnvelopeUpdateKSL(channel->slots[1]);
+    OPL3_EnvelopeUpdateRate(channel->slots[0]);
+    OPL3_EnvelopeUpdateRate(channel->slots[1]);
+    if (channel->chip->newm && channel->chtype == ch_4op)
+    {
+        channel->pair->f_num = channel->f_num;
+        channel->pair->block = channel->block;
+        channel->pair->ksv = channel->ksv;
+        OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]);
+        OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]);
+        OPL3_EnvelopeUpdateRate(channel->pair->slots[0]);
+        OPL3_EnvelopeUpdateRate(channel->pair->slots[1]);
+    }
+}
+
+static void OPL3_ChannelSetupAlg(opl3_channel *channel)
+{
+    if (channel->chtype == ch_drum)
+    {
+        switch (channel->alg & 0x01)
+        {
+        case 0x00:
+            channel->slots[0]->mod = &channel->slots[0]->fbmod;
+            channel->slots[1]->mod = &channel->slots[0]->out;
+            break;
+        case 0x01:
+            channel->slots[0]->mod = &channel->slots[0]->fbmod;
+            channel->slots[1]->mod = &channel->chip->zeromod;
+            break;
+        }
+        return;
+    }
+    if (channel->alg & 0x08)
+    {
+        return;
+    }
+    if (channel->alg & 0x04)
+    {
+        channel->pair->out[0] = &channel->chip->zeromod;
+        channel->pair->out[1] = &channel->chip->zeromod;
+        channel->pair->out[2] = &channel->chip->zeromod;
+        channel->pair->out[3] = &channel->chip->zeromod;
+        switch (channel->alg & 0x03)
+        {
+        case 0x00:
+            channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+            channel->pair->slots[1]->mod = &channel->pair->slots[0]->out;
+            channel->slots[0]->mod = &channel->pair->slots[1]->out;
+            channel->slots[1]->mod = &channel->slots[0]->out;
+            channel->out[0] = &channel->slots[1]->out;
+            channel->out[1] = &channel->chip->zeromod;
+            channel->out[2] = &channel->chip->zeromod;
+            channel->out[3] = &channel->chip->zeromod;
+            break;
+        case 0x01:
+            channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+            channel->pair->slots[1]->mod = &channel->pair->slots[0]->out;
+            channel->slots[0]->mod = &channel->chip->zeromod;
+            channel->slots[1]->mod = &channel->slots[0]->out;
+            channel->out[0] = &channel->pair->slots[1]->out;
+            channel->out[1] = &channel->slots[1]->out;
+            channel->out[2] = &channel->chip->zeromod;
+            channel->out[3] = &channel->chip->zeromod;
+            break;
+        case 0x02:
+            channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+            channel->pair->slots[1]->mod = &channel->chip->zeromod;
+            channel->slots[0]->mod = &channel->pair->slots[1]->out;
+            channel->slots[1]->mod = &channel->slots[0]->out;
+            channel->out[0] = &channel->pair->slots[0]->out;
+            channel->out[1] = &channel->slots[1]->out;
+            channel->out[2] = &channel->chip->zeromod;
+            channel->out[3] = &channel->chip->zeromod;
+            break;
+        case 0x03:
+            channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+            channel->pair->slots[1]->mod = &channel->chip->zeromod;
+            channel->slots[0]->mod = &channel->pair->slots[1]->out;
+            channel->slots[1]->mod = &channel->chip->zeromod;
+            channel->out[0] = &channel->pair->slots[0]->out;
+            channel->out[1] = &channel->slots[0]->out;
+            channel->out[2] = &channel->slots[1]->out;
+            channel->out[3] = &channel->chip->zeromod;
+            break;
+        }
+    }
+    else
+    {
+        switch (channel->alg & 0x01)
+        {
+        case 0x00:
+            channel->slots[0]->mod = &channel->slots[0]->fbmod;
+            channel->slots[1]->mod = &channel->slots[0]->out;
+            channel->out[0] = &channel->slots[1]->out;
+            channel->out[1] = &channel->chip->zeromod;
+            channel->out[2] = &channel->chip->zeromod;
+            channel->out[3] = &channel->chip->zeromod;
+            break;
+        case 0x01:
+            channel->slots[0]->mod = &channel->slots[0]->fbmod;
+            channel->slots[1]->mod = &channel->chip->zeromod;
+            channel->out[0] = &channel->slots[0]->out;
+            channel->out[1] = &channel->slots[1]->out;
+            channel->out[2] = &channel->chip->zeromod;
+            channel->out[3] = &channel->chip->zeromod;
+            break;
+        }
+    }
+}
+
+static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data)
+{
+    channel->fb = (data & 0x0e) >> 1;
+    channel->con = data & 0x01;
+    channel->alg = channel->con;
+    if (channel->chip->newm)
+    {
+        if (channel->chtype == ch_4op)
+        {
+            channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con);
+            channel->alg = 0x08;
+            OPL3_ChannelSetupAlg(channel->pair);
+        }
+        else if (channel->chtype == ch_4op2)
+        {
+            channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con);
+            channel->pair->alg = 0x08;
+            OPL3_ChannelSetupAlg(channel);
+        }
+        else
+        {
+            OPL3_ChannelSetupAlg(channel);
+        }
+    }
+    else
+    {
+        OPL3_ChannelSetupAlg(channel);
+    }
+    if (channel->chip->newm)
+    {
+        channel->cha = ((data >> 4) & 0x01) ? ~0 : 0;
+        channel->chb = ((data >> 5) & 0x01) ? ~0 : 0;
+    }
+    else
+    {
+        channel->cha = channel->chb = ~0;
+    }
+}
+
+static void OPL3_ChannelKeyOn(opl3_channel *channel)
+{
+    if (channel->chip->newm)
+    {
+        if (channel->chtype == ch_4op)
+        {
+            OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm);
+            OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm);
+            OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm);
+            OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm);
+        }
+        else if (channel->chtype == ch_2op || channel->chtype == ch_drum)
+        {
+            OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm);
+            OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm);
+        }
+    }
+    else
+    {
+        OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm);
+        OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm);
+    }
+}
+
+static void OPL3_ChannelKeyOff(opl3_channel *channel)
+{
+    if (channel->chip->newm)
+    {
+        if (channel->chtype == ch_4op)
+        {
+            OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm);
+            OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm);
+            OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm);
+            OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm);
+        }
+        else if (channel->chtype == ch_2op || channel->chtype == ch_drum)
+        {
+            OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm);
+            OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm);
+        }
+    }
+    else
+    {
+        OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm);
+        OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm);
+    }
+}
+
+static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data)
+{
+    Bit8u bit;
+    Bit8u chnum;
+    for (bit = 0; bit < 6; bit++)
+    {
+        chnum = bit;
+        if (bit >= 3)
+        {
+            chnum += 9 - 3;
+        }
+        if ((data >> bit) & 0x01)
+        {
+            chip->channel[chnum].chtype = ch_4op;
+            chip->channel[chnum + 3].chtype = ch_4op2;
+        }
+        else
+        {
+            chip->channel[chnum].chtype = ch_2op;
+            chip->channel[chnum + 3].chtype = ch_2op;
+        }
+    }
+}
+
+static Bit16s OPL3_ClipSample(Bit32s sample)
+{
+    if (sample > 32767)
+    {
+        sample = 32767;
+    }
+    else if (sample < -32768)
+    {
+        sample = -32768;
+    }
+    return (Bit16s)sample;
+}
+
+static void OPL3_GenerateRhythm1(opl3_chip *chip)
+{
+    opl3_channel *channel6;
+    opl3_channel *channel7;
+    opl3_channel *channel8;
+    Bit16u phase14;
+    Bit16u phase17;
+    Bit16u phase;
+    Bit16u phasebit;
+
+    channel6 = &chip->channel[6];
+    channel7 = &chip->channel[7];
+    channel8 = &chip->channel[8];
+    OPL3_SlotGenerate(channel6->slots[0]);
+    phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff;
+    phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff;
+    phase = 0x00;
+    //hh tc phase bit
+    phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04)
+             | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00;
+    //hh
+    phase = (phasebit << 9)
+          | (0x34 << ((phasebit ^ (chip->noise & 0x01) << 1)));
+    OPL3_SlotGeneratePhase(channel7->slots[0], phase);
+    //tt
+    OPL3_SlotGenerateZM(channel8->slots[0]);
+}
+
+static void OPL3_GenerateRhythm2(opl3_chip *chip)
+{
+    opl3_channel *channel6;
+    opl3_channel *channel7;
+    opl3_channel *channel8;
+    Bit16u phase14;
+    Bit16u phase17;
+    Bit16u phase;
+    Bit16u phasebit;
+
+    channel6 = &chip->channel[6];
+    channel7 = &chip->channel[7];
+    channel8 = &chip->channel[8];
+    OPL3_SlotGenerate(channel6->slots[1]);
+    phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff;
+    phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff;
+    phase = 0x00;
+    //hh tc phase bit
+    phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04)
+             | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00;
+    //sd
+    phase = (0x100 << ((phase14 >> 8) & 0x01)) ^ ((chip->noise & 0x01) << 8);
+    OPL3_SlotGeneratePhase(channel7->slots[1], phase);
+    //tc
+    phase = 0x100 | (phasebit << 9);
+    OPL3_SlotGeneratePhase(channel8->slots[1], phase);
+}
+
+void OPL3_Generate(opl3_chip *chip, Bit16s *buf)
+{
+    Bit8u ii;
+    Bit8u jj;
+    Bit16s accm;
+
+    buf[1] = OPL3_ClipSample(chip->mixbuff[1]);
+
+    for (ii = 0; ii < 12; ii++)
+    {
+        OPL3_SlotCalcFB(&chip->slot[ii]);
+        OPL3_PhaseGenerate(&chip->slot[ii]);
+        OPL3_EnvelopeCalc(&chip->slot[ii]);
+        OPL3_SlotGenerate(&chip->slot[ii]);
+    }
+
+    for (ii = 12; ii < 15; ii++)
+    {
+        OPL3_SlotCalcFB(&chip->slot[ii]);
+        OPL3_PhaseGenerate(&chip->slot[ii]);
+        OPL3_EnvelopeCalc(&chip->slot[ii]);
+    }
+
+    if (chip->rhy & 0x20)
+    {
+        OPL3_GenerateRhythm1(chip);
+    }
+    else
+    {
+        OPL3_SlotGenerate(&chip->slot[12]);
+        OPL3_SlotGenerate(&chip->slot[13]);
+        OPL3_SlotGenerate(&chip->slot[14]);
+    }
+
+    chip->mixbuff[0] = 0;
+    for (ii = 0; ii < 18; ii++)
+    {
+        accm = 0;
+        for (jj = 0; jj < 4; jj++)
+        {
+            accm += *chip->channel[ii].out[jj];
+        }
+        chip->mixbuff[0] += (Bit16s)(accm & chip->channel[ii].cha);
+    }
+
+    for (ii = 15; ii < 18; ii++)
+    {
+        OPL3_SlotCalcFB(&chip->slot[ii]);
+        OPL3_PhaseGenerate(&chip->slot[ii]);
+        OPL3_EnvelopeCalc(&chip->slot[ii]);
+    }
+
+    if (chip->rhy & 0x20)
+    {
+        OPL3_GenerateRhythm2(chip);
+    }
+    else
+    {
+        OPL3_SlotGenerate(&chip->slot[15]);
+        OPL3_SlotGenerate(&chip->slot[16]);
+        OPL3_SlotGenerate(&chip->slot[17]);
+    }
+
+    buf[0] = OPL3_ClipSample(chip->mixbuff[0]);
+
+    for (ii = 18; ii < 33; ii++)
+    {
+        OPL3_SlotCalcFB(&chip->slot[ii]);
+        OPL3_PhaseGenerate(&chip->slot[ii]);
+        OPL3_EnvelopeCalc(&chip->slot[ii]);
+        OPL3_SlotGenerate(&chip->slot[ii]);
+    }
+
+    chip->mixbuff[1] = 0;
+    for (ii = 0; ii < 18; ii++)
+    {
+        accm = 0;
+        for (jj = 0; jj < 4; jj++)
+        {
+            accm += *chip->channel[ii].out[jj];
+        }
+        chip->mixbuff[1] += (Bit16s)(accm & chip->channel[ii].chb);
+    }
+
+    for (ii = 33; ii < 36; ii++)
+    {
+        OPL3_SlotCalcFB(&chip->slot[ii]);
+        OPL3_PhaseGenerate(&chip->slot[ii]);
+        OPL3_EnvelopeCalc(&chip->slot[ii]);
+        OPL3_SlotGenerate(&chip->slot[ii]);
+    }
+
+    OPL3_NoiseGenerate(chip);
+
+    if ((chip->timer & 0x3f) == 0x3f)
+    {
+        chip->tremolopos = (chip->tremolopos + 1) % 210;
+        if (chip->tremolopos < 105)
+        {
+            chip->tremolo = chip->tremolopos >> chip->tremoloshift;
+        }
+        else
+        {
+            chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift;
+        }
+    }
+
+    if ((chip->timer & 0x3ff) == 0x3ff)
+    {
+        chip->vibpos = (chip->vibpos + 1) & 7;
+    }
+
+    chip->timer++;
+
+    while (chip->writebuf_cur != chip->writebuf_last
+        && chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt)
+    {
+        OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg,
+                      chip->writebuf[chip->writebuf_cur].data);
+        chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE;
+    }
+    chip->writebuf_samplecnt++;
+}
+
+void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf)
+{
+    while (chip->samplecnt >= chip->rateratio)
+    {
+        chip->oldsamples[0] = chip->samples[0];
+        chip->oldsamples[1] = chip->samples[1];
+        OPL3_Generate(chip, chip->samples);
+        chip->samplecnt -= chip->rateratio;
+    }
+    buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)
+                     + chip->samples[0] * chip->samplecnt) / chip->rateratio);
+    buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)
+                     + chip->samples[1] * chip->samplecnt) / chip->rateratio);
+    chip->samplecnt += 1 << RSM_FRAC;
+}
+
+void OPL3_Reset(opl3_chip *chip, Bit32u samplerate)
+{
+    Bit8u slotnum;
+    Bit8u channum;
+
+    memset(chip, 0, sizeof(opl3_chip));
+    for (slotnum = 0; slotnum < 36; slotnum++)
+    {
+        chip->slot[slotnum].chip = chip;
+        chip->slot[slotnum].mod = &chip->zeromod;
+        chip->slot[slotnum].eg_rout = 0x1ff;
+        chip->slot[slotnum].eg_out = 0x1ff;
+        chip->slot[slotnum].eg_gen = envelope_gen_num_off;
+        chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod;
+    }
+    for (channum = 0; channum < 18; channum++)
+    {
+        chip->channel[channum].slots[0] = &chip->slot[ch_slot[channum]];
+        chip->channel[channum].slots[1] = &chip->slot[ch_slot[channum] + 3];
+        chip->slot[ch_slot[channum]].channel = &chip->channel[channum];
+        chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum];
+        if ((channum % 9) < 3)
+        {
+            chip->channel[channum].pair = &chip->channel[channum + 3];
+        }
+        else if ((channum % 9) < 6)
+        {
+            chip->channel[channum].pair = &chip->channel[channum - 3];
+        }
+        chip->channel[channum].chip = chip;
+        chip->channel[channum].out[0] = &chip->zeromod;
+        chip->channel[channum].out[1] = &chip->zeromod;
+        chip->channel[channum].out[2] = &chip->zeromod;
+        chip->channel[channum].out[3] = &chip->zeromod;
+        chip->channel[channum].chtype = ch_2op;
+        chip->channel[channum].cha = ~0;
+        chip->channel[channum].chb = ~0;
+        OPL3_ChannelSetupAlg(&chip->channel[channum]);
+    }
+    chip->noise = 0x306600;
+    chip->rateratio = (samplerate << RSM_FRAC) / 49716;
+}
+
+void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v)
+{
+    Bit8u high = (reg >> 8) & 0x01;
+    Bit8u regm = reg & 0xff;
+    switch (regm & 0xf0)
+    {
+    case 0x00:
+        if (high)
+        {
+            switch (regm & 0x0f)
+            {
+            case 0x04:
+                OPL3_ChannelSet4Op(chip, v);
+                break;
+            case 0x05:
+                chip->newm = v & 0x01;
+                break;
+            }
+        }
+        else
+        {
+            switch (regm & 0x0f)
+            {
+            case 0x08:
+                chip->nts = (v >> 6) & 0x01;
+                break;
+            }
+        }
+        break;
+    case 0x20:
+    case 0x30:
+        if (ad_slot[regm & 0x1f] >= 0)
+        {
+            OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+        }
+        break;
+    case 0x40:
+    case 0x50:
+        if (ad_slot[regm & 0x1f] >= 0)
+        {
+            OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+        }
+        break;
+    case 0x60:
+    case 0x70:
+        if (ad_slot[regm & 0x1f] >= 0)
+        {
+            OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+        }
+        break;
+    case 0x80:
+    case 0x90:
+        if (ad_slot[regm & 0x1f] >= 0)
+        {
+            OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+        }
+        break;
+    case 0xe0:
+    case 0xf0:
+        if (ad_slot[regm & 0x1f] >= 0)
+        {
+            OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+        }
+        break;
+    case 0xa0:
+        if ((regm & 0x0f) < 9)
+        {
+            OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v);
+        }
+        break;
+    case 0xb0:
+        if (regm == 0xbd && !high)
+        {
+            chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2;
+            chip->vibshift = ((v >> 6) & 0x01) ^ 1;
+            OPL3_ChannelUpdateRhythm(chip, v);
+        }
+        else if ((regm & 0x0f) < 9)
+        {
+            OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v);
+            if (v & 0x20)
+            {
+                OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]);
+            }
+            else
+            {
+                OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]);
+            }
+        }
+        break;
+    case 0xc0:
+        if ((regm & 0x0f) < 9)
+        {
+            OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v);
+        }
+        break;
+    }
+}
+
+void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v)
+{
+    Bit64u time1, time2;
+    chip->writebuf[chip->writebuf_last % OPL_WRITEBUF_SIZE].reg = reg;
+    chip->writebuf[chip->writebuf_last % OPL_WRITEBUF_SIZE].data = v;
+    time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY;
+    time2 = chip->writebuf_samplecnt;
+
+    if (time1 < time2)
+    {
+        time1 = time2;
+    }
+
+    chip->writebuf[chip->writebuf_last % OPL_WRITEBUF_SIZE].time = time1;
+    chip->writebuf_lasttime = time1;
+    chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE;
+}
+
+void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples)
+{
+    Bit32u i;
+	
+    for(i = 0; i < numsamples; i++)
+    {
+        OPL3_GenerateResampled(chip, sndptr);
+        sndptr += 2;
+    }
+}
--- /dev/null
+++ b/opl/opl3.h
@@ -1,0 +1,135 @@
+//
+// Copyright (C) 2013-2016 Alexey Khokholov (Nuke.YKT)
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+//
+//  Nuked OPL3 emulator.
+//  Thanks:
+//      MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
+//          Feedback and Rhythm part calculation information.
+//      forums.submarine.org.uk(carbon14, opl3):
+//          Tremolo and phase generator calculation information.
+//      OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
+//          OPL2 ROMs.
+//
+// version: 1.7
+//
+
+#ifndef OPL_OPL3_H
+#define OPL_OPL3_H
+
+#include <inttypes.h>
+
+#define OPL_WRITEBUF_SIZE   1024
+#define OPL_WRITEBUF_DELAY  2
+
+typedef uintptr_t       Bitu;
+typedef intptr_t        Bits;
+typedef uint64_t        Bit64u;
+typedef int64_t         Bit64s;
+typedef uint32_t        Bit32u;
+typedef int32_t         Bit32s;
+typedef uint16_t        Bit16u;
+typedef int16_t         Bit16s;
+typedef uint8_t         Bit8u;
+typedef int8_t          Bit8s;
+
+typedef struct _opl3_slot opl3_slot;
+typedef struct _opl3_channel opl3_channel;
+typedef struct _opl3_chip opl3_chip;
+
+struct _opl3_slot {
+    opl3_channel *channel;
+    opl3_chip *chip;
+    Bit16s out;
+    Bit16s fbmod;
+    Bit16s *mod;
+    Bit16s prout;
+    Bit16s eg_rout;
+    Bit16s eg_out;
+    Bit8u eg_inc;
+    Bit8u eg_gen;
+    Bit8u eg_rate;
+    Bit8u eg_ksl;
+    Bit8u *trem;
+    Bit8u reg_vib;
+    Bit8u reg_type;
+    Bit8u reg_ksr;
+    Bit8u reg_mult;
+    Bit8u reg_ksl;
+    Bit8u reg_tl;
+    Bit8u reg_ar;
+    Bit8u reg_dr;
+    Bit8u reg_sl;
+    Bit8u reg_rr;
+    Bit8u reg_wf;
+    Bit8u key;
+    Bit32u pg_phase;
+    Bit32u timer;
+};
+
+struct _opl3_channel {
+    opl3_slot *slots[2];
+    opl3_channel *pair;
+    opl3_chip *chip;
+    Bit16s *out[4];
+    Bit8u chtype;
+    Bit16u f_num;
+    Bit8u block;
+    Bit8u fb;
+    Bit8u con;
+    Bit8u alg;
+    Bit8u ksv;
+    Bit16u cha, chb;
+};
+
+typedef struct _opl3_writebuf {
+    Bit64u time;
+    Bit16u reg;
+    Bit8u data;
+} opl3_writebuf;
+
+struct _opl3_chip {
+    opl3_channel channel[18];
+    opl3_slot slot[36];
+    Bit16u timer;
+    Bit8u newm;
+    Bit8u nts;
+    Bit8u rhy;
+    Bit8u vibpos;
+    Bit8u vibshift;
+    Bit8u tremolo;
+    Bit8u tremolopos;
+    Bit8u tremoloshift;
+    Bit32u noise;
+    Bit16s zeromod;
+    Bit32s mixbuff[2];
+    //OPL3L
+    Bit32s rateratio; 
+    Bit32s samplecnt;
+    Bit16s oldsamples[2];
+    Bit16s samples[2];
+
+    Bit64u writebuf_samplecnt;
+    Bit32u writebuf_cur;
+    Bit32u writebuf_last;
+    Bit64u writebuf_lasttime;
+    opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
+};
+
+void OPL3_Generate(opl3_chip *chip, Bit16s *buf);
+void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf);
+void OPL3_Reset(opl3_chip *chip, Bit32u samplerate);
+void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v);
+void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v);
+void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples);
+#endif
--- a/opl/opl_sdl.c
+++ b/opl/opl_sdl.c
@@ -25,7 +25,7 @@
 #include "SDL.h"
 #include "SDL_mixer.h"
 
-#include "dbopl.h"
+#include "opl3.h"
 
 #include "opl.h"
 #include "opl_internal.h"
@@ -70,7 +70,7 @@
 
 // OPL software emulator structure.
 
-static Chip opl_chip;
+static opl3_chip opl_chip;
 static int opl_opl3mode;
 
 // Temporary mixing buffer used by the mixing callback.
@@ -165,30 +165,7 @@
 
     assert(nsamples < mixing_freq);
 
-    if (opl_opl3mode)
-    {
-        Chip__GenerateBlock3(&opl_chip, nsamples, mix_buffer);
-
-        // Mix into the destination buffer, doubling up into stereo.
-
-        for (i=0; i<nsamples; ++i)
-        {
-            buffer[i * 2] = (int16_t) mix_buffer[i * 2];
-            buffer[i * 2 + 1] = (int16_t) mix_buffer[i * 2 + 1];
-        }
-    }
-    else
-    {
-        Chip__GenerateBlock2(&opl_chip, nsamples, mix_buffer);
-
-        // Mix into the destination buffer, doubling up into stereo.
-
-        for (i=0; i<nsamples; ++i)
-        {
-            buffer[i * 2] = (int16_t) mix_buffer[i];
-            buffer[i * 2 + 1] = (int16_t) mix_buffer[i];
-        }
-    }
+    OPL3_GenerateStream(&opl_chip, buffer, nsamples);
 }
 
 // Callback function to fill a new sound buffer:
@@ -371,9 +348,7 @@
 
     // Create the emulator structure:
 
-    DBOPL_InitTables();
-    Chip__Chip(&opl_chip);
-    Chip__Setup(&opl_chip, mixing_freq);
+    OPL3_Reset(&opl_chip, mixing_freq);
     opl_opl3mode = 0;
 
     callback_mutex = SDL_CreateMutex();
@@ -465,7 +440,7 @@
             opl_opl3mode = value & 0x01;
 
         default:
-            Chip__WriteReg(&opl_chip, reg_num, value);
+            OPL3_WriteRegBuffered(&opl_chip, reg_num, value);
             break;
     }
 }