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).
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"
@ -51,11 +60,6 @@
// device type definition
const device_type ZSG2 = &device_creator<zsg2_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// zsg2_device - constructor
//-------------------------------------------------
@ -86,9 +90,50 @@ void zsg2_device::device_start()
m_mem_blocks = m_mem_size / 4;
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)
{
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)
{
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)
{
// loop sample
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;
//..
//m_chan[ch].cur_pos = m_chan[ch].loop_pos;
continue;
}
}
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];
//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_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)
{
m_chan[ch].v[reg] = data;
switch (reg)
{
case 0x0:
// lo byte: ?
// lo byte: always 0?
// hi byte: start address low
m_chan[ch].start_pos = (m_chan[ch].start_pos & 0xff00) | (data >> 8 & 0xff);
break;
@ -199,7 +249,7 @@ void zsg2_device::chan_w(int ch, int reg, UINT16 data)
break;
case 0x4:
// frequency?
// frequency
m_chan[ch].step = data;
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);
break;
default:
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:
break;
}
m_chan[ch].v[reg] = data;
}
UINT16 zsg2_device::chan_r(int ch, int reg)
{
switch (reg)
{
case 0xb:
// ?
return 0;
default:
break;
}
return m_chan[ch].v[reg];
}
/******************************************************************************/
void zsg2_device::control_w(int reg, UINT16 data)
{
switch(reg)
switch (reg)
{
case 0x00: case 0x01: case 0x02:
{
// key on?
// key on
int base = (reg & 3) << 4;
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].step_ptr = 0;
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;
@ -324,25 +362,30 @@ f1a0 0000 0000 0000 f1a0 1b78 089e 1523
UINT16 zsg2_device::control_r(int reg)
{
switch(reg)
switch (reg)
{
case 0x14:
return 0xff00;
// memory bus busy?
// right before reading memory, it polls until low 8 bits are 0
return 0;
case 0x1e:
// rom readback word low
if (m_read_address >= m_mem_blocks) return 0;
return m_mem_base[m_read_address] & 0xffff;
return read_memory(m_read_address) & 0xffff;
case 0x1f:
// rom readback word high
if (m_read_address >= m_mem_blocks) return 0;
return m_mem_base[m_read_address] >> 16;
return read_memory(m_read_address) >> 16;
default:
break;
}
return 0xffff;
return 0;
}
/******************************************************************************/
WRITE16_MEMBER(zsg2_device::write)
{
// we only support full 16-bit accesses
@ -367,7 +410,6 @@ WRITE16_MEMBER(zsg2_device::write)
}
}
READ16_MEMBER(zsg2_device::read)
{
// we only support full 16-bit accesses

View File

@ -39,6 +39,7 @@ public:
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
// sound stream update overrides
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
struct zchan
{
zchan()
{
memset(v, 0, sizeof(UINT16)*16);
}
UINT16 v[16];
bool is_playing;
INT16 *samples;
UINT32 cur_pos;
@ -63,6 +58,7 @@ private:
UINT32 end_pos;
UINT32 loop_pos;
UINT32 page;
UINT16 vol;
};
zchan m_chan[48];
@ -79,8 +75,8 @@ private:
devcb2_read32 m_ext_read_handler;
UINT32 read_memory(UINT32 offset);
void chan_w(int chan, int reg, UINT16 data);
UINT16 chan_r(int chan, int reg);
void chan_w(int ch, int reg, UINT16 data);
UINT16 chan_r(int ch, int reg);
void control_w(int reg, UINT16 data);
UINT16 control_r(int reg);
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)
: device_t(mconfig, TAITO_ZOOM, "Taito Zoom Sound System", tag, owner, clock, "taito_zoom", __FILE__),
m_soundcpu(*this, ":mn10200"),
m_control(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);
// register for savestates
save_item(NAME(m_control));
save_item(NAME(m_tms_ctrl));
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 )
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(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
@ -136,13 +138,16 @@ READ16_MEMBER(taito_zoom_device::sound_irq_r)
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)
{
// d0: ? (toggles in soundtest)
// d2: reset sound cpu?
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;
// internal state
UINT16 m_control;
UINT8 m_tms_ctrl;
UINT8* m_snd_shared_ram;
};

View File

@ -403,40 +403,25 @@ private:
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;
}
WRITE8_MEMBER(taitogn_state::control_w)
{
// 20 = watchdog
// 04 = select bank
COMBINE_DATA(&m_control);
m_mb3773->write_line_ck((data & 0x20) >> 5);
#if 0
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
// 04 = select bank
// According to the rom code, bits 1-0 may be part of the bank
// 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)
{
COMBINE_DATA(&m_control2);
m_control2 = data;
}
READ8_MEMBER(taitogn_state::control3_r)
@ -446,7 +431,7 @@ READ8_MEMBER(taitogn_state::control3_r)
WRITE8_MEMBER(taitogn_state::control3_w)
{
COMBINE_DATA(&m_control3);
m_control3 = data;
}
READ16_MEMBER(taitogn_state::gn_1fb70000_r)
@ -494,11 +479,11 @@ READ8_MEMBER(taitogn_state::znsecsel_r)
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_znsec1->select( ( m_n_znsecsel >> 3 ) & 1 );
m_zndip->select( ( m_n_znsecsel & 0x8c ) != 0x8c );
m_n_znsecsel = data;
}
READ8_MEMBER(taitogn_state::boardconfig_r)

View File

@ -330,13 +330,13 @@ READ8_MEMBER(zn_state::znsecsel_r)
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 );
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)