exidysound: replace riot6532_device with mos6532_new_device, untangle exidy_sh8253_sound_device a bit,

mos6530n: use loops for repeated i/o callbacks, edge_w bits are on address, not data, add live timer status to savestate
This commit is contained in:
hap 2023-07-12 21:49:39 +02:00
parent 04961b2ff5
commit 01f70846e0
4 changed files with 322 additions and 465 deletions

View File

@ -119,16 +119,18 @@ mos6530_device_base::mos6530_device_base(const machine_config &mconfig, device_t
// mos6530_new_device - constructor
//-------------------------------------------------
mos6530_new_device::mos6530_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mos6530_device_base(mconfig, MOS6530_NEW, tag, owner, clock, 0x40) { }
mos6530_new_device::mos6530_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
mos6530_device_base(mconfig, MOS6530_NEW, tag, owner, clock, 0x40)
{ }
//-------------------------------------------------
// mos6532_new_device - constructor
//-------------------------------------------------
mos6532_new_device::mos6532_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mos6530_device_base(mconfig, MOS6532_NEW, tag, owner, clock, 0x80) { }
mos6532_new_device::mos6532_new_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
mos6530_device_base(mconfig, MOS6532_NEW, tag, owner, clock, 0x80)
{ }
//-------------------------------------------------
@ -155,6 +157,20 @@ void mos6530_device_base::device_start()
save_item(NAME(m_irq_edge));
save_item(NAME(m_prescale));
save_item(NAME(m_timer));
save_item(NAME(cur_live.tm));
save_item(NAME(cur_live.tm_irq));
save_item(NAME(cur_live.period));
save_item(NAME(cur_live.state));
save_item(NAME(cur_live.next_state));
save_item(NAME(cur_live.value));
save_item(NAME(checkpoint_live.tm));
save_item(NAME(checkpoint_live.tm_irq));
save_item(NAME(checkpoint_live.period));
save_item(NAME(checkpoint_live.state));
save_item(NAME(checkpoint_live.next_state));
save_item(NAME(checkpoint_live.value));
}
@ -183,9 +199,8 @@ void mos6530_device_base::device_reset()
m_timer = 0xff;
m_prescale = 1024;
if (cur_live.state != IDLE) {
if (cur_live.state != IDLE)
live_abort();
}
live_start();
live_run();
@ -209,25 +224,13 @@ TIMER_CALLBACK_MEMBER(mos6530_device_base::update)
void mos6530_device_base::update_pa()
{
uint8_t out = m_pa_out;
uint8_t ddr = m_pa_ddr;
uint8_t data = (out & ddr) | (ddr ^ 0xff);
uint8_t data = (m_pa_out & m_pa_ddr) | (m_pa_ddr ^ 0xff);
if (m_out8_pa_cb.isunset())
{
m_out_pa_cb[0](BIT(data, 0));
m_out_pa_cb[1](BIT(data, 1));
m_out_pa_cb[2](BIT(data, 2));
m_out_pa_cb[3](BIT(data, 3));
m_out_pa_cb[4](BIT(data, 4));
m_out_pa_cb[5](BIT(data, 5));
m_out_pa_cb[6](BIT(data, 6));
m_out_pa_cb[7](BIT(data, 7));
}
else
{
if (m_out8_pa_cb.isunset()) {
for (int i = 0; i < 8; i++)
m_out_pa_cb[i](BIT(data, i));
} else
m_out8_pa_cb(data);
}
}
@ -237,57 +240,31 @@ void mos6530_device_base::update_pa()
void mos6530_device_base::update_pb()
{
uint8_t out = m_pb_out;
uint8_t ddr = m_pb_ddr;
uint8_t data = (out & ddr) | (ddr ^ 0xff);
uint8_t data = (m_pb_out & m_pb_ddr) | (m_pb_ddr ^ 0xff);
if (m_out8_pb_cb.isunset())
{
m_out_pb_cb[0](BIT(data, 0));
m_out_pb_cb[1](BIT(data, 1));
m_out_pb_cb[2](BIT(data, 2));
m_out_pb_cb[3](BIT(data, 3));
m_out_pb_cb[4](BIT(data, 4));
m_out_pb_cb[5](BIT(data, 5));
m_out_pb_cb[6](BIT(data, 6));
m_out_pb_cb[7](BIT(data, 7));
}
else
{
if (m_out8_pb_cb.isunset()) {
for (int i = 0; i < 8; i++)
m_out_pb_cb[i](BIT(data, i));
} else
m_out8_pb_cb(data);
}
}
void mos6530_new_device::update_pb()
{
uint8_t out = m_pb_out;
uint8_t ddr = m_pb_ddr;
uint8_t data = (out & ddr) | (ddr ^ 0xff);
uint8_t data = (m_pb_out & m_pb_ddr) | (m_pb_ddr ^ 0xff);
if (m_ie_timer)
{
if (m_irq_timer) {
if (m_ie_timer) {
if (m_irq_timer)
data |= IRQ_TIMER;
} else {
else
data &= ~IRQ_TIMER;
}
}
if (m_out8_pb_cb.isunset())
{
m_out_pb_cb[0](BIT(data, 0));
m_out_pb_cb[1](BIT(data, 1));
m_out_pb_cb[2](BIT(data, 2));
m_out_pb_cb[3](BIT(data, 3));
m_out_pb_cb[4](BIT(data, 4));
m_out_pb_cb[5](BIT(data, 5));
m_out_pb_cb[6](BIT(data, 6));
m_out_pb_cb[7](BIT(data, 7));
}
else
{
if (m_out8_pb_cb.isunset()) {
for (int i = 0; i < 8; i++)
m_out_pb_cb[i](BIT(data, i));
} else
m_out8_pb_cb(data);
}
}
@ -341,13 +318,10 @@ uint8_t mos6530_new_device::get_irq_flags()
void mos6530_device_base::edge_detect()
{
uint8_t ddr_out = m_pa_ddr;
uint8_t ddr_in = m_pa_ddr ^ 0xff;
uint8_t data = (m_pa_out & ddr_out) | (m_pa_in & ddr_in);
uint8_t data = (m_pa_out & m_pa_ddr) | (m_pa_in & ~m_pa_ddr);
int state = BIT(data, 7);
if ((m_pa7 ^ state) && (m_pa7_dir ^ state) == 0 && !m_irq_edge)
{
if ((m_pa7 ^ state) && !(m_pa7_dir ^ state) && !m_irq_edge) {
LOG("%s %s edge-detect IRQ\n", machine().time().as_string(), name());
m_irq_edge = true;
@ -394,26 +368,13 @@ uint8_t mos6530_device_base::pa_data_r()
{
uint8_t in = 0;
if (m_in8_pa_cb.isunset())
{
in |= (m_in_pa_cb[0].isunset() ? BIT(m_pa_in, 0) : m_in_pa_cb[0]());
in |= (m_in_pa_cb[1].isunset() ? BIT(m_pa_in, 1) : m_in_pa_cb[1]()) << 1;
in |= (m_in_pa_cb[2].isunset() ? BIT(m_pa_in, 2) : m_in_pa_cb[2]()) << 2;
in |= (m_in_pa_cb[3].isunset() ? BIT(m_pa_in, 3) : m_in_pa_cb[3]()) << 3;
in |= (m_in_pa_cb[4].isunset() ? BIT(m_pa_in, 4) : m_in_pa_cb[4]()) << 4;
in |= (m_in_pa_cb[5].isunset() ? BIT(m_pa_in, 5) : m_in_pa_cb[5]()) << 5;
in |= (m_in_pa_cb[6].isunset() ? BIT(m_pa_in, 6) : m_in_pa_cb[6]()) << 6;
in |= (m_in_pa_cb[7].isunset() ? BIT(m_pa_in, 7) : m_in_pa_cb[7]()) << 7;
}
else
{
if (m_in8_pa_cb.isunset()) {
for (int i = 0; i < 8; i++)
in |= (m_in_pa_cb[i].isunset() ? BIT(m_pa_in, i) : m_in_pa_cb[i]()) << i;
} else
in = m_in8_pa_cb();
}
uint8_t out = m_pa_out;
uint8_t ddr_out = m_pa_ddr;
uint8_t ddr_in = m_pa_ddr ^ 0xff;
uint8_t data = (out & ddr_out) | (in & ddr_in);
uint8_t data = (m_pa_out & m_pa_ddr) | (in & ~m_pa_ddr);
LOG("%s %s %s Port A Data In %02x\n", machine().time().as_string(), machine().describe_context(), name(), data);
@ -459,26 +420,13 @@ uint8_t mos6530_device_base::pb_data_r()
{
uint8_t in = 0;
if (m_in8_pb_cb.isunset())
{
in |= (m_in_pb_cb[0].isunset() ? BIT(m_pb_in, 0) : m_in_pb_cb[0]());
in |= (m_in_pb_cb[1].isunset() ? BIT(m_pb_in, 1) : m_in_pb_cb[1]()) << 1;
in |= (m_in_pb_cb[2].isunset() ? BIT(m_pb_in, 2) : m_in_pb_cb[2]()) << 2;
in |= (m_in_pb_cb[3].isunset() ? BIT(m_pb_in, 3) : m_in_pb_cb[3]()) << 3;
in |= (m_in_pb_cb[4].isunset() ? BIT(m_pb_in, 4) : m_in_pb_cb[4]()) << 4;
in |= (m_in_pb_cb[5].isunset() ? BIT(m_pb_in, 5) : m_in_pb_cb[5]()) << 5;
in |= (m_in_pb_cb[6].isunset() ? BIT(m_pb_in, 6) : m_in_pb_cb[6]()) << 6;
in |= (m_in_pb_cb[7].isunset() ? BIT(m_pb_in, 7) : m_in_pb_cb[7]()) << 7;
}
else
{
if (m_in8_pb_cb.isunset()) {
for (int i = 0; i < 8; i++)
in |= (m_in_pb_cb[i].isunset() ? BIT(m_pb_in, i) : m_in_pb_cb[i]()) << i;
} else
in = m_in8_pb_cb();
}
uint8_t out = m_pb_out;
uint8_t ddr_out = m_pb_ddr;
uint8_t ddr_in = m_pb_ddr ^ 0xff;
uint8_t data = (out & ddr_out) | (in & ddr_in);
uint8_t data = (m_pb_out & m_pb_ddr) | (in & ~m_pb_ddr);
LOG("%s %s %s Port B Data In %02x\n", machine().time().as_string(), machine().describe_context(), name(), data);
@ -541,9 +489,8 @@ uint8_t mos6530_device_base::timer_r(bool ie)
live_sync();
m_ie_timer = ie;
if (cur_live.tm_irq != machine().time()) {
if (cur_live.tm_irq != machine().time())
m_irq_timer = false;
}
update_irq();
data = cur_live.value;
@ -604,18 +551,16 @@ void mos6530_device_base::timer_w(offs_t offset, uint8_t data, bool ie)
}
m_ie_timer = ie;
if (cur_live.tm_irq != machine().time()) {
if (cur_live.tm_irq != machine().time())
m_irq_timer = false;
}
update_irq();
LOGTIMER("%s %s %s Timer value %02x prescale %u IE %u\n", machine().time().as_string(), machine().describe_context(), name(), data, m_prescale, m_ie_timer ? 1 : 0);
checkpoint();
if (cur_live.state != IDLE) {
if (cur_live.state != IDLE)
live_abort();
}
live_start();
live_run();
@ -626,10 +571,11 @@ void mos6530_device_base::timer_w(offs_t offset, uint8_t data, bool ie)
// edge_w -
//-------------------------------------------------
void mos6530_device_base::edge_w(uint8_t data)
void mos6530_device_base::edge_w(offs_t offset, uint8_t data)
{
m_pa7_dir = BIT(data, 0);
m_ie_edge = BIT(data, 1) ? false : true;
m_pa7_dir = BIT(offset, 0);
m_ie_edge = bool(BIT(offset, 1));
update_irq();
LOG("%s %s %s %s edge-detect, %s interrupt\n", machine().time().as_string(), machine().describe_context(), name(), m_pa7_dir ? "positive" : "negative", m_ie_edge ? "enable" : "disable");
}
@ -666,7 +612,7 @@ void mos6530_device_base::rollback()
void mos6530_device_base::live_delay(int state)
{
cur_live.next_state = state;
if(cur_live.tm != machine().time())
if (cur_live.tm != machine().time())
t_gen->adjust(cur_live.tm - machine().time());
else
live_sync();
@ -674,16 +620,16 @@ void mos6530_device_base::live_delay(int state)
void mos6530_device_base::live_sync()
{
if(!cur_live.tm.is_never()) {
if(cur_live.tm > machine().time()) {
if (!cur_live.tm.is_never()) {
if (cur_live.tm > machine().time()) {
rollback();
live_run(machine().time());
} else {
if(cur_live.next_state != -1) {
if (cur_live.next_state != -1) {
cur_live.state = cur_live.next_state;
cur_live.next_state = -1;
}
if(cur_live.state == IDLE) {
if (cur_live.state == IDLE) {
cur_live.tm = attotime::never;
}
}
@ -694,7 +640,7 @@ void mos6530_device_base::live_sync()
void mos6530_device_base::live_abort()
{
if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
if (!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
rollback();
live_run(machine().time());
}
@ -707,11 +653,11 @@ void mos6530_device_base::live_abort()
void mos6530_device_base::live_run(const attotime &limit)
{
if(cur_live.state == IDLE || cur_live.next_state != -1)
if (cur_live.state == IDLE || cur_live.next_state != -1)
return;
for(;;) {
switch(cur_live.state) {
for (;;) {
switch (cur_live.state) {
case RUNNING: {
if (cur_live.tm > limit)
return;

View File

@ -136,16 +136,16 @@ protected:
uint8_t irq_r();
void timer_off_w(offs_t offset, uint8_t data);
void timer_on_w(offs_t offset, uint8_t data);
void edge_w(uint8_t data);
void edge_w(offs_t offset, uint8_t data);
memory_share_creator<uint8_t> m_ram;
optional_region_ptr<uint8_t> m_rom;
devcb_write_line m_irq_cb;
devcb_read8 m_in8_pa_cb;
devcb_write8 m_out8_pa_cb;
devcb_read8 m_in8_pb_cb;
devcb_write8 m_out8_pb_cb;
devcb_read8 m_in8_pa_cb;
devcb_write8 m_out8_pa_cb;
devcb_read8 m_in8_pb_cb;
devcb_write8 m_out8_pb_cb;
devcb_read_line::array<8> m_in_pa_cb;
devcb_write_line::array<8> m_out_pa_cb;
devcb_read_line::array<8> m_in_pb_cb;

View File

@ -5,7 +5,7 @@
Exidy 6502 hardware
TODO:
- use ptm6840_device and pit8253_device, maybe mos6532_new_device too
- use ptm6840_device and pit8253_device
*************************************************************************/
@ -27,6 +27,11 @@
*
*************************************/
#define LOG_VICTORY_SOUND (1U << 1)
#define VERBOSE (0)
#include "logmacro.h"
#define CRYSTAL_OSC (3.579545_MHz_XTAL)
#define SH8253_CLOCK (CRYSTAL_OSC / 2)
#define SH6840_CLOCK (CRYSTAL_OSC / 4)
@ -36,6 +41,7 @@
#define BASE_VOLUME (32767 / 6)
/*************************************
*
* 6840 clock counting helper
@ -44,23 +50,23 @@
inline void exidy_sound_device::sh6840_apply_clock(exidy_sound_device::sh6840_timer_channel *t, int clocks)
{
/* dual 8-bit case */
// dual 8-bit case
if (t->cr & 0x04)
{
/* handle full decrements */
// handle full decrements
while (clocks > t->counter.b.l)
{
clocks -= t->counter.b.l + 1;
t->counter.b.l = t->timer;
/* decrement MSB */
// decrement MSB
if (!t->counter.b.h--)
{
t->state = 0;
t->counter.w = t->timer;
}
/* state goes high when MSB is 0 */
// state goes high when MSB is 0
else if (!t->counter.b.h)
{
t->state = 1;
@ -68,14 +74,14 @@ inline void exidy_sound_device::sh6840_apply_clock(exidy_sound_device::sh6840_ti
}
}
/* subtract off the remainder */
// subtract off the remainder
t->counter.b.l -= clocks;
}
/* 16-bit case */
// 16-bit case
else
{
/* handle full decrements */
// handle full decrements
while (clocks > t->counter.w)
{
clocks -= t->counter.w + 1;
@ -84,7 +90,7 @@ inline void exidy_sound_device::sh6840_apply_clock(exidy_sound_device::sh6840_ti
t->counter.w = t->timer;
}
/* subtract off the remainder */
// subtract off the remainder
t->counter.w -= clocks;
}
}
@ -101,17 +107,14 @@ inline int exidy_sound_device::sh6840_update_noise(int clocks)
{
uint32_t newxor;
int noise_clocks = 0;
int i;
/* loop over clocks */
for (i = 0; i < clocks; i++)
// loop over clocks
for (int i = 0; i < clocks; i++)
{
/* shift the LFSR. its a LOOOONG LFSR, so we need
* four longs to hold it all!
* first we grab new sample, then shift the high bits,
* then the low ones; finally or in the result and see if we've
* had a 0->1 transition */
newxor = (m_sh6840_LFSR_3 ^ m_sh6840_LFSR_2) >> 31; /* high bits of 3 and 2 xored is new xor */
// shift the LFSR. its a LOOOONG LFSR, so we need four longs to hold it all!
// first we grab new sample, then shift the high bits, then the low ones;
// finally or in the result and see if we've had a 0->1 transition
newxor = (m_sh6840_LFSR_3 ^ m_sh6840_LFSR_2) >> 31; // high bits of 3 and 2 xored is new xor
m_sh6840_LFSR_3 <<= 1;
m_sh6840_LFSR_3 |= m_sh6840_LFSR_2 >> 31;
m_sh6840_LFSR_2 <<= 1;
@ -121,9 +124,9 @@ inline int exidy_sound_device::sh6840_update_noise(int clocks)
m_sh6840_LFSR_0 <<= 1;
m_sh6840_LFSR_0 |= newxor ^ m_sh6840_LFSR_oldxor;
m_sh6840_LFSR_oldxor = newxor;
/*printf("LFSR: %4x, %4x, %4x, %4x\n", sh6840_LFSR_3, sh6840_LFSR_2, sh6840_LFSR_1, sh6840_LFSR_0);*/
/* if we clocked 0->1, that will serve as an external clock */
if ((m_sh6840_LFSR_2 & 0x03) == 0x01) /* tap is at 96th bit */
//printf("LFSR: %4x, %4x, %4x, %4x\n", m_sh6840_LFSR_3, m_sh6840_LFSR_2, m_sh6840_LFSR_1, m_sh6840_LFSR_0);
// if we clocked 0->1, that will serve as an external clock
if ((m_sh6840_LFSR_2 & 0x03) == 0x01) // tap is at 96th bit
{
noise_clocks++;
}
@ -141,6 +144,15 @@ inline int exidy_sound_device::sh6840_update_noise(int clocks)
void exidy_sound_device::sh6840_register_state_globals()
{
save_item(STRUCT_MEMBER(m_sh6840_timer, cr));
save_item(STRUCT_MEMBER(m_sh6840_timer, state));
save_item(STRUCT_MEMBER(m_sh6840_timer, leftovers));
save_item(STRUCT_MEMBER(m_sh6840_timer, timer));
save_item(STRUCT_MEMBER(m_sh6840_timer, clocks));
save_item(NAME(m_sh6840_timer[0].counter.w));
save_item(NAME(m_sh6840_timer[1].counter.w));
save_item(NAME(m_sh6840_timer[2].counter.w));
save_item(NAME(m_sh6840_volume));
save_item(NAME(m_sh6840_MSB_latch));
save_item(NAME(m_sh6840_LSB_latch));
@ -151,27 +163,10 @@ void exidy_sound_device::sh6840_register_state_globals()
save_item(NAME(m_sh6840_LFSR_3));
save_item(NAME(m_sh6840_clock_count));
save_item(NAME(m_sfxctrl));
save_item(NAME(m_sh6840_timer[0].cr));
save_item(NAME(m_sh6840_timer[0].state));
save_item(NAME(m_sh6840_timer[0].leftovers));
save_item(NAME(m_sh6840_timer[0].timer));
save_item(NAME(m_sh6840_timer[0].clocks));
save_item(NAME(m_sh6840_timer[0].counter.w));
save_item(NAME(m_sh6840_timer[1].cr));
save_item(NAME(m_sh6840_timer[1].state));
save_item(NAME(m_sh6840_timer[1].leftovers));
save_item(NAME(m_sh6840_timer[1].timer));
save_item(NAME(m_sh6840_timer[1].clocks));
save_item(NAME(m_sh6840_timer[1].counter.w));
save_item(NAME(m_sh6840_timer[2].cr));
save_item(NAME(m_sh6840_timer[2].state));
save_item(NAME(m_sh6840_timer[2].leftovers));
save_item(NAME(m_sh6840_timer[2].timer));
save_item(NAME(m_sh6840_timer[2].clocks));
save_item(NAME(m_sh6840_timer[2].counter.w));
}
/*************************************
*
* Audio startup routines
@ -184,7 +179,7 @@ void exidy_sound_device::common_sh_start()
m_sh6840_clocks_per_sample = (int)(SH6840_CLOCK.dvalue() / (double)sample_rate * (double)(1 << 24));
/* allocate the stream */
// allocate the stream
m_stream = stream_alloc(0, 1, sample_rate);
sh6840_register_state_globals();
@ -197,18 +192,6 @@ exidy_sound_device::exidy_sound_device(const machine_config &mconfig, const char
{
}
exidy_sh8253_sound_device::exidy_sh8253_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: exidy_sound_device(mconfig, type, tag, owner, clock)
, m_riot(*this, "riot")
, m_cvsd(*this, "cvsd")
, m_cvsd_filter(*this, "cvsd_filter")
, m_cvsd_filter2(*this, "cvsd_filter2")
, m_cvsdcpu(*this, "cvsdcpu")
, m_tms(*this, "tms")
, m_pia(*this, "pia")
{
}
exidy_sound_device::exidy_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_sound_interface(mconfig, *this)
@ -227,6 +210,14 @@ exidy_sound_device::exidy_sound_device(const machine_config &mconfig, device_typ
{
}
exidy_sh8253_sound_device::exidy_sh8253_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: exidy_sound_device(mconfig, type, tag, owner, clock)
, m_riot(*this, "riot")
, m_pia(*this, "pia")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -236,6 +227,7 @@ void exidy_sound_device::device_start()
common_sh_start();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
@ -245,6 +237,7 @@ void exidy_sound_device::device_reset()
common_sh_reset();
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
@ -253,33 +246,33 @@ void exidy_sound_device::sound_stream_update(sound_stream &stream, std::vector<r
{
sh6840_timer_channel *sh6840_timer = m_sh6840_timer;
/* hack to skip the expensive lfsr noise generation unless at least one of the 3 channels actually depends on it being generated */
int noisy = ((sh6840_timer[0].cr & sh6840_timer[1].cr & sh6840_timer[2].cr & 0x02) == 0);
// hack to skip the expensive lfsr noise generation unless at least one of the 3 channels actually depends on it being generated
bool noisy = ((sh6840_timer[0].cr & sh6840_timer[1].cr & sh6840_timer[2].cr & 0x02) == 0);
auto &buffer = outputs[0];
/* loop over samples */
// loop over samples
for (int sampindex = 0; sampindex < buffer.samples(); sampindex++)
{
sh6840_timer_channel *t;
int clocks;
s32 sample = 0;
/* determine how many 6840 clocks this sample */
// determine how many 6840 clocks this sample
m_sh6840_clock_count += m_sh6840_clocks_per_sample;
int clocks_this_sample = m_sh6840_clock_count >> 24;
m_sh6840_clock_count &= (1 << 24) - 1;
/* skip if nothing enabled */
// skip if nothing enabled
if ((sh6840_timer[0].cr & 0x01) == 0)
{
int noise_clocks_this_sample = 0;
uint32_t chan0_clocks;
/* generate E-clocked noise if configured to do so */
// generate E-clocked noise if configured to do so
if (noisy && !(m_sfxctrl & 0x01))
noise_clocks_this_sample = sh6840_update_noise(clocks_this_sample);
/* handle timer 0 if enabled */
// handle timer 0 if enabled
t = &sh6840_timer[0];
chan0_clocks = t->clocks;
clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample;
@ -287,21 +280,22 @@ void exidy_sound_device::sound_stream_update(sound_stream &stream, std::vector<r
if (t->state && !(m_sfxctrl & 0x02) && (t->cr & 0x80))
sample += m_sh6840_volume[0];
/* generate channel 0-clocked noise if configured to do so */
// generate channel 0-clocked noise if configured to do so
if (noisy && (m_sfxctrl & 0x01))
noise_clocks_this_sample = sh6840_update_noise(t->clocks - chan0_clocks);
/* handle timer 1 if enabled */
// handle timer 1 if enabled
t = &sh6840_timer[1];
clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample;
sh6840_apply_clock(t, clocks);
if (t->state && (t->cr & 0x80))
sample += m_sh6840_volume[1];
/* handle timer 2 if enabled */
// handle timer 2 if enabled
t = &sh6840_timer[2];
clocks = (t->cr & 0x02) ? clocks_this_sample : noise_clocks_this_sample;
/* prescale */
// prescale
if (t->cr & 0x01)
{
clocks += t->leftovers;
@ -313,25 +307,20 @@ void exidy_sound_device::sound_stream_update(sound_stream &stream, std::vector<r
sample += m_sh6840_volume[2];
}
/* music (if present) */
// music (if present)
sample += generate_music_sample();
/* stash */
// stash
buffer.put_int(sampindex, sample, 32768);
}
}
s32 exidy_sound_device::generate_music_sample()
{
return 0;
}
s32 exidy_sh8253_sound_device::generate_music_sample()
{
sh8253_timer_channel *c;
s32 sample = 0;
/* music channel 0 */
// music channel 0
c = &m_sh8253_timer[0];
if (c->enable)
{
@ -340,7 +329,7 @@ s32 exidy_sh8253_sound_device::generate_music_sample()
sample += BASE_VOLUME;
}
/* music channel 1 */
// music channel 1
c = &m_sh8253_timer[1];
if (c->enable)
{
@ -349,7 +338,7 @@ s32 exidy_sh8253_sound_device::generate_music_sample()
sample += BASE_VOLUME;
}
/* music channel 2 */
// music channel 2
c = &m_sh8253_timer[2];
if (c->enable)
{
@ -371,7 +360,7 @@ s32 exidy_sh8253_sound_device::generate_music_sample()
void exidy_sound_device::common_sh_reset()
{
/* 6840 */
// 6840
memset(m_sh6840_timer, 0, sizeof(m_sh6840_timer));
m_sh6840_MSB_latch = 0;
m_sh6840_LSB_latch = 0;
@ -381,7 +370,7 @@ void exidy_sound_device::common_sh_reset()
m_sh6840_clock_count = 0;
m_sfxctrl = 0;
/* LFSR */
// LFSR
m_sh6840_LFSR_oldxor = 0;
m_sh6840_LFSR_0 = 0xffffffff;
m_sh6840_LFSR_1 = 0xffffffff;
@ -390,57 +379,6 @@ void exidy_sound_device::common_sh_reset()
}
/*************************************
*
* 6532 interface
*
*************************************/
void exidy_sh8253_sound_device::r6532_porta_w(uint8_t data)
{
if (m_cvsd.found())
m_cvsdcpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
if (m_tms.found())
{
logerror("(%f)%s:TMS5220 data write = %02X\n", machine().time().as_double(), machine().describe_context(), m_riot->porta_out_get());
m_tms->data_w(data);
}
}
uint8_t exidy_sh8253_sound_device::r6532_porta_r()
{
uint8_t status = 0xff;
if (m_tms.found())
{
status = m_tms->status_r();
logerror("(%f)%s:TMS5220 status read = %02X\n", machine().time().as_double(), machine().describe_context(), status);
}
return status;
}
void exidy_sh8253_sound_device::r6532_portb_w(uint8_t data)
{
if (m_tms.found())
{
m_tms->rsq_w(BIT(data, 0));
m_tms->wsq_w(BIT(data, 1));
}
}
uint8_t exidy_sh8253_sound_device::r6532_portb_r()
{
uint8_t newdata = m_riot->portb_in_get();
if (m_tms.found())
{
newdata &= ~0x0c;
if (m_tms->readyq_r()) newdata |= 0x04;
if (m_tms->intq_r()) newdata |= 0x08;
}
return newdata;
}
/*************************************
*
@ -450,24 +388,15 @@ uint8_t exidy_sh8253_sound_device::r6532_portb_r()
void exidy_sh8253_sound_device::sh8253_register_state_globals()
{
save_item(NAME(m_sh8253_timer[0].clstate));
save_item(NAME(m_sh8253_timer[0].enable));
save_item(NAME(m_sh8253_timer[0].count));
save_item(NAME(m_sh8253_timer[0].step));
save_item(NAME(m_sh8253_timer[0].fraction));
save_item(NAME(m_sh8253_timer[1].clstate));
save_item(NAME(m_sh8253_timer[1].enable));
save_item(NAME(m_sh8253_timer[1].count));
save_item(NAME(m_sh8253_timer[1].step));
save_item(NAME(m_sh8253_timer[1].fraction));
save_item(NAME(m_sh8253_timer[2].clstate));
save_item(NAME(m_sh8253_timer[2].enable));
save_item(NAME(m_sh8253_timer[2].count));
save_item(NAME(m_sh8253_timer[2].step));
save_item(NAME(m_sh8253_timer[2].fraction));
save_item(STRUCT_MEMBER(m_sh8253_timer, clstate));
save_item(STRUCT_MEMBER(m_sh8253_timer, enable));
save_item(STRUCT_MEMBER(m_sh8253_timer, count));
save_item(STRUCT_MEMBER(m_sh8253_timer, step));
save_item(STRUCT_MEMBER(m_sh8253_timer, fraction));
}
/*************************************
*
* 8253 timer handlers
@ -519,27 +448,27 @@ void exidy_sh8253_sound_device::sh8253_w(offs_t offset, uint8_t data)
uint8_t exidy_sound_device::sh6840_r(offs_t offset)
{
/* force an update of the stream */
// force an update of the stream
m_stream->update();
switch (offset)
{
/* offset 0: Motorola datasheet says it isn't used, Hitachi datasheet says it reads as 0s always*/
// offset 0: Motorola datasheet says it isn't used, Hitachi datasheet says it reads as 0s always
case 0:
return 0;
/* offset 1 reads the status register: bits 2 1 0 correspond to ints on channels 2,1,0, and bit 7 is an 'OR' of bits 2,1,0 */
// offset 1 reads the status register: bits 2 1 0 correspond to ints on channels 2,1,0, and bit 7 is an 'OR' of bits 2,1,0
case 1:
logerror("%s:exidy_sh6840_r - unexpected read, status register is TODO!\n", machine().describe_context());
return 0;
/* offsets 2,4,6 read channel 0,1,2 MSBs and latch the LSB*/
// offsets 2,4,6 read channel 0,1,2 MSBs and latch the LSB
case 2: case 4: case 6:
m_sh6840_LSB_latch = m_sh6840_timer[((offset>>1)-1)].counter.b.l;
return m_sh6840_timer[((offset>>1)-1)].counter.b.h;
/* offsets 3,5,7 read the LSB latch*/
default: /* case 3,5,7 */
// offsets 3,5,7 read the LSB latch
default: // case 3,5,7
return m_sh6840_LSB_latch;
}
}
@ -549,49 +478,49 @@ void exidy_sound_device::sh6840_w(offs_t offset, uint8_t data)
{
sh6840_timer_channel *sh6840_timer = m_sh6840_timer;
/* force an update of the stream */
// force an update of the stream
m_stream->update();
switch (offset)
{
/* offset 0 writes to either channel 0 control or channel 2 control */
// offset 0 writes to either channel 0 control or channel 2 control
case 0:
if (sh6840_timer[1].cr & 0x01)
sh6840_timer[0].cr = data;
else
sh6840_timer[2].cr = data;
/* only support mode 0 and 2 */
// only support mode 0 and 2
if (((data >> 3) & 5) != 0)
fatalerror("exidy_sh6840_w - channel %d configured for mode %d\n", (sh6840_timer[1].cr & 0x01) ? 0 : 2, (data >> 3) & 7);
break;
/* offset 1 writes to channel 1 control */
// offset 1 writes to channel 1 control
case 1:
sh6840_timer[1].cr = data;
/* only support mode 0 and 2 */
// only support mode 0 and 2
if (((data >> 3) & 5) != 0)
fatalerror("exidy_sh6840_w - channel 1 configured for mode %d\n", (data >> 3) & 7);
break;
/* offsets 2/4/6 write to the common MSB latch */
// offsets 2/4/6 write to the common MSB latch
case 2:
case 4:
case 6:
m_sh6840_MSB_latch = data;
break;
/* offsets 3/5/7 write to the LSB controls */
// offsets 3/5/7 write to the LSB controls
case 3:
case 5:
case 7:
{
/* latch the timer value */
// latch the timer value
int ch = (offset - 3) / 2;
sh6840_timer[ch].timer = (m_sh6840_MSB_latch << 8) | (data & 0xff);
/* if CR4 is clear, the value is loaded immediately */
// if CR4 is clear, the value is loaded immediately
if (!(sh6840_timer[ch].cr & 0x10))
sh6840_timer[ch].counter.w = sh6840_timer[ch].timer;
break;
@ -627,19 +556,6 @@ void exidy_sound_device::sfxctrl_w(offs_t offset, uint8_t data)
/*************************************
*
* Sound filter control
*
*************************************/
void venture_sound_device::filter_w(uint8_t data)
{
logerror("exidy_sound_filter_w = %02X\n", data);
}
/*************************************
*
* Venture, etc.
@ -662,6 +578,7 @@ venture_sound_device::venture_sound_device(const machine_config &mconfig, device
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -670,12 +587,12 @@ void exidy_sh8253_sound_device::device_start()
{
common_sh_start();
/* 8253 */
// 8253
m_freq_to_step = (1 << 24) / SH8253_CLOCK;
sh8253_register_state_globals();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
@ -684,84 +601,50 @@ void exidy_sh8253_sound_device::device_reset()
{
common_sh_reset();
/* 8253 */
// 8253
memset(m_sh8253_timer, 0, sizeof(m_sh8253_timer));
}
void venture_sound_device::pa_w(uint8_t data)
//-------------------------------------------------
// I/O handlers
//-------------------------------------------------
void venture_sound_device::filter_w(uint8_t data)
{
m_pia->porta_w(data);
logerror("exidy_sound_filter_w = %02X\n", data);
}
void venture_sound_device::pb_w(uint8_t data)
{
m_pia->portb_w(data);
}
void venture_sound_device::ca_w(int state)
{
m_pia->ca1_w(state);
}
void venture_sound_device::cb_w(int state)
{
m_pia->cb1_w(state);
}
void venture_sound_device::pia_pa_w(uint8_t data)
{
m_pa_callback(data);
}
void venture_sound_device::pia_pb_w(uint8_t data)
{
m_pb_callback(data);
}
void venture_sound_device::pia_ca2_w(int state)
{
m_ca2_callback(state);
}
void venture_sound_device::pia_cb2_w(int state)
{
m_cb2_callback(state);
}
//-------------------------------------------------
// Address maps
//-------------------------------------------------
void venture_sound_device::venture_audio_map(address_map &map)
{
map.global_mask(0x7fff);
map(0x0000, 0x007f).mirror(0x0780).ram();
map(0x0800, 0x087f).mirror(0x0780).rw("riot", FUNC(riot6532_device::read), FUNC(riot6532_device::write));
map(0x1000, 0x1003).mirror(0x07fc).rw("pia", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x0000, 0x007f).mirror(0x0780).m(m_riot, FUNC(mos6532_new_device::ram_map));
map(0x0800, 0x081f).mirror(0x07e0).m(m_riot, FUNC(mos6532_new_device::io_map));
map(0x1000, 0x1003).mirror(0x07fc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x1800, 0x1803).mirror(0x07fc).w(FUNC(venture_sound_device::sh8253_w)).nopr(); // no /RD
map(0x2000, 0x27ff).w(FUNC(venture_sound_device::filter_w));
map(0x2000, 0x2000).mirror(0x07ff).w(FUNC(venture_sound_device::filter_w));
map(0x2800, 0x2807).mirror(0x07f8).rw(FUNC(venture_sound_device::sh6840_r), FUNC(venture_sound_device::sh6840_w));
map(0x3000, 0x3003).mirror(0x07fc).w(FUNC(venture_sound_device::sfxctrl_w));
map(0x5800, 0x7fff).rom();
}
//-------------------------------------------------
// Machine config
//-------------------------------------------------
void venture_sound_device::device_add_mconfig(machine_config &config)
{
m6502_device &audiocpu(M6502(config, "audiocpu", 3.579545_MHz_XTAL / 4));
audiocpu.set_addrmap(AS_PROGRAM, &venture_sound_device::venture_audio_map);
RIOT6532(config, m_riot, SH6532_CLOCK);
m_riot->in_pa_callback().set(FUNC(venture_sound_device::r6532_porta_r));
m_riot->out_pa_callback().set(FUNC(venture_sound_device::r6532_porta_w));
m_riot->in_pb_callback().set(FUNC(venture_sound_device::r6532_portb_r));
m_riot->out_pb_callback().set(FUNC(venture_sound_device::r6532_portb_w));
m_riot->irq_callback().set("audioirq", FUNC(input_merger_device::in_w<0>));
MOS6532_NEW(config, m_riot, SH6532_CLOCK);
m_riot->irq_wr_callback().set("audioirq", FUNC(input_merger_device::in_w<0>));
PIA6821(config, m_pia, 0);
m_pia->writepa_handler().set(FUNC(venture_sound_device::pia_pa_w));
@ -789,11 +672,17 @@ DEFINE_DEVICE_TYPE(EXIDY_MTRAP, mtrap_sound_device, "mtrap_sound", "Exidy SFX+PS
mtrap_sound_device::mtrap_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: venture_sound_device(mconfig, EXIDY_MTRAP, tag, owner, clock)
, m_cvsd_timer(*this,"cvsd_timer")
, m_cvsd_clk(false)
, m_cvsd_timer(*this, "cvsd_timer")
, m_cvsd(*this, "cvsd")
, m_cvsd_filter(*this, "cvsd_filter")
, m_cvsd_filter2(*this, "cvsd_filter2")
, m_cvsdcpu(*this, "cvsdcpu")
, m_cvsd_data(0)
, m_cvsd_clk(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -802,17 +691,22 @@ void mtrap_sound_device::device_start()
{
common_sh_start();
/* 8253 */
// 8253
m_freq_to_step = (1 << 24) / SH8253_CLOCK;
sh8253_register_state_globals();
save_item(NAME(m_cvsd_data));
save_item(NAME(m_cvsd_clk));
}
//-------------------------------------------------
// I/O handlers
//-------------------------------------------------
TIMER_DEVICE_CALLBACK_MEMBER(mtrap_sound_device::cvsd_timer)
{
m_cvsd_clk = !m_cvsd_clk;
m_cvsd_clk ^= 1;
m_cvsd->clock_w(m_cvsd_clk);
}
@ -822,7 +716,7 @@ void mtrap_sound_device::voiceio_w(offs_t offset, uint8_t data)
m_cvsd->digit_w(data & 1);
if (!(offset & 0x20))
m_riot->portb_in_set(data & 1, 0xff);
m_riot->pb0_w(data & 1);
}
@ -832,11 +726,7 @@ uint8_t mtrap_sound_device::voiceio_r(offs_t offset)
if (!(offset & 0x80))
{
retval &= 0xf0;
uint8_t porta = m_riot->porta_out_get();
uint8_t data = (porta & 0x06) >> 1;
data |= (porta & 0x01) << 2;
data |= (porta & 0x08);
retval |= data;
retval |= bitswap(m_cvsd_data,3,0,2,1);
}
if (!(offset & 0x40))
@ -848,6 +738,16 @@ uint8_t mtrap_sound_device::voiceio_r(offs_t offset)
return retval;
}
void mtrap_sound_device::cvsd_data_w(uint8_t data)
{
m_cvsd_data = data;
m_cvsdcpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
}
//-------------------------------------------------
// Address maps
//-------------------------------------------------
void mtrap_sound_device::cvsd_map(address_map &map)
{
@ -863,36 +763,89 @@ void mtrap_sound_device::cvsd_iomap(address_map &map)
}
//-------------------------------------------------
// Machine config
//-------------------------------------------------
void mtrap_sound_device::device_add_mconfig(machine_config &config)
{
venture_sound_device::device_add_mconfig(config);
m_riot->pa_wr_callback().set(FUNC(mtrap_sound_device::cvsd_data_w));
Z80(config, m_cvsdcpu, CVSD_Z80_CLOCK);
m_cvsdcpu->set_addrmap(AS_PROGRAM, &mtrap_sound_device::cvsd_map);
m_cvsdcpu->set_addrmap(AS_IO, &mtrap_sound_device::cvsd_iomap);
// this is a 555 timer with 53% duty cycle, within margin of error of 50% duty cycle; the handler clocks on both clock edges, hence * 2.0
TIMER(config, m_cvsd_timer).configure_periodic(FUNC(mtrap_sound_device::cvsd_timer), attotime::from_hz(CVSD_CLOCK*2.0));
TIMER(config, m_cvsd_timer).configure_periodic(FUNC(mtrap_sound_device::cvsd_timer), attotime::from_hz(CVSD_CLOCK * 2.0));
/* audio hardware */
// audio hardware
FILTER_BIQUAD(config, m_cvsd_filter2).opamp_mfb_lowpass_setup(RES_K(10), RES_K(3.9), RES_K(18), CAP_N(20), CAP_N(2.2));
m_cvsd_filter2->add_route(ALL_OUTPUTS, "mono", 1.0);
FILTER_BIQUAD(config, m_cvsd_filter).opamp_mfb_lowpass_setup(RES_K(10), RES_K(3.9), RES_K(18), CAP_N(20), CAP_N(2.2));
m_cvsd_filter->add_route(ALL_OUTPUTS, m_cvsd_filter2, 1.0);
MC3417(config, m_cvsd, 0).add_route(ALL_OUTPUTS, m_cvsd_filter, 0.3086); // each filter has gain of 1.8 for total gain of 3.24, 0.3086 cancels this out.
}
/*************************************
*
* Victory
*
*************************************/
#define VICTORY_AUDIO_CPU_CLOCK (3.579545_MHz_XTAL / 4)
#define VICTORY_LOG_SOUND 0
DEFINE_DEVICE_TYPE(EXIDY_VICTORY, victory_sound_device, "victory_sound", "Exidy SFX+PSG+Speech")
victory_sound_device::victory_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: exidy_sh8253_sound_device(mconfig, EXIDY_VICTORY, tag, owner, clock)
, m_tms(*this, "tms")
, m_sound_response_ack_clk(0)
, m_pia_ca1(0)
, m_pia_cb1(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void victory_sound_device::device_start()
{
exidy_sh8253_sound_device::device_start();
save_item(NAME(m_sound_response_ack_clk));
save_item(NAME(m_pia_ca1));
save_item(NAME(m_pia_cb1));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void victory_sound_device::device_reset()
{
exidy_sh8253_sound_device::device_reset();
// the flip-flop @ F4 is reset
m_sound_response_ack_clk = 0;
m_pia_cb1 = 1;
m_pia->cb1_w(m_pia_cb1);
// these two lines shouldn't be needed, but it avoids the log entry
// as the sound CPU checks port A before the main CPU ever writes to it
m_pia->porta_w(0);
m_pia_ca1 = 1;
m_pia->ca1_w(m_pia_ca1);
}
//-------------------------------------------------
// I/O handlers
//-------------------------------------------------
uint8_t victory_sound_device::response_r()
{
@ -900,7 +853,7 @@ uint8_t victory_sound_device::response_r()
if (!machine().side_effects_disabled())
{
if (VICTORY_LOG_SOUND) logerror("%s:!!!! Sound response read = %02X\n", machine().describe_context(), ret);
LOGMASKED(LOG_VICTORY_SOUND, "%s:!!!! Sound response read = %02X\n", machine().describe_context(), ret);
m_pia_cb1 = 0;
m_pia->cb1_w(m_pia_cb1);
@ -909,17 +862,14 @@ uint8_t victory_sound_device::response_r()
return ret;
}
uint8_t victory_sound_device::status_r()
{
uint8_t ret = (m_pia_ca1 << 7) | (m_pia_cb1 << 6);
if (VICTORY_LOG_SOUND) logerror("%s:!!!! Sound status read = %02X\n", machine().describe_context(), ret);
LOGMASKED(LOG_VICTORY_SOUND, "%s:!!!! Sound status read = %02X\n", machine().describe_context(), ret);
return ret;
}
TIMER_CALLBACK_MEMBER(victory_sound_device::delayed_command_w)
{
m_pia->porta_w(param);
@ -929,15 +879,13 @@ TIMER_CALLBACK_MEMBER(victory_sound_device::delayed_command_w)
void victory_sound_device::command_w(uint8_t data)
{
if (VICTORY_LOG_SOUND) logerror("%s:!!!! Sound command = %02X\n", machine().describe_context(), data);
LOGMASKED(LOG_VICTORY_SOUND, "%s:!!!! Sound command = %02X\n", machine().describe_context(), data);
machine().scheduler().synchronize(timer_expired_delegate(FUNC(victory_sound_device::delayed_command_w), this), data);
}
void victory_sound_device::irq_clear_w(int state)
{
if (VICTORY_LOG_SOUND) logerror("%s:!!!! Sound IRQ clear = %02X\n", machine().describe_context(), state);
LOGMASKED(LOG_VICTORY_SOUND, "%s:!!!! Sound IRQ clear = %02X\n", machine().describe_context(), state);
if (!state)
{
@ -946,70 +894,30 @@ void victory_sound_device::irq_clear_w(int state)
}
}
void victory_sound_device::main_ack_w(int state)
{
if (VICTORY_LOG_SOUND) logerror("%s:!!!! Sound Main ACK W = %02X\n", machine().describe_context(), state);
LOGMASKED(LOG_VICTORY_SOUND, "%s:!!!! Sound Main ACK W = %02X\n", machine().describe_context(), state);
if (m_victory_sound_response_ack_clk && !state)
if (m_sound_response_ack_clk && !state)
{
m_pia_cb1 = 1;
m_pia->cb1_w(m_pia_cb1);
}
m_victory_sound_response_ack_clk = state;
m_sound_response_ack_clk = state;
}
DEFINE_DEVICE_TYPE(EXIDY_VICTORY, victory_sound_device, "victory_sound", "Exidy SFX+PSG+Speech")
victory_sound_device::victory_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: exidy_sh8253_sound_device(mconfig, EXIDY_VICTORY, tag, owner, clock)
, m_victory_sound_response_ack_clk(0)
, m_pia_ca1(0)
, m_pia_cb1(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
// Address maps
//-------------------------------------------------
void victory_sound_device::device_start()
{
save_item(NAME(m_victory_sound_response_ack_clk));
save_item(NAME(m_pia_ca1));
save_item(NAME(m_pia_cb1));
exidy_sh8253_sound_device::device_start();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void victory_sound_device::device_reset()
{
exidy_sh8253_sound_device::device_reset();
/* the flip-flop @ F4 is reset */
m_victory_sound_response_ack_clk = 0;
m_pia_cb1 = 1;
m_pia->cb1_w(m_pia_cb1);
/* these two lines shouldn't be needed, but it avoids the log entry
as the sound CPU checks port A before the main CPU ever writes to it */
m_pia->porta_w(0);
m_pia_ca1 = 1;
m_pia->ca1_w(m_pia_ca1);
}
void victory_sound_device::victory_audio_map(address_map &map)
{
map(0x0000, 0x00ff).mirror(0x0f00).ram();
map(0x1000, 0x107f).mirror(0x0f80).rw("riot", FUNC(riot6532_device::read), FUNC(riot6532_device::write));
map(0x2000, 0x2003).mirror(0x0ffc).rw("pia", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x0000, 0x007f).mirror(0x0f00).m(m_riot, FUNC(mos6532_new_device::ram_map));
map(0x0080, 0x00ff).mirror(0x0f00).ram();
map(0x1000, 0x101f).mirror(0x0fe0).m(m_riot, FUNC(mos6532_new_device::io_map));
map(0x2000, 0x2003).mirror(0x0ffc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x3000, 0x3003).mirror(0x0ffc).w(FUNC(victory_sound_device::sh8253_w)).nopr(); // no /RD
map(0x4000, 0x4fff).noprw();
map(0x5000, 0x5007).mirror(0x0ff8).rw(FUNC(victory_sound_device::sh6840_r), FUNC(victory_sound_device::sh6840_w));
@ -1019,17 +927,23 @@ void victory_sound_device::victory_audio_map(address_map &map)
}
//-------------------------------------------------
// Machine config
//-------------------------------------------------
void victory_sound_device::device_add_mconfig(machine_config &config)
{
m6502_device &audiocpu(M6502(config, "audiocpu", VICTORY_AUDIO_CPU_CLOCK));
m6502_device &audiocpu(M6502(config, "audiocpu", 3.579545_MHz_XTAL / 4));
audiocpu.set_addrmap(AS_PROGRAM, &victory_sound_device::victory_audio_map);
RIOT6532(config, m_riot, SH6532_CLOCK);
m_riot->in_pa_callback().set(FUNC(victory_sound_device::r6532_porta_r));
m_riot->out_pa_callback().set(FUNC(victory_sound_device::r6532_porta_w));
m_riot->in_pb_callback().set(FUNC(victory_sound_device::r6532_portb_r));
m_riot->out_pb_callback().set(FUNC(victory_sound_device::r6532_portb_w));
m_riot->irq_callback().set("audioirq", FUNC(input_merger_device::in_w<0>));
MOS6532_NEW(config, m_riot, SH6532_CLOCK);
m_riot->pa_wr_callback().set(m_tms, FUNC(tms5220_device::data_w));
m_riot->pa_rd_callback().set(m_tms, FUNC(tms5220_device::status_r));
m_riot->pb_wr_callback<0>().set(m_tms, FUNC(tms5220_device::rsq_w));
m_riot->pb_wr_callback<1>().set(m_tms, FUNC(tms5220_device::wsq_w));
m_riot->pb_rd_callback<2>().set(m_tms, FUNC(tms5220_device::readyq_r));
m_riot->pb_rd_callback<3>().set(m_tms, FUNC(tms5220_device::intq_r));
m_riot->irq_wr_callback().set("audioirq", FUNC(input_merger_device::in_w<0>));
PIA6821(config, m_pia, 0);
m_pia->ca2_handler().set(FUNC(victory_sound_device::irq_clear_w));
@ -1039,7 +953,6 @@ void victory_sound_device::device_add_mconfig(machine_config &config)
INPUT_MERGER_ANY_HIGH(config, "audioirq").output_handler().set_inputline("audiocpu", m6502_device::IRQ_LINE); // open collector
SPEAKER(config, "mono").front_center();
this->add_route(ALL_OUTPUTS, "mono", 1.0);
TMS5220(config, m_tms, 640000).add_route(ALL_OUTPUTS, "mono", 1.0);

View File

@ -5,18 +5,17 @@
#pragma once
#include "machine/6532riot.h"
#include "machine/6821pia.h"
#include "machine/mos6530n.h"
#include "machine/timer.h"
#include "sound/flt_biquad.h"
#include "sound/hc55516.h"
#include "sound/tms5220.h"
class exidy_sound_device : public device_t,
public device_sound_interface
class exidy_sound_device : public device_t, public device_sound_interface
{
/* 6840 variables */
// 6840 variables
struct sh6840_timer_channel
{
uint8_t cr = 0;
@ -57,11 +56,11 @@ protected:
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual s32 generate_music_sample();
virtual s32 generate_music_sample() { return 0; }
static inline void sh6840_apply_clock(sh6840_timer_channel *t, int clocks);
/* sound streaming variables */
// sound streaming variables
sound_stream *m_stream;
double m_freq_to_step;
@ -86,6 +85,7 @@ private:
DECLARE_DEVICE_TYPE(EXIDY, exidy_sound_device)
class exidy_sh8253_sound_device : public exidy_sound_device
{
struct sh8253_timer_channel
@ -106,30 +106,16 @@ protected:
virtual s32 generate_music_sample() override;
void r6532_porta_w(uint8_t data);
uint8_t r6532_porta_r();
void r6532_portb_w(uint8_t data);
uint8_t r6532_portb_r();
void sh8253_w(offs_t offset, uint8_t data);
void sh8253_register_state_globals();
/* 8253 variables */
sh8253_timer_channel m_sh8253_timer[3];
/* 6532 variables */
required_device<riot6532_device> m_riot;
/* 5220/CVSD variables */
optional_device<mc3417_device> m_cvsd;
optional_device<filter_biquad_device> m_cvsd_filter;
optional_device<filter_biquad_device> m_cvsd_filter2;
optional_device<cpu_device> m_cvsdcpu;
optional_device<tms5220_device> m_tms;
required_device<mos6532_new_device> m_riot;
required_device<pia6821_device> m_pia;
};
class venture_sound_device : public exidy_sh8253_sound_device
{
public:
@ -142,10 +128,10 @@ public:
auto cb2_callback() { return m_cb2_callback.bind(); }
// external access
void pa_w(uint8_t data);
void pb_w(uint8_t data);
void ca_w(int state);
void cb_w(int state);
void pa_w(uint8_t data) { m_pia->porta_w(data); }
void pb_w(uint8_t data) { m_pia->portb_w(data); }
void ca_w(int state) { m_pia->ca1_w(state); }
void cb_w(int state) { m_pia->cb1_w(state); }
protected:
venture_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@ -158,10 +144,10 @@ protected:
private:
void filter_w(uint8_t data);
void pia_pa_w(uint8_t data);
void pia_pb_w(uint8_t data);
void pia_ca2_w(int state);
void pia_cb2_w(int state);
void pia_pa_w(uint8_t data) { m_pa_callback(data); }
void pia_pb_w(uint8_t data) { m_pb_callback(data); }
void pia_ca2_w(int state) { m_ca2_callback(state); }
void pia_cb2_w(int state) { m_cb2_callback(state); }
void venture_audio(machine_config &config);
@ -173,6 +159,7 @@ private:
DECLARE_DEVICE_TYPE(EXIDY_VENTURE, venture_sound_device)
class mtrap_sound_device : public venture_sound_device
{
public:
@ -185,10 +172,18 @@ protected:
private:
required_device<timer_device> m_cvsd_timer;
required_device<mc3417_device> m_cvsd;
required_device<filter_biquad_device> m_cvsd_filter;
required_device<filter_biquad_device> m_cvsd_filter2;
required_device<cpu_device> m_cvsdcpu;
TIMER_DEVICE_CALLBACK_MEMBER(cvsd_timer);
void voiceio_w(offs_t offset, uint8_t data);
uint8_t voiceio_r(offs_t offset);
bool m_cvsd_clk;
void cvsd_data_w(uint8_t data);
uint8_t m_cvsd_data;
uint8_t m_cvsd_clk;
void cvsd_map(address_map &map);
void cvsd_iomap(address_map &map);
@ -196,6 +191,7 @@ private:
DECLARE_DEVICE_TYPE(EXIDY_MTRAP, mtrap_sound_device)
class victory_sound_device : public exidy_sh8253_sound_device
{
public:
@ -213,15 +209,17 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
required_device<tms5220_device> m_tms;
void irq_clear_w(int state);
void main_ack_w(int state);
void victory_audio_map(address_map &map);
// internal state
uint8_t m_victory_sound_response_ack_clk; /* 7474 @ F4 */
uint8_t m_sound_response_ack_clk; // 7474 @ F4
TIMER_CALLBACK_MEMBER( delayed_command_w );
TIMER_CALLBACK_MEMBER(delayed_command_w);
int m_pia_ca1;
int m_pia_cb1;