(MESS) modernized the Mac Sound device. [Fabio Priuli]

This commit is contained in:
Fabio Priuli 2013-06-02 21:40:08 +00:00
parent eb1eff0fe9
commit 0e35391d20
3 changed files with 138 additions and 184 deletions

View File

@ -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++;
}

View File

@ -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

View File

@ -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)