commit
a0ef4eda48
7 changed files with 1579 additions and 1876 deletions
|
|
@ -158,10 +158,6 @@
|
|||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\opl\dbopl.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opl\ioperm_sys.c"
|
||||
>
|
||||
|
|
@ -194,6 +190,10 @@
|
|||
RelativePath="..\opl\opl_win32.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opl\opl3.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
|
|
@ -224,6 +224,10 @@
|
|||
RelativePath="..\opl\opl_timer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\opl\opl3.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@ libopl_a_SOURCES = \
|
|||
opl_timer.c opl_timer.h \
|
||||
opl_win32.c \
|
||||
ioperm_sys.c ioperm_sys.h \
|
||||
dbopl.c dbopl.h
|
||||
opl3.c opl3.h
|
||||
|
||||
|
|
|
|||
1638
opl/dbopl.c
1638
opl/dbopl.c
File diff suppressed because it is too large
Load diff
203
opl/dbopl.h
203
opl/dbopl.h
|
|
@ -1,203 +0,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
|
||||
1430
opl/opl3.c
Normal file
1430
opl/opl3.c
Normal file
File diff suppressed because it is too large
Load diff
135
opl/opl3.h
Normal file
135
opl/opl3.h
Normal file
|
|
@ -0,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
|
||||
|
|
@ -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 @@ static uint64_t pause_offset;
|
|||
|
||||
// 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 @@ static void FillBuffer(int16_t *buffer, unsigned int nsamples)
|
|||
|
||||
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 @@ static int OPL_SDL_Init(unsigned int port_base)
|
|||
|
||||
// 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 @@ static void WriteRegister(unsigned int reg_num, unsigned int value)
|
|||
opl_opl3mode = value & 0x01;
|
||||
|
||||
default:
|
||||
Chip__WriteReg(&opl_chip, reg_num, value);
|
||||
OPL3_WriteRegBuffered(&opl_chip, reg_num, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue