mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
(MESS) modernized the Mac Sound device. [Fabio Priuli]
This commit is contained in:
parent
eb1eff0fe9
commit
0e35391d20
@ -26,174 +26,20 @@
|
||||
#define SND_CACHE_SIZE 128
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
struct mac_sound
|
||||
{
|
||||
sound_stream *mac_stream;
|
||||
int sample_enable;
|
||||
UINT16 *mac_snd_buf_ptr;
|
||||
UINT8 *snd_cache;
|
||||
int snd_cache_len;
|
||||
int snd_cache_head;
|
||||
int snd_cache_tail;
|
||||
int indexx;
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
INLINE mac_sound *get_token(device_t *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == MAC_SOUND);
|
||||
return (mac_sound *) downcast<mac_sound_device *>(device)->token();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
IMPLEMENTATION
|
||||
***************************************************************************/
|
||||
|
||||
/************************************/
|
||||
/* Stream updater */
|
||||
/************************************/
|
||||
|
||||
static STREAM_UPDATE( mac_sound_update )
|
||||
{
|
||||
INT16 last_val = 0;
|
||||
stream_sample_t *buffer = outputs[0];
|
||||
mac_sound *token = get_token(device);
|
||||
mac_state *mac = device->machine().driver_data<mac_state>();
|
||||
|
||||
if ((mac->m_model == MODEL_MAC_PORTABLE) || (mac->m_model == MODEL_MAC_PB100))
|
||||
{
|
||||
memset(buffer, 0, samples * sizeof(*buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we're not enabled, just fill with 0 */
|
||||
if (device->machine().sample_rate() == 0)
|
||||
{
|
||||
memset(buffer, 0, samples * sizeof(*buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill in the sample */
|
||||
while (samples && token->snd_cache_len)
|
||||
{
|
||||
*buffer++ = last_val = ((token->snd_cache[token->snd_cache_head] << 8) ^ 0x8000) & 0xff00;
|
||||
token->snd_cache_head++;
|
||||
token->snd_cache_head %= SND_CACHE_SIZE;
|
||||
token->snd_cache_len--;
|
||||
samples--;
|
||||
}
|
||||
|
||||
while (samples--)
|
||||
{
|
||||
/* should never happen */
|
||||
*buffer++ = last_val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************/
|
||||
/* Sound handler start */
|
||||
/************************************/
|
||||
|
||||
static DEVICE_START(mac_sound)
|
||||
{
|
||||
mac_sound *token = get_token(device);
|
||||
|
||||
memset(token, 0, sizeof(*token));
|
||||
|
||||
token->snd_cache = auto_alloc_array(device->machine(), UINT8, SND_CACHE_SIZE);
|
||||
token->mac_stream = device->machine().sound().stream_alloc(*device, 0, 1, MAC_SAMPLE_RATE, 0, mac_sound_update);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Set the sound enable flag (VIA port line)
|
||||
*/
|
||||
void mac_enable_sound(device_t *device, int on)
|
||||
{
|
||||
mac_sound *token = get_token(device);
|
||||
token->sample_enable = on;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Set the current sound buffer (one VIA port line)
|
||||
*/
|
||||
void mac_set_sound_buffer(device_t *device, int buffer)
|
||||
{
|
||||
mac_sound *token = get_token(device);
|
||||
ram_device *ram = device->machine().device<ram_device>(RAM_TAG);
|
||||
|
||||
if (buffer)
|
||||
token->mac_snd_buf_ptr = (UINT16 *) (ram->pointer() + ram->size() - MAC_MAIN_SND_BUF_OFFSET);
|
||||
else
|
||||
token->mac_snd_buf_ptr = (UINT16 *) (ram->pointer() + ram->size() - MAC_ALT_SND_BUF_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Set the current sound volume (3 VIA port line)
|
||||
*/
|
||||
void mac_set_volume(device_t *device, int volume)
|
||||
{
|
||||
mac_sound *token = get_token(device);
|
||||
|
||||
token->mac_stream->update();
|
||||
volume = (100 / 7) * volume;
|
||||
token->mac_stream->set_output_gain(0, volume / 100.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Fetch one byte from sound buffer and put it to sound output (called every scanline)
|
||||
*/
|
||||
void mac_sh_updatebuffer(device_t *device)
|
||||
{
|
||||
mac_sound *token = get_token(device);
|
||||
UINT16 *base = token->mac_snd_buf_ptr;
|
||||
|
||||
token->indexx++;
|
||||
token->indexx %= 370;
|
||||
|
||||
if (token->snd_cache_len >= SND_CACHE_SIZE)
|
||||
{
|
||||
/* clear buffer */
|
||||
token->mac_stream->update();
|
||||
}
|
||||
|
||||
if (token->snd_cache_len >= SND_CACHE_SIZE)
|
||||
/* should never happen */
|
||||
return;
|
||||
|
||||
token->snd_cache[token->snd_cache_tail] = token->sample_enable ? (base[token->indexx] >> 8) & 0xff : 0;
|
||||
token->snd_cache_tail++;
|
||||
token->snd_cache_tail %= SND_CACHE_SIZE;
|
||||
token->snd_cache_len++;
|
||||
}
|
||||
|
||||
|
||||
const device_type MAC_SOUND = &device_creator<mac_sound_device>;
|
||||
|
||||
mac_sound_device::mac_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, MAC_SOUND, "Mac Custom", tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this)
|
||||
: device_t(mconfig, MAC_SOUND, "Mac Custom", tag, owner, clock),
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_sample_enable(0),
|
||||
m_mac_snd_buf_ptr(NULL),
|
||||
m_snd_cache_len(0),
|
||||
m_snd_cache_head(0),
|
||||
m_snd_cache_tail(0),
|
||||
m_indexx(0)
|
||||
{
|
||||
m_token = global_alloc_clear(mac_sound);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -212,7 +58,20 @@ void mac_sound_device::device_config_complete()
|
||||
|
||||
void mac_sound_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( mac_sound )(this);
|
||||
mac_state *mac = machine().driver_data<mac_state>();
|
||||
|
||||
m_snd_cache = auto_alloc_array_clear(machine(), UINT8, SND_CACHE_SIZE);
|
||||
m_mac_stream = machine().sound().stream_alloc(*this, 0, 1, MAC_SAMPLE_RATE, this);
|
||||
|
||||
m_ram = machine().device<ram_device>(RAM_TAG);
|
||||
m_mac_model = mac->m_model;
|
||||
|
||||
save_pointer(NAME(m_snd_cache), SND_CACHE_SIZE);
|
||||
save_item(NAME(m_sample_enable));
|
||||
save_item(NAME(m_snd_cache_len));
|
||||
save_item(NAME(m_snd_cache_head));
|
||||
save_item(NAME(m_snd_cache_tail));
|
||||
save_item(NAME(m_indexx));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -221,6 +80,93 @@ void mac_sound_device::device_start()
|
||||
|
||||
void mac_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
// should never get here
|
||||
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
|
||||
INT16 last_val = 0;
|
||||
stream_sample_t *buffer = outputs[0];
|
||||
|
||||
if ((m_mac_model == MODEL_MAC_PORTABLE) || (m_mac_model == MODEL_MAC_PB100))
|
||||
{
|
||||
memset(buffer, 0, samples * sizeof(*buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we're not enabled, just fill with 0 */
|
||||
if (machine().sample_rate() == 0)
|
||||
{
|
||||
memset(buffer, 0, samples * sizeof(*buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill in the sample */
|
||||
while (samples && m_snd_cache_len)
|
||||
{
|
||||
*buffer++ = last_val = ((m_snd_cache[m_snd_cache_head] << 8) ^ 0x8000) & 0xff00;
|
||||
m_snd_cache_head++;
|
||||
m_snd_cache_head %= SND_CACHE_SIZE;
|
||||
m_snd_cache_len--;
|
||||
samples--;
|
||||
}
|
||||
|
||||
while (samples--)
|
||||
{
|
||||
/* should never happen */
|
||||
*buffer++ = last_val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
IMPLEMENTATION
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
// Set the sound enable flag (VIA port line)
|
||||
void mac_sound_device::enable_sound(int on)
|
||||
{
|
||||
m_sample_enable = on;
|
||||
}
|
||||
|
||||
|
||||
// Set the current sound buffer (one VIA port line)
|
||||
void mac_sound_device::set_sound_buffer(int buffer)
|
||||
{
|
||||
if (buffer)
|
||||
m_mac_snd_buf_ptr = (UINT16 *) (m_ram->pointer() + m_ram->size() - MAC_MAIN_SND_BUF_OFFSET);
|
||||
else
|
||||
m_mac_snd_buf_ptr = (UINT16 *) (m_ram->pointer() + m_ram->size() - MAC_ALT_SND_BUF_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Set the current sound volume (3 VIA port line)
|
||||
void mac_sound_device::set_volume(int volume)
|
||||
{
|
||||
m_mac_stream->update();
|
||||
volume = (100 / 7) * volume;
|
||||
m_mac_stream->set_output_gain(0, volume / 100.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Fetch one byte from sound buffer and put it to sound output (called every scanline)
|
||||
void mac_sound_device::sh_updatebuffer()
|
||||
{
|
||||
UINT16 *base = m_mac_snd_buf_ptr;
|
||||
|
||||
m_indexx++;
|
||||
m_indexx %= 370;
|
||||
|
||||
if (m_snd_cache_len >= SND_CACHE_SIZE)
|
||||
{
|
||||
/* clear buffer */
|
||||
m_mac_stream->update();
|
||||
}
|
||||
|
||||
if (m_snd_cache_len >= SND_CACHE_SIZE)
|
||||
/* should never happen */
|
||||
return;
|
||||
|
||||
m_snd_cache[m_snd_cache_tail] = m_sample_enable ? (base[m_indexx] >> 8) & 0xff : 0;
|
||||
m_snd_cache_tail++;
|
||||
m_snd_cache_tail %= SND_CACHE_SIZE;
|
||||
m_snd_cache_len++;
|
||||
}
|
||||
|
@ -147,14 +147,17 @@ void mac_fdc_set_enable_lines(device_t *device, int enable_mask);
|
||||
/*----------- defined in audio/mac.c -----------*/
|
||||
|
||||
class mac_sound_device : public device_t,
|
||||
public device_sound_interface
|
||||
public device_sound_interface
|
||||
{
|
||||
public:
|
||||
mac_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
~mac_sound_device() { global_free(m_token); }
|
||||
~mac_sound_device() {}
|
||||
|
||||
void enable_sound(int on);
|
||||
void set_sound_buffer(int buffer);
|
||||
void set_volume(int volume);
|
||||
void sh_updatebuffer();
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
@ -164,18 +167,23 @@ protected:
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
private:
|
||||
// internal state
|
||||
void *m_token;
|
||||
|
||||
ram_device *m_ram;
|
||||
model_t m_mac_model;
|
||||
|
||||
sound_stream *m_mac_stream;
|
||||
int m_sample_enable;
|
||||
UINT16 *m_mac_snd_buf_ptr;
|
||||
UINT8 *m_snd_cache;
|
||||
int m_snd_cache_len;
|
||||
int m_snd_cache_head;
|
||||
int m_snd_cache_tail;
|
||||
int m_indexx;
|
||||
};
|
||||
|
||||
extern const device_type MAC_SOUND;
|
||||
|
||||
|
||||
void mac_enable_sound( device_t *device, int on );
|
||||
void mac_set_sound_buffer( device_t *device, int buffer );
|
||||
void mac_set_volume( device_t *device, int volume );
|
||||
|
||||
void mac_sh_updatebuffer(device_t *device);
|
||||
|
||||
/* Mac driver data */
|
||||
|
||||
class mac_state : public driver_device
|
||||
|
@ -1356,7 +1356,7 @@ READ8_MEMBER(mac_state::mac_via_in_b)
|
||||
|
||||
WRITE8_MEMBER(mac_state::mac_via_out_a)
|
||||
{
|
||||
device_t *sound = machine().device("custom");
|
||||
mac_sound_device *sound = machine().device<mac_sound_device>("custom");
|
||||
device_t *fdc = machine().device("fdc");
|
||||
// printf("VIA1 OUT A: %02x (PC %x)\n", data, m_maincpu->safe_pc());
|
||||
|
||||
@ -1379,12 +1379,12 @@ WRITE8_MEMBER(mac_state::mac_via_out_a)
|
||||
|
||||
if (m_model < MODEL_MAC_SE) // SE no longer has dual buffers
|
||||
{
|
||||
mac_set_sound_buffer(sound, (data & 0x08) >> 3);
|
||||
sound->set_sound_buffer((data & 0x08) >> 3);
|
||||
}
|
||||
|
||||
if (m_model < MODEL_MAC_II)
|
||||
{
|
||||
mac_set_volume(sound, data & 0x07);
|
||||
sound->set_volume(data & 0x07);
|
||||
}
|
||||
|
||||
/* Early Mac models had VIA A4 control overlaying. In the Mac SE (and
|
||||
@ -1398,7 +1398,7 @@ WRITE8_MEMBER(mac_state::mac_via_out_a)
|
||||
|
||||
WRITE8_MEMBER(mac_state::mac_via_out_b)
|
||||
{
|
||||
device_t *sound = machine().device("custom");
|
||||
mac_sound_device *sound = machine().device<mac_sound_device>("custom");
|
||||
// printf("VIA1 OUT B: %02x (PC %x)\n", data, m_maincpu->safe_pc());
|
||||
|
||||
if (ADB_IS_PM_VIA1)
|
||||
@ -1467,7 +1467,7 @@ WRITE8_MEMBER(mac_state::mac_via_out_b)
|
||||
|
||||
if (AUDIO_IS_CLASSIC)
|
||||
{
|
||||
mac_enable_sound(sound, (data & 0x80) == 0);
|
||||
sound->enable_sound((data & 0x80) == 0);
|
||||
}
|
||||
|
||||
// SE and Classic have SCSI enable/disable here
|
||||
@ -1859,7 +1859,7 @@ void mac_state::machine_reset()
|
||||
/* setup 'classic' sound */
|
||||
if (machine().device("custom") != NULL)
|
||||
{
|
||||
mac_set_sound_buffer(machine().device("custom"), 0);
|
||||
machine().device<mac_sound_device>("custom")->set_sound_buffer(0);
|
||||
}
|
||||
else if (MAC_HAS_VIA2) // prime CB1 for ASC and slot interrupts
|
||||
{
|
||||
@ -1874,7 +1874,7 @@ void mac_state::machine_reset()
|
||||
|
||||
if ((m_model == MODEL_MAC_SE) || (m_model == MODEL_MAC_CLASSIC))
|
||||
{
|
||||
mac_set_sound_buffer(machine().device("custom"), 1);
|
||||
machine().device<mac_sound_device>("custom")->set_sound_buffer(1);
|
||||
|
||||
// classic will fail RAM test and try to boot appletalk if RAM is not all zero
|
||||
memset(m_ram->pointer(), 0, m_ram->size());
|
||||
@ -2205,7 +2205,7 @@ TIMER_CALLBACK_MEMBER(mac_state::mac_scanline_tick)
|
||||
|
||||
if (machine().device("custom") != NULL)
|
||||
{
|
||||
mac_sh_updatebuffer(machine().device("custom"));
|
||||
machine().device<mac_sound_device>("custom")->sh_updatebuffer();
|
||||
}
|
||||
|
||||
if (m_rbv_vbltime > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user