Switched to OPL emulation to DOSBox dbopl emulator.

Fixed SB Pro v2.
Clarified GPL license in readme.txt.
This commit is contained in:
TomW 2014-02-27 19:42:06 +00:00
commit 78f2d4a229
13 changed files with 1985 additions and 5609 deletions

View file

@ -1,5 +1,7 @@
PCem v8.1
PCem is licensed under the GPL, see COPYING for more details.
Changes since v8:
- Fixed various issues with ROM detection/loading
@ -403,8 +405,8 @@ introduced in 1987. Has two Philips SAA1099, giving 12 voices of square waves pl
voices. In stereo!
Adlib
Has a Yamaha YM3812, giving 9 voices of 2 op FM, or 6 voices plus a useless section. PCem
uses Jarek Burczynski's emulator for this.
Has a Yamaha YM3812, giving 9 voices of 2 op FM, or 6 voices plus a rhythm section. PCem
uses the DOSBox dbopl emulator.
Adlib Gold
OPL3 with YM318Z 12-bit digital section. Possibly some bugs (not a lot of software to test).

View file

@ -1,4 +1,4 @@
VPATH = . mame
VPATH = . dosbox
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
@ -9,7 +9,7 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o \
mouse.o mouse_ps2.o mouse_serial.o neat.o nvr.o olivetti_m24.o \
opti.o pc.o pci.o pic.o piix.o pit.o ppi.o rom.o serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o \
sound_adlibgold.o sound_cms.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o \
sound_adlibgold.o sound_cms.o sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o \
sound_pas16.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o \
sound_wss.o soundopenal.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o \
vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
@ -20,7 +20,7 @@ OBJ = 386.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o \
vid_voodoo.o video.o wd76c10.o win.o win-d3d.o win-d3d-fs.o win-ddraw.o win-ddraw-fs.o win-keyboard.o win-midi.o \
win-mouse.o win-timer.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = fmopl.o ymf262.o
FMOBJ = dbopl.o
LIBS = -mwindows -lwinmm -lalut -lopenal32 -lddraw -ldinput -ldxguid -ld3d9

1520
src/dosbox/dbopl.cpp Normal file

File diff suppressed because it is too large Load diff

273
src/dosbox/dbopl.h Normal file
View file

@ -0,0 +1,273 @@
/*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//#include "adlib.h"
//#include "dosbox.h"
#include <stdint.h>
typedef signed int Bits;
typedef unsigned int Bitu;
typedef int8_t Bit8s;
typedef uint8_t Bit8u;
typedef int16_t Bit16s;
typedef uint16_t Bit16u;
typedef int32_t Bit32s;
typedef uint32_t Bit32u;
#define INLINE inline
#define GCC_UNLIKELY(x) (x)
//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
namespace DBOPL {
struct Chip;
struct Operator;
struct Channel;
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
typedef Channel* ( DBOPL::Channel::*SynthHandler) ( 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,
};
struct Operator {
public:
//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,
} State;
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;
private:
void SetState( Bit8u s );
void UpdateAttack( const Chip* chip );
void UpdateRelease( const Chip* chip );
void UpdateDecay( const Chip* chip );
public:
void UpdateAttenuation();
void UpdateRates( const Chip* chip );
void UpdateFrequency( );
void Write20( const Chip* chip, Bit8u val );
void Write40( const Chip* chip, Bit8u val );
void Write60( const Chip* chip, Bit8u val );
void Write80( const Chip* chip, Bit8u val );
void WriteE0( const Chip* chip, Bit8u val );
bool Silent() const;
void Prepare( const Chip* chip );
void KeyOn( Bit8u mask);
void KeyOff( Bit8u mask);
template< State state>
Bits TemplateVolume( );
Bit32s RateForward( Bit32u add );
Bitu ForwardWave();
Bitu ForwardVolume();
Bits GetSample( Bits modulation );
Bits GetWave( Bitu index, Bitu vol );
public:
Operator();
};
struct Channel {
Operator op[2];
inline Operator* Op( Bitu index ) {
return &( ( this + (index >> 1) )->op[ index & 1 ]);
}
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;
//Forward the channel data to the operators of the channel
void SetChanData( const Chip* chip, Bit32u data );
//Change in the chandata, check for new values and if we have to forward to operators
void UpdateFrequency( const Chip* chip, Bit8u fourOp );
void WriteA0( const Chip* chip, Bit8u val );
void WriteB0( const Chip* chip, Bit8u val );
void WriteC0( const Chip* chip, Bit8u val );
void ResetC0( const Chip* chip );
//call this for the first channel
template< bool opl3Mode >
void GeneratePercussion( Chip* chip, Bit32s* output );
//Generate blocks of data in specific modes
template<SynthMode mode>
Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
Channel();
};
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;
int is_opl3;
//Return the maximum amount of samples before and LFO change
Bit32u ForwardLFO( Bit32u samples );
Bit32u ForwardNoise();
void WriteBD( Bit8u val );
void WriteReg(Bit32u reg, Bit8u val );
Bit32u WriteAddr( Bit32u port, Bit8u val );
void GenerateBlock2( Bitu samples, Bit32s* output );
void GenerateBlock3( Bitu samples, Bit32s* output );
void Generate( Bit32u samples );
void Setup( Bit32u r, int chip_is_opl3 );
Chip();
};
/*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 InitTables( void );
}; //Namespace

File diff suppressed because it is too large Load diff

View file

@ -1,126 +0,0 @@
#pragma once
#ifndef __FMOPL_H__
#define __FMOPL_H__
#ifndef STUFF
#define STUFF
typedef int64_t attotime;
#define ATTOTIME_IN_HZ(x) (1000000000/(x))
#define attotime_mul(x,y) ((x)*(y))
#define attotime_to_double(x) ((double)(x)/1000000000.0)
#define attotime_zero 0
#define running_device void
#define INLINE static
//#define M_PI 3.142
#endif
/* --- select emulation chips --- */
#define BUILD_YM3812 (1)
#define BUILD_YM3526 (0)
#define BUILD_Y8950 (0)
/* select output bits size of output : 8 or 16 */
#define OPL_SAMPLE_BITS 16
/* compiler dependence */
#ifndef __OSDCOMM_H__
#define __OSDCOMM_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 /* __OSDCOMM_H__ */
typedef signed short OPLSAMPLE;
/*
#if (OPL_SAMPLE_BITS==16)
typedef INT16 OPLSAMPLE;
#endif
#if (OPL_SAMPLE_BITS==8)
typedef INT8 OPLSAMPLE;
#endif
*/
typedef void (*OPL_TIMERHANDLER)(void *param,int timer,attotime period);
typedef void (*OPL_IRQHANDLER)(void *param,int irq);
typedef void (*OPL_UPDATEHANDLER)(void *param,int min_interval_us);
typedef void (*OPL_PORTHANDLER_W)(void *param,unsigned char data);
typedef unsigned char (*OPL_PORTHANDLER_R)(void *param);
#if BUILD_YM3812
void *ym3812_init(running_device *device, UINT32 clock, UINT32 rate);
void ym3812_shutdown(void *chip);
void ym3812_reset_chip(void *chip);
int ym3812_write(void *chip, int a, int v);
unsigned char ym3812_read(void *chip, int a);
int ym3812_timer_over(void *chip, int c);
void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length);
void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
void ym3812_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
void ym3812_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
#endif /* BUILD_YM3812 */
#if BUILD_YM3526
/*
** Initialize YM3526 emulator(s).
**
** 'num' is the number of virtual YM3526's to allocate
** 'clock' is the chip clock in Hz
** 'rate' is sampling rate
*/
void *ym3526_init(running_device *device, UINT32 clock, UINT32 rate);
/* shutdown the YM3526 emulators*/
void ym3526_shutdown(void *chip);
void ym3526_reset_chip(void *chip);
int ym3526_write(void *chip, int a, int v);
unsigned char ym3526_read(void *chip, int a);
int ym3526_timer_over(void *chip, int c);
/*
** Generate samples for one of the YM3526's
**
** 'which' is the virtual YM3526 number
** '*buffer' is the output buffer pointer
** 'length' is the number of samples that should be generated
*/
void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length);
void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
void ym3526_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
void ym3526_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
#endif /* BUILD_YM3526 */
#if BUILD_Y8950
/* Y8950 port handlers */
void y8950_set_port_handler(void *chip, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, void *param);
void y8950_set_keyboard_handler(void *chip, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, void *param);
void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size );
void * y8950_init(running_device *device, UINT32 clock, UINT32 rate);
void y8950_shutdown(void *chip);
void y8950_reset_chip(void *chip);
int y8950_write(void *chip, int a, int v);
unsigned char y8950_read (void *chip, int a);
int y8950_timer_over(void *chip, int c);
void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length);
void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
void y8950_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
void y8950_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
#endif /* BUILD_Y8950 */
#endif /* __FMOPL_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,62 +0,0 @@
#pragma once
#ifndef __YMF262_H__
#define __YMF262_H__
#ifndef STUFF
#define STUFF
typedef int64_t attotime;
#define ATTOTIME_IN_HZ(x) (1000000000/(x))
#define attotime_mul(x,y) ((x)*(y))
#define attotime_to_double(x) ((double)(x)/1000000000.0)
#define attotime_zero 0
#define running_device void
#define INLINE static
//#define M_PI 3.142
#endif
/* select number of output bits: 8 or 16 */
#define OPL3_SAMPLE_BITS 16
/* compiler dependence */
#ifndef __OSDCOMM_H__
#define __OSDCOMM_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 signed short OPL3SAMPLE;
//typedef stream_sample_t OPL3SAMPLE;
/*
#if (OPL3_SAMPLE_BITS==16)
typedef INT16 OPL3SAMPLE;
#endif
#if (OPL3_SAMPLE_BITS==8)
typedef INT8 OPL3SAMPLE;
#endif
*/
typedef void (*OPL3_TIMERHANDLER)(void *param,int timer,attotime period);
typedef void (*OPL3_IRQHANDLER)(void *param,int irq);
typedef void (*OPL3_UPDATEHANDLER)(void *param,int min_interval_us);
void *ymf262_init(running_device *device, int clock, int rate);
void ymf262_shutdown(void *chip);
void ymf262_reset_chip(void *chip);
int ymf262_write(void *chip, int a, int v);
unsigned char ymf262_read(void *chip, int a);
int ymf262_timer_over(void *chip, int c);
void ymf262_update_one(void *chip, OPL3SAMPLE **buffers, int length);
void ymf262_set_timer_handler(void *chip, OPL3_TIMERHANDLER TimerHandler, void *param);
void ymf262_set_irq_handler(void *chip, OPL3_IRQHANDLER IRQHandler, void *param);
void ymf262_set_update_handler(void *chip, OPL3_UPDATEHANDLER UpdateHandler, void *param);
#endif /* __YMF262_H__ */

View file

@ -34,7 +34,7 @@ static SOUND_CARD sound_cards[] =
{"Sound Blaster 1.5", &sb_15_device},
{"Sound Blaster 2.0", &sb_2_device},
{"Sound Blaster Pro v1", &sb_pro_v1_device},
{"Sound Blaster Pro v2", &sb_pro_v1_device},
{"Sound Blaster Pro v2", &sb_pro_v2_device},
{"Sound Blaster 16", &sb_16_device},
{"Sound Blaster AWE32", &sb_awe32_device},
{"Adlib Gold", &adgold_device},

144
src/sound_dbopl.cc Normal file
View file

@ -0,0 +1,144 @@
#include "dosbox/dbopl.h"
#include "sound_dbopl.h"
static struct
{
DBOPL::Chip chip;
int addr;
int timer[2];
uint8_t timer_ctrl;
uint8_t status_mask;
uint8_t status;
int is_opl3;
void (*timer_callback)(void *param, int timer, int64_t period);
void *timer_param;
} opl[2];
enum
{
STATUS_TIMER_1 = 0x40,
STATUS_TIMER_2 = 0x20,
STATUS_TIMER_ALL = 0x80
};
enum
{
CTRL_IRQ_RESET = 0x80,
CTRL_TIMER1_MASK = 0x40,
CTRL_TIMER2_MASK = 0x20,
CTRL_TIMER2_CTRL = 0x02,
CTRL_TIMER1_CTRL = 0x01
};
void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3)
{
DBOPL::InitTables();
opl[nr].chip.Setup(48000, is_opl3);
opl[nr].timer_callback = timer_callback;
opl[nr].timer_param = timer_param;
opl[nr].is_opl3 = is_opl3;
}
void opl_status_update(int nr)
{
if (opl[nr].status & (STATUS_TIMER_1 | STATUS_TIMER_2) & opl[nr].status_mask)
opl[nr].status |= STATUS_TIMER_ALL;
else
opl[nr].status &= ~STATUS_TIMER_ALL;
}
void opl_timer_over(int nr, int timer)
{
if (!timer)
{
opl[nr].status |= STATUS_TIMER_1;
opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4);
}
else
{
opl[nr].status |= STATUS_TIMER_2;
opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16);
}
opl_status_update(nr);
}
void opl_write(int nr, uint16_t addr, uint8_t val)
{
if (!(addr & 1))
opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & (opl[nr].is_opl3 ? 0x1ff : 0xff);
else
{
opl[nr].chip.WriteReg(opl[nr].addr, val);
switch (opl[nr].addr)
{
case 0x02: /*Timer 1*/
opl[nr].timer[0] = 256 - val;
break;
case 0x03: /*Timer 2*/
opl[nr].timer[1] = 256 - val;
break;
case 0x04: /*Timer control*/
if (val & CTRL_IRQ_RESET) /*IRQ reset*/
{
opl[nr].status &= ~(STATUS_TIMER_1 | STATUS_TIMER_2);
opl_status_update(nr);
return;
}
if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER1_CTRL)
{
if (val & CTRL_TIMER1_CTRL)
opl[nr].timer_callback(opl[nr].timer_param, 0, opl[nr].timer[0] * 4);
else
opl[nr].timer_callback(opl[nr].timer_param, 0, 0);
}
if ((val ^ opl[nr].timer_ctrl) & CTRL_TIMER2_CTRL)
{
if (val & CTRL_TIMER2_CTRL)
opl[nr].timer_callback(opl[nr].timer_param, 1, opl[nr].timer[1] * 16);
else
opl[nr].timer_callback(opl[nr].timer_param, 1, 0);
}
opl[nr].status_mask = (~val & (CTRL_TIMER1_MASK | CTRL_TIMER2_MASK)) | 0x80;
opl[nr].timer_ctrl = val;
break;
}
}
}
uint8_t opl_read(int nr, uint16_t addr)
{
if (!(addr & 1))
{
return (opl[nr].status & opl[nr].status_mask) | 0x06;
}
return 0xff;
}
void opl2_update(int nr, int16_t *buffer, int samples)
{
int c;
Bit32s buffer_32[samples];
opl[nr].chip.GenerateBlock2(samples, buffer_32);
for (c = 0; c < samples; c++)
buffer[c] = (int16_t)buffer_32[c];
}
void opl3_update(int nr, int16_t *bufferl, int16_t *bufferr, int samples)
{
int c;
Bit32s buffer_32[samples*2];
opl[nr].chip.GenerateBlock3(samples, buffer_32);
for (c = 0; c < samples; c++)
{
bufferl[c] = (int16_t)buffer_32[c*2];
bufferr[c] = (int16_t)buffer_32[(c*2)+1];
}
}

12
src/sound_dbopl.h Normal file
View file

@ -0,0 +1,12 @@
#ifdef __cplusplus
extern "C" {
#endif
void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3);
void opl_write(int nr, uint16_t addr, uint8_t val);
uint8_t opl_read(int nr, uint16_t addr);
void opl_timer_over(int nr, int timer);
void opl2_update(int nr, int16_t *buffer, int samples);
void opl3_update(int nr, int16_t *bufferl, int16_t *bufferr, int samples);
#ifdef __cplusplus
}
#endif

View file

@ -3,6 +3,7 @@
#include "ibm.h"
#include "io.h"
#include "sound_opl.h"
#include "sound_dbopl.h"
/*Interfaces between PCem and the actual OPL emulator*/
@ -12,14 +13,14 @@ uint8_t opl2_read(uint16_t a, void *priv)
opl_t *opl = (opl_t *)priv;
cycles -= (int)(isa_timing * 8);
return ym3812_read(opl->YM3812[0], a);
return opl_read(0, a);
}
void opl2_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
ym3812_write(opl->YM3812[0],a,v);
ym3812_write(opl->YM3812[1],a,v);
opl_write(0, a, v);
opl_write(1, a, v);
}
uint8_t opl2_l_read(uint16_t a, void *priv)
@ -27,13 +28,13 @@ uint8_t opl2_l_read(uint16_t a, void *priv)
opl_t *opl = (opl_t *)priv;
cycles -= (int)(isa_timing * 8);
return ym3812_read(opl->YM3812[0], a);
return opl_read(0, a);
}
void opl2_l_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
ym3812_write(opl->YM3812[0],a,v);
opl_write(0, a, v);
}
uint8_t opl2_r_read(uint16_t a, void *priv)
@ -41,13 +42,13 @@ uint8_t opl2_r_read(uint16_t a, void *priv)
opl_t *opl = (opl_t *)priv;
cycles -= (int)(isa_timing * 8);
return ym3812_read(opl->YM3812[1], a);
return opl_read(1, a);
}
void opl2_r_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
ym3812_write(opl->YM3812[1],a,v);
opl_write(1, a, v);
}
uint8_t opl3_read(uint16_t a, void *priv)
@ -55,20 +56,20 @@ uint8_t opl3_read(uint16_t a, void *priv)
opl_t *opl = (opl_t *)priv;
cycles -= (int)(isa_timing * 8);
return ymf262_read(opl->YMF262, a);
return opl_read(0, a);
}
void opl3_write(uint16_t a, uint8_t v, void *priv)
{
opl_t *opl = (opl_t *)priv;
ymf262_write(opl->YMF262, a, v);
opl_write(0, a, v);
}
void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr)
{
ym3812_update_one(opl->YM3812[0], bufl, 1);
ym3812_update_one(opl->YM3812[1], bufr, 1);
opl2_update(0, bufl, 1);
opl2_update(1, bufr, 1);
opl->filtbuf[0] = *bufl = ((*bufl) / 4) + ((opl->filtbuf[0] * 11) / 16);
opl->filtbuf[1] = *bufr = ((*bufr) / 4) + ((opl->filtbuf[1] * 11) / 16);
@ -76,31 +77,31 @@ void opl2_poll(opl_t *opl, int16_t *bufl, int16_t *bufr)
if (opl->timers_enable[0][0])
{
opl->timers[0][0]--;
if (opl->timers[0][0] < 0) ym3812_timer_over(opl->YM3812[0], 0);
if (opl->timers[0][0] < 0) opl_timer_over(0, 0);
}
if (opl->timers_enable[0][1])
{
opl->timers[0][1]--;
if (opl->timers[0][1] < 0) ym3812_timer_over(opl->YM3812[0], 1);
if (opl->timers[0][1] < 0) opl_timer_over(0, 1);
}
if (opl->timers_enable[1][0])
{
opl->timers[1][0]--;
if (opl->timers[1][0] < 0) ym3812_timer_over(opl->YM3812[1], 0);
if (opl->timers[1][0] < 0) opl_timer_over(1, 0);
}
if (opl->timers_enable[1][1])
{
opl->timers[1][1]--;
if (opl->timers[1][1] < 0) ym3812_timer_over(opl->YM3812[1], 1);
if (opl->timers[1][1] < 0) opl_timer_over(1, 1);
}
}
void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr)
{
ymf262_update_one(opl->YMF262, opl->bufs, 1);
opl3_update(0, bufl, bufr, 1);
opl->filtbuf[0] = *bufl = ((opl->bufs[0][0]) / 4) + ((opl->filtbuf[0] * 11) / 16);
opl->filtbuf[1] = *bufr = ((opl->bufs[1][0]) / 4) + ((opl->filtbuf[1] * 11) / 16);
opl->filtbuf[0] = *bufl = ((*bufl) / 4) + ((opl->filtbuf[0] * 11) / 16);
opl->filtbuf[1] = *bufr = ((*bufr) / 4) + ((opl->filtbuf[1] * 11) / 16);
if (opl->timers_enable[0][0])
{
@ -108,7 +109,7 @@ void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr)
if (opl->timers[0][0] < 0)
{
opl->timers_enable[0][0] = 0;
ymf262_timer_over(opl->YMF262, 0);
opl_timer_over(0, 0);
}
}
if (opl->timers_enable[0][1])
@ -117,12 +118,12 @@ void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr)
if (opl->timers[0][1] < 0)
{
opl->timers_enable[0][1] = 0;
ymf262_timer_over(opl->YMF262, 1);
opl_timer_over(0, 1);
}
}
}
void ym3812_timer_set_0(void *param, int timer, attotime period)
void ym3812_timer_set_0(void *param, int timer, int64_t period)
{
opl_t *opl = (opl_t *)param;
@ -130,7 +131,7 @@ void ym3812_timer_set_0(void *param, int timer, attotime period)
if (!opl->timers[0][timer]) opl->timers[0][timer] = 1;
opl->timers_enable[0][timer] = period ? 1 : 0;
}
void ym3812_timer_set_1(void *param, int timer, attotime period)
void ym3812_timer_set_1(void *param, int timer, int64_t period)
{
opl_t *opl = (opl_t *)param;
@ -139,7 +140,7 @@ void ym3812_timer_set_1(void *param, int timer, attotime period)
opl->timers_enable[1][timer] = period ? 1 : 0;
}
void ymf262_timer_set(void *param, int timer, attotime period)
void ymf262_timer_set(void *param, int timer, int64_t period)
{
opl_t *opl = (opl_t *)param;
@ -150,46 +151,12 @@ void ymf262_timer_set(void *param, int timer, attotime period)
void opl2_init(opl_t *opl)
{
opl->bufs[0] = (int16_t *)malloc(4);
opl->bufs[1] = (int16_t *)malloc(4);
opl->bufs[2] = (int16_t *)malloc(4);
opl->bufs[3] = (int16_t *)malloc(4);
opl->YM3812[0] = ym3812_init(NULL, 3579545, 48000);
ym3812_reset_chip(opl->YM3812[0]);
ym3812_set_timer_handler(opl->YM3812[0], ym3812_timer_set_0, opl);
opl->YM3812[1] = ym3812_init(NULL, 3579545, 48000);
ym3812_reset_chip(opl->YM3812[1]);
ym3812_set_timer_handler(opl->YM3812[1], ym3812_timer_set_1, opl);
opl_init(ym3812_timer_set_0, opl, 0, 0);
opl_init(ym3812_timer_set_1, opl, 1, 0);
}
void opl3_init(opl_t *opl)
{
opl->bufs[0] = (int16_t *)malloc(4);
opl->bufs[1] = (int16_t *)malloc(4);
opl->bufs[2] = (int16_t *)malloc(4);
opl->bufs[3] = (int16_t *)malloc(4);
opl->YMF262 = ymf262_init(NULL, 3579545 * 4, 48000);
ymf262_reset_chip(opl->YMF262);
ymf262_set_timer_handler(opl->YMF262, ymf262_timer_set, opl);
opl_init(ymf262_timer_set, opl, 0, 1);
}
void opl2_close(opl_t *opl)
{
free(opl->bufs[0]);
free(opl->bufs[1]);
ym3812_shutdown(opl->YM3812[0]);
ym3812_shutdown(opl->YM3812[1]);
}
void opl3_close(opl_t *opl)
{
free(opl->bufs[0]);
free(opl->bufs[1]);
ym3812_shutdown(opl->YM3812[0]);
ymf262_shutdown(opl->YMF262);
}

View file

@ -1,21 +1,13 @@
#include "mame/fmopl.h"
#include "mame/ymf262.h"
typedef struct opl_t
{
void *YM3812[2];
void *YMF262;
int chip_nr[2];
int timers[2][2];
int timers_enable[2][2];
int16_t *bufs[4];
int16_t filtbuf[2];
} opl_t;
uint8_t opl_read(uint16_t a, void *priv);
void opl_write(uint16_t a, uint8_t v, void *priv);
uint8_t opl2_read(uint16_t a, void *priv);
void opl2_write(uint16_t a, uint8_t v, void *priv);
uint8_t opl2_l_read(uint16_t a, void *priv);
@ -30,6 +22,3 @@ void opl3_poll(opl_t *opl, int16_t *bufl, int16_t *bufr);
void opl2_init(opl_t *opl);
void opl3_init(opl_t *opl);
void opl2_close(opl_t *opl);
void opl3_close(opl_t *opl);