mirror of
https://github.com/holub/mame
synced 2025-06-05 20:33:45 +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/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",
|
||||
|
@ -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 "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")
|
||||
|
Loading…
Reference in New Issue
Block a user