Merge pull request #1923 from ajrhacker/efo_zsu

Cedar Magnet/EFO ZSU
This commit is contained in:
R. Belmont 2017-01-04 21:16:49 -05:00 committed by GitHub
commit d58d1fa0ec
12 changed files with 476 additions and 352 deletions

View File

@ -851,6 +851,8 @@ files {
MAME_DIR .. "src/mame/audio/dcs.h",
MAME_DIR .. "src/mame/audio/decobsmt.cpp",
MAME_DIR .. "src/mame/audio/decobsmt.h",
MAME_DIR .. "src/mame/audio/efo_zsu.cpp",
MAME_DIR .. "src/mame/audio/efo_zsu.h",
MAME_DIR .. "src/mame/audio/segam1audio.cpp",
MAME_DIR .. "src/mame/audio/segam1audio.h",
}
@ -4351,7 +4353,6 @@ files {
MAME_DIR .. "src/mame/machine/cdicdic.cpp",
MAME_DIR .. "src/mame/machine/cdicdic.h",
MAME_DIR .. "src/mame/drivers/cedar_magnet.cpp",
MAME_DIR .. "src/mame/machine/cedar_magnet_sound.cpp",
MAME_DIR .. "src/mame/machine/cedar_magnet_plane.cpp",
MAME_DIR .. "src/mame/machine/cedar_magnet_sprite.cpp",
MAME_DIR .. "src/mame/machine/cedar_magnet_board.cpp",

275
src/mame/audio/efo_zsu.cpp Normal file
View File

@ -0,0 +1,275 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood,AJR
/***************************************************************************
ZSU Sound Control Unit (Proyectado 21/4/86 J. Gamell)
ZSU1 Sound Control Unit (Proyectado 12/6/86 J. Gamell)
Cedar Magnet Sound Board
The ZSU board is a component of the Z-Pinball hardware developed by
E.F.O. (Electrónica Funcional Operativa) S.A. of Barcelona, Spain. Its
sound generators are 2 AY-3-8910As and 1 OKI MSM5205, and 2 MF10s and
1 HC4066 are used to mix their outputs. The timing circuits are rather
intricate, using Z80-CTCs, HC74s and HC393s and various other gates to
drive both the 5205 and the SGS HCF40105BE through which its samples
are funneled.
There are no available schematics for the Cedar Magnet video game
system (also designed by E.F.O.), but its sound board is believed to be
a close analogue of ZSU, since it includes all of the aforementioned
devices. The main known difference is that the Cedar Magnet sound
code and data are externally loaded into 64K of RAM (2xTMM41464P-15),
whereas ZSU's memory map consists primarily of a bank of up to 5 27256
EPROMs switched from two output lines of the first 8910, overlaid with
a mere 2K of RAM.
irq vectors
0xe6 - from ctc0 channel 3 (vector = E0) used to drive MSM5205 through FIFO
0xee - from ctc0 channel 3 (vector = E8) ^^
0xf6 - drive AY (once per frame?) triggered by ctc1 channel 3 (vector = F0)
0xff - read sound latch (triggered by write from master board; default vector set by 5K/+5 pullups on D0-D7)
***************************************************************************/
#include "emu.h"
#include "audio/efo_zsu.h"
#include "machine/clock.h"
#include "machine/input_merger.h"
extern const device_type EFO_ZSU = &device_creator<efo_zsu_device>;
extern const device_type EFO_ZSU1 = &device_creator<efo_zsu1_device>;
extern const device_type CEDAR_MAGNET_SOUND = &device_creator<cedar_magnet_sound_device>;
efo_zsu_device::efo_zsu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
m_ctc0(*this, "ctc0"),
m_ctc1(*this, "ctc1"),
m_soundlatch(*this, "soundlatch"),
m_fifo(*this, "fifo"),
m_adpcm(*this, "adpcm")
{
}
efo_zsu_device::efo_zsu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: efo_zsu_device(mconfig, EFO_ZSU, "ZSU Sound Control Unit", tag, owner, clock, "efo_zsu", __FILE__)
{
}
efo_zsu1_device::efo_zsu1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: efo_zsu_device(mconfig, EFO_ZSU1, "ZSU1 Sound Control Unit", tag, owner, clock, "efo_zsu1", __FILE__)
{
}
cedar_magnet_sound_device::cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: efo_zsu_device(mconfig, CEDAR_MAGNET_SOUND, "Cedar Sound", tag, owner, clock, "cedmag_sound", __FILE__),
cedar_magnet_board_interface(mconfig, *this, "soundcpu", "ram")
{
}
WRITE8_MEMBER(efo_zsu_device::sound_command_w)
{
m_soundlatch->write(space, 0, data);
}
static ADDRESS_MAP_START( zsu_map, AS_PROGRAM, 8, efo_zsu_device )
AM_RANGE(0x0000, 0x6fff) AM_ROM
AM_RANGE(0x7000, 0x77ff) AM_MIRROR(0x0800) AM_RAM
AM_RANGE(0x8000, 0xffff) AM_ROMBANK("rombank")
ADDRESS_MAP_END
static ADDRESS_MAP_START( cedar_magnet_sound_map, AS_PROGRAM, 8, cedar_magnet_sound_device )
AM_RANGE(0x0000, 0xffff) AM_RAM AM_SHARE("ram")
ADDRESS_MAP_END
static ADDRESS_MAP_START( zsu_io, AS_IO, 8, efo_zsu_device )
ADDRESS_MAP_GLOBAL_MASK(0xff)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("ctc0", z80ctc_device, read, write)
AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("ctc1", z80ctc_device, read, write)
AM_RANGE(0x08, 0x08) AM_WRITE(adpcm_fifo_w)
AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("aysnd0", ay8910_device, address_w)
AM_RANGE(0x0d, 0x0d) AM_DEVWRITE("aysnd0", ay8910_device, data_w)
AM_RANGE(0x10, 0x10) AM_DEVWRITE("aysnd1", ay8910_device, address_w)
AM_RANGE(0x11, 0x11) AM_DEVWRITE("aysnd1", ay8910_device, data_w)
AM_RANGE(0x14, 0x14) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
ADDRESS_MAP_END
WRITE8_MEMBER(efo_zsu_device::adpcm_fifo_w)
{
// Z80 code first unpacks 8 bytes of ADPCM sample data into nibbles
// and, upon receiving interrupt vector E6, fills FIFO at once using OTIR
// 4-bit data is shifted out of the FIFO to the MSM5205 by another timer
m_fifo->write(data & 0x0f); // only low nibble is used here
m_fifo->si_w(1);
m_fifo->si_w(0);
}
WRITE8_MEMBER(cedar_magnet_sound_device::ay0_porta_w)
{
// unknown (not in ZSU schematic); 0x80 written on reset
}
WRITE8_MEMBER(efo_zsu_device::ay1_porta_w)
{
m_adpcm->reset_w(data & 1);
if (data & 1)
m_fifo->reset();
// D4-D6 likely used to select clock for ctc0 channel 2
// other bits probably used to modulate analog sound output
}
WRITE_LINE_MEMBER(efo_zsu_device::ctc0_z0_w)
{
// printf("USED ctc0_z0_w %d\n", state);
}
WRITE_LINE_MEMBER(efo_zsu_device::ctc0_z1_w)
{
// printf("USED ctc0_z1_w %d\n", state);
}
WRITE_LINE_MEMBER(efo_zsu_device::ctc1_z0_w)
{
printf("ctc1_z0_w %d\n", state);
}
WRITE_LINE_MEMBER(efo_zsu_device::ctc1_z1_w)
{
printf("ctc1_z1_w %d\n", state);
}
WRITE_LINE_MEMBER(efo_zsu_device::ctc1_z2_w)
{
printf("ctc1_z2_w %d\n", state);
}
WRITE_LINE_MEMBER(efo_zsu_device::ctc0_z2_w)
{
printf("ctc0_z2_w %d\n", state);
}
WRITE_LINE_MEMBER(efo_zsu_device::fifo_dor_w)
{
// combined with a clock signal and used to drive ctc0 channel 3
}
static const z80_daisy_config daisy_chain[] =
{
{ "ctc1" },
{ "ctc0" },
{ nullptr }
};
TIMER_CALLBACK_MEMBER(cedar_magnet_sound_device::reset_assert_callback)
{
cedar_magnet_board_interface::reset_assert_callback(ptr,param);
// reset lines go to the ctc as well?
m_ctc0->reset();
m_ctc1->reset();
}
static MACHINE_CONFIG_FRAGMENT( efo_zsu )
MCFG_CPU_ADD("soundcpu", Z80, 4000000)
MCFG_CPU_PROGRAM_MAP(zsu_map)
MCFG_CPU_IO_MAP(zsu_io)
MCFG_Z80_DAISY_CHAIN(daisy_chain)
MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000)
MCFG_Z80CTC_INTR_CB(DEVWRITELINE("soundirq", input_merger_device, in0_w))
MCFG_Z80CTC_ZC0_CB(WRITELINE(efo_zsu_device, ctc0_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(efo_zsu_device, ctc0_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(efo_zsu_device, ctc0_z2_w))
MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000)
MCFG_Z80CTC_INTR_CB(DEVWRITELINE("soundirq", input_merger_device, in0_w))
MCFG_Z80CTC_ZC0_CB(WRITELINE(efo_zsu_device, ctc1_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(efo_zsu_device, ctc1_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(efo_zsu_device, ctc1_z2_w))
#if 0 // does nothing useful now
MCFG_DEVICE_ADD("ck1mhz", CLOCK, 4000000/4)
MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("ctc1", z80ctc_device, trg0))
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg1))
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg2))
#endif
MCFG_GENERIC_LATCH_8_ADD("soundlatch")
MCFG_GENERIC_LATCH_DATA_PENDING_CB(DEVWRITELINE("soundirq", input_merger_device, in1_w))
MCFG_INPUT_MERGER_ACTIVE_HIGH("soundirq") // 74HC03 NAND gate
MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("soundcpu", INPUT_LINE_IRQ0))
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2)
MCFG_AY8910_PORT_A_WRITE_CB(MEMBANK("rombank")) MCFG_DEVCB_MASK(0x03)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
MCFG_SOUND_ADD("aysnd1", AY8910, 4000000/2)
MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(efo_zsu_device, ay1_porta_w))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
MCFG_DEVICE_ADD("fifo", HC40105, 0)
MCFG_40105_DATA_OUT_READY_CB(WRITELINE(efo_zsu_device, fifo_dor_w))
MCFG_40105_DATA_OUT_CB(DEVWRITELINE("adpcm", msm5205_device, data_w))
MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/8)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MACHINE_CONFIG_END
static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
MCFG_FRAGMENT_ADD(efo_zsu)
MCFG_CPU_MODIFY("soundcpu")
MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map)
MCFG_SOUND_MODIFY("aysnd0")
MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay0_porta_w))
MACHINE_CONFIG_END
machine_config_constructor efo_zsu_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( efo_zsu );
}
machine_config_constructor cedar_magnet_sound_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( cedar_magnet_sound );
}
void efo_zsu_device::device_start()
{
memory_bank *rombank = membank("rombank");
rombank->configure_entries(0, 4, &static_cast<u8 *>(memregion("soundcpu")->base())[0x8000], 0x8000);
rombank->set_entry(0); // 10K/GND pulldowns on banking lines
}
void efo_zsu1_device::device_start()
{
memory_bank *rombank = membank("rombank");
rombank->configure_entries(0, 4, &static_cast<u8 *>(memregion("soundcpu")->base())[0x8000], 0x8000);
rombank->set_entry(3); // 10K/+5 pullups on banking lines
}
void cedar_magnet_sound_device::device_start()
{
}

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
// copyright-holders:David Haywood,AJR
#pragma once
@ -9,36 +9,37 @@
#include "cpu/z80/z80.h"
#include "cpu/z80/z80daisy.h"
#include "machine/z80ctc.h"
#include "machine/gen_latch.h"
#include "machine/40105.h"
#include "sound/ay8910.h"
#include "sound/msm5205.h"
#include "machine/cedar_magnet_board.h"
extern const device_type EFO_ZSU;
extern const device_type EFO_ZSU1;
extern const device_type CEDAR_MAGNET_SOUND;
#define MCFG_CEDAR_MAGNET_SOUND_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_SOUND, 0)
class cedar_magnet_sound_device : public cedar_magnet_board_device
class efo_zsu_device : public device_t
{
public:
// construction/destruction
cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
efo_zsu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source);
efo_zsu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
required_device<z80ctc_device> m_ctc0;
required_device<z80ctc_device> m_ctc1;
required_device<generic_latch_8_device> m_soundlatch;
required_device<cmos_40105_device> m_fifo;
required_device<msm5205_device> m_adpcm;
DECLARE_READ8_MEMBER(soundlatch_r);
DECLARE_WRITE8_MEMBER(sound_command_w);
DECLARE_WRITE8_MEMBER(adpcm_fifo_w);
DECLARE_WRITE8_MEMBER(ay0_porta_w);
DECLARE_WRITE8_MEMBER(ay1_porta_w);
void write_command(uint8_t data);
uint8_t m_command;
DECLARE_WRITE_LINE_MEMBER(ctc1_z0_w);
DECLARE_WRITE_LINE_MEMBER(ctc1_z1_w);
DECLARE_WRITE_LINE_MEMBER(ctc1_z2_w);
@ -47,12 +48,38 @@ public:
DECLARE_WRITE_LINE_MEMBER(ctc0_z2_w);
DECLARE_WRITE_LINE_MEMBER(fifo_dor_w);
protected:
virtual machine_config_constructor device_mconfig_additions() const override;
virtual void device_start() override;
private:
};
class efo_zsu1_device : public efo_zsu_device
{
public:
// construction/destruction
efo_zsu1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
virtual void device_start() override;
};
class cedar_magnet_sound_device : public efo_zsu_device, public cedar_magnet_board_interface
{
public:
// construction/destruction
cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
DECLARE_WRITE8_MEMBER(ay0_porta_w);
TIMER_CALLBACK_MEMBER(reset_assert_callback) override;
protected:
virtual machine_config_constructor device_mconfig_additions() const override;
virtual void device_start() override;
virtual void device_reset() override;
private:
};

View File

@ -110,7 +110,7 @@ I suspect the additional memory was an afterthought.
#include "machine/z80ctc.h"
#include "sound/ay8910.h"
#include "machine/cedar_magnet_sound.h"
#include "audio/efo_zsu.h"
#include "machine/cedar_magnet_plane.h"
#include "machine/cedar_magnet_sprite.h"
#include "machine/cedar_magnet_flop.h"
@ -185,8 +185,6 @@ public:
DECLARE_READ8_MEMBER(port7c_r);
// other ports
DECLARE_WRITE8_MEMBER(soundlatch_w);
uint8_t portff_data;
DECLARE_READ8_MEMBER(other_cpu_r);
DECLARE_WRITE8_MEMBER(other_cpu_w);
@ -203,7 +201,7 @@ public:
DECLARE_WRITE8_MEMBER(palette_g_w);
DECLARE_WRITE8_MEMBER(palette_b_w);
void handle_sub_board_cpu_lines(cedar_magnet_board_device* dev, int old_data, int data);
void handle_sub_board_cpu_lines(cedar_magnet_board_interface &dev, int old_data, int data);
INTERRUPT_GEN_MEMBER(irq);
void(*m_prothack)(cedar_magnet_state*);
@ -271,7 +269,7 @@ static ADDRESS_MAP_START( cedar_magnet_io, AS_IO, 8, cedar_magnet_state )
AM_RANGE(0x78, 0x78) AM_READWRITE(watchdog_r, paladdr_w)
AM_RANGE(0x7c, 0x7c) AM_READ(port7c_r) // protection??
AM_RANGE(0xff, 0xff) AM_WRITE(soundlatch_w)
AM_RANGE(0xff, 0xff) AM_DEVWRITE("cedtop", cedar_magnet_sound_device, sound_command_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( cedar_bank0, AS_PROGRAM, 8, cedar_magnet_state )
@ -441,13 +439,6 @@ void cedar_magnet_state::video_start()
***********************/
WRITE8_MEMBER(cedar_magnet_state::soundlatch_w)
{
// printf("%s: writing soundlatch_w! %02x\n", machine().describe_context(), data);
portff_data = data;
m_cedsound->write_command(data);
}
READ8_MEMBER(cedar_magnet_state::other_cpu_r)
{
int bankbit0 = (m_ic48_pio_pa_val & 0x60) >> 5;
@ -544,19 +535,19 @@ WRITE8_MEMBER(cedar_magnet_state::other_cpu_w)
}
void cedar_magnet_state::handle_sub_board_cpu_lines(cedar_magnet_board_device* dev, int old_data, int data)
void cedar_magnet_state::handle_sub_board_cpu_lines(cedar_magnet_board_interface &dev, int old_data, int data)
{
if (old_data != data)
{
if (data & 0x04)
dev->reset_assert();
dev.reset_assert();
else
dev->reset_clear();
dev.reset_clear();
if (data & 0x02)
dev->halt_clear();
dev.halt_clear();
else
dev->halt_assert();
dev.halt_assert();
}
}
@ -605,7 +596,7 @@ WRITE8_MEMBER( cedar_magnet_state::ic48_pio_pa_w ) // 0x20
int plane0select = (m_ic48_pio_pa_val & 0x07) >> 0;
handle_sub_board_cpu_lines(m_cedplane0, oldplane0select, plane0select);
handle_sub_board_cpu_lines(*m_cedplane0, oldplane0select, plane0select);
}
@ -644,8 +635,8 @@ WRITE8_MEMBER(cedar_magnet_state::ic48_pio_pb_w) // 0x22
int plane1select = (m_ic48_pio_pb_val & 0x07) >> 0;
int spriteselect = (m_ic48_pio_pb_val & 0x70) >> 4;
handle_sub_board_cpu_lines(m_cedplane1, oldplane1select, plane1select);
handle_sub_board_cpu_lines(m_cedsprite, oldspriteselect, spriteselect);
handle_sub_board_cpu_lines(*m_cedplane1, oldplane1select, plane1select);
handle_sub_board_cpu_lines(*m_cedsprite, oldspriteselect, spriteselect);
}
/***********************
@ -688,7 +679,7 @@ WRITE8_MEMBER( cedar_magnet_state::ic49_pio_pb_w ) // 0x42
int soundselect = (m_ic49_pio_pb_val & 0x70) >> 4;
handle_sub_board_cpu_lines(m_cedsound, oldsoundselect, soundselect);
handle_sub_board_cpu_lines(*m_cedsound, oldsoundselect, soundselect);
}
/***********************
@ -705,7 +696,6 @@ void cedar_magnet_state::machine_start()
void cedar_magnet_state::machine_reset()
{
m_ic48_pio_pa_val = 0xff;
portff_data = 0x00;
int bankbit0 = (m_ic48_pio_pa_val & 0x60) >> 5;
m_bank0->set_bank(bankbit0);
@ -752,7 +742,9 @@ INTERRUPT_GEN_MEMBER(cedar_magnet_state::irq)
m_prothack(this);
m_maincpu->set_input_line(0, HOLD_LINE);
// maybe generate the irqs for the other PCBs here?
m_cedplane0->irq_hold();
m_cedplane1->irq_hold();
m_cedsprite->irq_hold();
}
static MACHINE_CONFIG_START( cedar_magnet, cedar_magnet_state )

View File

@ -11,16 +11,13 @@ Status:
- Lots of loud siren-like noises when there should be silence
- Mechanical sounds to add
- Most games work
-- Spain82: not working (no manual available)
-- Spain82: not working (no manual available; uses same sound board as Cerberus)
-- Nautilus: sound is broken (runs into the weeds)
-- Skill Flight: not working
-- Skill Flight, Phantom Ship: not working
-- Eight Ball Champ, Cobra: not working (different hardware)
-- Miss Disco: not working (no manual available)
-- Phantom Ship: no sound (no manual available)
-- Meg Aaton: Ball number doesn't show
It looks like Skill Flight and Phantom Ship use a new sound card that contains
Z80A, 5205, 2x AY-3-8910, 2x Z80CTC, 2x MF10.
Note: The input lines INT, EF1-4 are inverted (not true voltage).
First time:
@ -51,6 +48,7 @@ The manual is not that clear, there's a lot we don't know, this *seems* to work.
#include "machine/clock.h"
#include "machine/7474.h"
#include "sound/ay8910.h"
#include "audio/efo_zsu.h"
#include "play_3.lh"
@ -65,6 +63,7 @@ public:
, m_4013b(*this, "4013b")
, m_aysnd1(*this, "aysnd1")
, m_aysnd2(*this, "aysnd2")
, m_zsu(*this, "zsu")
, m_keyboard(*this, "X.%u", 0)
{ }
@ -72,6 +71,7 @@ public:
DECLARE_WRITE8_MEMBER(megaaton_port01_w);
DECLARE_WRITE8_MEMBER(port02_w);
DECLARE_WRITE8_MEMBER(port03_w);
DECLARE_WRITE8_MEMBER(sklflite_port03_w);
DECLARE_READ8_MEMBER(port04_r);
DECLARE_READ8_MEMBER(port05_r);
DECLARE_WRITE8_MEMBER(port06_w);
@ -87,22 +87,24 @@ public:
DECLARE_READ_LINE_MEMBER(clear_a_r);
private:
uint16_t m_clockcnt;
uint16_t m_resetcnt;
uint16_t m_resetcnt_a;
uint8_t m_soundlatch;
uint8_t m_a_irqset;
uint16_t m_a_irqcnt;
uint8_t m_kbdrow;
uint8_t m_segment[5];
u16 m_clockcnt;
u16 m_resetcnt;
u16 m_resetcnt_a;
u8 m_soundlatch;
u8 m_port03_old;
u8 m_a_irqset;
u16 m_a_irqcnt;
u8 m_kbdrow;
u8 m_segment[5];
bool m_disp_sw;
virtual void machine_reset() override;
required_device<cosmac_device> m_maincpu;
required_device<cosmac_device> m_audiocpu;
optional_device<cosmac_device> m_audiocpu;
required_device<ttl7474_device> m_4013a;
required_device<ttl7474_device> m_4013b;
required_device<ay8910_device> m_aysnd1;
required_device<ay8910_device> m_aysnd2;
optional_device<ay8910_device> m_aysnd1;
optional_device<ay8910_device> m_aysnd2;
optional_device<efo_zsu_device> m_zsu;
required_ioport_array<10> m_keyboard;
};
@ -124,12 +126,12 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( megaaton_io, AS_IO, 8, play_3_state )
AM_RANGE(0x01, 0x01) AM_WRITE(megaaton_port01_w) // digits, scan-lines
AM_RANGE(0x02, 0x02) AM_WRITE(port02_w) // sound code
AM_RANGE(0x03, 0x03) AM_WRITE(port03_w) //
AM_RANGE(0x04, 0x04) AM_READ(port04_r) // switches
AM_RANGE(0x05, 0x05) AM_READ(port05_r) // more switches
AM_RANGE(0x06, 0x06) AM_WRITE(port06_w) // segments
AM_RANGE(0x07, 0x07) AM_WRITE(port07_w) // flipflop clear
AM_IMPORT_FROM(play_3_io)
ADDRESS_MAP_END
static ADDRESS_MAP_START( sklflite_io, AS_IO, 8, play_3_state )
AM_RANGE(0x03, 0x03) AM_WRITE(sklflite_port03_w) //
AM_IMPORT_FROM(play_3_io)
ADDRESS_MAP_END
static ADDRESS_MAP_START( play_3_audio_map, AS_PROGRAM, 8, play_3_state )
@ -258,6 +260,7 @@ void play_3_state::machine_reset()
m_disp_sw = 0;
for (uint8_t i = 0; i < 5; i++)
m_segment[i] = 0;
m_port03_old = 0;
}
WRITE8_MEMBER( play_3_state::port01_w )
@ -320,6 +323,21 @@ WRITE8_MEMBER( play_3_state::port03_w )
}
WRITE8_MEMBER( play_3_state::sklflite_port03_w )
{
if (BIT(data, 6) && !BIT(m_port03_old, 6))
m_zsu->sound_command_w(space, 0, m_soundlatch);
if (BIT(data, 5))
{
if (m_soundlatch == 11)
m_samples->start(0, 5); // outhole
//if (m_soundlatch == 13)
//m_samples->start(0, 6); // no knocker?
}
m_port03_old = data;
}
READ8_MEMBER( play_3_state::port04_r )
{
if (m_kbdrow & 0x3f)
@ -405,15 +423,18 @@ WRITE_LINE_MEMBER( play_3_state::clock_w )
if ((m_clockcnt & 0x3ff) == 0)
m_4013b->preset_w(BIT(m_clockcnt, 10)); // Q10 output
// sound irq
m_a_irqcnt--;
if (m_a_irqcnt == 1)
m_audiocpu->int_w(1); // inverted
else
if (m_a_irqcnt == 0)
if (m_audiocpu.found())
{
m_a_irqcnt = (m_a_irqset << 3) | 7;
m_audiocpu->int_w(0); // inverted
// sound irq
m_a_irqcnt--;
if (m_a_irqcnt == 1)
m_audiocpu->int_w(1); // inverted
else
if (m_a_irqcnt == 0)
{
m_a_irqcnt = (m_a_irqset << 3) | 7;
m_audiocpu->int_w(0); // inverted
}
}
}
}
@ -482,6 +503,19 @@ static MACHINE_CONFIG_DERIVED( megaaton, play_3 )
MCFG_CPU_IO_MAP(megaaton_io)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sklflite, play_3 )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_IO_MAP(sklflite_io)
MCFG_DEVICE_REMOVE("audiocpu")
MCFG_DEVICE_REMOVE("aysnd1")
MCFG_DEVICE_REMOVE("aysnd2")
MCFG_DEVICE_REMOVE("lspeaker")
MCFG_DEVICE_REMOVE("rspeaker")
MCFG_DEVICE_ADD("zsu", EFO_ZSU1, 0)
MACHINE_CONFIG_END
/*-------------------------------------------------------------------
/ Spain 82 (10/82)
@ -642,7 +676,7 @@ ROM_START(sklflite)
ROM_LOAD("skflcpu1.rom", 0x0000, 0x2000, CRC(8f833b55) SHA1(1729203582c22b51d1cc401aa8f270aa5cdadabe))
ROM_LOAD("skflaudiocpu.rom", 0x2000, 0x2000, CRC(ffc497aa) SHA1(3e88539ae1688322b9268f502d8ca41cffb28df3))
ROM_REGION(0x20000, "audiocpu", 0) // Z80A soundcard
ROM_REGION(0x28000, "zsu:soundcpu", 0) // Z80A soundcard
ROM_LOAD("skflsnd.rom", 0x0000, 0x8000, CRC(926a1da9) SHA1(16c762fbfe6a55597f26ff55d380192bb8647ee0))
ROM_END
@ -654,7 +688,7 @@ ROM_START(phntmshp)
ROM_LOAD("video1.bin", 0x0000, 0x2000, CRC(2b61a8d2) SHA1(1b5cabbab252b2ffb6ed12fb7e4181de7695ed9a))
ROM_LOAD("video2.bin", 0x2000, 0x2000, CRC(50126db1) SHA1(58d89e44131554cb087c4cad62869f90366704ad))
ROM_REGION(0x20000, "audiocpu", 0) // Z80A soundcard
ROM_REGION(0x28000, "zsu:soundcpu", 0) // Z80A soundcard
ROM_LOAD("sonido1.bin", 0x00000, 0x8000, CRC(3294611d) SHA1(5f790b41bcb6d87418c80e61ac8ae69c57864b1d))
ROM_LOAD("sonido2.bin", 0x08000, 0x8000, CRC(c2efc826) SHA1(44ee144b902627745853011968e0d654b35b3b08))
ROM_LOAD("sonido3.bin", 0x10000, 0x8000, CRC(13d50f39) SHA1(70624de2dd8412c83866183a83f16cc5b8bdccb8))
@ -699,7 +733,7 @@ ROM_START(eballchps)
ROM_REGION(0x8000, "maincpu", 0) // Z80-based
ROM_LOAD("U18-JEB 5A0 - CPU.BIN", 0x0000, 0x8000, CRC(87615a7d) SHA1(b27ca2d863040a2641f88f9bd3143467a83f181b))
ROM_REGION(0x20000, "audiocpu", 0) // Z80-based
ROM_REGION(0x28000, "zsu:soundcpu", 0) // Z80-based
ROM_LOAD("U3-EBE A02 - Sonido.BIN", 0x00000, 0x8000, CRC(34be32ee) SHA1(ce0271540164639f28d617753760ecc479b6b0d0))
ROM_LOAD("U4-EBE B01 - Sonido.BIN", 0x08000, 0x8000, CRC(d696c4e8) SHA1(501e18c258e6d42819d25d72e1907984a6cfeecb))
ROM_LOAD("U5-EBE C01 - Sonido.BIN", 0x10000, 0x8000, CRC(fe78d7ef) SHA1(ed91c51dd230854a007f88446011f786759687ca))
@ -711,12 +745,25 @@ ROM_START(cobrapb)
ROM_REGION(0x8000, "maincpu", 0) // Z80-based
ROM_LOAD("U18 - JCB 4 A0 - CPU.BIN", 0x0000, 0x8000, CRC(c663910e) SHA1(c38692343f114388259c4e7b7943e5be934189ca))
ROM_REGION(0x20000, "audiocpu", 0) // Z80-based
ROM_REGION(0x28000, "zsu:soundcpu", 0) // Z80-based
ROM_LOAD("U3 - SCB 1 A0 - Sonido.BIN", 0x00000, 0x8000, CRC(d3675770) SHA1(882ce748308f2d78cccd28fc8cd64fe69bd223e3))
ROM_LOAD("U4 - SCB 1 B0 - Sonido.BIN", 0x08000, 0x8000, CRC(e8e1bdbb) SHA1(215bdfab751cb0ea47aa529df0ac30976de4f772))
ROM_LOAD("U5 - SCB 1 C0 - Sonido.BIN", 0x10000, 0x8000, CRC(c36340ab) SHA1(cd662457959de3a929ba02779e2046ed18b797e2))
ROM_END
#ifdef UNUSED_DEFINITION
// Come Back (Nondum)
ROM_START(comeback)
ROM_REGION(0x8000, "maincpu", 0)
ROM_LOAD("JCO_6a0.u18", 0x0000, 0x8000, NO_DUMP)
ROM_REGION(0x28000, "zsu:soundcpu", 0)
ROM_LOAD("CBS_3a0.u3", 0x00000, 0x8000, NO_DUMP)
ROM_LOAD("CBS_3b0.u4", 0x08000, 0x8000, NO_DUMP)
ROM_LOAD("CBS_1c0.u5", 0x10000, 0x8000, NO_DUMP)
ROM_END
#endif
GAME(1982, spain82, 0, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Spain '82", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
GAME(1983, megaaton, 0, megaaton, megaaton, driver_device, 0, ROT0, "Playmatic", "Meg-Aaton", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
GAME(1983, megaatona, megaaton, megaaton, megaaton, driver_device, 0, ROT0, "Playmatic", "Meg-Aaton (alternate set)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
@ -730,13 +777,14 @@ GAME(1985, starfirpa, starfirp, play_3, play_3, driver_device, 0, ROT0, "Pl
GAME(1985, trailer, 0, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Trailer", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
GAME(1986, fldragon, 0, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Flash Dragon", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
GAME(1986, fldragona, fldragon, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Flash Dragon (alternate set)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
GAME(1987, phntmshp, 0, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Phantom Ship", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
GAME(1987, sklflite, 0, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Skill Flight (Playmatic)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
GAME(1987, phntmshp, 0, sklflite, play_3, driver_device, 0, ROT0, "Playmatic", "Phantom Ship", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
GAME(1987, sklflite, 0, sklflite, play_3, driver_device, 0, ROT0, "Playmatic", "Skill Flight (Playmatic)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
// not by Playmatic, but same hardware
GAME(1986, ridersrf, 0, play_3, play_3, driver_device, 0, ROT0, "JocMatic", "Rider's Surf", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
GAME(1987, ironball, 0, play_3, play_3, driver_device, 0, ROT0, "Stargame", "Iron Balls", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND)
// "Z-Pinball" hardware, Z80 main and sound CPUs - to be split (?)
GAME(1986, eballchps, eballchp, play_3, play_3, driver_device, 0, ROT0, "Bally (Maibesa license)", "Eight Ball Champ (Spain, Z-Pinball hardware)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
GAME(1987, cobrapb, 0, play_3, play_3, driver_device, 0, ROT0, "Playbar", "Cobra (Playbar)", MACHINE_MECHANICAL | MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
GAME(1986, eballchps, eballchp, sklflite, play_3, driver_device, 0, ROT0, "Bally (Maibesa license)", "Eight Ball Champ (Spain, Z-Pinball hardware)", MACHINE_IS_SKELETON_MECHANICAL)
GAME(1987, cobrapb, 0, sklflite, play_3, driver_device, 0, ROT0, "Playbar", "Cobra (Playbar)", MACHINE_IS_SKELETON_MECHANICAL)
//GAME(198?, comeback, 0, sklflite, play_3, driver_device, 0, ROT0, "Nondum", "Come Back", MACHINE_IS_SKELETON_MECHANICAL) // undumped
// bingo hardware, to be split (?)
GAME(1983, msdisco, 0, play_3, play_3, driver_device, 0, ROT0, "Playmatic", "Miss Disco (Bingo)", MACHINE_IS_SKELETON_MECHANICAL)

View File

@ -1,90 +1,81 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
#include "emu.h"
#include "cedar_magnet_plane.h"
#include "cedar_magnet_board.h"
//const device_type CEDAR_MAGNET_BASE = &device_creator<cedar_magnet_board_device>;
cedar_magnet_board_device::cedar_magnet_board_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
// m_ram(*this, "ram")
cedar_magnet_board_interface::cedar_magnet_board_interface(const machine_config &mconfig, device_t &device, const char *cputag, const char *ramtag)
: device_interface(device, "cedmag_board"),
m_cpu(device, cputag),
m_ram(device, ramtag)
{
}
INTERRUPT_GEN_MEMBER(cedar_magnet_board_device::irq)
void cedar_magnet_board_interface::write_cpu_bus(int offset, u8 data)
{
m_cpu->set_input_line(0, HOLD_LINE);
}
void cedar_magnet_board_device::device_start()
{
}
void cedar_magnet_board_device::write_cpu_bus(int offset, uint8_t data)
{
device_t* cpu = m_cpu;
address_space& ap = cpu->memory().space(AS_PROGRAM);
address_space &ap = m_cpu->space(AS_PROGRAM);
ap.write_byte(offset, data);
}
uint8_t cedar_magnet_board_device::read_cpu_bus(int offset)
uint8_t cedar_magnet_board_interface::read_cpu_bus(int offset)
{
device_t* cpu = m_cpu;
address_space& ap = cpu->memory().space(AS_PROGRAM);
address_space &ap = m_cpu->space(AS_PROGRAM);
return ap.read_byte(offset);
}
bool cedar_magnet_board_device::is_running(void)
bool cedar_magnet_board_interface::is_running() const
{
return m_is_running;
}
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::reset_assert_callback)
TIMER_CALLBACK_MEMBER(cedar_magnet_board_interface::reset_assert_callback)
{
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
}
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::reset_clear_callback)
TIMER_CALLBACK_MEMBER(cedar_magnet_board_interface::reset_clear_callback)
{
m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
}
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::halt_assert_callback)
TIMER_CALLBACK_MEMBER(cedar_magnet_board_interface::halt_assert_callback)
{
m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
m_is_running = false;
}
TIMER_CALLBACK_MEMBER(cedar_magnet_board_device::halt_clear_callback)
TIMER_CALLBACK_MEMBER(cedar_magnet_board_interface::halt_clear_callback)
{
m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
m_is_running = true;
}
void cedar_magnet_board_device::halt_assert(void)
void cedar_magnet_board_interface::irq_hold()
{
machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(cedar_magnet_board_device::halt_assert_callback),this));
m_cpu->set_input_line(INPUT_LINE_IRQ0, HOLD_LINE);
}
void cedar_magnet_board_device::halt_clear(void)
void cedar_magnet_board_interface::halt_assert()
{
machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(cedar_magnet_board_device::halt_clear_callback),this));
device().machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(cedar_magnet_board_interface::halt_assert_callback),this));
}
void cedar_magnet_board_device::reset_assert(void)
void cedar_magnet_board_interface::halt_clear()
{
machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(cedar_magnet_board_device::reset_assert_callback),this));
device().machine().scheduler().timer_set(attotime::from_usec(2), timer_expired_delegate(FUNC(cedar_magnet_board_interface::halt_clear_callback),this));
}
void cedar_magnet_board_device::reset_clear(void)
void cedar_magnet_board_interface::reset_assert()
{
machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(cedar_magnet_board_device::reset_clear_callback),this));
device().machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(cedar_magnet_board_interface::reset_assert_callback),this));
}
void cedar_magnet_board_device::device_reset()
void cedar_magnet_board_interface::reset_clear()
{
device().machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(cedar_magnet_board_interface::reset_clear_callback),this));
}
void cedar_magnet_board_interface::interface_pre_reset()
{
halt_assert();
}

View File

@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
// just a base device to hold some common functions of the EFO / Cedar Magnet System PCBs
// device interface to hold some common functions of the EFO / Cedar Magnet System PCBs
#pragma once
@ -10,41 +10,40 @@
#include "cpu/z80/z80.h"
#include "cpu/z80/z80daisy.h"
#include "machine/z80pio.h"
extern const device_type CEDAR_MAGNET_PLANE;
class cedar_magnet_board_device : public device_t
class cedar_magnet_board_interface : public device_interface
{
public:
// construction/destruction
cedar_magnet_board_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source);
cedar_magnet_board_interface(const machine_config &mconfig, device_t &device, const char *cputag, const char *ramtag);
uint8_t* m_ram;
z80_device* m_cpu;
z80_device &cpu() { assert(m_cpu != nullptr); return *m_cpu; }
u8 *ram() { return &m_ram[0]; }
virtual uint8_t read_cpu_bus(int offset);
virtual u8 read_cpu_bus(int offset);
virtual void write_cpu_bus(int offset, uint8_t data);
TIMER_CALLBACK_MEMBER(halt_assert_callback);
TIMER_CALLBACK_MEMBER(halt_clear_callback);
virtual TIMER_CALLBACK_MEMBER(reset_assert_callback);
TIMER_CALLBACK_MEMBER(reset_clear_callback);
void irq_hold();
void halt_assert();
void halt_clear();
void reset_assert();
void reset_clear();
bool is_running() const;
void halt_assert(void);
void halt_clear(void);
void reset_assert(void);
void reset_clear(void);
bool is_running(void);
bool m_is_running;
INTERRUPT_GEN_MEMBER(irq);
protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void interface_pre_reset() override;
virtual TIMER_CALLBACK_MEMBER(reset_assert_callback);
required_device<z80_device> m_cpu;
optional_shared_ptr<u8> m_ram;
private:
TIMER_CALLBACK_MEMBER(halt_assert_callback);
TIMER_CALLBACK_MEMBER(halt_clear_callback);
TIMER_CALLBACK_MEMBER(reset_clear_callback);
bool m_is_running;
};
#endif

View File

@ -10,7 +10,8 @@ extern const device_type CEDAR_MAGNET_PLANE = &device_creator<cedar_magnet_plane
cedar_magnet_plane_device::cedar_magnet_plane_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_PLANE, "Cedar Plane", tag, owner, clock, "cedmag_plane", __FILE__)
: device_t(mconfig, CEDAR_MAGNET_PLANE, "Cedar Plane", tag, owner, clock, "cedmag_plane", __FILE__),
cedar_magnet_board_interface(mconfig, *this, "planecpu", "ram")
{
}
@ -72,7 +73,6 @@ static MACHINE_CONFIG_FRAGMENT( cedar_magnet_plane )
MCFG_CPU_ADD("planecpu", Z80,4000000)
MCFG_CPU_PROGRAM_MAP(cedar_magnet_plane_map)
MCFG_CPU_IO_MAP(cedar_magnet_plane_io)
MCFG_CPU_VBLANK_INT_DRIVER(":screen", cedar_magnet_board_device, irq)
MCFG_DEVICE_ADD("z80pio0", Z80PIO, 4000000/2)
// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
@ -133,8 +133,6 @@ machine_config_constructor cedar_magnet_plane_device::device_mconfig_additions()
void cedar_magnet_plane_device::device_start()
{
m_cpu = subdevice<z80_device>("planecpu");
m_ram = (uint8_t*)memshare("ram")->ptr();
save_item(NAME(m_framebuffer));
}

View File

@ -7,6 +7,7 @@
#define CEDAR_MAGNET_PLANE_DEF
#include "machine/cedar_magnet_board.h"
#include "machine/z80pio.h"
extern const device_type CEDAR_MAGNET_PLANE;
@ -14,7 +15,7 @@ extern const device_type CEDAR_MAGNET_PLANE;
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_PLANE, 0)
class cedar_magnet_plane_device : public cedar_magnet_board_device
class cedar_magnet_plane_device : public device_t, public cedar_magnet_board_interface
{
public:
// construction/destruction
@ -35,6 +36,8 @@ public:
DECLARE_WRITE8_MEMBER(plane_portce_w);
DECLARE_WRITE8_MEMBER(plane_portcf_w);
INTERRUPT_GEN_MEMBER(vblank_irq);
uint8_t m_framebuffer[0x10000];
int m_curline;
int m_lineoffset;

View File

@ -1,208 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*
This is very similar to the ZSU1 Sound Control Unit, also manufactured by
EFO SA and used in the Playmatic pinballs Skill Flight and Phantom Ship;
the emulation here is influenced by available schematics for that board.
irq vectors
0xe6 - from ctc0 channel 3 (vector = E0) used to drive MSM5205 through FIFO
0xee - from ctc0 channel 3 (vector = E8) ^^
0xf6 - drive AY (once per frame?) triggered by ctc1 channel 3 (vector = F0)
0xff - read sound latch (triggered by write from master board; default vector set by 5K/+5 pullups on D0-D7)
*/
#include "emu.h"
#include "cedar_magnet_sound.h"
#include "machine/clock.h"
extern const device_type CEDAR_MAGNET_SOUND = &device_creator<cedar_magnet_sound_device>;
cedar_magnet_sound_device::cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_SOUND, "Cedar Sound", tag, owner, clock, "cedmag_sound", __FILE__),
m_ctc0(*this, "ctc0"),
m_ctc1(*this, "ctc1"),
m_fifo(*this, "fifo"),
m_adpcm(*this, "adpcm")
{
}
READ8_MEMBER(cedar_magnet_sound_device::soundlatch_r)
{
return m_command;
}
void cedar_magnet_sound_device::write_command(uint8_t data)
{
m_command = data;
// this interrupt causes it to read the soundlatch at 0x14
m_cpu->set_input_line_and_vector(0, HOLD_LINE, 0xff);
}
static ADDRESS_MAP_START( cedar_magnet_sound_map, AS_PROGRAM, 8, cedar_magnet_sound_device )
AM_RANGE(0x0000, 0xffff) AM_RAM AM_SHARE("ram")
ADDRESS_MAP_END
static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_device )
ADDRESS_MAP_GLOBAL_MASK(0xff)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("ctc0", z80ctc_device, read, write)
AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("ctc1", z80ctc_device, read, write)
AM_RANGE(0x08, 0x08) AM_WRITE(adpcm_fifo_w)
AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("aysnd0", ay8910_device, address_w)
AM_RANGE(0x0d, 0x0d) AM_DEVWRITE("aysnd0", ay8910_device, data_w)
AM_RANGE(0x10, 0x10) AM_DEVWRITE("aysnd1", ay8910_device, address_w)
AM_RANGE(0x11, 0x11) AM_DEVWRITE("aysnd1", ay8910_device, data_w)
AM_RANGE(0x14, 0x14) AM_READ(soundlatch_r)
ADDRESS_MAP_END
WRITE8_MEMBER(cedar_magnet_sound_device::adpcm_fifo_w)
{
// Z80 code first unpacks 8 bytes of ADPCM sample data into nibbles
// and, upon receiving interrupt vector E6, fills FIFO at once using OTIR
// 4-bit data is shifted out of the FIFO to the MSM5205 by another timer
m_fifo->write(data & 0x0f); // only low nibble is used here
m_fifo->si_w(1);
m_fifo->si_w(0);
}
WRITE8_MEMBER(cedar_magnet_sound_device::ay0_porta_w)
{
// unknown; 0x80 written on reset
}
WRITE8_MEMBER(cedar_magnet_sound_device::ay1_porta_w)
{
m_adpcm->reset_w(data & 1);
if (data & 1)
m_fifo->reset();
// D4-D6 likely used to select clock for ctc0 channel 2
// other bits probably used to modulate analog sound output
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z0_w)
{
// printf("USED ctc0_z0_w %d\n", state);
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z1_w)
{
// printf("USED ctc0_z1_w %d\n", state);
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z0_w)
{
printf("ctc1_z0_w %d\n", state);
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z1_w)
{
printf("ctc1_z1_w %d\n", state);
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z2_w)
{
printf("ctc1_z2_w %d\n", state);
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z2_w)
{
printf("ctc0_z2_w %d\n", state);
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::fifo_dor_w)
{
// combined with a clock signal and used to drive ctc0 channel 3
}
static const z80_daisy_config daisy_chain[] =
{
{ "ctc1" },
{ "ctc0" },
{ nullptr }
};
TIMER_CALLBACK_MEMBER(cedar_magnet_sound_device::reset_assert_callback)
{
cedar_magnet_board_device::reset_assert_callback(ptr,param);
// reset lines go to the ctc as well?
m_ctc0->reset();
m_ctc1->reset();
}
static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
MCFG_CPU_ADD("topcpu", Z80, 4000000)
MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map)
MCFG_CPU_IO_MAP(cedar_magnet_sound_io)
MCFG_Z80_DAISY_CHAIN(daisy_chain)
MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000)
MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z2_w))
MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000)
MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z2_w))
#if 0 // does nothing useful now
MCFG_DEVICE_ADD("ck1mhz", CLOCK, 4000000/4)
MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("ctc1", z80ctc_device, trg0))
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg1))
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg2))
#endif
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2)
MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay0_porta_w))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
MCFG_SOUND_ADD("aysnd1", AY8910, 4000000/2)
MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay1_porta_w))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
MCFG_DEVICE_ADD("fifo", HC40105, 0) // HCF40105BE at IC13
MCFG_40105_DATA_OUT_READY_CB(WRITELINE(cedar_magnet_sound_device, fifo_dor_w))
MCFG_40105_DATA_OUT_CB(DEVWRITELINE("adpcm", msm5205_device, data_w))
MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/8)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MACHINE_CONFIG_END
machine_config_constructor cedar_magnet_sound_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( cedar_magnet_sound );
}
void cedar_magnet_sound_device::device_start()
{
m_cpu = subdevice<z80_device>("topcpu");
m_ram = (uint8_t*)memshare("ram")->ptr();
}
void cedar_magnet_sound_device::device_reset()
{
m_command = 0;
cedar_magnet_board_device::device_reset();
}

View File

@ -14,7 +14,8 @@ extern const device_type CEDAR_MAGNET_SPRITE = &device_creator<cedar_magnet_spri
cedar_magnet_sprite_device::cedar_magnet_sprite_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_SPRITE, "Cedar Sprite", tag, owner, clock, "cedmag_sprite", __FILE__),
: device_t(mconfig, CEDAR_MAGNET_SPRITE, "Cedar Sprite", tag, owner, clock, "cedmag_sprite", __FILE__),
cedar_magnet_board_interface(mconfig, *this, "spritecpu", "ram"),
m_sprite_ram_bankdev(*this, "sp_sub_ram"),
m_pio0(*this, "z80pio0"),
m_pio1(*this, "z80pio1"),
@ -202,7 +203,6 @@ static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sprite )
MCFG_CPU_ADD("spritecpu", Z80,4000000)
MCFG_CPU_PROGRAM_MAP(cedar_magnet_sprite_map)
MCFG_CPU_IO_MAP(cedar_magnet_sprite_io)
MCFG_CPU_VBLANK_INT_DRIVER(":screen", cedar_magnet_board_device, irq)
MCFG_DEVICE_ADD("z80pio0", Z80PIO, 4000000/2)
// MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0))
@ -291,14 +291,12 @@ machine_config_constructor cedar_magnet_sprite_device::device_mconfig_additions(
return MACHINE_CONFIG_NAME( cedar_magnet_sprite );
}
void cedar_magnet_sprite_device::device_start()
{
m_cpu = subdevice<z80_device>("spritecpu");
m_ram = (uint8_t*)memshare("ram")->ptr();
}
void cedar_magnet_sprite_device::device_reset()
{
halt_assert();

View File

@ -18,7 +18,7 @@ extern const device_type CEDAR_MAGNET_SPRITE;
MCFG_DEVICE_ADD(_tag, CEDAR_MAGNET_SPRITE, 0)
class cedar_magnet_sprite_device : public cedar_magnet_board_device
class cedar_magnet_sprite_device : public device_t, public cedar_magnet_board_interface
{
public:
// construction/destruction