Gamate sound is 100% AY8910 compatible according to Kevtris and Peter Wilhelmsen, us the AY8910 core.

This commit is contained in:
David Haywood 2017-10-18 15:38:46 +01:00
parent e3cdd178ef
commit 4fb8e776b3
4 changed files with 24 additions and 360 deletions

View File

@ -3467,8 +3467,6 @@ files {
MAME_DIR .. "src/mame/drivers/fk1.cpp",
MAME_DIR .. "src/mame/drivers/ft68m.cpp",
MAME_DIR .. "src/mame/drivers/gamate.cpp",
MAME_DIR .. "src/mame/audio/gamate.cpp",
MAME_DIR .. "src/mame/audio/gamate.h",
MAME_DIR .. "src/mame/drivers/gameking.cpp",
MAME_DIR .. "src/mame/drivers/gimix.cpp",
MAME_DIR .. "src/mame/drivers/goupil.cpp",

View File

@ -1,253 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Peter Trauner
/***************************************************************************
gamate sound hardware
PeT mess@utanet.at 2015
***************************************************************************/
#include "emu.h"
#include "audio/gamate.h"
enum { ClockDelay=32 };
// device type definition
DEFINE_DEVICE_TYPE(GAMATE_SND, gamate_sound_device, "gamate_sound", "Gamate Audio Custom")
const int gamate_sound_device::DAConverter[]={ 0, 3, 7, 13, 23, 41, 75, 137, 249, 453, 825, 1499, 2726, 4956, 9011, 16383 }; // (*.55) on the real below index 8 bareless measureable
const uint8_t Mask[]={ 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x1f, 0x3f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xf };
const int EnvelopeVolumes[]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// gamate_sound_device - constructor
//-------------------------------------------------
gamate_sound_device::gamate_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, GAMATE_SND, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, m_mixer_channel(nullptr)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void gamate_sound_device::device_start()
{
// bind callbacks
// m_irq_cb.bind_relative_to(*owner());
memset(m_channels, 0, sizeof(m_channels));
memset(reg, 0, sizeof(reg));
m_mixer_channel = stream_alloc(0, 2, machine().sample_rate());
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void gamate_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
stream_sample_t *left=outputs[0], *right=outputs[1];
int i, j;
Tone *channel;
for (i = 0; i < samples; i++, left++, right++)
{
noise.pos += noise.step;
while (noise.pos >= 1.0)
{
// guess (white noise register taken from supervision)
noise.level = noise.state & 0x40 ? 1 : 0;
bool b1 = (noise.state & 0x40) != 0, b2 = (noise.state & 0x20) != 0;
noise.state=(noise.state<<1)+(b1!=b2?1:0);
noise.pos -= 1;
}
envelope.pos += envelope.step;
while (envelope.pos >= 1.0) {
envelope.pos -= 1;
envelope.index++;
switch (envelope.control)
{
case 0: case 1: case 2: case 3:
case 4: case 5: case 6: case 7:
case 8: case 9: case 0xb:
case 0xd: case 0xf:
if (envelope.index>=ARRAY_LENGTH(EnvelopeVolumes)/2)
{
envelope.index=0;
envelope.first=false;
}
break;
default:
if (envelope.index>=ARRAY_LENGTH(EnvelopeVolumes))
{
envelope.index=0;
envelope.first=false;
}
break;
}
}
*left = 0;
*right = 0;
for (channel=m_channels, j=0; j<ARRAY_LENGTH(m_channels); j++, channel++)
{
if (channel->size != 0)
{
channel->level= channel->pos <= channel->size / 2;
bool l= channel->full_cycle? true: channel->level;
if (!channel->tone)
l= l && noise.level;
int volume=0;
if (l)
{
if (channel->envelope_on)
{
switch (envelope.control)
{
case 0: case 1: case 2: case 3:
case 0x9: // one time falling, low
if (envelope.first && channel->level)
volume=0xf-EnvelopeVolumes[envelope.index];
break;
case 4: case 5: case 6: case 7:
case 0xf: // one time rising, low
if (envelope.first && channel->level)
volume=EnvelopeVolumes[envelope.index];
break;
case 8: // falling
if (channel->level)
volume=0xf-EnvelopeVolumes[envelope.index];
break;
case 0xa: // rising, falling
if (channel->level)
volume=0xf-EnvelopeVolumes[envelope.index]; // cube up
break;
case 0xb: // one time falling, high
if (channel->level)
volume=envelope.first ? 0xf-EnvelopeVolumes[envelope.index] : 0xf;
break;
case 0xc: // rising, low
if (channel->level)
volume=envelope.index<ARRAY_LENGTH(EnvelopeVolumes)/2 ? EnvelopeVolumes[envelope.index] : 0;
break;
case 0xd: // one time rising, high
if (channel->level)
volume=envelope.first ? EnvelopeVolumes[envelope.index] : 0xf;
break;
case 0xe: // falling, rising
if (channel->level)
volume=0xf-EnvelopeVolumes[envelope.index];
break;
}
}
else
{
volume=channel->volume;
}
}
if (j == Right)
*right += Value2Volume(volume);
else
if (j==Left)
*left += Value2Volume(volume);
else
{
*right += Value2Volume(volume);
*left += Value2Volume(volume);
}
channel->pos++;
if (channel->pos >= channel->size)
channel->pos = 0;
}
}
}
}
WRITE8_MEMBER( gamate_sound_device::device_w )
{
uint16_t size;
m_mixer_channel->update();
reg[offset] = data;
int chan=-1;
switch (offset&0xf)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
chan=offset/2;
size = reg[chan*2] | ((reg[chan*2+1] & 0xf) << 8);
if (size)
{
m_channels[chan].size= (int) (machine().sample_rate() * size*ClockDelay / m_clock);
}
else
{
m_channels[chan].size = 0;
}
m_channels[chan].pos = 0;
break;
case 6:
size=data&0x1f;
if (size==0)
size=1;
noise.step= m_clock / (1.0*ClockDelay*machine().sample_rate()*size);
break;
case 7:
m_channels[Right].full_cycle=data&1;
m_channels[Right].tone=data&8;
m_channels[Left].full_cycle=data&2;
m_channels[Left].tone=data&0x10;
m_channels[Both].full_cycle=data&4;
m_channels[Both].tone=data&0x20;
noise.state=1;
noise.pos=0.0;
noise.level=false;
break;
case 8:
case 9:
case 0xa:
chan=offset-8;
m_channels[chan].envelope_on = data & 0x10; // buggy aussetzer cube up
m_channels[chan].volume = data & 0xf;
break;
case 0xb: case 0xc:
size = reg[0xb] | ((reg[0xc]) << 8);
if (size==0)
size=1;
envelope.step= m_clock / (1.0*ClockDelay*machine().sample_rate()*size);
break;
case 0xd:
envelope.control=data&0xf;
envelope.pos=0;
envelope.index=0;
envelope.first=true;
break;
}
envelope.pos=0; // guess
envelope.index=0;
envelope.first=true;
}
READ8_MEMBER( gamate_sound_device::device_r )
{
uint8_t data=0;
if ((offset&0xf)<ARRAY_LENGTH(Mask))
data=reg[offset&0xf]&Mask[offset&0xf]; // unused bits set to last write value? in this area
return data;
}

View File

@ -1,96 +0,0 @@
// license:GPL-2.0+
// copyright-holders:Peter Trauner
/*****************************************************************************
*
* includes/gamate.h
*
****************************************************************************/
#ifndef MAME_AUDIO_GAMATE_H
#define MAME_AUDIO_GAMATE_H
// ======================> gamate_sound_device
class gamate_sound_device : public device_t, public device_sound_interface
{
public:
gamate_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE8_MEMBER( device_w );
DECLARE_READ8_MEMBER( device_r );
protected:
// device-level overrides
virtual void device_start() override;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
private:
static const int DAConverter[];
static int Value2Volume(int volume) { return DAConverter[volume]*1; }
sound_stream *m_mixer_channel;
struct Tone
{
Tone() :
envelope_on(false),
level(false),
tone(false), full_cycle(false),
volume(0),
pos(0),
size(0)
{
}
bool envelope_on, level;
bool tone/*else noise*/, full_cycle/* else square signal/pulse */;
int volume;
int pos, size;
};
enum
{
Right,
Left,
Both
};
Tone m_channels[3];
struct Noise
{
Noise():
state(1),
level(false),
step(0.0),
pos(0.0)
{}
int state;
bool level;
double step, pos;
} noise;
struct Envelope
{
Envelope():
control(0),
index(0),
first(false)
{}
int control;
int index;
bool first;
double step, pos;
} envelope;
uint8_t reg[14];
};
DECLARE_DEVICE_TYPE(GAMATE_SND, gamate_sound_device)
#endif // MAME_AUDIO_GAMATE_H

View File

@ -14,8 +14,7 @@
******************************************************************************/
#include "emu.h"
#include "audio/gamate.h"
#include "sound/ay8910.h"
#include "bus/generic/carts.h"
#include "bus/generic/slot.h"
#include "cpu/m6502/m6502.h"
@ -30,7 +29,7 @@ public:
gamate_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_sound(*this, "custom")
, m_ay(*this, "ay8910")
, m_cart(*this, "cartslot")
, m_io_joy(*this, "JOY")
, m_palette(*this, "palette")
@ -50,6 +49,8 @@ public:
DECLARE_READ8_MEMBER(gamate_video_r);
DECLARE_READ8_MEMBER(gamate_nmi_r);
DECLARE_WRITE8_MEMBER(gamate_video_w);
DECLARE_WRITE8_MEMBER(sound_w);
DECLARE_READ8_MEMBER(sound_r);
DECLARE_DRIVER_INIT(gamate);
uint32_t screen_update_gamate(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(gamate_interrupt);
@ -83,7 +84,7 @@ private:
} card_protection;
required_device<cpu_device> m_maincpu;
required_device<gamate_sound_device> m_sound;
required_device<ay8910_device> m_ay;
required_device<generic_slot_device> m_cart;
required_ioport m_io_joy;
required_device<palette_device> m_palette;
@ -229,9 +230,21 @@ READ8_MEMBER( gamate_state::gamate_nmi_r )
return data;
}
READ8_MEMBER(gamate_state::sound_r)
{
m_ay->address_w(space, 0, offset);
return m_ay->data_r(space, 0);
}
WRITE8_MEMBER(gamate_state::sound_w)
{
m_ay->address_w(space, 0, offset);
m_ay->data_w(space, 0, data & 0xff);
}
static ADDRESS_MAP_START( gamate_mem, AS_PROGRAM, 8, gamate_state )
AM_RANGE(0x0000, 0x03ff) AM_RAM
AM_RANGE(0x4000, 0x400d) AM_DEVREADWRITE("custom", gamate_sound_device, device_r, device_w)
AM_RANGE(0x4000, 0x400f) AM_READWRITE(sound_r,sound_w)
AM_RANGE(0x4400, 0x4400) AM_READ_PORT("JOY")
AM_RANGE(0x4800, 0x4800) AM_READ(gamate_nmi_r)
AM_RANGE(0x5000, 0x5007) AM_READWRITE(gamate_video_r, gamate_video_w)
@ -394,10 +407,12 @@ static MACHINE_CONFIG_START( gamate )
MCFG_DEFAULT_LAYOUT(layout_lcd)
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("custom", GAMATE_SND, 4433000/2)
MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") // Stereo headphone output
MCFG_SOUND_ADD("ay8910", AY8910, 4433000 / 2) // AY compatible, no actual AY chip present
MCFG_SOUND_ROUTE(0, "lspeaker", 0.5)
MCFG_SOUND_ROUTE(1, "rspeaker", 0.5)
MCFG_SOUND_ROUTE(2, "lspeaker", 0.25)
MCFG_SOUND_ROUTE(2, "rspeaker", 0.25)
MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_linear_slot, "gamate_cart")
MCFG_SOFTWARE_LIST_ADD("cart_list","gamate")