1
0
Fork 0

Add emu.h header to make the mame files work without too many changes

Small changes to remove or disable timer and update handlers
Add cheap sample rate conversion to the sn76496 emulation

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/branches/mamesound@4032
This commit is contained in:
Sjoerd van der Berg 2017-08-12 09:17:33 +00:00
parent 6c796f4162
commit 051c0f3afd
8 changed files with 197 additions and 38 deletions

123
src/hardware/mame/emu.h Normal file
View file

@ -0,0 +1,123 @@
#ifndef DOSBOX_EMU_H
#define DOSBOX_EMU_H
#include "dosbox.h"
#include <stdint.h>
#include <math.h>
#include <float.h>
#include <stdlib.h>
#include <memory.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
typedef Bit16s stream_sample_t;
typedef Bit8u u8;
typedef Bit32u u32;
class device_t;
struct machine_config;
#define NAME( _ASDF_ ) 0
#define BIT( _INPUT_, _BIT_ ) ( ( _INPUT_) >> (_BIT_)) & 1
#define ATTR_UNUSED
#define DECLARE_READ8_MEMBER(name) u8 name( int, int)
#define DECLARE_WRITE8_MEMBER(name) void name( int, int, u8 data)
#define READ8_MEMBER(name) u8 name( int, int)
#define WRITE8_MEMBER(name) void name( int offset, int space, u8 data)
#define DECLARE_DEVICE_TYPE(Type, Class) \
extern const device_type Type; \
class Class;
#define DEFINE_DEVICE_TYPE(Type, Class, ShortName, FullName) \
const device_type Type = 0;
class device_sound_interface {
public:
struct sound_stream {
void update() {
}
};
sound_stream temp;
sound_stream* stream_alloc(int whatever, int channels, int size) {
return &temp;
};
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) = 0;
device_sound_interface(const machine_config &mconfig, device_t& _device) {
}
};
struct attotime {
int whatever;
static attotime from_hz(int hz) {
return attotime();
}
};
struct machine_config {
};
typedef int device_type;
class device_t {
u32 clockRate;
public:
struct machine_t {
int describe_context() const {
return 0;
}
};
machine_t machine() const {
return machine_t();
}
//int offset, space;
u32 clock() const {
return clockRate;
}
void logerror(const char* msg, ...) {
}
static int tag() {
return 0;
}
virtual void device_start() {
}
void save_item(int wtf, int blah= 0) {
}
device_t(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 _clock) : clockRate( _clock ) {
}
};
static void auto_free(const device_t::machine_t& machine, void * buffer) {
free(buffer);
}
#define auto_alloc_array_clear(m, t, c) calloc(c, sizeof(t) )
#define auto_alloc_clear(m, t) static_cast<t*>( calloc(1, sizeof(t) ) )
#endif

View file

@ -379,7 +379,7 @@ struct FM_OPL
uint32_t clock; /* master clock (Hz) */
uint32_t rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
attotime TimerBase; /* Timer base time (==sampling time)*/
//attotime TimerBase; /* Timer base time (==sampling time)*/
device_t *device;
signed int phase_modulation; /* phase modulation input (SLOT 2) */
@ -1434,7 +1434,7 @@ void FM_OPL::initialize()
/*logerror("freqbase=%f\n", freqbase);*/
/* Timer base time */
TimerBase = attotime::from_hz(clock) * 72;
//TimerBase = attotime::from_hz(clock) * 72;
/* make fnumber -> increment counter table */
for( i=0 ; i < 1024 ; i++ )
@ -1514,6 +1514,7 @@ void FM_OPL::WriteReg(int r, int v)
case 0x03: /* Timer 2 */
T[1] = (256-v)*16;
break;
#if 0
case 0x04: /* IRQ clear / mask and Timer enable */
if(v&0x80)
{ /* IRQ flag clear */
@ -1544,6 +1545,7 @@ void FM_OPL::WriteReg(int r, int v)
}
}
break;
#endif
#if BUILD_Y8950
case 0x06: /* Key Board OUT */
if(type&OPL_TYPE_KEYBOARD)
@ -1846,6 +1848,7 @@ void FM_OPL::postload()
} // anonymous namespace
#if 0
static void OPLsave_state_channel(device_t *device, OPL_CH *CH)
{
int slot, ch;
@ -1887,7 +1890,6 @@ static void OPLsave_state_channel(device_t *device, OPL_CH *CH)
}
}
/* Register savestate for a virtual YM3812/YM3526Y8950 */
static void OPL_save_state(FM_OPL *OPL, device_t *device)
@ -1936,6 +1938,8 @@ static void OPL_save_state(FM_OPL *OPL, device_t *device)
device->machine().save().register_postload(save_prepost_delegate(FUNC(FM_OPL::postload), OPL));
}
#endif
static void OPL_clock_changed(FM_OPL *OPL, uint32_t clock, uint32_t rate)
{
OPL->clock = clock;
@ -2103,7 +2107,6 @@ static inline void CSMKeyControll(OPL_CH *CH)
CH->SLOT[SLOT2].KEYOFF(~4);
}
static int OPLTimerOver(FM_OPL *OPL,int c)
{
if( c )
@ -2123,15 +2126,14 @@ static int OPLTimerOver(FM_OPL *OPL,int c)
}
}
/* reload timer */
if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,OPL->TimerBase * OPL->T[c]);
//if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,OPL->TimerBase * OPL->T[c]);
return OPL->status>>7;
}
#define MAX_OPL_CHIPS 2
#if (BUILD_YM3812)
#if BUILD_YM3812
void ym3812_clock_changed(void *chip, uint32_t clock, uint32_t rate)
{
@ -2144,7 +2146,7 @@ void * ym3812_init(device_t *device, uint32_t clock, uint32_t rate)
FM_OPL *YM3812 = OPLCreate(device,clock,rate,OPL_TYPE_YM3812);
if (YM3812)
{
OPL_save_state(YM3812, device);
//OPL_save_state(YM3812, device);
ym3812_reset_chip(YM3812);
}
return YM3812;
@ -2197,7 +2199,6 @@ void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,device
OPLSetUpdateHandler(YM3812, UpdateHandler, device);
}
/*
** Generate samples for one of the YM3812's
**
@ -2277,7 +2278,7 @@ void *ym3526_init(device_t *device, uint32_t clock, uint32_t rate)
FM_OPL *YM3526 = OPLCreate(device,clock,rate,OPL_TYPE_YM3526);
if (YM3526)
{
OPL_save_state(YM3526, device);
//OPL_save_state(YM3526, device);
ym3526_reset_chip(YM3526);
}
return YM3526;
@ -2425,7 +2426,7 @@ void *y8950_init(device_t *device, uint32_t clock, uint32_t rate)
/*Y8950->deltat->write_time = 10.0 / clock;*/ /* a single byte write takes 10 cycles of main clock */
/*Y8950->deltat->read_time = 8.0 / clock;*/ /* a single byte read takes 8 cycles of main clock */
/* reset */
OPL_save_state(Y8950, device);
//OPL_save_state(Y8950, device);
y8950_reset_chip(Y8950);
}
@ -2569,4 +2570,5 @@ void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,O
OPL->keyboard_param = device;
}
#endif

View file

@ -9,9 +9,9 @@
/* --- select emulation chips --- */
#define BUILD_YM3812 (1)
#define BUILD_YM3526 (1)
#define BUILD_Y8950 (1)
#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

View file

@ -125,7 +125,8 @@ static constexpr uint8_t envelope[8][64] = {
// device type definition
DEFINE_DEVICE_TYPE(SAA1099, saa1099_device, "saa1099", "Philips SAA1099")
//DEFINE_DEVICE_TYPE(SAA1099, saa1099_device, "saa1099", "Philips SAA1099")
#define SAA1099 1
//**************************************************************************
// LIVE DEVICE

View file

@ -37,7 +37,7 @@ public:
DECLARE_WRITE8_MEMBER( write );
protected:
//protected:
// device-level overrides
virtual void device_start() override;

View file

@ -128,7 +128,8 @@
#include "sn76496.h"
#define MAX_OUTPUT 0x7fff
//When you go over this create sample
#define RATE_MAX ( 1 << 30)
sn76496_base_device::sn76496_base_device(
const machine_config &mconfig,
@ -145,7 +146,7 @@ sn76496_base_device::sn76496_base_device(
uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, m_ready_handler(*this)
// , m_ready_handler(*this)
, m_feedback_mask(feedbackmask)
, m_whitenoise_tap1(noisetap1)
, m_whitenoise_tap2(noisetap2)
@ -156,6 +157,7 @@ sn76496_base_device::sn76496_base_device(
{
}
sn76496_device::sn76496_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: sn76496_base_device(mconfig, SN76496, tag, 0x10000, 0x04, 0x08, false, false, 8, true, owner, clock)
{
@ -206,17 +208,19 @@ segapsg_device::segapsg_device(const machine_config &mconfig, const char *tag, d
{
}
void sn76496_base_device::device_start()
{
int sample_rate = clock()/2;
sample_rate = clock()/2;
rate_add = RATE_MAX;
rate_counter = 0;
int i;
double out;
int gain;
m_ready_handler.resolve_safe();
//m_ready_handler.resolve_safe();
m_sound = machine().sound().stream_alloc(*this, 0, (m_stereo? 2:1), sample_rate);
//m_sound = machine().sound().stream_alloc(*this, 0, (m_stereo? 2:1), sample_rate);
for (i = 0; i < 4; i++) m_volume[i] = 0;
@ -264,14 +268,14 @@ void sn76496_base_device::device_start()
m_ready_state = true;
register_for_save_states();
//register_for_save_states();
}
WRITE8_MEMBER( sn76496_base_device::stereo_w )
{
m_sound->update();
if (m_stereo) m_stereo_mask = data;
else fatalerror("sn76496_base_device: Call to stereo write with mono chip!\n");
// m_sound->update();
// if (m_stereo) m_stereo_mask = data;
// else fatalerror("sn76496_base_device: Call to stereo write with mono chip!\n");
}
void sn76496_base_device::write(uint8_t data)
@ -279,7 +283,7 @@ void sn76496_base_device::write(uint8_t data)
int n, r, c;
// update the output buffer before changing the registers
m_sound->update();
// m_sound->update();
// set number of cycles until READY is active; this is always one
// 'sample', i.e. it equals the clock divider exactly
@ -347,12 +351,12 @@ void sn76496_base_device::countdown_cycles()
if (m_cycles_to_ready > 0)
{
m_cycles_to_ready--;
if (m_ready_state==true) m_ready_handler(CLEAR_LINE);
//if (m_ready_state==true) m_ready_handler(CLEAR_LINE);
m_ready_state = false;
}
else
{
if (m_ready_state==false) m_ready_handler(ASSERT_LINE);
//if (m_ready_state==false) m_ready_handler(ASSERT_LINE);
m_ready_state = true;
}
}
@ -412,6 +416,12 @@ void sn76496_base_device::sound_stream_update(sound_stream &stream, stream_sampl
}
}
//Skip final generation if you don't need an actual sample
rate_counter += rate_add;
if (rate_counter < RATE_MAX)
continue;
rate_counter -= RATE_MAX;
if (m_stereo)
{
out = ((((m_stereo_mask & 0x10)!=0) && (m_output[0]!=0))? m_volume[0] : 0)
@ -433,13 +443,19 @@ void sn76496_base_device::sound_stream_update(sound_stream &stream, stream_sampl
}
if (m_negate) { out = -out; out2 = -out2; }
*(lbuffer++) = out;
if (m_stereo) *(rbuffer++) = out2;
samples--;
}
}
void sn76496_base_device::convert_samplerate(int32_t target_rate) {
//Simple 10 bit shift for samplerate conversion
rate_add = (int32_t)( RATE_MAX * (target_rate / (double)sample_rate) );
rate_counter = 0;
}
void sn76496_base_device::register_for_save_states()
{
save_item(NAME(m_vol_table));
@ -472,3 +488,4 @@ DEFINE_DEVICE_TYPE(SN94624, sn94624_device, "sn94624", "SN94624")
DEFINE_DEVICE_TYPE(NCR7496, ncr7496_device, "ncr7496", "NCR7496")
DEFINE_DEVICE_TYPE(GAMEGEAR, gamegear_device, "gamegear_psg", "Game Gear PSG")
DEFINE_DEVICE_TYPE(SEGAPSG, segapsg_device, "segapsg", "Sega VDP PSG")

View file

@ -17,21 +17,26 @@ DECLARE_DEVICE_TYPE(NCR7496, ncr7496_device)
DECLARE_DEVICE_TYPE(GAMEGEAR, gamegear_device)
DECLARE_DEVICE_TYPE(SEGAPSG, segapsg_device)
#if 0
#define MCFG_SN76496_READY_HANDLER(cb) \
devcb = &sn76496_base_device::set_ready_handler(*device, (DEVCB_##cb));
#endif
class sn76496_base_device : public device_t, public device_sound_interface
{
public:
// static configuration helpers
template <class Object> static devcb_base &set_ready_handler(device_t &device, Object &&cb) { return downcast<sn76496_base_device &>(device).m_ready_handler.set_callback(std::forward<Object>(cb)); }
// template <class Object> static devcb_base &set_ready_handler(device_t &device, Object &&cb) { return downcast<sn76496_base_device &>(device).m_ready_handler.set_callback(std::forward<Object>(cb)); }
DECLARE_WRITE8_MEMBER( stereo_w );
void write(uint8_t data);
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; }
// DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; }
void convert_samplerate(int32_t target_rate);
protected:
sn76496_base_device(
const machine_config &mconfig,
@ -55,11 +60,13 @@ private:
void register_for_save_states();
void countdown_cycles();
bool m_ready_state;
devcb_write_line m_ready_handler;
//devcb_write_line m_ready_handler;
sound_stream* m_sound;
//sound_stream* m_sound;
const int32_t m_feedback_mask; // mask for feedback
const int32_t m_whitenoise_tap1; // mask for white noise tap 1 (higher one, usually bit 14)
@ -80,6 +87,11 @@ private:
int32_t m_count[4]; // Position within the waveform
int32_t m_output[4]; // 1-bit output of each channel, pre-volume
int32_t m_cycles_to_ready; // number of cycles until the READY line goes active
//Modifications for easier sample conversion
int32_t sample_rate;
//Sample rate conversion
int32_t rate_add;
int32_t rate_counter;
};
// SN76496: Whitenoise verified, phase verified, periodic verified (by Michael Zapf)

View file

@ -279,7 +279,7 @@ struct OPL3
int clock; /* master clock (Hz) */
int rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
attotime TimerBase; /* Timer base time (==sampling time)*/
//attotime TimerBase; /* Timer base time (==sampling time)*/
device_t *device;
/* Optional handlers */
@ -1351,7 +1351,7 @@ static void OPL3_initalize(OPL3 *chip)
/* logerror("YMF262: freqbase=%f\n", chip->freqbase); */
/* Timer base time */
chip->TimerBase = attotime::from_hz(chip->clock) * (8*36);
//chip->TimerBase = attotime::from_hz(chip->clock) * (8*36);
/* make fnumber -> increment counter table */
for( i=0 ; i < 1024 ; i++ )
@ -1745,6 +1745,7 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
case 0x03: /* Timer 2 */
chip->T[1] = (256-v)*16;
break;
#if 0
case 0x04: /* IRQ clear / mask and Timer enable */
if(v&0x80)
{ /* IRQ flags clear */
@ -1774,6 +1775,7 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,0,period);
}
}
#endif
break;
case 0x08: /* x,NTS,x,x, x,x,x,x */
chip->nts = v;
@ -2356,7 +2358,7 @@ static OPL3 *OPL3Create(device_t *device, int clock, int rate, int type)
if (OPL3_LockTable(device) == -1) return nullptr;
/* allocate memory block */
chip = auto_alloc_clear(device->machine(), <OPL3>());
chip = auto_alloc_clear(device->machine(), OPL3 );
chip->device = device;
chip->type = type;
@ -2452,11 +2454,12 @@ static int OPL3TimerOver(OPL3 *chip,int c)
OPL3_STATUS_SET(chip,0x40);
}
/* reload timer */
if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,c,chip->TimerBase * chip->T[c]);
// if (chip->timer_handler) (chip->timer_handler)(chip->TimerParam,c,chip->TimerBase * chip->T[c]);
return chip->status>>7;
}
static void OPL3_save_state(OPL3 *chip, device_t *device) {
#if 0
for (int ch=0; ch<18; ch++) {
OPL3_CH *channel = &chip->P_CH[ch];
device->save_item(NAME(channel->block_fnum), ch);
@ -2521,6 +2524,7 @@ static void OPL3_save_state(OPL3 *chip, device_t *device) {
device->save_item(NAME(chip->address));
device->save_item(NAME(chip->status));
device->save_item(NAME(chip->statusmask));
#endif
}
void * ymf262_init(device_t *device, int clock, int rate)