mirror of
https://github.com/holub/mame
synced 2025-06-25 05:44:23 +03:00
mac: rewrite audio output for original Macs to work like hardware. [R. Belmont]
This commit is contained in:
parent
8cf46d65c5
commit
cd29619484
@ -1388,7 +1388,6 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/lisa.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/mac.cpp",
|
||||
MAME_DIR .. "src/mame/includes/mac.h",
|
||||
MAME_DIR .. "src/mame/audio/mac.cpp",
|
||||
MAME_DIR .. "src/mame/machine/egret.cpp",
|
||||
MAME_DIR .. "src/mame/machine/egret.h",
|
||||
MAME_DIR .. "src/mame/machine/mac.cpp",
|
||||
|
@ -1,174 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont
|
||||
/***************************************************************************
|
||||
|
||||
mac.c
|
||||
|
||||
Sound handler
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "sound/asc.h"
|
||||
#include "includes/mac.h"
|
||||
#include "machine/ram.h"
|
||||
|
||||
/***************************************************************************
|
||||
MACROS / CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
#define MAC_MAIN_SND_BUF_OFFSET 0x0300
|
||||
#define MAC_ALT_SND_BUF_OFFSET 0x5F00
|
||||
#define MAC_SND_BUF_SIZE 370 /* total number of scan lines */
|
||||
#define MAC_SAMPLE_RATE ( MAC_SND_BUF_SIZE * 60 /*22255*/ ) /* scan line rate, should be 22254.5 Hz */
|
||||
|
||||
|
||||
/* intermediate buffer */
|
||||
#define SND_CACHE_SIZE 128
|
||||
|
||||
|
||||
|
||||
|
||||
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 Audio Custom", tag, owner, clock, "mac_sound", __FILE__),
|
||||
device_sound_interface(mconfig, *this),
|
||||
m_sample_enable(0),
|
||||
m_mac_snd_buf_ptr(nullptr),
|
||||
m_snd_cache_len(0),
|
||||
m_snd_cache_head(0),
|
||||
m_snd_cache_tail(0),
|
||||
m_indexx(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void mac_sound_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void mac_sound_device::device_start()
|
||||
{
|
||||
mac_state *mac = machine().driver_data<mac_state>();
|
||||
|
||||
m_snd_cache = make_unique_clear<UINT8[]>(SND_CACHE_SIZE);
|
||||
m_mac_stream = machine().sound().stream_alloc(*this, 0, 1, MAC_SAMPLE_RATE);
|
||||
|
||||
m_ram = machine().device<ram_device>(RAM_TAG);
|
||||
m_mac_model = mac->m_model;
|
||||
|
||||
save_pointer(NAME(m_snd_cache.get()), 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));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle a stream update
|
||||
//-------------------------------------------------
|
||||
|
||||
void mac_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
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++;
|
||||
}
|
@ -567,6 +567,41 @@ WRITE8_MEMBER(mac_state::mac_5396_w)
|
||||
}
|
||||
}
|
||||
|
||||
#define MAC_MAIN_SND_BUF_OFFSET 0x0300
|
||||
#define MAC_ALT_SND_BUF_OFFSET 0x5F00
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(mac_state::mac_scanline)
|
||||
{
|
||||
int scanline = param;
|
||||
UINT16 *mac_snd_buf_ptr;
|
||||
UINT16 last_val;
|
||||
|
||||
if (m_snd_enable)
|
||||
{
|
||||
if (m_main_buffer)
|
||||
{
|
||||
mac_snd_buf_ptr = (UINT16 *)(m_ram->pointer() + m_ram->size() - MAC_MAIN_SND_BUF_OFFSET);
|
||||
}
|
||||
else
|
||||
{
|
||||
mac_snd_buf_ptr = (UINT16 *)(m_ram->pointer() + m_ram->size() - MAC_ALT_SND_BUF_OFFSET);
|
||||
}
|
||||
|
||||
last_val = (UINT8)((mac_snd_buf_ptr[scanline] >> 8) & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
last_val = 0x80;
|
||||
}
|
||||
|
||||
// apply 0-7 volume
|
||||
last_val *= m_snd_vol;
|
||||
last_val <<= 5;
|
||||
|
||||
m_dac->write_unsigned16(last_val);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
ADDRESS MAPS
|
||||
***************************************************************************/
|
||||
@ -898,11 +933,7 @@ static MACHINE_CONFIG_START( mac512ke, mac_state )
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD(MAC_SCREEN_NAME, RASTER)
|
||||
MCFG_SCREEN_REFRESH_RATE(60.15)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(1260))
|
||||
MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
|
||||
MCFG_SCREEN_SIZE(MAC_H_TOTAL, MAC_V_TOTAL)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, MAC_H_VIS-1, 0, MAC_V_VIS-1)
|
||||
MCFG_SCREEN_RAW_PARAMS(C7M*2, MAC_H_TOTAL, 0, MAC_H_VIS, MAC_V_TOTAL, 0, MAC_V_VIS)
|
||||
MCFG_SCREEN_UPDATE_DRIVER(mac_state, screen_update_mac)
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
|
||||
@ -911,9 +942,12 @@ static MACHINE_CONFIG_START( mac512ke, mac_state )
|
||||
|
||||
MCFG_VIDEO_START_OVERRIDE(mac_state,mac)
|
||||
|
||||
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", mac_state, mac_scanline, "screen", 0, 1)
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("custom", MAC_SOUND, 0)
|
||||
//MCFG_SOUND_ADD("custom", MAC_SOUND, 0)
|
||||
MCFG_SOUND_ADD(DAC_TAG, DAC, 0)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
|
||||
/* devices */
|
||||
|
@ -24,12 +24,14 @@
|
||||
#include "machine/macrtc.h"
|
||||
#include "sound/asc.h"
|
||||
#include "sound/awacs.h"
|
||||
#include "sound/dac.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
|
||||
#define MAC_SCREEN_NAME "screen"
|
||||
#define MAC_539X_1_TAG "539x_1"
|
||||
#define MAC_539X_2_TAG "539x_2"
|
||||
#define MACKBD_TAG "mackbd"
|
||||
#define DAC_TAG "macdac"
|
||||
|
||||
// uncomment to run i8021 keyboard in original Mac/512(e)/Plus
|
||||
//#define MAC_USE_EMULATED_KBD (1)
|
||||
@ -145,46 +147,6 @@ enum model_t
|
||||
|
||||
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:
|
||||
mac_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
~mac_sound_device() {}
|
||||
|
||||
void enable_sound(int on);
|
||||
void set_sound_buffer(int buffer);
|
||||
void set_volume(int volume);
|
||||
void sh_updatebuffer();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete() override;
|
||||
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:
|
||||
// internal state
|
||||
|
||||
ram_device *m_ram;
|
||||
model_t m_mac_model;
|
||||
|
||||
sound_stream *m_mac_stream;
|
||||
int m_sample_enable;
|
||||
UINT16 *m_mac_snd_buf_ptr;
|
||||
std::unique_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;
|
||||
|
||||
|
||||
/* Mac driver data */
|
||||
|
||||
class mac_state : public driver_device
|
||||
@ -214,7 +176,8 @@ public:
|
||||
m_vram16(*this,"vram16"),
|
||||
m_via2_ca1_hack(0),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette")
|
||||
m_palette(*this, "palette"),
|
||||
m_dac(*this, DAC_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
@ -252,6 +215,11 @@ public:
|
||||
emu_timer *m_overlay_timeout;
|
||||
TIMER_CALLBACK_MEMBER(overlay_timeout_func);
|
||||
DECLARE_READ32_MEMBER(rom_switch_r);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(mac_scanline);
|
||||
bool m_snd_enable;
|
||||
bool m_main_buffer;
|
||||
int m_snd_vol;
|
||||
|
||||
#ifndef MAC_USE_EMULATED_KBD
|
||||
/* used to store the reply to most keyboard commands */
|
||||
@ -449,6 +417,8 @@ private:
|
||||
int m_via2_ca1_hack;
|
||||
optional_device<screen_device> m_screen;
|
||||
optional_device<palette_device> m_palette;
|
||||
optional_device<dac_device> m_dac;
|
||||
|
||||
public:
|
||||
emu_timer *m_scanline_timer;
|
||||
emu_timer *m_adb_timer;
|
||||
|
@ -1421,7 +1421,6 @@ READ8_MEMBER(mac_state::mac_via_in_b_pmu)
|
||||
|
||||
WRITE8_MEMBER(mac_state::mac_via_out_a)
|
||||
{
|
||||
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());
|
||||
|
||||
@ -1435,12 +1434,12 @@ WRITE8_MEMBER(mac_state::mac_via_out_a)
|
||||
|
||||
if (m_model < MODEL_MAC_SE) // SE no longer has dual buffers
|
||||
{
|
||||
sound->set_sound_buffer((data & 0x08) >> 3);
|
||||
m_main_buffer = ((data & 0x08) == 0x08) ? true : false;
|
||||
}
|
||||
|
||||
if (m_model < MODEL_MAC_II)
|
||||
{
|
||||
sound->set_volume(data & 0x07);
|
||||
m_snd_vol = data & 0x07;
|
||||
}
|
||||
|
||||
/* Early Mac models had VIA A4 control overlaying. In the Mac SE (and
|
||||
@ -1465,12 +1464,11 @@ WRITE8_MEMBER(mac_state::mac_via_out_a_pmu)
|
||||
|
||||
WRITE8_MEMBER(mac_state::mac_via_out_b)
|
||||
{
|
||||
mac_sound_device *sound = machine().device<mac_sound_device>("custom");
|
||||
// printf("VIA1 OUT B: %02x (PC %x)\n", data, m_maincpu->safe_pc());
|
||||
|
||||
if (AUDIO_IS_CLASSIC)
|
||||
{
|
||||
sound->enable_sound((data & 0x80) == 0);
|
||||
m_snd_enable = ((data & 0x80) == 0) ? true : false;
|
||||
}
|
||||
|
||||
m_rtc->ce_w((data & 0x04)>>2);
|
||||
@ -1955,12 +1953,7 @@ void mac_state::machine_reset()
|
||||
/* setup videoram */
|
||||
this->m_screen_buffer = 1;
|
||||
|
||||
/* setup 'classic' sound */
|
||||
if (machine().device("custom") != nullptr)
|
||||
{
|
||||
machine().device<mac_sound_device>("custom")->set_sound_buffer(0);
|
||||
}
|
||||
else if (MAC_HAS_VIA2) // prime CB1 for ASC and slot interrupts
|
||||
if (MAC_HAS_VIA2) // prime CB1 for ASC and slot interrupts
|
||||
{
|
||||
m_via2_ca1_hack = 1;
|
||||
m_via2->write_ca1(1);
|
||||
@ -1974,8 +1967,6 @@ void mac_state::machine_reset()
|
||||
|
||||
if ((m_model == MODEL_MAC_SE) || (m_model == MODEL_MAC_CLASSIC))
|
||||
{
|
||||
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());
|
||||
}
|
||||
@ -1998,6 +1989,10 @@ void mac_state::machine_reset()
|
||||
m_pm_data_send = m_pm_data_recv = m_pm_ack = m_pm_req = m_pm_dptr = 0;
|
||||
m_pm_state = 0;
|
||||
m_last_taken_interrupt = 0;
|
||||
|
||||
m_snd_enable = false;
|
||||
m_main_buffer = true;
|
||||
m_snd_vol = 3;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(mac_state::cuda_reset_w)
|
||||
@ -2290,11 +2285,6 @@ TIMER_CALLBACK_MEMBER(mac_state::mac_scanline_tick)
|
||||
{
|
||||
int scanline;
|
||||
|
||||
if (machine().device("custom") != nullptr)
|
||||
{
|
||||
machine().device<mac_sound_device>("custom")->sh_updatebuffer();
|
||||
}
|
||||
|
||||
if (m_rbv_vbltime > 0)
|
||||
{
|
||||
m_rbv_vbltime--;
|
||||
|
Loading…
Reference in New Issue
Block a user