From 55eec18bfe6e575a59809fe645d7b895cb5dcdb5 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Sun, 30 Mar 2014 17:19:18 -0700 Subject: [PATCH] Updated ft2play and fixed up dbopl --- Frameworks/modplay/modplay/dbopl.c | 181 +++++++++++++++++++++++++-- Frameworks/modplay/modplay/dbopl.h | 162 ++---------------------- Frameworks/modplay/modplay/ft2play.c | 12 +- 3 files changed, 189 insertions(+), 166 deletions(-) diff --git a/Frameworks/modplay/modplay/dbopl.c b/Frameworks/modplay/modplay/dbopl.c index 2c4d7b217..30b1c74de 100644 --- a/Frameworks/modplay/modplay/dbopl.c +++ b/Frameworks/modplay/modplay/dbopl.c @@ -38,9 +38,159 @@ #include #include #include -//#include "dosbox.h" #include "dbopl.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 + +#if (DBOPL_WAVE == WAVE_HANDLER) +typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume ); +#endif + +typedef struct Operator Operator; +typedef struct Channel Channel; +typedef struct Chip Chip; + +typedef Bits ( *Operator_VolumeHandler) ( struct Operator * ); +typedef struct Channel* ( *Channel_SynthHandler) ( struct Channel *, struct 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 +}; + +enum { + MASK_KSR = 0x10, + MASK_SUSTAIN = 0x20, + MASK_VIBRATO = 0x40, + MASK_TREMOLO = 0x80 +}; + +typedef enum { + OFF, + RELEASE, + SUSTAIN, + DECAY, + ATTACK +} Operator_State; + +struct Operator { + //Masks for operator 20 values + 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 { + struct Operator op[2]; + Channel_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 + struct 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; +}; #ifndef PI #define PI 3.14159265358979323846 @@ -905,8 +1055,8 @@ static Bit32s Channel_GeneratePercussion( struct Channel *chan, struct Chip* chi //Precalculate stuff used by other outputs noiseBit = Chip_ForwardNoise( chip ) & 0x1; - c2 = Operator_ForwardWave( Channel_Operator( chan, 2 ) ); - c5 = Operator_ForwardWave( Channel_Operator( chan, 5 ) ); + c2 = Operator_ForwardWave( Channel_Op( chan, 2 ) ); + c5 = Operator_ForwardWave( Channel_Op( chan, 5 ) ); phaseBit = (((c2 & 0x88) ^ ((c2<<5) & 0x80)) | ((c5 ^ (c5<<2)) & 0x20)) ? 0x02 : 0x00; //Hi-Hat @@ -1136,10 +1286,16 @@ static void Channel_ResetC0( struct Channel *c, const struct Chip* chip ) { Chip */ +Bitu Chip_GetSize() +{ + return sizeof(struct Chip); +} + static void InitTables( void ); -void Chip_Init(struct Chip *chip) { +void Chip_Init(void *_chip) { Bit32u i; + struct Chip *chip = (struct Chip *)_chip; InitTables(); chip->reg08 = 0; chip->reg04 = 0; @@ -1267,8 +1423,9 @@ static void Chip_WriteBD( struct Chip *chip, Bit8u val ) { Channel_##_FUNC_( regChan, chip, val ); \ } -void Chip_WriteReg( struct Chip *chip, Bit32u reg, Bit8u val ) { +void Chip_WriteReg( void *_chip, Bit32u reg, Bit8u val ) { Bitu index; + struct Chip *chip = (struct Chip *)_chip; switch ( (reg & 0xf0) >> 4 ) { case 0x00 >> 4: if ( reg == 0x01 ) { @@ -1330,7 +1487,8 @@ void Chip_WriteReg( struct Chip *chip, Bit32u reg, Bit8u val ) { } } -Bit32u Chip_WriteAddr( struct Chip *chip, Bit32u port, Bit8u val ) { +Bit32u Chip_WriteAddr( void *_chip, Bit32u port, Bit8u val ) { + struct Chip *chip = (struct Chip *)_chip; switch ( port & 3 ) { case 0: return val; @@ -1343,7 +1501,8 @@ Bit32u Chip_WriteAddr( struct Chip *chip, Bit32u port, Bit8u val ) { return 0; } -void Chip_GenerateBlock2( struct Chip *chip, Bitu total, Bit32s* output ) { +void Chip_GenerateBlock2( void *_chip, Bitu total, Bit32s* output ) { + struct Chip *chip = (struct Chip *)_chip; while ( total > 0 ) { struct Channel* ch; int count; @@ -1361,11 +1520,12 @@ void Chip_GenerateBlock2( struct Chip *chip, Bitu total, Bit32s* output ) { } } -void Chip_GenerateBlock3( struct Chip *chip, Bitu total, Bit32s* output ) { +void Chip_GenerateBlock3( void *_chip, Bitu total, Bit32s* output ) { + struct Chip *chip = (struct Chip *)_chip; while ( total > 0 ) { struct Channel* ch; int count; - Bit32u samples = ForwardLFO( total ); + Bit32u samples = Chip_ForwardLFO( chip, total ); for ( Bitu i = 0; i < samples; i++ ) { output[i * 2 + 0 ] = 0; output[i * 2 + 1 ] = 0; @@ -1380,7 +1540,8 @@ void Chip_GenerateBlock3( struct Chip *chip, Bitu total, Bit32s* output ) { } } -void Chip_Setup( struct Chip *chip, Bit32u clock, Bit32u rate ) { +void Chip_Setup( void *_chip, Bit32u clock, Bit32u rate ) { + struct Chip *chip = (struct Chip *)_chip; double original = (double)clock / 288.0; double scale = original / (double)rate; if (fabs(scale - 1.0) < 0.00001) diff --git a/Frameworks/modplay/modplay/dbopl.h b/Frameworks/modplay/modplay/dbopl.h index 3fab2ea04..8861da622 100644 --- a/Frameworks/modplay/modplay/dbopl.h +++ b/Frameworks/modplay/modplay/dbopl.h @@ -57,161 +57,13 @@ typedef signed long long Bit64s; typedef unsigned int Bitu; typedef signed int Bits; -//#include "dosbox.h" +Bitu Chip_GetSize(); -//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 +void Chip_Init( void *chip ); +void Chip_Setup( void *chip, Bit32u clock, Bit32u rate ); -//Select the type of wave generator routine -#define DBOPL_WAVE WAVE_TABLEMUL +void Chip_WriteReg( void *chip, Bit32u reg, Bit8u val ); +Bit32u Chip_WriteAddr( void *chip, Bit32u port, Bit8u val ); -#if (DBOPL_WAVE == WAVE_HANDLER) -typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume ); -#endif - -typedef Bits ( *Operator_VolumeHandler) ( struct Operator * ); -typedef struct Channel* ( *Channel_SynthHandler) ( struct Channel *, struct 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 -}; - -enum { - MASK_KSR = 0x10, - MASK_SUSTAIN = 0x20, - MASK_VIBRATO = 0x40, - MASK_TREMOLO = 0x80 -}; - -typedef enum { - OFF, - RELEASE, - SUSTAIN, - DECAY, - ATTACK -} Operator_State; - -struct Operator { - //Masks for operator 20 values - 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 { - struct Operator op[2]; - Channel_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 - struct 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; -}; - -void Chip_Init(struct Chip *chip); -void Chip_Setup( struct Chip *chip, Bit32u clock, Bit32u rate ); - -void Chip_WriteReg( struct Chip *chip, Bit32u reg, Bit8u val ); -Bit32u Chip_WriteAddr( struct Chip *chip, Bit32u port, Bit8u val ); - -void Chip_GenerateBlock2( struct Chip *chip, Bitu total, Bit32s* output ); -void Chip_GenerateBlock3( struct Chip *chip, Bitu total, Bit32s* output ); +void Chip_GenerateBlock2( void *chip, Bitu total, Bit32s* output ); +void Chip_GenerateBlock3( void *chip, Bitu total, Bit32s* output ); diff --git a/Frameworks/modplay/modplay/ft2play.c b/Frameworks/modplay/modplay/ft2play.c index c04af2946..3000383ca 100644 --- a/Frameworks/modplay/modplay/ft2play.c +++ b/Frameworks/modplay/modplay/ft2play.c @@ -9,6 +9,9 @@ ** It's just an accurate FastTracker II replayer port for people to enjoy. ** ** + ** non-FT2 effects: + ** - E8x - set panning + ** ** (extreme) non-FT2 extensions: ** - Max 127 channels (was 32) ** - Any amount-of-channels number (FT2 supports *even* numbers only) @@ -966,7 +969,14 @@ CheckEffects: // E7x - set tremolo waveform else if ((ch->Eff & 0xF0) == 0x70) ch->WaveCtrl = ((ch->Eff & 0x0F) << 4) | (ch->WaveCtrl & 0x0F); - + + // E8x - set panning - *non-FT2* + else if ((ch->Eff & 0xF0) == 0x80) + { + ch->OutPan = (ch->Eff & 0x0F) << 4; + ch->Status |= IS_Pan; + } + // EAx - fine volume slide up else if ((ch->Eff & 0xF0) == 0xA0) {