Updated ft2play and fixed up dbopl
parent
0839cbbd9d
commit
55eec18bfe
|
@ -38,9 +38,159 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
//#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)
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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)
|
||||
|
@ -967,6 +970,13 @@ 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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue