mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 15:02:39 +00:00
- Make OPL emulation more of a black box.
SVN r3942 (trunk)
This commit is contained in:
parent
47d9859246
commit
df1e802412
9 changed files with 188 additions and 261 deletions
|
@ -102,6 +102,17 @@ Revision History:
|
||||||
//#include "driver.h" /* use M.A.M.E. */
|
//#include "driver.h" /* use M.A.M.E. */
|
||||||
#include "fmopl.h"
|
#include "fmopl.h"
|
||||||
|
|
||||||
|
/* compiler dependence */
|
||||||
|
#ifndef OSD_CPU_H
|
||||||
|
#define OSD_CPU_H
|
||||||
|
typedef unsigned char UINT8; /* unsigned 8bit */
|
||||||
|
typedef unsigned short UINT16; /* unsigned 16bit */
|
||||||
|
typedef unsigned int UINT32; /* unsigned 32bit */
|
||||||
|
typedef signed char INT8; /* signed 8bit */
|
||||||
|
typedef signed short INT16; /* signed 16bit */
|
||||||
|
typedef signed int INT32; /* signed 32bit */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PI
|
#ifndef PI
|
||||||
#define PI 3.14159265358979323846
|
#define PI 3.14159265358979323846
|
||||||
#endif
|
#endif
|
||||||
|
@ -1343,13 +1354,11 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
|
||||||
/* timer 2 */
|
/* timer 2 */
|
||||||
if(OPL->st[1] != st2)
|
if(OPL->st[1] != st2)
|
||||||
{
|
{
|
||||||
double interval = st2 ? (double)OPL->T[1]*OPL_TIMERBASE : 0.0;
|
|
||||||
OPL->st[1] = st2;
|
OPL->st[1] = st2;
|
||||||
}
|
}
|
||||||
/* timer 1 */
|
/* timer 1 */
|
||||||
if(OPL->st[0] != st1)
|
if(OPL->st[0] != st1)
|
||||||
{
|
{
|
||||||
double interval = st1 ? (double)OPL->T[0]*OPL_TIMERBASE : 0.0;
|
|
||||||
OPL->st[0] = st1;
|
OPL->st[0] = st1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1560,165 +1569,80 @@ static void OPLResetChip(FM_OPL *OPL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create one of virtual YM3812 */
|
|
||||||
/* 'clock' is chip clock in Hz */
|
class YM3812 : public OPLEmul
|
||||||
/* 'rate' is sampling rate */
|
|
||||||
static FM_OPL *OPLCreate()
|
|
||||||
{
|
{
|
||||||
char *ptr;
|
private:
|
||||||
FM_OPL *OPL;
|
FM_OPL Chip;
|
||||||
int state_size;
|
|
||||||
|
|
||||||
if (OPL_LockTable() ==-1) return NULL;
|
public:
|
||||||
|
/* Create one of virtual YM3812 */
|
||||||
/* calculate OPL state size */
|
YM3812(bool stereo)
|
||||||
state_size = sizeof(FM_OPL);
|
{
|
||||||
|
if (OPL_LockTable() == -1) return;
|
||||||
/* allocate memory block */
|
|
||||||
ptr = (char *)malloc(state_size);
|
|
||||||
|
|
||||||
if (ptr==NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* clear */
|
/* clear */
|
||||||
memset(ptr,0,state_size);
|
memset(&Chip, 0, sizeof(Chip));
|
||||||
|
|
||||||
OPL = (FM_OPL *)ptr;
|
|
||||||
|
|
||||||
ptr += sizeof(FM_OPL);
|
|
||||||
|
|
||||||
/* init global tables */
|
/* init global tables */
|
||||||
OPL_initalize(OPL);
|
OPL_initalize(&Chip);
|
||||||
|
|
||||||
return OPL;
|
Chip.IsStereo = true;
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy one of virtual YM3812 */
|
Reset();
|
||||||
static void OPLDestroy(FM_OPL *OPL)
|
}
|
||||||
{
|
|
||||||
|
/* Destroy one of virtual YM3812 */
|
||||||
|
~YM3812()
|
||||||
|
{
|
||||||
OPL_UnLockTable();
|
OPL_UnLockTable();
|
||||||
free(OPL);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* YM3812 I/O interface */
|
/* YM3812 I/O interface */
|
||||||
static int OPLWrite(FM_OPL *OPL,int a,int v)
|
int Write(int a, int v)
|
||||||
{
|
{
|
||||||
if( !(a&1) )
|
if( !(a&1) )
|
||||||
{ /* address port */
|
{ /* address port */
|
||||||
OPL->address = v & 0xff;
|
Chip.address = v & 0xff;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* data port */
|
{ /* data port */
|
||||||
OPLWriteReg(OPL,OPL->address,v);
|
OPLWriteReg(&Chip, Chip.address, v);
|
||||||
}
|
}
|
||||||
return OPL->status>>7;
|
return Chip.status>>7;
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned char OPLRead(FM_OPL *OPL,int a)
|
|
||||||
{
|
|
||||||
if( !(a&1) )
|
|
||||||
{
|
|
||||||
/* status port */
|
|
||||||
/* OPL and OPL2 */
|
|
||||||
return OPL->status & (OPL->statusmask|0x80);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xff;
|
void Reset()
|
||||||
}
|
|
||||||
|
|
||||||
/* CSM Key Controll */
|
|
||||||
INLINE void CSMKeyControll(OPL_CH *CH)
|
|
||||||
{
|
|
||||||
FM_KEYON (&CH->SLOT[SLOT1], 4);
|
|
||||||
FM_KEYON (&CH->SLOT[SLOT2], 4);
|
|
||||||
|
|
||||||
/* The key off should happen exactly one sample later - not implemented correctly yet */
|
|
||||||
|
|
||||||
FM_KEYOFF(&CH->SLOT[SLOT1], ~4);
|
|
||||||
FM_KEYOFF(&CH->SLOT[SLOT2], ~4);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *YM3812Init()
|
|
||||||
{
|
|
||||||
/* emulator create */
|
|
||||||
FM_OPL *YM3812 = OPLCreate();
|
|
||||||
if (YM3812)
|
|
||||||
YM3812ResetChip(YM3812);
|
|
||||||
return YM3812;
|
|
||||||
}
|
|
||||||
|
|
||||||
void YM3812Shutdown(void *chip)
|
|
||||||
{
|
|
||||||
FM_OPL *YM3812 = (FM_OPL *)chip;
|
|
||||||
|
|
||||||
/* emulator shutdown */
|
|
||||||
OPLDestroy(YM3812);
|
|
||||||
}
|
|
||||||
void YM3812ResetChip(void *chip)
|
|
||||||
{
|
|
||||||
FM_OPL *YM3812 = (FM_OPL *)chip;
|
|
||||||
OPLResetChip(YM3812);
|
|
||||||
}
|
|
||||||
|
|
||||||
int YM3812Write(void *chip, int a, int v)
|
|
||||||
{
|
|
||||||
FM_OPL *YM3812 = (FM_OPL *)chip;
|
|
||||||
return OPLWrite(YM3812, a, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char YM3812Read(void *chip, int a)
|
|
||||||
{
|
|
||||||
FM_OPL *YM3812 = (FM_OPL *)chip;
|
|
||||||
/* YM3812 always returns bit2 and bit1 in HIGH state */
|
|
||||||
return OPLRead(YM3812, a) | 0x06 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* [RH] Full support for MIDI panning */
|
|
||||||
void YM3812SetStereo(void *chip, bool stereo)
|
|
||||||
{
|
|
||||||
if (chip != NULL)
|
|
||||||
{
|
{
|
||||||
FM_OPL *YM3812 = (FM_OPL *)chip;
|
OPLResetChip(&Chip);
|
||||||
YM3812->IsStereo = stereo;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void YM3812SetPanning(void *chip, int c, int pan)
|
/* [RH] Full support for MIDI panning */
|
||||||
{
|
void SetPanning(int c, int pan)
|
||||||
if (chip != NULL)
|
|
||||||
{
|
{
|
||||||
FM_OPL *YM3812 = (FM_OPL *)chip;
|
|
||||||
// This is the MIDI-recommended pan formula. 0 and 1 are
|
// This is the MIDI-recommended pan formula. 0 and 1 are
|
||||||
// both hard left so that 64 can be perfectly center.
|
// both hard left so that 64 can be perfectly center.
|
||||||
double level = (pan <= 1) ? 0 : (pan - 1) / 126.0;
|
double level = (pan <= 1) ? 0 : (pan - 1) / 126.0;
|
||||||
YM3812->P_CH[c].LeftVol = (float)cos(HALF_PI * level);
|
Chip.P_CH[c].LeftVol = (float)cos(HALF_PI * level);
|
||||||
YM3812->P_CH[c].RightVol = (float)sin(HALF_PI * level);
|
Chip.P_CH[c].RightVol = (float)sin(HALF_PI * level);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Generate samples for one of the YM3812's
|
/*
|
||||||
**
|
** Generate samples for one of the YM3812's
|
||||||
** 'which' is the virtual YM3812 number
|
**
|
||||||
** '*buffer' is the output buffer pointer
|
** '*buffer' is the output buffer pointer
|
||||||
** 'length' is the number of samples that should be generated
|
** 'length' is the number of samples that should be generated
|
||||||
*/
|
*/
|
||||||
void YM3812UpdateOne(void *chip, float *buffer, int length)
|
void Update(float *buffer, int length)
|
||||||
{
|
{
|
||||||
FM_OPL *OPL = (FM_OPL *)chip;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (OPL == NULL)
|
UINT8 rhythm = Chip.rhythm&0x20;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT8 rhythm = OPL->rhythm&0x20;
|
UINT32 lfo_am_cnt_bak = Chip.lfo_am_cnt;
|
||||||
|
UINT32 eg_timer_bak = Chip.eg_timer;
|
||||||
UINT32 lfo_am_cnt_bak = OPL->lfo_am_cnt;
|
UINT32 eg_cnt_bak = Chip.eg_cnt;
|
||||||
UINT32 eg_timer_bak = OPL->eg_timer;
|
|
||||||
UINT32 eg_cnt_bak = OPL->eg_cnt;
|
|
||||||
|
|
||||||
UINT32 lfo_am_cnt_out = lfo_am_cnt_bak;
|
UINT32 lfo_am_cnt_out = lfo_am_cnt_bak;
|
||||||
UINT32 eg_timer_out = eg_timer_bak;
|
UINT32 eg_timer_out = eg_timer_bak;
|
||||||
|
@ -1726,28 +1650,59 @@ void YM3812UpdateOne(void *chip, float *buffer, int length)
|
||||||
|
|
||||||
for (i = 0; i <= (rhythm ? 5 : 8); ++i)
|
for (i = 0; i <= (rhythm ? 5 : 8); ++i)
|
||||||
{
|
{
|
||||||
OPL->lfo_am_cnt = lfo_am_cnt_bak;
|
Chip.lfo_am_cnt = lfo_am_cnt_bak;
|
||||||
OPL->eg_timer = eg_timer_bak;
|
Chip.eg_timer = eg_timer_bak;
|
||||||
OPL->eg_cnt = eg_cnt_bak;
|
Chip.eg_cnt = eg_cnt_bak;
|
||||||
if (CalcVoice (OPL, i, buffer, length))
|
if (CalcVoice (&Chip, i, buffer, length))
|
||||||
{
|
{
|
||||||
lfo_am_cnt_out = OPL->lfo_am_cnt;
|
lfo_am_cnt_out = Chip.lfo_am_cnt;
|
||||||
eg_timer_out = OPL->eg_timer;
|
eg_timer_out = Chip.eg_timer;
|
||||||
eg_cnt_out = OPL->eg_cnt;
|
eg_cnt_out = Chip.eg_cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OPL->lfo_am_cnt = lfo_am_cnt_out;
|
Chip.lfo_am_cnt = lfo_am_cnt_out;
|
||||||
OPL->eg_timer = eg_timer_out;
|
Chip.eg_timer = eg_timer_out;
|
||||||
OPL->eg_cnt = eg_cnt_out;
|
Chip.eg_cnt = eg_cnt_out;
|
||||||
|
|
||||||
if (rhythm) /* Rhythm part */
|
if (rhythm) /* Rhythm part */
|
||||||
{
|
{
|
||||||
OPL->lfo_am_cnt = lfo_am_cnt_bak;
|
Chip.lfo_am_cnt = lfo_am_cnt_bak;
|
||||||
OPL->eg_timer = eg_timer_bak;
|
Chip.eg_timer = eg_timer_bak;
|
||||||
OPL->eg_cnt = eg_cnt_bak;
|
Chip.eg_cnt = eg_cnt_bak;
|
||||||
CalcRhythm (OPL, buffer, length);
|
CalcRhythm (&Chip, buffer, length);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FString GetVoiceString(void *chip)
|
||||||
|
{
|
||||||
|
FM_OPL *OPL = (FM_OPL *)chip;
|
||||||
|
char out[9*3];
|
||||||
|
|
||||||
|
for (int i = 0; i <= 8; ++i)
|
||||||
|
{
|
||||||
|
int color;
|
||||||
|
|
||||||
|
if (OPL != NULL && (OPL->P_CH[i].SLOT[0].state != EG_OFF || OPL->P_CH[i].SLOT[1].state != EG_OFF))
|
||||||
|
{
|
||||||
|
color = 'D'; // Green means in use
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = 'A'; // Brick means free
|
||||||
|
}
|
||||||
|
out[i*3+0] = '\x1c';
|
||||||
|
out[i*3+1] = color;
|
||||||
|
out[i*3+2] = '*';
|
||||||
|
}
|
||||||
|
return FString (out, 9*3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OPLEmul *YM3812Init(bool stereo)
|
||||||
|
{
|
||||||
|
/* emulator create */
|
||||||
|
return new YM3812(stereo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Render a whole voice at once. If nothing else, it lets us avoid
|
// [RH] Render a whole voice at once. If nothing else, it lets us avoid
|
||||||
|
@ -1813,27 +1768,3 @@ static bool CalcRhythm (FM_OPL *OPL, float *buffer, int length)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString YM3812GetVoiceString(void *chip)
|
|
||||||
{
|
|
||||||
FM_OPL *OPL = (FM_OPL *)chip;
|
|
||||||
char out[9*3];
|
|
||||||
|
|
||||||
for (int i = 0; i <= 8; ++i)
|
|
||||||
{
|
|
||||||
int color;
|
|
||||||
|
|
||||||
if (OPL != NULL && (OPL->P_CH[i].SLOT[0].state != EG_OFF || OPL->P_CH[i].SLOT[1].state != EG_OFF))
|
|
||||||
{
|
|
||||||
color = 'D'; // Green means in use
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color = 'A'; // Brick means free
|
|
||||||
}
|
|
||||||
out[i*3+0] = '\x1c';
|
|
||||||
out[i*3+1] = color;
|
|
||||||
out[i*3+2] = '*';
|
|
||||||
}
|
|
||||||
return FString (out, 9*3);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,39 +1,11 @@
|
||||||
#ifndef __FMOPL_H_
|
#ifndef __FMOPL_H_
|
||||||
#define __FMOPL_H_
|
#define __FMOPL_H_
|
||||||
|
|
||||||
#include "zstring.h"
|
#include "opl.h"
|
||||||
|
|
||||||
// Multiplying OPL_SAMPLE_RATE by ADLIB_CLOCK_MUL gives the number
|
// Multiplying OPL_SAMPLE_RATE by ADLIB_CLOCK_MUL gives the number
|
||||||
// Adlib clocks per second, as used by the RAWADATA file format.
|
// Adlib clocks per second, as used by the RAWADATA file format.
|
||||||
|
|
||||||
/* compiler dependence */
|
OPLEmul *YM3812Init(bool stereo);
|
||||||
#ifndef OSD_CPU_H
|
|
||||||
#define OSD_CPU_H
|
|
||||||
typedef unsigned char UINT8; /* unsigned 8bit */
|
|
||||||
typedef unsigned short UINT16; /* unsigned 16bit */
|
|
||||||
typedef unsigned int UINT32; /* unsigned 32bit */
|
|
||||||
typedef signed char INT8; /* signed 8bit */
|
|
||||||
typedef signed short INT16; /* signed 16bit */
|
|
||||||
typedef signed int INT32; /* signed 32bit */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
|
|
||||||
typedef void (*OPL_IRQHANDLER)(int param,int irq);
|
|
||||||
typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
|
|
||||||
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
|
|
||||||
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
|
|
||||||
|
|
||||||
|
|
||||||
void *YM3812Init();
|
|
||||||
void YM3812Shutdown(void *chip);
|
|
||||||
void YM3812ResetChip(void *chip);
|
|
||||||
int YM3812Write(void *chip, int a, int v);
|
|
||||||
unsigned char YM3812Read(void *chip, int a);
|
|
||||||
void YM3812UpdateOne(void *chip, float *buffer, int length);
|
|
||||||
void YM3812SetStereo(void *chip, bool stereo);
|
|
||||||
void YM3812SetPanning(void *chip, int c, int pan);
|
|
||||||
|
|
||||||
FString YM3812GetVoiceString(void *chip);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -58,8 +58,8 @@ void OPLio::WriteDelay(int ticks)
|
||||||
|
|
||||||
void OPLio::OPLwriteReg(int which, uint reg, uchar data)
|
void OPLio::OPLwriteReg(int which, uint reg, uchar data)
|
||||||
{
|
{
|
||||||
YM3812Write (chips[which], 0, reg);
|
chips[which]->Write(0, reg);
|
||||||
YM3812Write (chips[which], 1, data);
|
chips[which]->Write(1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -256,7 +256,7 @@ void OPLio::OPLwritePan(uint channel, struct OPL2instrument *instr, int pan)
|
||||||
// Set real panning if we're using emulated chips.
|
// Set real panning if we're using emulated chips.
|
||||||
if (chips[0] != NULL)
|
if (chips[0] != NULL)
|
||||||
{
|
{
|
||||||
YM3812SetPanning(chips[channel/9], channel%9, pan+64);
|
chips[channel/9]->SetPanning(channel%9, pan+64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,33 +307,22 @@ void OPLio::OPLshutup(void)
|
||||||
int OPLio::OPLinit(uint numchips, bool stereo)
|
int OPLio::OPLinit(uint numchips, bool stereo)
|
||||||
{
|
{
|
||||||
assert(numchips >= 1 && numchips <= 2);
|
assert(numchips >= 1 && numchips <= 2);
|
||||||
chips[0] = YM3812Init();
|
uint i;
|
||||||
chips[1] = NULL;
|
memset(chips, 0, sizeof(chips));
|
||||||
if (chips[0] != NULL)
|
for (i = 0; i < numchips; ++i)
|
||||||
{
|
{
|
||||||
YM3812SetStereo(chips[0], stereo);
|
OPLEmul *chip = YM3812Init(stereo);
|
||||||
if (numchips > 1)
|
|
||||||
|
if (chip == NULL)
|
||||||
{
|
{
|
||||||
chips[1] = YM3812Init();
|
break;
|
||||||
if (chips[1] == NULL)
|
|
||||||
{
|
|
||||||
YM3812Shutdown(chips[0]);
|
|
||||||
chips[0] = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
else
|
chips[i] = chip;
|
||||||
{
|
|
||||||
YM3812SetStereo(chips[1], stereo);
|
|
||||||
}
|
}
|
||||||
}
|
NumChips = i;
|
||||||
}
|
OPLchannels = OPL2CHANNELS * i;
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
OPLchannels = OPL2CHANNELS * numchips;
|
|
||||||
OPLwriteInitState();
|
OPLwriteInitState();
|
||||||
return 0;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPLio::OPLwriteInitState()
|
void OPLio::OPLwriteInitState()
|
||||||
|
@ -352,8 +341,12 @@ void OPLio::OPLwriteInitState()
|
||||||
*/
|
*/
|
||||||
void OPLio::OPLdeinit(void)
|
void OPLio::OPLdeinit(void)
|
||||||
{
|
{
|
||||||
YM3812Shutdown (chips[0]);
|
for (size_t i = 0; i < countof(chips); ++i)
|
||||||
chips[0] = NULL;
|
{
|
||||||
YM3812Shutdown (chips[1]);
|
if (chips[i] != NULL)
|
||||||
chips[1] = NULL;
|
{
|
||||||
|
delete chips[i];
|
||||||
|
chips[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ OPLMIDIDevice::OPLMIDIDevice()
|
||||||
|
|
||||||
int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
int OPLMIDIDevice::Open(void (*callback)(unsigned int, void *, DWORD, DWORD), void *userdata)
|
||||||
{
|
{
|
||||||
if (io == NULL || io->OPLinit(TwoChips + 1, IsStereo))
|
if (io == NULL || 0 == io->OPLinit(TwoChips + 1, IsStereo))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ int DiskWriterIO::OPLinit(uint numchips, bool dontcare)
|
||||||
if (File == NULL)
|
if (File == NULL)
|
||||||
{
|
{
|
||||||
Printf("Could not open %s for writing.\n", Filename.GetChars());
|
Printf("Could not open %s for writing.\n", Filename.GetChars());
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Format == FMT_RDOS)
|
if (Format == FMT_RDOS)
|
||||||
|
@ -189,7 +189,7 @@ int DiskWriterIO::OPLinit(uint numchips, bool dontcare)
|
||||||
CurChip = 0;
|
CurChip = 0;
|
||||||
OPLchannels = OPL2CHANNELS * numchips;
|
OPLchannels = OPL2CHANNELS * numchips;
|
||||||
OPLwriteInitState();
|
OPLwriteInitState();
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -183,8 +183,9 @@ struct OPLio {
|
||||||
virtual void SetClockRate(double samples_per_tick);
|
virtual void SetClockRate(double samples_per_tick);
|
||||||
virtual void WriteDelay(int ticks);
|
virtual void WriteDelay(int ticks);
|
||||||
|
|
||||||
|
class OPLEmul *chips[2];
|
||||||
uint OPLchannels;
|
uint OPLchannels;
|
||||||
void *chips[2];
|
uint NumChips;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DiskWriterIO : public OPLio
|
struct DiskWriterIO : public OPLio
|
||||||
|
|
21
src/oplsynth/opl.h
Normal file
21
src/oplsynth/opl.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef OPL_H
|
||||||
|
#define OPL_H
|
||||||
|
|
||||||
|
#include "zstring.h"
|
||||||
|
|
||||||
|
// Abstract base class for OPL emulators
|
||||||
|
|
||||||
|
class OPLEmul
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OPLEmul() {}
|
||||||
|
virtual ~OPLEmul() {}
|
||||||
|
|
||||||
|
virtual void Reset() = 0;
|
||||||
|
virtual int Write(int a, int v) = 0;
|
||||||
|
virtual void Update(float *buffer, int length) = 0;
|
||||||
|
virtual void SetPanning(int c, int pan) = 0;
|
||||||
|
virtual FString GetVoiceString() { return FString(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -40,7 +40,7 @@ void OPLmusicBlock::ResetChips ()
|
||||||
TwoChips = !opl_onechip;
|
TwoChips = !opl_onechip;
|
||||||
ChipAccess.Enter();
|
ChipAccess.Enter();
|
||||||
io->OPLdeinit ();
|
io->OPLdeinit ();
|
||||||
io->OPLinit (TwoChips + 1, IsStereo);
|
TwoChips = io->OPLinit(TwoChips + 1, IsStereo) == 2;
|
||||||
ChipAccess.Leave();
|
ChipAccess.Leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ fail: delete[] scoredata;
|
||||||
memcpy(scoredata, &musiccache[0], len);
|
memcpy(scoredata, &musiccache[0], len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (io->OPLinit (TwoChips + 1))
|
if (0 == io->OPLinit (TwoChips + 1))
|
||||||
{
|
{
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -236,11 +236,14 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
||||||
double ticky = NextTickIn;
|
double ticky = NextTickIn;
|
||||||
int tick_in = int(NextTickIn);
|
int tick_in = int(NextTickIn);
|
||||||
int samplesleft = MIN(numsamples, tick_in);
|
int samplesleft = MIN(numsamples, tick_in);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (samplesleft > 0)
|
if (samplesleft > 0)
|
||||||
{
|
{
|
||||||
YM3812UpdateOne (io->chips[0], samples1, samplesleft);
|
for (i = 0; i < io->NumChips; ++i)
|
||||||
YM3812UpdateOne (io->chips[1], samples1, samplesleft);
|
{
|
||||||
|
io->chips[i]->Update(samples1, samplesleft);
|
||||||
|
}
|
||||||
OffsetSamples(samples1, samplesleft << int(IsStereo));
|
OffsetSamples(samples1, samplesleft << int(IsStereo));
|
||||||
assert(NextTickIn == ticky);
|
assert(NextTickIn == ticky);
|
||||||
NextTickIn -= samplesleft;
|
NextTickIn -= samplesleft;
|
||||||
|
@ -259,8 +262,10 @@ bool OPLmusicBlock::ServiceStream (void *buff, int numbytes)
|
||||||
{
|
{
|
||||||
if (numsamples > 0)
|
if (numsamples > 0)
|
||||||
{
|
{
|
||||||
YM3812UpdateOne (io->chips[0], samples1, numsamples);
|
for (i = 0; i < io->NumChips; ++i)
|
||||||
YM3812UpdateOne (io->chips[1], samples1, numsamples);
|
{
|
||||||
|
io->chips[i]->Update(samples1, samplesleft);
|
||||||
|
}
|
||||||
OffsetSamples(samples1, numsamples << int(IsStereo));
|
OffsetSamples(samples1, numsamples << int(IsStereo));
|
||||||
}
|
}
|
||||||
res = false;
|
res = false;
|
||||||
|
|
|
@ -2618,6 +2618,10 @@
|
||||||
RelativePath=".\src\oplsynth\muslib.h"
|
RelativePath=".\src\oplsynth\muslib.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\oplsynth\opl.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\oplsynth\opl_mus_player.cpp"
|
RelativePath=".\src\oplsynth\opl_mus_player.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue