mirror of
https://github.com/holub/mame
synced 2025-06-07 13:23:50 +03:00
Gamate sound is 100% AY8910 compatible according to Kevtris and Peter Wilhelmsen, us the AY8910 core.
This commit is contained in:
parent
e3cdd178ef
commit
4fb8e776b3
@ -3467,8 +3467,6 @@ files {
|
|||||||
MAME_DIR .. "src/mame/drivers/fk1.cpp",
|
MAME_DIR .. "src/mame/drivers/fk1.cpp",
|
||||||
MAME_DIR .. "src/mame/drivers/ft68m.cpp",
|
MAME_DIR .. "src/mame/drivers/ft68m.cpp",
|
||||||
MAME_DIR .. "src/mame/drivers/gamate.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/gameking.cpp",
|
||||||
MAME_DIR .. "src/mame/drivers/gimix.cpp",
|
MAME_DIR .. "src/mame/drivers/gimix.cpp",
|
||||||
MAME_DIR .. "src/mame/drivers/goupil.cpp",
|
MAME_DIR .. "src/mame/drivers/goupil.cpp",
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
@ -14,8 +14,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "audio/gamate.h"
|
#include "sound/ay8910.h"
|
||||||
|
|
||||||
#include "bus/generic/carts.h"
|
#include "bus/generic/carts.h"
|
||||||
#include "bus/generic/slot.h"
|
#include "bus/generic/slot.h"
|
||||||
#include "cpu/m6502/m6502.h"
|
#include "cpu/m6502/m6502.h"
|
||||||
@ -30,7 +29,7 @@ public:
|
|||||||
gamate_state(const machine_config &mconfig, device_type type, const char *tag)
|
gamate_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||||
: driver_device(mconfig, type, tag)
|
: driver_device(mconfig, type, tag)
|
||||||
, m_maincpu(*this, "maincpu")
|
, m_maincpu(*this, "maincpu")
|
||||||
, m_sound(*this, "custom")
|
, m_ay(*this, "ay8910")
|
||||||
, m_cart(*this, "cartslot")
|
, m_cart(*this, "cartslot")
|
||||||
, m_io_joy(*this, "JOY")
|
, m_io_joy(*this, "JOY")
|
||||||
, m_palette(*this, "palette")
|
, m_palette(*this, "palette")
|
||||||
@ -50,6 +49,8 @@ public:
|
|||||||
DECLARE_READ8_MEMBER(gamate_video_r);
|
DECLARE_READ8_MEMBER(gamate_video_r);
|
||||||
DECLARE_READ8_MEMBER(gamate_nmi_r);
|
DECLARE_READ8_MEMBER(gamate_nmi_r);
|
||||||
DECLARE_WRITE8_MEMBER(gamate_video_w);
|
DECLARE_WRITE8_MEMBER(gamate_video_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(sound_w);
|
||||||
|
DECLARE_READ8_MEMBER(sound_r);
|
||||||
DECLARE_DRIVER_INIT(gamate);
|
DECLARE_DRIVER_INIT(gamate);
|
||||||
uint32_t screen_update_gamate(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
uint32_t screen_update_gamate(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||||
INTERRUPT_GEN_MEMBER(gamate_interrupt);
|
INTERRUPT_GEN_MEMBER(gamate_interrupt);
|
||||||
@ -83,7 +84,7 @@ private:
|
|||||||
} card_protection;
|
} card_protection;
|
||||||
|
|
||||||
required_device<cpu_device> m_maincpu;
|
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_device<generic_slot_device> m_cart;
|
||||||
required_ioport m_io_joy;
|
required_ioport m_io_joy;
|
||||||
required_device<palette_device> m_palette;
|
required_device<palette_device> m_palette;
|
||||||
@ -229,9 +230,21 @@ READ8_MEMBER( gamate_state::gamate_nmi_r )
|
|||||||
return data;
|
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 )
|
static ADDRESS_MAP_START( gamate_mem, AS_PROGRAM, 8, gamate_state )
|
||||||
AM_RANGE(0x0000, 0x03ff) AM_RAM
|
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(0x4400, 0x4400) AM_READ_PORT("JOY")
|
||||||
AM_RANGE(0x4800, 0x4800) AM_READ(gamate_nmi_r)
|
AM_RANGE(0x4800, 0x4800) AM_READ(gamate_nmi_r)
|
||||||
AM_RANGE(0x5000, 0x5007) AM_READWRITE(gamate_video_r, gamate_video_w)
|
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)
|
MCFG_DEFAULT_LAYOUT(layout_lcd)
|
||||||
|
|
||||||
/* sound hardware */
|
/* sound hardware */
|
||||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") // Stereo headphone output
|
||||||
MCFG_SOUND_ADD("custom", GAMATE_SND, 4433000/2)
|
MCFG_SOUND_ADD("ay8910", AY8910, 4433000 / 2) // AY compatible, no actual AY chip present
|
||||||
MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
|
MCFG_SOUND_ROUTE(0, "lspeaker", 0.5)
|
||||||
MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
|
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_GENERIC_CARTSLOT_ADD("cartslot", generic_linear_slot, "gamate_cart")
|
||||||
MCFG_SOFTWARE_LIST_ADD("cart_list","gamate")
|
MCFG_SOFTWARE_LIST_ADD("cart_list","gamate")
|
||||||
|
Loading…
Reference in New Issue
Block a user