mirror of
https://github.com/holub/mame
synced 2025-06-06 04:43:45 +03:00
Modernized TX1 custom sound device. [Osso]
This commit is contained in:
parent
8e4b11a87e
commit
68a838669d
@ -8,112 +8,8 @@
|
||||
#include "sound/ay8910.h"
|
||||
#include "video/resnet.h"
|
||||
#include "includes/tx1.h"
|
||||
#include "devlegcy.h"
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* 8253 Programmable Interval Timer
|
||||
*
|
||||
*************************************/
|
||||
struct pit8253_state
|
||||
{
|
||||
union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { UINT8 LSB; UINT8 MSB; };
|
||||
#else
|
||||
struct { UINT8 MSB; UINT8 LSB; };
|
||||
#endif
|
||||
UINT16 val;
|
||||
} counts[3];
|
||||
|
||||
int idx[3];
|
||||
};
|
||||
|
||||
struct tx1_sound_state
|
||||
{
|
||||
sound_stream *m_stream;
|
||||
UINT32 m_freq_to_step;
|
||||
UINT32 m_step0;
|
||||
UINT32 m_step1;
|
||||
UINT32 m_step2;
|
||||
|
||||
pit8253_state m_pit8253;
|
||||
|
||||
UINT8 m_ay_outputa;
|
||||
UINT8 m_ay_outputb;
|
||||
|
||||
stream_sample_t m_pit0;
|
||||
stream_sample_t m_pit1;
|
||||
stream_sample_t m_pit2;
|
||||
|
||||
double m_weights0[4];
|
||||
double m_weights1[3];
|
||||
double m_weights2[3];
|
||||
int m_eng0[4];
|
||||
int m_eng1[4];
|
||||
int m_eng2[4];
|
||||
|
||||
int m_noise_lfsra;
|
||||
int m_noise_lfsrb;
|
||||
int m_noise_lfsrc;
|
||||
int m_noise_lfsrd;
|
||||
int m_noise_counter;
|
||||
UINT8 m_ym1_outputa;
|
||||
UINT8 m_ym2_outputa;
|
||||
UINT8 m_ym2_outputb;
|
||||
UINT16 m_eng_voltages[16];
|
||||
};
|
||||
|
||||
INLINE tx1_sound_state *get_safe_token(device_t *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == TX1 || device->type() == BUGGYBOY);
|
||||
|
||||
return (tx1_sound_state *)downcast<tx1_sound_device *>(device)->token();
|
||||
}
|
||||
|
||||
WRITE8_DEVICE_HANDLER( tx1_pit8253_w )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
state->m_stream->update();
|
||||
|
||||
if (offset < 3)
|
||||
{
|
||||
if (state->m_pit8253.idx[offset] == 0)
|
||||
{
|
||||
state->m_pit8253.counts[offset].LSB = data;
|
||||
state->m_pit8253.idx[offset] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->m_pit8253.counts[offset].MSB = data;
|
||||
state->m_pit8253.idx[offset] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int mode = (data >> 1) & 7;
|
||||
|
||||
if (mode == 3)
|
||||
{
|
||||
int cntsel = (data >> 6) & 3;
|
||||
state->m_pit8253.idx[cntsel] = 0;
|
||||
state->m_pit8253.counts[cntsel].val = 0;
|
||||
}
|
||||
else
|
||||
mame_printf_debug("PIT8253: Unsupported mode %d.\n", mode);
|
||||
}
|
||||
}
|
||||
|
||||
READ8_DEVICE_HANDLER( tx1_pit8253_r )
|
||||
{
|
||||
mame_printf_debug("PIT R: %x", offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* TX-1
|
||||
@ -152,6 +48,118 @@ static const double tx1_engine_gains[16] =
|
||||
-( 1.0/(1.0/TX1_R + 1.0/TX1_SHUNT + 1.0/TX1_R2 + 1.0/TX1_R1 + 1.0/TX1_R0) )/TX1_RI
|
||||
};
|
||||
|
||||
|
||||
const device_type TX1 = &device_creator<tx1_sound_device>;
|
||||
|
||||
tx1_sound_device::tx1_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, TX1, "TX-1 Custom", tag, owner, clock, "tx1_sound", __FILE__),
|
||||
device_sound_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
tx1_sound_device::tx1_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_stream(NULL),
|
||||
m_freq_to_step(0),
|
||||
m_step0(0),
|
||||
m_step1(0),
|
||||
m_step2(0),
|
||||
m_ay_outputa(0),
|
||||
m_ay_outputb(0),
|
||||
m_pit0(0),
|
||||
m_pit1(0),
|
||||
m_pit2(0),
|
||||
m_noise_lfsra(0),
|
||||
m_noise_lfsrb(1),
|
||||
m_noise_lfsrc(0),
|
||||
m_noise_lfsrd(0),
|
||||
m_noise_counter(0),
|
||||
m_ym1_outputa(0),
|
||||
m_ym2_outputa(0),
|
||||
m_ym2_outputb(0)
|
||||
{
|
||||
}
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::device_start()
|
||||
{
|
||||
static const int r0[4] = { 390e3, 180e3, 180e3, 180e3 };
|
||||
static const int r1[3] = { 180e3, 390e3, 56e3 };
|
||||
static const int r2[3] = { 390e3, 390e3, 180e3 };
|
||||
|
||||
|
||||
/* Allocate the stream */
|
||||
m_stream = machine().sound().stream_alloc(*this, 0, 2, machine().sample_rate(), this);
|
||||
m_freq_to_step = (double)(1 << TX1_FRAC) / (double)machine().sample_rate();
|
||||
|
||||
/* Compute the engine resistor weights */
|
||||
compute_resistor_weights(0, 10000, -1.0,
|
||||
4, &r0[0], m_weights0, 0, 0,
|
||||
3, &r1[0], m_weights1, 0, 0,
|
||||
3, &r2[0], m_weights2, 0, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::device_reset()
|
||||
{
|
||||
m_step0 = m_step1 = m_step2 = 0;
|
||||
}
|
||||
|
||||
|
||||
WRITE8_MEMBER( tx1_sound_device::pit8253_w )
|
||||
{
|
||||
m_stream->update();
|
||||
|
||||
if (offset < 3)
|
||||
{
|
||||
if (m_pit8253.idx[offset] == 0)
|
||||
{
|
||||
m_pit8253.counts[offset].LSB = data;
|
||||
m_pit8253.idx[offset] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pit8253.counts[offset].MSB = data;
|
||||
m_pit8253.idx[offset] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int mode = (data >> 1) & 7;
|
||||
|
||||
if (mode == 3)
|
||||
{
|
||||
int cntsel = (data >> 6) & 3;
|
||||
m_pit8253.idx[cntsel] = 0;
|
||||
m_pit8253.counts[cntsel].val = 0;
|
||||
}
|
||||
else
|
||||
mame_printf_debug("PIT8253: Unsupported mode %d.\n", mode);
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( tx1_sound_device::pit8253_r )
|
||||
{
|
||||
mame_printf_debug("PIT R: %x", offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
AY-8910 port mappings:
|
||||
@ -170,28 +178,26 @@ static const double tx1_engine_gains[16] =
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
WRITE8_DEVICE_HANDLER( tx1_ay8910_a_w )
|
||||
WRITE8_MEMBER( tx1_sound_device::ay8910_a_w )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
state->m_stream->update();
|
||||
m_stream->update();
|
||||
|
||||
/* All outputs inverted */
|
||||
state->m_ay_outputa = ~data;
|
||||
m_ay_outputa = ~data;
|
||||
}
|
||||
|
||||
WRITE8_DEVICE_HANDLER( tx1_ay8910_b_w )
|
||||
WRITE8_MEMBER( tx1_sound_device::ay8910_b_w )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
double gain;
|
||||
|
||||
state->m_stream->update();
|
||||
m_stream->update();
|
||||
/* Only B3-0 are inverted */
|
||||
state->m_ay_outputb = data ^ 0xf;
|
||||
m_ay_outputb = data ^ 0xf;
|
||||
|
||||
/* It'll do until we get quadrophonic speaker support! */
|
||||
gain = BIT(state->m_ay_outputb, 4) ? 1.5 : 2.0;
|
||||
gain = BIT(m_ay_outputb, 4) ? 1.5 : 2.0;
|
||||
device_sound_interface *sound;
|
||||
device->interface(sound);
|
||||
interface(sound);
|
||||
sound->set_output_gain(0, gain);
|
||||
sound->set_output_gain(1, gain);
|
||||
sound->set_output_gain(2, gain);
|
||||
@ -237,9 +243,12 @@ INLINE void update_engine(int eng[4])
|
||||
}
|
||||
|
||||
|
||||
static STREAM_UPDATE( tx1_stream_update )
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
UINT32 step_0, step_1, step_2;
|
||||
double /*gain_0, gain_1,*/ gain_2, gain_3;
|
||||
|
||||
@ -251,75 +260,48 @@ static STREAM_UPDATE( tx1_stream_update )
|
||||
memset(outputs[1], 0, samples * sizeof(*outputs[1]));
|
||||
|
||||
/* 8253 outputs for the player/opponent engine sounds. */
|
||||
step_0 = state->m_pit8253.counts[0].val ? (TX1_PIT_CLOCK / state->m_pit8253.counts[0].val) * state->m_freq_to_step : 0;
|
||||
step_1 = state->m_pit8253.counts[1].val ? (TX1_PIT_CLOCK / state->m_pit8253.counts[1].val) * state->m_freq_to_step : 0;
|
||||
step_2 = state->m_pit8253.counts[2].val ? (TX1_PIT_CLOCK / state->m_pit8253.counts[2].val) * state->m_freq_to_step : 0;
|
||||
step_0 = m_pit8253.counts[0].val ? (TX1_PIT_CLOCK / m_pit8253.counts[0].val) * m_freq_to_step : 0;
|
||||
step_1 = m_pit8253.counts[1].val ? (TX1_PIT_CLOCK / m_pit8253.counts[1].val) * m_freq_to_step : 0;
|
||||
step_2 = m_pit8253.counts[2].val ? (TX1_PIT_CLOCK / m_pit8253.counts[2].val) * m_freq_to_step : 0;
|
||||
|
||||
//gain_0 = tx1_engine_gains[state->m_ay_outputa & 0xf];
|
||||
//gain_1 = tx1_engine_gains[state->m_ay_outputa >> 4];
|
||||
gain_2 = tx1_engine_gains[state->m_ay_outputb & 0xf];
|
||||
gain_3 = BIT(state->m_ay_outputb, 5) ? 1.0f : 1.5f;
|
||||
//gain_0 = tx1_engine_gains[m_ay_outputa & 0xf];
|
||||
//gain_1 = tx1_engine_gains[m_ay_outputa >> 4];
|
||||
gain_2 = tx1_engine_gains[m_ay_outputb & 0xf];
|
||||
gain_3 = BIT(m_ay_outputb, 5) ? 1.0f : 1.5f;
|
||||
|
||||
while (samples--)
|
||||
{
|
||||
if (state->m_step0 & ((1 << TX1_FRAC)))
|
||||
if (m_step0 & ((1 << TX1_FRAC)))
|
||||
{
|
||||
update_engine(state->m_eng0);
|
||||
state->m_pit0 = combine_4_weights(state->m_weights0, state->m_eng0[0], state->m_eng0[1], state->m_eng0[2], state->m_eng0[3]);
|
||||
state->m_step0 &= ((1 << TX1_FRAC) - 1);
|
||||
update_engine(m_eng0);
|
||||
m_pit0 = combine_4_weights(m_weights0, m_eng0[0], m_eng0[1], m_eng0[2], m_eng0[3]);
|
||||
m_step0 &= ((1 << TX1_FRAC) - 1);
|
||||
}
|
||||
|
||||
if (state->m_step1 & ((1 << TX1_FRAC)))
|
||||
if (m_step1 & ((1 << TX1_FRAC)))
|
||||
{
|
||||
update_engine(state->m_eng1);
|
||||
state->m_pit1 = combine_3_weights(state->m_weights1, state->m_eng1[0], state->m_eng1[1], state->m_eng1[3]);
|
||||
state->m_step1 &= ((1 << TX1_FRAC) - 1);
|
||||
update_engine(m_eng1);
|
||||
m_pit1 = combine_3_weights(m_weights1, m_eng1[0], m_eng1[1], m_eng1[3]);
|
||||
m_step1 &= ((1 << TX1_FRAC) - 1);
|
||||
}
|
||||
|
||||
if (state->m_step2 & ((1 << TX1_FRAC)))
|
||||
if (m_step2 & ((1 << TX1_FRAC)))
|
||||
{
|
||||
update_engine(state->m_eng2);
|
||||
state->m_pit2 = combine_3_weights(state->m_weights2, state->m_eng2[0], state->m_eng2[1], state->m_eng2[3]);
|
||||
state->m_step2 &= ((1 << TX1_FRAC) - 1);
|
||||
update_engine(m_eng2);
|
||||
m_pit2 = combine_3_weights(m_weights2, m_eng2[0], m_eng2[1], m_eng2[3]);
|
||||
m_step2 &= ((1 << TX1_FRAC) - 1);
|
||||
}
|
||||
|
||||
*fl++ = (state->m_pit0 + state->m_pit1)*gain_3 + 2*state->m_pit2*gain_2;
|
||||
*fr++ = (state->m_pit0 + state->m_pit1)*gain_3 + 2*state->m_pit2*gain_2;
|
||||
*fl++ = (m_pit0 + m_pit1)*gain_3 + 2*m_pit2*gain_2;
|
||||
*fr++ = (m_pit0 + m_pit1)*gain_3 + 2*m_pit2*gain_2;
|
||||
|
||||
state->m_step0 += step_0;
|
||||
state->m_step1 += step_1;
|
||||
state->m_step2 += step_2;
|
||||
m_step0 += step_0;
|
||||
m_step1 += step_1;
|
||||
m_step2 += step_2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static DEVICE_START( tx1_sound )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
running_machine &machine = device->machine();
|
||||
static const int r0[4] = { 390e3, 180e3, 180e3, 180e3 };
|
||||
static const int r1[3] = { 180e3, 390e3, 56e3 };
|
||||
static const int r2[3] = { 390e3, 390e3, 180e3 };
|
||||
|
||||
|
||||
/* Allocate the stream */
|
||||
state->m_stream = device->machine().sound().stream_alloc(*device, 0, 2, machine.sample_rate(), NULL, tx1_stream_update);
|
||||
state->m_freq_to_step = (double)(1 << TX1_FRAC) / (double)machine.sample_rate();
|
||||
|
||||
/* Compute the engine resistor weights */
|
||||
compute_resistor_weights(0, 10000, -1.0,
|
||||
4, &r0[0], state->m_weights0, 0, 0,
|
||||
3, &r1[0], state->m_weights1, 0, 0,
|
||||
3, &r2[0], state->m_weights2, 0, 0);
|
||||
}
|
||||
|
||||
static DEVICE_RESET( tx1_sound )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
|
||||
state->m_step0 = state->m_step1 = state->m_step2 = 0;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Buggy Boy
|
||||
@ -360,7 +342,64 @@ static const double bb_engine_gains[16] =
|
||||
-1.0/(1.0/(BUGGYBOY_R1S + BUGGYBOY_R2S + BUGGYBOY_R3S + BUGGYBOY_R4S) + 1.0/100e3)/100e3,
|
||||
};
|
||||
|
||||
const device_type BUGGYBOY = &device_creator<buggyboy_sound_device>;
|
||||
|
||||
buggyboy_sound_device::buggyboy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tx1_sound_device(mconfig, BUGGYBOY, "Buggy Boy Custom", tag, owner, clock, "buggyboy_sound", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::device_start()
|
||||
{
|
||||
static const int resistors[4] = { 330000, 220000, 330000, 220000 };
|
||||
double aweights[4];
|
||||
int i;
|
||||
static const int tmp[16] =
|
||||
{
|
||||
0x0, 0x1, 0xe, 0xf, 0x8, 0x9, 0x6, 0x7, 0xc, 0xd, 0xe, 0xf, 0x4, 0x5, 0x6, 0x7
|
||||
};
|
||||
|
||||
compute_resistor_weights(0, 16384, -1.0,
|
||||
4, &resistors[0], aweights, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0 );
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
m_eng_voltages[i] = combine_4_weights(aweights, BIT(tmp[i], 0), BIT(tmp[i], 1), BIT(tmp[i], 2), BIT(tmp[i], 3));
|
||||
|
||||
/* Allocate the stream */
|
||||
m_stream = machine().sound().stream_alloc(*this, 0, 2, machine().sample_rate(), this);
|
||||
m_freq_to_step = (double)(1 << 24) / (double)machine().sample_rate();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::device_reset()
|
||||
{
|
||||
m_step0 = m_step1 = 0;
|
||||
|
||||
/* Reset noise LFSR */
|
||||
m_noise_lfsra = 0;
|
||||
m_noise_lfsrb = 1;
|
||||
m_noise_lfsrc = 0;
|
||||
m_noise_lfsrd = 0;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
@ -399,32 +438,27 @@ static const double bb_engine_gains[16] =
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
WRITE8_DEVICE_HANDLER( bb_ym1_a_w )
|
||||
WRITE8_MEMBER( buggyboy_sound_device::ym1_a_w )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
|
||||
state->m_stream->update();
|
||||
state->m_ym1_outputa = data ^ 0xff;
|
||||
m_stream->update();
|
||||
m_ym1_outputa = data ^ 0xff;
|
||||
}
|
||||
|
||||
WRITE8_DEVICE_HANDLER( bb_ym2_a_w )
|
||||
WRITE8_MEMBER( buggyboy_sound_device::ym2_a_w )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
|
||||
state->m_stream->update();
|
||||
state->m_ym2_outputa = data ^ 0xff;
|
||||
m_stream->update();
|
||||
m_ym2_outputa = data ^ 0xff;
|
||||
}
|
||||
|
||||
WRITE8_DEVICE_HANDLER( bb_ym2_b_w )
|
||||
WRITE8_MEMBER( buggyboy_sound_device::ym2_b_w )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
device_t *ym1 = space.machine().device("ym1");
|
||||
device_t *ym2 = space.machine().device("ym2");
|
||||
double gain;
|
||||
|
||||
state->m_stream->update();
|
||||
m_stream->update();
|
||||
|
||||
state->m_ym2_outputb = data ^ 0xff;
|
||||
m_ym2_outputb = data ^ 0xff;
|
||||
|
||||
if (!strcmp(space.machine().system().name, "buggyboyjr"))
|
||||
{
|
||||
@ -454,10 +488,15 @@ WRITE8_DEVICE_HANDLER( bb_ym2_b_w )
|
||||
sound->set_output_gain(2, gain);
|
||||
}
|
||||
|
||||
/* This is admittedly a bit of a hack job... */
|
||||
static STREAM_UPDATE( buggyboy_stream_update )
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
/* This is admittedly a bit of a hack job... */
|
||||
|
||||
UINT32 step_0, step_1;
|
||||
int n1_en, n2_en;
|
||||
double gain0, gain1_l, gain1_r;
|
||||
@ -470,59 +509,59 @@ static STREAM_UPDATE( buggyboy_stream_update )
|
||||
memset(outputs[1], 0, samples * sizeof(*outputs[1]));
|
||||
|
||||
/* 8253 outputs for the player/opponent buggy engine sounds. */
|
||||
step_0 = state->m_pit8253.counts[0].val ? (BUGGYBOY_PIT_CLOCK / state->m_pit8253.counts[0].val) * state->m_freq_to_step : 0;
|
||||
step_1 = state->m_pit8253.counts[1].val ? (BUGGYBOY_PIT_CLOCK / state->m_pit8253.counts[1].val) * state->m_freq_to_step : 0;
|
||||
step_0 = m_pit8253.counts[0].val ? (BUGGYBOY_PIT_CLOCK / m_pit8253.counts[0].val) * m_freq_to_step : 0;
|
||||
step_1 = m_pit8253.counts[1].val ? (BUGGYBOY_PIT_CLOCK / m_pit8253.counts[1].val) * m_freq_to_step : 0;
|
||||
|
||||
if (!strcmp(device->machine().system().name, "buggyboyjr"))
|
||||
gain0 = BIT(state->m_ym2_outputb, 3) ? 1.0 : 2.0;
|
||||
if (!strcmp(machine().system().name, "buggyboyjr"))
|
||||
gain0 = BIT(m_ym2_outputb, 3) ? 1.0 : 2.0;
|
||||
else
|
||||
gain0 = BIT(state->m_ym1_outputa, 3) ? 1.0 : 2.0;
|
||||
gain0 = BIT(m_ym1_outputa, 3) ? 1.0 : 2.0;
|
||||
|
||||
n1_en = BIT(state->m_ym2_outputb, 4);
|
||||
n2_en = BIT(state->m_ym2_outputb, 5);
|
||||
n1_en = BIT(m_ym2_outputb, 4);
|
||||
n2_en = BIT(m_ym2_outputb, 5);
|
||||
|
||||
gain1_l = bb_engine_gains[state->m_ym2_outputa >> 4] * 5;
|
||||
gain1_r = bb_engine_gains[state->m_ym2_outputa & 0xf] * 5;
|
||||
gain1_l = bb_engine_gains[m_ym2_outputa >> 4] * 5;
|
||||
gain1_r = bb_engine_gains[m_ym2_outputa & 0xf] * 5;
|
||||
|
||||
while (samples--)
|
||||
{
|
||||
int i;
|
||||
stream_sample_t pit0, pit1, n1, n2;
|
||||
pit0 = state->m_eng_voltages[(state->m_step0 >> 24) & 0xf];
|
||||
pit1 = state->m_eng_voltages[(state->m_step1 >> 24) & 0xf];
|
||||
pit0 = m_eng_voltages[(m_step0 >> 24) & 0xf];
|
||||
pit1 = m_eng_voltages[(m_step1 >> 24) & 0xf];
|
||||
|
||||
/* Calculate the tyre screech noise source */
|
||||
for (i = 0; i < BUGGYBOY_NOISE_CLOCK / device->machine().sample_rate(); ++i)
|
||||
for (i = 0; i < BUGGYBOY_NOISE_CLOCK / machine().sample_rate(); ++i)
|
||||
{
|
||||
/* CD4006 is a 4-4-1-4-4-1 shift register */
|
||||
int p13 = BIT(state->m_noise_lfsra, 3);
|
||||
int p12 = BIT(state->m_noise_lfsrb, 4);
|
||||
int p10 = BIT(state->m_noise_lfsrc, 3);
|
||||
int p8 = BIT(state->m_noise_lfsrd, 3);
|
||||
int p13 = BIT(m_noise_lfsra, 3);
|
||||
int p12 = BIT(m_noise_lfsrb, 4);
|
||||
int p10 = BIT(m_noise_lfsrc, 3);
|
||||
int p8 = BIT(m_noise_lfsrd, 3);
|
||||
|
||||
/* Update the register */
|
||||
state->m_noise_lfsra = p12 | ((state->m_noise_lfsra << 1) & 0xf);
|
||||
state->m_noise_lfsrb = (p8 ^ p12) | ((state->m_noise_lfsrb << 1) & 0x1f);
|
||||
state->m_noise_lfsrc = p13 | ((state->m_noise_lfsrc << 1) & 0xf);
|
||||
state->m_noise_lfsrd = p10 | ((state->m_noise_lfsrd << 1) & 0x1f);
|
||||
m_noise_lfsra = p12 | ((m_noise_lfsra << 1) & 0xf);
|
||||
m_noise_lfsrb = (p8 ^ p12) | ((m_noise_lfsrb << 1) & 0x1f);
|
||||
m_noise_lfsrc = p13 | ((m_noise_lfsrc << 1) & 0xf);
|
||||
m_noise_lfsrd = p10 | ((m_noise_lfsrd << 1) & 0x1f);
|
||||
|
||||
/* 4040 12-bit counter is clocked on the falling edge of Q13 */
|
||||
if ( !BIT(state->m_noise_lfsrc, 3) && p10 )
|
||||
state->m_noise_counter = (state->m_noise_counter + 1) & 0x0fff;
|
||||
if ( !BIT(m_noise_lfsrc, 3) && p10 )
|
||||
m_noise_counter = (m_noise_counter + 1) & 0x0fff;
|
||||
}
|
||||
|
||||
if (n1_en)
|
||||
{
|
||||
n1 = !BIT(state->m_noise_counter, 7-1) * 16000;
|
||||
if ( BIT(state->m_noise_counter, 11-1) ) n1 /=2;
|
||||
n1 = !BIT(m_noise_counter, 7-1) * 16000;
|
||||
if ( BIT(m_noise_counter, 11-1) ) n1 /=2;
|
||||
}
|
||||
else
|
||||
n1 = 8192;
|
||||
|
||||
if (n2_en)
|
||||
{
|
||||
n2 = !BIT(state->m_noise_counter, 6-1) * 16000;
|
||||
if ( BIT(state->m_noise_counter, 11-1) ) n2 /=2;
|
||||
n2 = !BIT(m_noise_counter, 6-1) * 16000;
|
||||
if ( BIT(m_noise_counter, 11-1) ) n2 /=2;
|
||||
}
|
||||
else
|
||||
n2 = 8192;
|
||||
@ -530,144 +569,7 @@ static STREAM_UPDATE( buggyboy_stream_update )
|
||||
*fl++ = n1 + n2 + (pit0 * gain0) + (pit1 * gain1_l);
|
||||
*fr++ = n1 + n2 + (pit0 * gain0) + (pit1 * gain1_r);
|
||||
|
||||
state->m_step0 += step_0;
|
||||
state->m_step1 += step_1;
|
||||
m_step0 += step_0;
|
||||
m_step1 += step_1;
|
||||
}
|
||||
}
|
||||
|
||||
static DEVICE_START( buggyboy_sound )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
running_machine &machine = device->machine();
|
||||
static const int resistors[4] = { 330000, 220000, 330000, 220000 };
|
||||
double aweights[4];
|
||||
int i;
|
||||
static const int tmp[16] =
|
||||
{
|
||||
0x0, 0x1, 0xe, 0xf, 0x8, 0x9, 0x6, 0x7, 0xc, 0xd, 0xe, 0xf, 0x4, 0x5, 0x6, 0x7
|
||||
};
|
||||
|
||||
compute_resistor_weights(0, 16384, -1.0,
|
||||
4, &resistors[0], aweights, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0 );
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
state->m_eng_voltages[i] = combine_4_weights(aweights, BIT(tmp[i], 0), BIT(tmp[i], 1), BIT(tmp[i], 2), BIT(tmp[i], 3));
|
||||
|
||||
/* Allocate the stream */
|
||||
state->m_stream = device->machine().sound().stream_alloc(*device, 0, 2, machine.sample_rate(), NULL, buggyboy_stream_update);
|
||||
state->m_freq_to_step = (double)(1 << 24) / (double)machine.sample_rate();
|
||||
}
|
||||
|
||||
static DEVICE_RESET( buggyboy_sound )
|
||||
{
|
||||
tx1_sound_state *state = get_safe_token(device);
|
||||
|
||||
state->m_step0 = state->m_step1 = 0;
|
||||
|
||||
/* Reset noise LFSR */
|
||||
state->m_noise_lfsra = 0;
|
||||
state->m_noise_lfsrb = 1;
|
||||
state->m_noise_lfsrc = 0;
|
||||
state->m_noise_lfsrd = 0;
|
||||
}
|
||||
|
||||
const device_type BUGGYBOY = &device_creator<buggyboy_sound_device>;
|
||||
|
||||
buggyboy_sound_device::buggyboy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tx1_sound_device(mconfig, BUGGYBOY, "Buggy Boy Custom", tag, owner, clock, "buggyboy_sound", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( buggyboy_sound )(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::device_reset()
|
||||
{
|
||||
DEVICE_RESET_NAME( buggyboy_sound )(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
|
||||
void buggyboy_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
// should never get here
|
||||
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
|
||||
}
|
||||
|
||||
|
||||
const device_type TX1 = &device_creator<tx1_sound_device>;
|
||||
|
||||
tx1_sound_device::tx1_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, TX1, "TX-1 Custom", tag, owner, clock, "tx1_sound", __FILE__),
|
||||
device_sound_interface(mconfig, *this)
|
||||
{
|
||||
m_token = global_alloc_clear(tx1_sound_state);
|
||||
}
|
||||
|
||||
tx1_sound_device::tx1_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
|
||||
device_sound_interface(mconfig, *this)
|
||||
{
|
||||
m_token = global_alloc_clear(tx1_sound_state);
|
||||
}
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( tx1_sound )(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::device_reset()
|
||||
{
|
||||
DEVICE_RESET_NAME( tx1_sound )(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
|
||||
void tx1_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
// should never get here
|
||||
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
|
||||
}
|
||||
}
|
@ -534,7 +534,7 @@ static ADDRESS_MAP_START( tx1_sound_prg, AS_PROGRAM, 8, tx1_state )
|
||||
AM_RANGE(0x3000, 0x37ff) AM_RAM AM_MIRROR(0x800) AM_SHARE("z80_ram")
|
||||
AM_RANGE(0x4000, 0x4000) AM_WRITE(z80_intreq_w)
|
||||
AM_RANGE(0x5000, 0x5003) AM_DEVREADWRITE("ppi8255", i8255_device, read, write)
|
||||
AM_RANGE(0x6000, 0x6003) AM_DEVREADWRITE_LEGACY("tx1", tx1_pit8253_r, tx1_pit8253_w)
|
||||
AM_RANGE(0x6000, 0x6003) AM_DEVREADWRITE("tx1", tx1_sound_device, pit8253_r, pit8253_w)
|
||||
AM_RANGE(0x7000, 0x7fff) AM_WRITE(tx1_ppi_latch_w)
|
||||
AM_RANGE(0xb000, 0xbfff) AM_READWRITE(ts_r, ts_w)
|
||||
ADDRESS_MAP_END
|
||||
@ -598,7 +598,7 @@ static ADDRESS_MAP_START( buggyboy_sound_prg, AS_PROGRAM, 8, tx1_state )
|
||||
AM_RANGE(0x4000, 0x47ff) AM_RAM AM_SHARE("z80_ram")
|
||||
AM_RANGE(0x6000, 0x6001) AM_READ(bb_analog_r)
|
||||
AM_RANGE(0x6800, 0x6803) AM_DEVREADWRITE("ppi8255", i8255_device, read, write)
|
||||
AM_RANGE(0x7000, 0x7003) AM_DEVREADWRITE_LEGACY("buggyboy", tx1_pit8253_r, tx1_pit8253_w)
|
||||
AM_RANGE(0x7000, 0x7003) AM_DEVREADWRITE("buggyboy", buggyboy_sound_device, pit8253_r, pit8253_w)
|
||||
AM_RANGE(0x7800, 0x7800) AM_WRITE(z80_intreq_w)
|
||||
AM_RANGE(0xc000, 0xc7ff) AM_READWRITE(ts_r, ts_w)
|
||||
ADDRESS_MAP_END
|
||||
@ -607,7 +607,7 @@ ADDRESS_MAP_END
|
||||
static ADDRESS_MAP_START( buggybjr_sound_prg, AS_PROGRAM, 8, tx1_state )
|
||||
AM_RANGE(0x0000, 0x3fff) AM_ROM
|
||||
AM_RANGE(0x4000, 0x47ff) AM_RAM AM_SHARE("z80_ram")
|
||||
AM_RANGE(0x5000, 0x5003) AM_DEVREADWRITE_LEGACY("buggyboy", tx1_pit8253_r, tx1_pit8253_w)
|
||||
AM_RANGE(0x5000, 0x5003) AM_DEVREADWRITE("buggyboy", buggyboy_sound_device, pit8253_r, pit8253_w)
|
||||
AM_RANGE(0x6000, 0x6001) AM_READ(bbjr_analog_r)
|
||||
AM_RANGE(0x7000, 0x7000) AM_WRITE(z80_intreq_w)
|
||||
AM_RANGE(0xc000, 0xc7ff) AM_READWRITE(ts_r, ts_w)
|
||||
@ -635,8 +635,8 @@ static const ay8910_interface tx1_ay8910_interface =
|
||||
AY8910_DEFAULT_LOADS,
|
||||
DEVCB_NULL,
|
||||
DEVCB_NULL,
|
||||
DEVCB_DEVICE_HANDLER("tx1", tx1_ay8910_a_w),
|
||||
DEVCB_DEVICE_HANDLER("tx1", tx1_ay8910_b_w),
|
||||
DEVCB_DEVICE_MEMBER("tx1", tx1_sound_device, ay8910_a_w),
|
||||
DEVCB_DEVICE_MEMBER("tx1", tx1_sound_device, ay8910_b_w),
|
||||
};
|
||||
|
||||
|
||||
@ -646,7 +646,7 @@ static const ay8910_interface buggyboy_ym2149_interface_1 =
|
||||
AY8910_DEFAULT_LOADS,
|
||||
DEVCB_NULL,
|
||||
DEVCB_NULL,
|
||||
DEVCB_DEVICE_HANDLER("buggyboy", bb_ym1_a_w),
|
||||
DEVCB_DEVICE_MEMBER("buggyboy", buggyboy_sound_device, ym1_a_w),
|
||||
DEVCB_NULL,
|
||||
};
|
||||
|
||||
@ -656,8 +656,8 @@ static const ay8910_interface buggyboy_ym2149_interface_2 =
|
||||
AY8910_DEFAULT_LOADS,
|
||||
DEVCB_NULL,
|
||||
DEVCB_NULL,
|
||||
DEVCB_DEVICE_HANDLER("buggyboy", bb_ym2_a_w),
|
||||
DEVCB_DEVICE_HANDLER("buggyboy", bb_ym2_b_w),
|
||||
DEVCB_DEVICE_MEMBER("buggyboy", buggyboy_sound_device, ym2_a_w),
|
||||
DEVCB_DEVICE_MEMBER("buggyboy", buggyboy_sound_device, ym2_b_w),
|
||||
};
|
||||
|
||||
|
||||
@ -679,8 +679,8 @@ static const ay8910_interface buggybjr_ym2149_interface_2 =
|
||||
AY8910_DEFAULT_LOADS,
|
||||
DEVCB_NULL,
|
||||
DEVCB_NULL,
|
||||
DEVCB_DEVICE_HANDLER("buggyboy", bb_ym2_a_w),
|
||||
DEVCB_DEVICE_HANDLER("buggyboy", bb_ym2_b_w),
|
||||
DEVCB_DEVICE_MEMBER("buggyboy", buggyboy_sound_device, ym2_a_w),
|
||||
DEVCB_DEVICE_MEMBER("buggyboy", buggyboy_sound_device, ym2_b_w),
|
||||
};
|
||||
|
||||
|
||||
|
@ -213,16 +213,26 @@ public:
|
||||
};
|
||||
|
||||
/*----------- defined in audio/tx1.c -----------*/
|
||||
DECLARE_READ8_DEVICE_HANDLER( tx1_pit8253_r );
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( tx1_pit8253_w );
|
||||
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( bb_ym1_a_w );
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( bb_ym2_a_w );
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( bb_ym2_b_w );
|
||||
/*************************************
|
||||
*
|
||||
* 8253 Programmable Interval Timer
|
||||
*
|
||||
*************************************/
|
||||
struct pit8253_state
|
||||
{
|
||||
union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { UINT8 LSB; UINT8 MSB; };
|
||||
#else
|
||||
struct { UINT8 MSB; UINT8 LSB; };
|
||||
#endif
|
||||
UINT16 val;
|
||||
} counts[3];
|
||||
|
||||
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( tx1_ay8910_a_w );
|
||||
DECLARE_WRITE8_DEVICE_HANDLER( tx1_ay8910_b_w );
|
||||
int idx[3];
|
||||
};
|
||||
|
||||
class tx1_sound_device : public device_t,
|
||||
public device_sound_interface
|
||||
@ -230,10 +240,13 @@ class tx1_sound_device : public device_t,
|
||||
public:
|
||||
tx1_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
tx1_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
|
||||
~tx1_sound_device() { global_free(m_token); }
|
||||
~tx1_sound_device() {}
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
DECLARE_READ8_MEMBER( pit8253_r );
|
||||
DECLARE_WRITE8_MEMBER( pit8253_w );
|
||||
DECLARE_WRITE8_MEMBER( ay8910_a_w );
|
||||
DECLARE_WRITE8_MEMBER( ay8910_b_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
@ -242,9 +255,39 @@ protected:
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
private:
|
||||
|
||||
// internal state
|
||||
void *m_token;
|
||||
sound_stream *m_stream;
|
||||
UINT32 m_freq_to_step;
|
||||
UINT32 m_step0;
|
||||
UINT32 m_step1;
|
||||
UINT32 m_step2;
|
||||
|
||||
pit8253_state m_pit8253;
|
||||
|
||||
UINT8 m_ay_outputa;
|
||||
UINT8 m_ay_outputb;
|
||||
|
||||
stream_sample_t m_pit0;
|
||||
stream_sample_t m_pit1;
|
||||
stream_sample_t m_pit2;
|
||||
|
||||
double m_weights0[4];
|
||||
double m_weights1[3];
|
||||
double m_weights2[3];
|
||||
int m_eng0[4];
|
||||
int m_eng1[4];
|
||||
int m_eng2[4];
|
||||
|
||||
int m_noise_lfsra;
|
||||
int m_noise_lfsrb;
|
||||
int m_noise_lfsrc;
|
||||
int m_noise_lfsrd;
|
||||
int m_noise_counter;
|
||||
UINT8 m_ym1_outputa;
|
||||
UINT8 m_ym2_outputa;
|
||||
UINT8 m_ym2_outputb;
|
||||
UINT16 m_eng_voltages[16];
|
||||
};
|
||||
|
||||
extern const device_type TX1;
|
||||
@ -253,6 +296,11 @@ class buggyboy_sound_device : public tx1_sound_device
|
||||
{
|
||||
public:
|
||||
buggyboy_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_WRITE8_MEMBER( ym1_a_w );
|
||||
DECLARE_WRITE8_MEMBER( ym2_a_w );
|
||||
DECLARE_WRITE8_MEMBER( ym2_b_w );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
@ -261,6 +309,7 @@ protected:
|
||||
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
|
||||
private:
|
||||
// internal state
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user