mirror of
https://github.com/holub/mame
synced 2025-05-15 02:18:16 +03:00
vrc6.cpp : Updates (#4819)
* vrc6.cpp : Updates Implement master frequency register, Fix frequency / square duty behaviors, Use shorter type values, Reduce unnecessary lines device/bus/nes/konami.cpp : Fix vrc6 sound volume, Remove outdated comment * vrc6.cpp : Fix regression
This commit is contained in:
parent
8b08ad2ce6
commit
6dbd636a80
@ -560,8 +560,6 @@ void nes_konami_vrc4_device::write_h(offs_t offset, uint8_t data)
|
|||||||
In MESS: Supported. It also uses konami_irq (there are IRQ
|
In MESS: Supported. It also uses konami_irq (there are IRQ
|
||||||
issues though: see Akumajou Densetsu intro).
|
issues though: see Akumajou Densetsu intro).
|
||||||
|
|
||||||
TODO: Add sound capabilities support!
|
|
||||||
|
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
void nes_konami_vrc6_device::write_h(offs_t offset, uint8_t data)
|
void nes_konami_vrc6_device::write_h(offs_t offset, uint8_t data)
|
||||||
@ -644,7 +642,7 @@ void nes_konami_vrc6_device::device_add_mconfig(machine_config &config)
|
|||||||
|
|
||||||
// TODO: this is not how VRC6 clock signaling works!
|
// TODO: this is not how VRC6 clock signaling works!
|
||||||
// The board uses the CLK pin in reality, not hardcoded NTSC values!
|
// The board uses the CLK pin in reality, not hardcoded NTSC values!
|
||||||
VRC6(config, m_vrc6snd, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.5);
|
VRC6(config, m_vrc6snd, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "vrc6.h"
|
#include "vrc6.h"
|
||||||
|
|
||||||
#define DISABLE_VRC6_SOUND // not ready yet
|
|
||||||
|
|
||||||
// device type definition
|
// device type definition
|
||||||
DEFINE_DEVICE_TYPE(VRC6, vrc6snd_device, "vrc6snd", "Konami VRC6 (Sound)")
|
DEFINE_DEVICE_TYPE(VRC6, vrc6snd_device, "vrc6snd", "Konami VRC6 (Sound)")
|
||||||
|
|
||||||
@ -29,10 +27,10 @@ DEFINE_DEVICE_TYPE(VRC6, vrc6snd_device, "vrc6snd", "Konami VRC6 (Sound)")
|
|||||||
// vrc6snd_device - constructor
|
// vrc6snd_device - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
vrc6snd_device::vrc6snd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
vrc6snd_device::vrc6snd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||||
: device_t(mconfig, VRC6, tag, owner, clock)
|
: device_t(mconfig, VRC6, tag, owner, clock)
|
||||||
, device_sound_interface(mconfig, *this)
|
, device_sound_interface(mconfig, *this)
|
||||||
, m_freqctrl(0), m_pulsectrl{ 0, 0 }, m_sawrate(0)
|
, m_freqctrl(0), m_pulsectrl{ 0, 0 }, m_sawrate(0), m_master_freq(0)
|
||||||
, m_pulsefrql{ 0, 0 }, m_pulsefrqh{ 0, 0 }, m_pulseduty{ 0, 0 }
|
, m_pulsefrql{ 0, 0 }, m_pulsefrqh{ 0, 0 }, m_pulseduty{ 0, 0 }
|
||||||
, m_sawfrql(0), m_sawfrqh(0), m_sawclock(0), m_sawaccum(0)
|
, m_sawfrql(0), m_sawfrqh(0), m_sawclock(0), m_sawaccum(0)
|
||||||
, m_ticks{ 0, 0, 0 }
|
, m_ticks{ 0, 0, 0 }
|
||||||
@ -55,10 +53,12 @@ void vrc6snd_device::device_start()
|
|||||||
m_ticks[0] = m_ticks[1] = m_ticks[2] = 0;
|
m_ticks[0] = m_ticks[1] = m_ticks[2] = 0;
|
||||||
m_output[0] = m_output[1] = m_output[2] = 0;
|
m_output[0] = m_output[1] = m_output[2] = 0;
|
||||||
m_pulseduty[0] = m_pulseduty[1] = 15;
|
m_pulseduty[0] = m_pulseduty[1] = 15;
|
||||||
|
m_master_freq = 0;
|
||||||
|
|
||||||
save_item(NAME(m_freqctrl));
|
save_item(NAME(m_freqctrl));
|
||||||
save_item(NAME(m_pulsectrl));
|
save_item(NAME(m_pulsectrl));
|
||||||
save_item(NAME(m_sawrate));
|
save_item(NAME(m_sawrate));
|
||||||
|
save_item(NAME(m_master_freq));
|
||||||
save_item(NAME(m_sawaccum));
|
save_item(NAME(m_sawaccum));
|
||||||
save_item(NAME(m_pulsefrql));
|
save_item(NAME(m_pulsefrql));
|
||||||
save_item(NAME(m_pulsefrqh));
|
save_item(NAME(m_pulsefrqh));
|
||||||
@ -85,6 +85,7 @@ void vrc6snd_device::device_reset()
|
|||||||
m_output[0] = m_output[1] = m_output[2] = 0;
|
m_output[0] = m_output[1] = m_output[2] = 0;
|
||||||
m_pulseduty[0] = m_pulseduty[1] = 15;
|
m_pulseduty[0] = m_pulseduty[1] = 15;
|
||||||
m_pulsefrqh[0] = m_pulsefrqh[1] = m_sawfrqh = 0;
|
m_pulsefrqh[0] = m_pulsefrqh[1] = m_sawfrqh = 0;
|
||||||
|
m_master_freq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -94,27 +95,22 @@ void vrc6snd_device::device_reset()
|
|||||||
|
|
||||||
void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||||
{
|
{
|
||||||
stream_sample_t *out = outputs[0];
|
std::fill_n(&outputs[0][0], samples, 0);
|
||||||
int16_t tmp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// check global halt bit
|
// check global halt bit
|
||||||
if (m_freqctrl & 1)
|
if (m_freqctrl & 1)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
{
|
{
|
||||||
// update pulse1
|
// update pulse1
|
||||||
if (m_pulsefrqh[0] & 0x80)
|
if (m_pulsefrqh[0] & 0x80)
|
||||||
{
|
{
|
||||||
m_ticks[0]--;
|
|
||||||
if (m_ticks[0] == 0)
|
if (m_ticks[0] == 0)
|
||||||
{
|
{
|
||||||
m_ticks[0] = m_pulsefrql[0] | (m_pulsefrqh[0] & 0xf)<<4;
|
m_ticks[0] = (m_pulsefrql[0] | ((m_pulsefrqh[0] & 0xf) << 8)) >> m_master_freq;
|
||||||
|
|
||||||
m_pulseduty[0]--;
|
m_pulseduty[0] = (m_pulseduty[0] - 1) & 0xf;
|
||||||
if (m_pulsectrl[0] & 0x80)
|
if (m_pulsectrl[0] & 0x80)
|
||||||
{
|
{
|
||||||
m_output[0] = m_pulsectrl[0] & 0xf;
|
m_output[0] = m_pulsectrl[0] & 0xf;
|
||||||
@ -130,12 +126,9 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
m_output[0] = 0;
|
m_output[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pulseduty[0] == 0)
|
|
||||||
{
|
|
||||||
m_pulseduty[0] = 15;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
m_ticks[0]--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -145,12 +138,11 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
// update pulse2
|
// update pulse2
|
||||||
if (m_pulsefrqh[1] & 0x80)
|
if (m_pulsefrqh[1] & 0x80)
|
||||||
{
|
{
|
||||||
m_ticks[1]--;
|
|
||||||
if (m_ticks[1] == 0)
|
if (m_ticks[1] == 0)
|
||||||
{
|
{
|
||||||
m_ticks[1] = m_pulsefrql[1] | (m_pulsefrqh[1] & 0xf)<<4;
|
m_ticks[1] = (m_pulsefrql[1] | ((m_pulsefrqh[1] & 0xf) << 8)) >> m_master_freq;
|
||||||
|
|
||||||
m_pulseduty[1]--;
|
m_pulseduty[1] = (m_pulseduty[1] - 1) & 0xf;
|
||||||
if (m_pulsectrl[1] & 0x80)
|
if (m_pulsectrl[1] & 0x80)
|
||||||
{
|
{
|
||||||
m_output[1] = m_pulsectrl[1] & 0xf;
|
m_output[1] = m_pulsectrl[1] & 0xf;
|
||||||
@ -166,12 +158,9 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
m_output[1] = 0;
|
m_output[1] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pulseduty[1] == 0)
|
|
||||||
{
|
|
||||||
m_pulseduty[1] = 15;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
m_ticks[1]--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -181,10 +170,9 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
// update saw
|
// update saw
|
||||||
if (m_sawfrqh & 0x80)
|
if (m_sawfrqh & 0x80)
|
||||||
{
|
{
|
||||||
m_ticks[2]--;
|
|
||||||
if (m_ticks[2] == 0)
|
if (m_ticks[2] == 0)
|
||||||
{
|
{
|
||||||
m_ticks[2] = m_sawfrql | (m_sawfrqh & 0xf)<<4;
|
m_ticks[2] = (m_sawfrql | ((m_sawfrqh & 0xf) << 8)) >> m_master_freq;
|
||||||
|
|
||||||
// only update on even steps
|
// only update on even steps
|
||||||
if ((m_sawclock > 0) && (!(m_sawclock & 1)))
|
if ((m_sawclock > 0) && (!(m_sawclock & 1)))
|
||||||
@ -200,6 +188,8 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
m_output[2] = 0;
|
m_output[2] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
m_ticks[2]--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -207,10 +197,10 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sum 2 4-bit pulses, 1 5-bit saw = unsigned 6 bit output
|
// sum 2 4-bit pulses, 1 5-bit saw = unsigned 6 bit output
|
||||||
tmp = (int16_t)(uint8_t)(m_output[0] + m_output[1] + m_output[2]);
|
s16 tmp = (s16)(u8)(m_output[0] + m_output[1] + m_output[2]);
|
||||||
tmp <<= 8;
|
tmp <<= 8;
|
||||||
|
|
||||||
out[i] = tmp;
|
outputs[0][i] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +208,7 @@ void vrc6snd_device::sound_stream_update(sound_stream &stream, stream_sample_t *
|
|||||||
// write - write to the chip's registers
|
// write - write to the chip's registers
|
||||||
//---------------------------------------
|
//---------------------------------------
|
||||||
|
|
||||||
void vrc6snd_device::write(offs_t offset, uint8_t data)
|
void vrc6snd_device::write(offs_t offset, u8 data)
|
||||||
{
|
{
|
||||||
switch (offset >> 8)
|
switch (offset >> 8)
|
||||||
{
|
{
|
||||||
@ -232,28 +222,43 @@ void vrc6snd_device::write(offs_t offset, uint8_t data)
|
|||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
m_pulsefrql[0] = data;
|
m_pulsefrql[0] = data;
|
||||||
if (!(m_pulsefrqh[1] & 0x80))
|
if (!(m_pulsefrqh[0] & 0x80))
|
||||||
{
|
{
|
||||||
m_ticks[0] &= ~0xff;
|
m_ticks[0] = (m_pulsefrql[0] | ((m_pulsefrqh[0] & 0xf) << 8)) >> m_master_freq;
|
||||||
m_ticks[0] |= m_pulsefrql[0];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
#ifndef DISABLE_VRC6_SOUND
|
|
||||||
m_pulsefrqh[0] = data;
|
m_pulsefrqh[0] = data;
|
||||||
// if disabling channel, reset phase
|
// if disabling channel, reset phase
|
||||||
if (!(data & 0x80))
|
if (!(data & 0x80))
|
||||||
{
|
{
|
||||||
m_pulseduty[0] = 15;
|
m_pulseduty[0] = 15;
|
||||||
m_ticks[0] &= 0xff;
|
m_ticks[0] = (m_pulsefrql[0] | ((m_pulsefrqh[0] & 0xf) << 8)) >> m_master_freq;
|
||||||
m_ticks[0] |= (m_pulsefrqh[0] & 0xf)<<4;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
m_freqctrl = data;
|
m_freqctrl = data;
|
||||||
|
if (m_freqctrl & 4)
|
||||||
|
m_master_freq = 0x8;
|
||||||
|
else if (m_freqctrl & 2)
|
||||||
|
m_master_freq = 0x4;
|
||||||
|
else
|
||||||
|
m_master_freq = 0;
|
||||||
|
|
||||||
|
if (!(m_pulsefrqh[0] & 0x80))
|
||||||
|
{
|
||||||
|
m_ticks[0] = (m_pulsefrql[0] | ((m_pulsefrqh[0] & 0xf) << 8)) >> m_master_freq;
|
||||||
|
}
|
||||||
|
if (!(m_pulsefrqh[1] & 0x80))
|
||||||
|
{
|
||||||
|
m_ticks[1] = (m_pulsefrql[1] | ((m_pulsefrqh[1] & 0xf) << 8)) >> m_master_freq;
|
||||||
|
}
|
||||||
|
if (!(m_sawfrqh & 0x80))
|
||||||
|
{
|
||||||
|
m_ticks[2] = (m_sawfrql | ((m_sawfrqh & 0xf) << 8)) >> m_master_freq;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -270,22 +275,18 @@ void vrc6snd_device::write(offs_t offset, uint8_t data)
|
|||||||
m_pulsefrql[1] = data;
|
m_pulsefrql[1] = data;
|
||||||
if (!(m_pulsefrqh[1] & 0x80))
|
if (!(m_pulsefrqh[1] & 0x80))
|
||||||
{
|
{
|
||||||
m_ticks[1] &= ~0xff;
|
m_ticks[1] = (m_pulsefrql[1] | ((m_pulsefrqh[1] & 0xf) << 8)) >> m_master_freq;
|
||||||
m_ticks[1] |= m_pulsefrql[1];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
#ifndef DISABLE_VRC6_SOUND
|
|
||||||
m_pulsefrqh[1] = data;
|
m_pulsefrqh[1] = data;
|
||||||
// if disabling channel, reset phase
|
// if disabling channel, reset phase
|
||||||
if (!(data & 0x80))
|
if (!(data & 0x80))
|
||||||
{
|
{
|
||||||
m_pulseduty[1] = 15;
|
m_pulseduty[1] = 15;
|
||||||
m_ticks[1] &= 0xff;
|
m_ticks[1] = (m_pulsefrql[1] | ((m_pulsefrqh[1] & 0xf) << 8)) >> m_master_freq;
|
||||||
m_ticks[1] |= (m_pulsefrqh[1] & 0xf)<<4;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -302,22 +303,18 @@ void vrc6snd_device::write(offs_t offset, uint8_t data)
|
|||||||
m_sawfrql = data;
|
m_sawfrql = data;
|
||||||
if (!(m_sawfrqh & 0x80))
|
if (!(m_sawfrqh & 0x80))
|
||||||
{
|
{
|
||||||
m_ticks[2] &= ~0xff;
|
m_ticks[2] = (m_sawfrql | ((m_sawfrqh & 0xf) << 8)) >> m_master_freq;
|
||||||
m_ticks[2] |= m_sawfrql;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
#ifndef DISABLE_VRC6_SOUND
|
|
||||||
m_sawfrqh = data;
|
m_sawfrqh = data;
|
||||||
// if disabling channel, reset phase
|
// if disabling channel, reset phase
|
||||||
if (!(data & 0x80))
|
if (!(data & 0x80))
|
||||||
{
|
{
|
||||||
m_sawaccum = 0;
|
m_sawaccum = 0;
|
||||||
m_ticks[2] &= 0xff;
|
m_ticks[2] = (m_sawfrql | ((m_sawfrqh & 0xf) << 8)) >> m_master_freq;
|
||||||
m_ticks[2] |= (m_sawfrqh & 0xf)<<4;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -22,9 +22,9 @@ class vrc6snd_device : public device_t, public device_sound_interface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
vrc6snd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
vrc6snd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||||
|
|
||||||
void write(offs_t offset, uint8_t data);
|
void write(offs_t offset, u8 data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
@ -34,11 +34,11 @@ protected:
|
|||||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t m_freqctrl, m_pulsectrl[2], m_sawrate;
|
u8 m_freqctrl, m_pulsectrl[2], m_sawrate, m_master_freq;
|
||||||
uint8_t m_pulsefrql[2], m_pulsefrqh[2], m_pulseduty[2];
|
u8 m_pulsefrql[2], m_pulsefrqh[2], m_pulseduty[2];
|
||||||
uint8_t m_sawfrql, m_sawfrqh, m_sawclock, m_sawaccum;
|
u8 m_sawfrql, m_sawfrqh, m_sawclock, m_sawaccum;
|
||||||
uint16_t m_ticks[3];
|
u16 m_ticks[3];
|
||||||
uint8_t m_output[3];
|
u8 m_output[3];
|
||||||
|
|
||||||
sound_stream *m_stream;
|
sound_stream *m_stream;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user