redalert, demoneye: Audio updates

- More accurate emulation of 555-based IRQ timing
- Use 6821 PIA device to generate sound IRQ in Demoneye
- Simplify handler signatures (nw)
This commit is contained in:
AJR 2020-05-01 21:33:36 -04:00
parent 8a4aca5899
commit d563a7a2d6
4 changed files with 79 additions and 46 deletions

View File

@ -15,7 +15,6 @@
#include "cpu/m6800/m6800.h"
#include "cpu/m6502/m6502.h"
#include "machine/rescap.h"
#include "machine/6821pia.h"
#include "speaker.h"
@ -23,25 +22,45 @@
#define REDALERT_AUDIO_PCB_CLOCK (XTAL(12'500'000))
#define REDALERT_AUDIO_CPU_CLOCK (REDALERT_AUDIO_PCB_CLOCK / 12)
#define REDALERT_AY8910_CLOCK (REDALERT_AUDIO_PCB_CLOCK / 6)
#define REDALERT_AUDIO_CPU_IRQ_FREQ (1000000000.0 / PERIOD_OF_555_ASTABLE_NSEC(RES_K(120), RES_K(2.7), CAP_U(0.01)))
#define REDALERT_AUDIO_CPU_IRQ_FREQ (PERIOD_OF_555_ASTABLE(RES_K(120), RES_K(2.7), CAP_U(0.01)))
#define REDALERT_AUDIO_CPU_IRQ_TIME (PERIOD_OF_555_ASTABLE(RES_K(2.7), 0, CAP_U(0.01))) /* 555 discharge time */
#define REDALERT_VOICE_PCB_CLOCK (XTAL(6'000'000))
#define REDALERT_VOICE_CPU_CLOCK (REDALERT_VOICE_PCB_CLOCK)
#define REDALERT_HC55516_CLOCK (REDALERT_VOICE_PCB_CLOCK / 256)
#define DEMONEYE_AUDIO_PCB_CLOCK (XTAL(3'579'545))
#define DEMONEYE_AUDIO_CPU_CLOCK (DEMONEYE_AUDIO_PCB_CLOCK / 4) /* what's the real divisor? */
#define DEMONEYE_AUDIO_CPU_CLOCK (DEMONEYE_AUDIO_PCB_CLOCK) /* what's the real divisor? */
#define DEMONEYE_AY8910_CLOCK (DEMONEYE_AUDIO_PCB_CLOCK / 2) /* what's the real divisor? */
TIMER_CALLBACK_MEMBER(redalert_state::audio_irq_on)
{
if (m_sndpia.found())
m_sndpia->cb1_w(0); // guess
else
m_audiocpu->set_input_line(m6502_device::IRQ_LINE, ASSERT_LINE);
m_audio_irq_off_timer->adjust(REDALERT_AUDIO_CPU_IRQ_TIME);
}
TIMER_CALLBACK_MEMBER(redalert_state::audio_irq_off)
{
if (m_sndpia.found())
m_sndpia->cb1_w(1); // guess
else
m_audiocpu->set_input_line(m6502_device::IRQ_LINE, CLEAR_LINE);
}
/*************************************
*
* Read Alert analog sounds
* Red Alert analog sounds
*
*************************************/
WRITE8_MEMBER(redalert_state::redalert_analog_w)
void redalert_state::redalert_analog_w(uint8_t data)
{
/* this port triggers analog sounds
D0 = Formation Aircraft?
@ -63,7 +82,7 @@ WRITE8_MEMBER(redalert_state::redalert_analog_w)
*
*************************************/
WRITE8_MEMBER(redalert_state::redalert_audio_command_w)
void redalert_state::redalert_audio_command_w(uint8_t data)
{
/* the byte is connected to port A of the AY8910 */
m_soundlatch->write(data);
@ -75,7 +94,7 @@ WRITE8_MEMBER(redalert_state::redalert_audio_command_w)
}
WRITE8_MEMBER(redalert_state::redalert_AY8910_w)
void redalert_state::redalert_AY8910_w(uint8_t data)
{
/* BC2 is connected to a pull-up resistor, so BC2=1 always */
switch (data & 0x03)
@ -100,13 +119,13 @@ WRITE8_MEMBER(redalert_state::redalert_AY8910_w)
}
READ8_MEMBER(redalert_state::redalert_ay8910_latch_1_r)
uint8_t redalert_state::redalert_ay8910_latch_1_r()
{
return m_ay8910_latch_1;
}
WRITE8_MEMBER(redalert_state::redalert_ay8910_latch_2_w)
void redalert_state::redalert_ay8910_latch_2_w(uint8_t data)
{
m_ay8910_latch_2 = data;
}
@ -129,6 +148,11 @@ void redalert_state::redalert_audio_map(address_map &map)
void redalert_state::sound_start()
{
m_audio_irq_on_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(redalert_state::audio_irq_on), this));
m_audio_irq_off_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(redalert_state::audio_irq_off), this));
m_audio_irq_on_timer->adjust(REDALERT_AUDIO_CPU_IRQ_FREQ, 0, REDALERT_AUDIO_CPU_IRQ_FREQ);
save_item(NAME(m_ay8910_latch_1));
save_item(NAME(m_ay8910_latch_2));
}
@ -140,7 +164,7 @@ void redalert_state::sound_start()
*
*************************************/
WRITE8_MEMBER(redalert_state::redalert_voice_command_w)
void redalert_state::redalert_voice_command_w(uint8_t data)
{
m_soundlatch2->write((data & 0x78) >> 3);
m_voicecpu->set_input_line(I8085_RST75_LINE, (~data & 0x80) ? ASSERT_LINE : CLEAR_LINE);
@ -179,7 +203,6 @@ void redalert_state::redalert_audio_m37b(machine_config &config)
{
M6502(config, m_audiocpu, REDALERT_AUDIO_CPU_CLOCK);
m_audiocpu->set_addrmap(AS_PROGRAM, &redalert_state::redalert_audio_map);
m_audiocpu->set_periodic_int(FUNC(redalert_state::irq0_line_hold), attotime::from_hz(REDALERT_AUDIO_CPU_IRQ_FREQ));
GENERIC_LATCH_8(config, m_soundlatch);
@ -243,7 +266,7 @@ void redalert_state::ww3_audio(machine_config &config)
*************************************/
WRITE8_MEMBER(redalert_state::demoneye_audio_command_w)
void redalert_state::demoneye_audio_command_w(uint8_t data)
{
/* the byte is connected to port A of the AY8910 */
m_soundlatch->write(data);
@ -251,19 +274,19 @@ WRITE8_MEMBER(redalert_state::demoneye_audio_command_w)
}
WRITE8_MEMBER(redalert_state::demoneye_ay8910_latch_1_w)
void redalert_state::demoneye_ay8910_latch_1_w(uint8_t data)
{
m_ay8910_latch_1 = data;
}
READ8_MEMBER(redalert_state::demoneye_ay8910_latch_2_r)
uint8_t redalert_state::demoneye_ay8910_latch_2_r()
{
return m_ay8910_latch_2;
}
WRITE8_MEMBER(redalert_state::demoneye_ay8910_data_w)
void redalert_state::demoneye_ay8910_data_w(uint8_t data)
{
switch (m_ay8910_latch_1 & 0x03)
{
@ -303,7 +326,7 @@ WRITE8_MEMBER(redalert_state::demoneye_ay8910_data_w)
void redalert_state::demoneye_audio_map(address_map &map)
{
map(0x0500, 0x0503).mirror(0xc000).rw("sndpia", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x0500, 0x0503).mirror(0xc000).rw(m_sndpia, FUNC(pia6821_device::read), FUNC(pia6821_device::write));
map(0x2000, 0x3fff).mirror(0xc000).rom();
}
@ -319,12 +342,12 @@ void redalert_state::demoneye_audio(machine_config &config)
{
M6802(config, m_audiocpu, DEMONEYE_AUDIO_CPU_CLOCK);
m_audiocpu->set_addrmap(AS_PROGRAM, &redalert_state::demoneye_audio_map);
m_audiocpu->set_periodic_int(FUNC(redalert_state::irq0_line_hold), attotime::from_hz(REDALERT_AUDIO_CPU_IRQ_FREQ)); /* guess */
pia6821_device &sndpia(PIA6821(config, "sndpia", 0));
sndpia.readpa_handler().set(FUNC(redalert_state::demoneye_ay8910_latch_2_r));
sndpia.writepa_handler().set(FUNC(redalert_state::demoneye_ay8910_data_w));
sndpia.writepb_handler().set(FUNC(redalert_state::demoneye_ay8910_latch_1_w));
PIA6821(config, m_sndpia);
m_sndpia->readpa_handler().set(FUNC(redalert_state::demoneye_ay8910_latch_2_r));
m_sndpia->writepa_handler().set(FUNC(redalert_state::demoneye_ay8910_data_w));
m_sndpia->writepb_handler().set(FUNC(redalert_state::demoneye_ay8910_latch_1_w));
m_sndpia->irqb_handler().set_inputline(m_audiocpu, M6802_IRQ_LINE);
SPEAKER(config, "mono").front_center();

View File

@ -119,9 +119,10 @@ INTERRUPT_GEN_MEMBER(redalert_state::redalert_vblank_interrupt)
}
READ8_MEMBER(redalert_state::redalert_interrupt_clear_r)
uint8_t redalert_state::redalert_interrupt_clear_r()
{
m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
if (!machine().side_effects_disabled())
m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
/* the result never seems to be actually used */
return m_screen->vpos();
@ -129,19 +130,20 @@ READ8_MEMBER(redalert_state::redalert_interrupt_clear_r)
WRITE8_MEMBER(redalert_state::redalert_interrupt_clear_w)
{
redalert_interrupt_clear_r(space, 0);
}
READ8_MEMBER(redalert_state::panther_interrupt_clear_r)
void redalert_state::redalert_interrupt_clear_w(uint8_t data)
{
m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
}
uint8_t redalert_state::panther_interrupt_clear_r()
{
if (!machine().side_effects_disabled())
m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
return ioport("STICK0")->read();
}
READ8_MEMBER(redalert_state::panther_unk_r)
uint8_t redalert_state::panther_unk_r()
{
return ((machine().rand() & 0x01) | (ioport("C020")->read() & 0xfe));
}

View File

@ -19,6 +19,7 @@
#pragma once
#include "cpu/i8085/i8085.h"
#include "machine/6821pia.h"
#include "machine/gen_latch.h"
#include "sound/ay8910.h"
#include "sound/hc55516.h"
@ -39,6 +40,7 @@ public:
m_ay8910(*this, "aysnd"),
m_ay(*this, "ay%u", 1U),
m_cvsd(*this, "cvsd"),
m_sndpia(*this, "sndpia"),
m_screen(*this, "screen"),
m_soundlatch(*this, "soundlatch"),
m_soundlatch2(*this, "soundlatch2")
@ -72,35 +74,38 @@ private:
optional_device<ay8910_device> m_ay8910;
optional_device_array<ay8910_device, 2> m_ay;
optional_device<hc55516_device> m_cvsd;
optional_device<pia6821_device> m_sndpia;
required_device<screen_device> m_screen;
required_device<generic_latch_8_device> m_soundlatch;
optional_device<generic_latch_8_device> m_soundlatch2;
std::unique_ptr<uint8_t[]> m_bitmap_colorram;
uint8_t m_control_xor;
DECLARE_READ8_MEMBER(redalert_interrupt_clear_r);
DECLARE_WRITE8_MEMBER(redalert_interrupt_clear_w);
DECLARE_READ8_MEMBER(panther_interrupt_clear_r);
DECLARE_READ8_MEMBER(panther_unk_r);
DECLARE_WRITE8_MEMBER(redalert_bitmap_videoram_w);
DECLARE_WRITE8_MEMBER(redalert_audio_command_w);
DECLARE_READ8_MEMBER(redalert_ay8910_latch_1_r);
DECLARE_WRITE8_MEMBER(redalert_ay8910_latch_2_w);
DECLARE_WRITE8_MEMBER(redalert_voice_command_w);
DECLARE_WRITE8_MEMBER(demoneye_audio_command_w);
uint8_t redalert_interrupt_clear_r();
void redalert_interrupt_clear_w(uint8_t data);
uint8_t panther_interrupt_clear_r();
uint8_t panther_unk_r();
void redalert_bitmap_videoram_w(offs_t offset, uint8_t data);
void redalert_audio_command_w(uint8_t data);
uint8_t redalert_ay8910_latch_1_r();
void redalert_ay8910_latch_2_w(uint8_t data);
void redalert_voice_command_w(uint8_t data);
void demoneye_audio_command_w(uint8_t data);
DECLARE_VIDEO_START(redalert);
DECLARE_VIDEO_START(ww3);
uint32_t screen_update_redalert(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint32_t screen_update_demoneye(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint32_t screen_update_panther(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(redalert_vblank_interrupt);
DECLARE_WRITE8_MEMBER(redalert_analog_w);
DECLARE_WRITE8_MEMBER(redalert_AY8910_w);
TIMER_CALLBACK_MEMBER(audio_irq_on);
TIMER_CALLBACK_MEMBER(audio_irq_off);
void redalert_analog_w(uint8_t data);
void redalert_AY8910_w(uint8_t data);
DECLARE_WRITE_LINE_MEMBER(sod_callback);
DECLARE_READ_LINE_MEMBER(sid_callback);
DECLARE_WRITE8_MEMBER(demoneye_ay8910_latch_1_w);
DECLARE_READ8_MEMBER(demoneye_ay8910_latch_2_r);
DECLARE_WRITE8_MEMBER(demoneye_ay8910_data_w);
void demoneye_ay8910_latch_1_w(uint8_t data);
uint8_t demoneye_ay8910_latch_2_r();
void demoneye_ay8910_data_w(uint8_t data);
void get_pens(pen_t *pens);
void get_panther_pens(pen_t *pens);
@ -116,6 +121,9 @@ private:
void redalert_voice_map(address_map &map);
emu_timer *m_audio_irq_on_timer;
emu_timer *m_audio_irq_off_timer;
uint8_t m_ay8910_latch_1;
uint8_t m_ay8910_latch_2;
};

View File

@ -24,7 +24,7 @@
*
*************************************/
WRITE8_MEMBER(redalert_state::redalert_bitmap_videoram_w)
void redalert_state::redalert_bitmap_videoram_w(offs_t offset, uint8_t data)
{
m_bitmap_videoram[offset ] = data;
m_bitmap_colorram[offset >> 3] = *m_bitmap_color & 0x07;