preliminary zsg2 sound now works in taitogn.c, remove the // from

//AM_RANGE(0x1fb80000, 0x1fb80003) AM_DEVWRITE16("taito_zoom", taito_zoom_device, reset_control_w, 0xffff0000)
This commit is contained in:
Michaël Banaan Ananas 2014-02-17 00:41:33 +00:00
parent b81f228f85
commit 4c77c15cce
6 changed files with 131 additions and 102 deletions

View File

@ -42,6 +42,15 @@
To compute the final 16bits value just shift left by (9-s). To compute the final 16bits value just shift left by (9-s).
Yes, that simple. Yes, that simple.
---------------------------------------------------------
Emulation is still preliminary.
TODO:
- channel volume, 16bits?? need to make a lookup table?
- memory reads out of range sometimes
- a lot of unknowns
*/ */
#include "emu.h" #include "emu.h"
@ -51,11 +60,6 @@
// device type definition // device type definition
const device_type ZSG2 = &device_creator<zsg2_device>; const device_type ZSG2 = &device_creator<zsg2_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//------------------------------------------------- //-------------------------------------------------
// zsg2_device - constructor // zsg2_device - constructor
//------------------------------------------------- //-------------------------------------------------
@ -86,9 +90,50 @@ void zsg2_device::device_start()
m_mem_blocks = m_mem_size / 4; m_mem_blocks = m_mem_size / 4;
m_mem_copy = auto_alloc_array_clear(machine(), UINT32, m_mem_blocks); m_mem_copy = auto_alloc_array_clear(machine(), UINT32, m_mem_blocks);
m_full_samples = auto_alloc_array_clear(machine(), INT16, m_mem_blocks * 4 + 4); m_full_samples = auto_alloc_array_clear(machine(), INT16, m_mem_blocks * 4 + 4); // +4 is for empty block
// register for savestates
save_pointer(NAME(m_mem_copy), m_mem_blocks / sizeof(UINT32));
save_pointer(NAME(m_full_samples), (m_mem_blocks * 4 + 4) / sizeof(INT16));
save_item(NAME(m_read_address));
for (int ch = 0; ch < 48; ch++)
{
save_item(NAME(m_chan[ch].v), ch);
save_item(NAME(m_chan[ch].is_playing), ch);
save_item(NAME(m_chan[ch].cur_pos), ch);
save_item(NAME(m_chan[ch].step_ptr), ch);
save_item(NAME(m_chan[ch].step), ch);
save_item(NAME(m_chan[ch].start_pos), ch);
save_item(NAME(m_chan[ch].end_pos), ch);
save_item(NAME(m_chan[ch].loop_pos), ch);
save_item(NAME(m_chan[ch].page), ch);
save_item(NAME(m_chan[ch].vol), ch);
}
} }
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void zsg2_device::device_reset()
{
m_read_address = 0;
// stop playing and clear all channels
control_w(4, 0xffff);
control_w(5, 0xffff);
control_w(6, 0xffff);
for (int ch = 0; ch < 48; ch++)
for (int reg = 0; reg < 0x10; reg++)
chan_w(ch, reg, 0);
}
/******************************************************************************/
UINT32 zsg2_device::read_memory(UINT32 offset) UINT32 zsg2_device::read_memory(UINT32 offset)
{ {
if (offset >= m_mem_blocks) if (offset >= m_mem_blocks)
@ -155,18 +200,24 @@ void zsg2_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
if (m_chan[ch].step_ptr & 0x80000) if (m_chan[ch].step_ptr & 0x80000)
{ {
m_chan[ch].step_ptr &= 0xffff; m_chan[ch].step_ptr &= 0xffff;
if (++m_chan[ch].cur_pos >= m_chan[ch].end_pos) if (++m_chan[ch].cur_pos > m_chan[ch].end_pos)
{ {
m_chan[ch].is_playing = false; // loop sample
//.. m_chan[ch].cur_pos = m_chan[ch].loop_pos;
//m_chan[ch].cur_pos = m_chan[ch].loop_pos; if ((m_chan[ch].cur_pos + 1) >= m_chan[ch].end_pos)
{
// end of sample
m_chan[ch].is_playing = false;
continue;
}
} }
m_chan[ch].samples = prepare_samples(m_chan[ch].page | m_chan[ch].cur_pos); m_chan[ch].samples = prepare_samples(m_chan[ch].page | m_chan[ch].cur_pos);
} }
INT16 sample = m_chan[ch].samples[m_chan[ch].step_ptr >> 16 & 3]; INT16 sample = m_chan[ch].samples[m_chan[ch].step_ptr >> 16 & 3];
//sample = (sample * (m_chan[ch].vol & 0xffff)) / 0x10000;
if (m_chan[ch].vol == 0) sample = 0; // temp hack to prevent stuck notes
mix_l += sample; mix_l += sample;
mix_r += sample; mix_r += sample;
@ -178,15 +229,14 @@ void zsg2_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
} }
/******************************************************************************/
void zsg2_device::chan_w(int ch, int reg, UINT16 data) void zsg2_device::chan_w(int ch, int reg, UINT16 data)
{ {
m_chan[ch].v[reg] = data;
switch (reg) switch (reg)
{ {
case 0x0: case 0x0:
// lo byte: ? // lo byte: always 0?
// hi byte: start address low // hi byte: start address low
m_chan[ch].start_pos = (m_chan[ch].start_pos & 0xff00) | (data >> 8 & 0xff); m_chan[ch].start_pos = (m_chan[ch].start_pos & 0xff00) | (data >> 8 & 0xff);
break; break;
@ -199,7 +249,7 @@ void zsg2_device::chan_w(int ch, int reg, UINT16 data)
break; break;
case 0x4: case 0x4:
// frequency? // frequency
m_chan[ch].step = data; m_chan[ch].step = data;
break; break;
@ -220,27 +270,48 @@ void zsg2_device::chan_w(int ch, int reg, UINT16 data)
m_chan[ch].loop_pos = (m_chan[ch].loop_pos & 0x00ff) | (data << 8 & 0xff00); m_chan[ch].loop_pos = (m_chan[ch].loop_pos & 0x00ff) | (data << 8 & 0xff00);
break; break;
case 0xb:
// always writes 0
// this register is read-only
break;
case 0xe:
// channel volume, reg 0xc is also related?
m_chan[ch].vol = data;
break;
default: default:
break; break;
} }
m_chan[ch].v[reg] = data;
} }
UINT16 zsg2_device::chan_r(int ch, int reg) UINT16 zsg2_device::chan_r(int ch, int reg)
{ {
switch (reg)
{
case 0xb:
// ?
return 0;
default:
break;
}
return m_chan[ch].v[reg]; return m_chan[ch].v[reg];
} }
/******************************************************************************/
void zsg2_device::control_w(int reg, UINT16 data) void zsg2_device::control_w(int reg, UINT16 data)
{ {
switch(reg) switch (reg)
{ {
case 0x00: case 0x01: case 0x02: case 0x00: case 0x01: case 0x02:
{ {
// key on? // key on
int base = (reg & 3) << 4; int base = (reg & 3) << 4;
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
@ -251,39 +322,6 @@ void zsg2_device::control_w(int reg, UINT16 data)
m_chan[ch].cur_pos = m_chan[ch].start_pos; m_chan[ch].cur_pos = m_chan[ch].start_pos;
m_chan[ch].step_ptr = 0; m_chan[ch].step_ptr = 0;
m_chan[ch].samples = prepare_samples(m_chan[ch].page | m_chan[ch].cur_pos); m_chan[ch].samples = prepare_samples(m_chan[ch].page | m_chan[ch].cur_pos);
#if 0
printf("keyon %02x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
ch,
m_chan[ch].v[0x0], m_chan[ch].v[0x1], m_chan[ch].v[0x2], m_chan[ch].v[0x3],
m_chan[ch].v[0x4], m_chan[ch].v[0x5], m_chan[ch].v[0x6], m_chan[ch].v[0x7],
m_chan[ch].v[0x8], m_chan[ch].v[0x9], m_chan[ch].v[0xa], m_chan[ch].v[0xb],
m_chan[ch].v[0xc], m_chan[ch].v[0xd], m_chan[ch].v[0xe], m_chan[ch].v[0xf]);
/*
r 0020 0010 - 0000ee50 00003b94
r 0020 0014 - 00019be0 000066f8
r 0020 0018 - 00018eac 000063ab
r 0020 001c - 0000003c 0000000f
keyon 15
9400 083b 00 01 start addr 083b94
0000 0400 02 03
2cec 04
1cab 05 ab = loop addr low
66f8 06 end addr
1c63 07 63 = loop addr high
f1a0 0000 0000 0000 f1a0 1b78 089e 1523
*/
#endif
} }
} }
break; break;
@ -324,25 +362,30 @@ f1a0 0000 0000 0000 f1a0 1b78 089e 1523
UINT16 zsg2_device::control_r(int reg) UINT16 zsg2_device::control_r(int reg)
{ {
switch(reg) switch (reg)
{ {
case 0x14: case 0x14:
return 0xff00; // memory bus busy?
// right before reading memory, it polls until low 8 bits are 0
return 0;
case 0x1e: case 0x1e:
// rom readback word low // rom readback word low
if (m_read_address >= m_mem_blocks) return 0; return read_memory(m_read_address) & 0xffff;
return m_mem_base[m_read_address] & 0xffff;
case 0x1f: case 0x1f:
// rom readback word high // rom readback word high
if (m_read_address >= m_mem_blocks) return 0; return read_memory(m_read_address) >> 16;
return m_mem_base[m_read_address] >> 16;
}
return 0xffff; default:
break;
}
return 0;
} }
/******************************************************************************/
WRITE16_MEMBER(zsg2_device::write) WRITE16_MEMBER(zsg2_device::write)
{ {
// we only support full 16-bit accesses // we only support full 16-bit accesses
@ -367,7 +410,6 @@ WRITE16_MEMBER(zsg2_device::write)
} }
} }
READ16_MEMBER(zsg2_device::read) READ16_MEMBER(zsg2_device::read)
{ {
// we only support full 16-bit accesses // we only support full 16-bit accesses

View File

@ -39,6 +39,7 @@ public:
protected: protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
virtual void device_reset();
// sound stream update overrides // sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
@ -47,13 +48,7 @@ private:
// 16 registers per channel, 48 channels // 16 registers per channel, 48 channels
struct zchan struct zchan
{ {
zchan()
{
memset(v, 0, sizeof(UINT16)*16);
}
UINT16 v[16]; UINT16 v[16];
bool is_playing; bool is_playing;
INT16 *samples; INT16 *samples;
UINT32 cur_pos; UINT32 cur_pos;
@ -63,6 +58,7 @@ private:
UINT32 end_pos; UINT32 end_pos;
UINT32 loop_pos; UINT32 loop_pos;
UINT32 page; UINT32 page;
UINT16 vol;
}; };
zchan m_chan[48]; zchan m_chan[48];
@ -79,8 +75,8 @@ private:
devcb2_read32 m_ext_read_handler; devcb2_read32 m_ext_read_handler;
UINT32 read_memory(UINT32 offset); UINT32 read_memory(UINT32 offset);
void chan_w(int chan, int reg, UINT16 data); void chan_w(int ch, int reg, UINT16 data);
UINT16 chan_r(int chan, int reg); UINT16 chan_r(int ch, int reg);
void control_w(int reg, UINT16 data); void control_w(int reg, UINT16 data);
UINT16 control_r(int reg); UINT16 control_r(int reg);
INT16 *prepare_samples(UINT32 offset); INT16 *prepare_samples(UINT32 offset);

View File

@ -43,6 +43,7 @@ const device_type TAITO_ZOOM = &device_creator<taito_zoom_device>;
taito_zoom_device::taito_zoom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) taito_zoom_device::taito_zoom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, TAITO_ZOOM, "Taito Zoom Sound System", tag, owner, clock, "taito_zoom", __FILE__), : device_t(mconfig, TAITO_ZOOM, "Taito Zoom Sound System", tag, owner, clock, "taito_zoom", __FILE__),
m_soundcpu(*this, ":mn10200"), m_soundcpu(*this, ":mn10200"),
m_control(0),
m_tms_ctrl(0) m_tms_ctrl(0)
{ {
} }
@ -56,6 +57,7 @@ void taito_zoom_device::device_start()
m_snd_shared_ram = auto_alloc_array_clear(machine(), UINT8, 0x100); m_snd_shared_ram = auto_alloc_array_clear(machine(), UINT8, 0x100);
// register for savestates // register for savestates
save_item(NAME(m_control));
save_item(NAME(m_tms_ctrl)); save_item(NAME(m_tms_ctrl));
save_pointer(NAME(m_snd_shared_ram), 0x100); save_pointer(NAME(m_snd_shared_ram), 0x100);
} }
@ -105,7 +107,7 @@ WRITE8_MEMBER(taito_zoom_device::tms_ctrl_w)
ADDRESS_MAP_START( taitozoom_mn_map, AS_PROGRAM, 16, driver_device ) ADDRESS_MAP_START( taitozoom_mn_map, AS_PROGRAM, 16, driver_device )
AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("mn10200", 0) AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("mn10200", 0)
AM_RANGE(0x400000, 0x40ffff) AM_RAM AM_RANGE(0x400000, 0x41ffff) AM_RAM
AM_RANGE(0x800000, 0x8007ff) AM_DEVREADWRITE("zsg2", zsg2_device, read, write) AM_RANGE(0x800000, 0x8007ff) AM_DEVREADWRITE("zsg2", zsg2_device, read, write)
AM_RANGE(0xc00000, 0xc00001) AM_RAM // TMS57002 comms AM_RANGE(0xc00000, 0xc00001) AM_RAM // TMS57002 comms
AM_RANGE(0xe00000, 0xe000ff) AM_DEVREADWRITE8("taito_zoom", taito_zoom_device, shared_ram_r, shared_ram_w, 0xffff) // M66220FP for comms with maincpu AM_RANGE(0xe00000, 0xe000ff) AM_DEVREADWRITE8("taito_zoom", taito_zoom_device, shared_ram_r, shared_ram_w, 0xffff) // M66220FP for comms with maincpu
@ -136,13 +138,16 @@ READ16_MEMBER(taito_zoom_device::sound_irq_r)
WRITE16_MEMBER(taito_zoom_device::global_volume_w) WRITE16_MEMBER(taito_zoom_device::global_volume_w)
{ {
// TODO
// m_control d0 selects left/right speaker volume (zsg2+dsp)
} }
WRITE16_MEMBER(taito_zoom_device::reset_control_w) WRITE16_MEMBER(taito_zoom_device::reset_control_w)
{ {
// d0: ? (toggles in soundtest)
// d2: reset sound cpu? // d2: reset sound cpu?
m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 4) ? CLEAR_LINE : ASSERT_LINE); m_soundcpu->set_input_line(INPUT_LINE_RESET, (data & 4) ? CLEAR_LINE : ASSERT_LINE);
m_control = data;
} }

View File

@ -32,6 +32,7 @@ private:
required_device<mn10200_device> m_soundcpu; required_device<mn10200_device> m_soundcpu;
// internal state // internal state
UINT16 m_control;
UINT8 m_tms_ctrl; UINT8 m_tms_ctrl;
UINT8* m_snd_shared_ram; UINT8* m_snd_shared_ram;
}; };

View File

@ -403,40 +403,25 @@ private:
READ8_MEMBER(taitogn_state::control_r) READ8_MEMBER(taitogn_state::control_r)
{ {
// fprintf(stderr, "gn_r %08x @ %08x (%s)\n", 0x1fb00000+4*offset, mem_mask, machine().describe_context());
return m_control; return m_control;
} }
WRITE8_MEMBER(taitogn_state::control_w) WRITE8_MEMBER(taitogn_state::control_w)
{ {
// 20 = watchdog // 20 = watchdog
// 04 = select bank
COMBINE_DATA(&m_control);
m_mb3773->write_line_ck((data & 0x20) >> 5); m_mb3773->write_line_ck((data & 0x20) >> 5);
#if 0 // 04 = select bank
if((p ^ control) & ~0x20)
fprintf(stderr, "control = %c%c.%c %c%c%c%c (%s)\n",
control & 0x80 ? '1' : '0',
control & 0x40 ? '1' : '0',
control & 0x10 ? '1' : '0',
control & 0x08 ? '1' : '0',
control & 0x04 ? 'f' : '-',
control & 0x02 ? '1' : '0',
control & 0x01 ? '1' : '0',
machine().describe_context());
#endif
// According to the rom code, bits 1-0 may be part of the bank // According to the rom code, bits 1-0 may be part of the bank
// selection too, but they're always 0. // selection too, but they're always 0.
m_flashbank->set_bank(m_control & 4); m_flashbank->set_bank(data & 4);
m_control = data;
} }
WRITE16_MEMBER(taitogn_state::control2_w) WRITE16_MEMBER(taitogn_state::control2_w)
{ {
COMBINE_DATA(&m_control2); m_control2 = data;
} }
READ8_MEMBER(taitogn_state::control3_r) READ8_MEMBER(taitogn_state::control3_r)
@ -446,7 +431,7 @@ READ8_MEMBER(taitogn_state::control3_r)
WRITE8_MEMBER(taitogn_state::control3_w) WRITE8_MEMBER(taitogn_state::control3_w)
{ {
COMBINE_DATA(&m_control3); m_control3 = data;
} }
READ16_MEMBER(taitogn_state::gn_1fb70000_r) READ16_MEMBER(taitogn_state::gn_1fb70000_r)
@ -494,11 +479,11 @@ READ8_MEMBER(taitogn_state::znsecsel_r)
WRITE8_MEMBER(taitogn_state::znsecsel_w) WRITE8_MEMBER(taitogn_state::znsecsel_w)
{ {
COMBINE_DATA( &m_n_znsecsel ); m_znsec0->select( ( data >> 2 ) & 1 );
m_znsec1->select( ( data >> 3 ) & 1 );
m_zndip->select( ( data & 0x8c ) != 0x8c );
m_znsec0->select( ( m_n_znsecsel >> 2 ) & 1 ); m_n_znsecsel = data;
m_znsec1->select( ( m_n_znsecsel >> 3 ) & 1 );
m_zndip->select( ( m_n_znsecsel & 0x8c ) != 0x8c );
} }
READ8_MEMBER(taitogn_state::boardconfig_r) READ8_MEMBER(taitogn_state::boardconfig_r)

View File

@ -330,13 +330,13 @@ READ8_MEMBER(zn_state::znsecsel_r)
WRITE8_MEMBER(zn_state::znsecsel_w) WRITE8_MEMBER(zn_state::znsecsel_w)
{ {
COMBINE_DATA( &m_n_znsecsel );
m_znsec0->select( ( m_n_znsecsel >> 2 ) & 1 );
m_znsec1->select( ( m_n_znsecsel >> 3 ) & 1 );
m_zndip->select( ( m_n_znsecsel & 0x8c ) != 0x8c );
verboselog(2, "znsecsel_w( %08x, %08x, %08x )\n", offset, data, mem_mask ); verboselog(2, "znsecsel_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
m_znsec0->select( ( data >> 2 ) & 1 );
m_znsec1->select( ( data >> 3 ) & 1 );
m_zndip->select( ( data & 0x8c ) != 0x8c );
m_n_znsecsel = data;
} }
READ8_MEMBER(zn_state::boardconfig_r) READ8_MEMBER(zn_state::boardconfig_r)