diff options
author | Dirk Best <mail@dirk-best.de> | 2014-05-13 11:46:43 +0000 |
---|---|---|
committer | Dirk Best <mail@dirk-best.de> | 2014-05-13 11:46:43 +0000 |
commit | 39e6b343ed946a62e0442bc479f66f6a0497967a (patch) | |
tree | fd8071af73eaca4bf6b56149342738491670dbf1 /src/emu | |
parent | 8882453f5a3236d20f75227b784e4a1edacd4496 (diff) | |
parent | 640354ad9efa2b8c0027c0bce444e652cb593333 (diff) |
Merge branch 'master' of ssh://mess.org/mame
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/bus/bus.mak | 12 | ||||
-rw-r--r-- | src/emu/bus/zorro/a590.c | 346 | ||||
-rw-r--r-- | src/emu/bus/zorro/a590.h | 135 | ||||
-rw-r--r-- | src/emu/bus/zorro/action_replay.c | 150 | ||||
-rw-r--r-- | src/emu/bus/zorro/action_replay.h | 83 | ||||
-rw-r--r-- | src/emu/bus/zorro/cards.c | 31 | ||||
-rw-r--r-- | src/emu/bus/zorro/cards.h | 38 | ||||
-rw-r--r-- | src/emu/bus/zorro/zorro.c | 358 | ||||
-rw-r--r-- | src/emu/bus/zorro/zorro.h | 443 | ||||
-rw-r--r-- | src/emu/machine/6525tpi.c | 6 | ||||
-rw-r--r-- | src/emu/machine/6525tpi.h | 12 | ||||
-rw-r--r-- | src/emu/machine/akiko.c | 925 | ||||
-rw-r--r-- | src/emu/machine/akiko.h | 153 | ||||
-rw-r--r-- | src/emu/machine/amigafdc.c | 7 | ||||
-rw-r--r-- | src/emu/machine/autoconfig.c | 167 | ||||
-rw-r--r-- | src/emu/machine/autoconfig.h | 72 | ||||
-rw-r--r-- | src/emu/machine/cr511b.c | 123 | ||||
-rw-r--r-- | src/emu/machine/cr511b.h | 152 | ||||
-rw-r--r-- | src/emu/machine/dmac.c | 467 | ||||
-rw-r--r-- | src/emu/machine/dmac.h | 173 | ||||
-rw-r--r-- | src/emu/machine/machine.mak | 40 | ||||
-rw-r--r-- | src/emu/sound/amiga.c | 240 | ||||
-rw-r--r-- | src/emu/sound/amiga.h | 63 | ||||
-rw-r--r-- | src/emu/sound/sound.mak | 11 |
24 files changed, 4203 insertions, 4 deletions
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak index e47605433d8..9067f5bca1d 100644 --- a/src/emu/bus/bus.mak +++ b/src/emu/bus/bus.mak @@ -1082,3 +1082,15 @@ BUSOBJS += $(BUSOBJ)/a1bus/a1cassette.o BUSOBJS += $(BUSOBJ)/a1bus/a1cffa.o endif +#------------------------------------------------- +# +#@src/emu/bus/zorro/zorro.h,BUSES += ZORRO +#------------------------------------------------- + +ifneq ($(filter ZORRO,$(BUSES)),) +OBJDIRS += $(BUSOBJ)/zorro +BUSOBJS += $(BUSOBJ)/zorro/zorro.o +BUSOBJS += $(BUSOBJ)/zorro/cards.o +BUSOBJS += $(BUSOBJ)/zorro/a590.o +BUSOBJS += $(BUSOBJ)/zorro/action_replay.o +endif diff --git a/src/emu/bus/zorro/a590.c b/src/emu/bus/zorro/a590.c new file mode 100644 index 00000000000..d6ca7d12b6b --- /dev/null +++ b/src/emu/bus/zorro/a590.c @@ -0,0 +1,346 @@ +/*************************************************************************** + + Commodore A590 / A2091 + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + DMAC based HD controller for the Amiga 500 and Zorro-II + +***************************************************************************/ + +#include "a590.h" +#include "bus/scsi/scsi.h" +#include "bus/scsi/scsihd.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type A590 = &device_creator<a590_device>; +const device_type A2091 = &device_creator<a2091_device>; + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( a590_pcb ) + PORT_START("dips") + PORT_DIPNAME(0x01, 0x01, "A590 Auto-Boot") + PORT_DIPLOCATION("DIP:1") + PORT_DIPSETTING(0x00, "Enabled") + PORT_DIPSETTING(0x01, "Disabled") + PORT_DIPNAME(0x02, 0x00, "A590 LUN") + PORT_DIPLOCATION("DIP:2") + PORT_DIPSETTING(0x00, "Disabled") + PORT_DIPSETTING(0x02, "Enabled") + PORT_DIPNAME(0x04, 0x04, "A590 Wait period") + PORT_DIPLOCATION("DIP:3") + PORT_DIPSETTING(0x00, "Short") + PORT_DIPSETTING(0x04, "Long") + PORT_DIPNAME(0x08, 0x00, "A590 Reserved") + PORT_DIPLOCATION("DIP:4") + PORT_DIPSETTING(0x00, "Enabled") + PORT_DIPSETTING(0x08, "Disabled") + PORT_START("jp1") + PORT_DIPNAME(0x0f, 0x01, "A590 Memory size") + PORT_DIPLOCATION("JP1:1,2,3,4") + PORT_DIPSETTING(0x01, "Amnesia") + PORT_DIPSETTING(0x02, "512K") + PORT_DIPSETTING(0x04, "1MB") + PORT_DIPSETTING(0x08, "2MB") + PORT_START("jp2") + PORT_DIPNAME(0x01, 0x00, "A590 Drive LED") + PORT_DIPLOCATION("JP2:1") + PORT_DIPSETTING(0x00, "XT Drive") + PORT_DIPSETTING(0x01, "SCSI Drive") + PORT_START("jp4") + PORT_DIPNAME(0x01, 0x00, "A590 Interrupt") + PORT_DIPLOCATION("JP4:1") + PORT_DIPSETTING(0x00, "INT 2") + PORT_DIPSETTING(0x01, "INT 6") +INPUT_PORTS_END + +ioport_constructor a590_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( a590_pcb ); +} + +static INPUT_PORTS_START( a2091_pcb ) + PORT_START("jp1") + PORT_DIPNAME(0x0f, 0x01, "A2091 Memory size") + PORT_DIPLOCATION("JP1:1,2,3,4") + PORT_DIPSETTING(0x01, "0K") + PORT_DIPSETTING(0x02, "512K") + PORT_DIPSETTING(0x04, "1MB") + PORT_DIPSETTING(0x08, "2MB") + PORT_START("jp2") + PORT_DIPNAME(0x01, 0x00, "A2091 Auto-Boot") + PORT_DIPLOCATION("JP2:1") + PORT_DIPSETTING(0x00, "Enabled") + PORT_DIPSETTING(0x01, "Disabled") + PORT_START("jp3") + PORT_DIPNAME(0x01, 0x00, "A2091 Interrupt") + PORT_DIPLOCATION("JP3:1") + PORT_DIPSETTING(0x00, "INT 2") + PORT_DIPSETTING(0x01, "INT 6") + PORT_START("jp5") + PORT_DIPNAME(0x01, 0x00, "A2091 LUN") + PORT_DIPLOCATION("JP5:1") + PORT_DIPSETTING(0x00, "Disabled") + PORT_DIPSETTING(0x01, "Enabled") + PORT_DIPNAME(0x02, 0x00, "A2091 Time-Out") + PORT_DIPLOCATION("JP5:2") + PORT_DIPSETTING(0x00, "Short") + PORT_DIPSETTING(0x02, "Long") + PORT_DIPNAME(0x04, 0x00, "A2091 Reserved") + PORT_DIPLOCATION("JP5:3") + PORT_DIPSETTING(0x00, "Disabled") + PORT_DIPSETTING(0x02, "Enabled") + PORT_START("jp201") + PORT_DIPNAME(0x01, 0x00, "A2091 WD33C93 Clock") + PORT_DIPLOCATION("JP201:1") + PORT_DIPSETTING(0x00, "7 MHz") + PORT_DIPSETTING(0x01, "14 MHz") +INPUT_PORTS_END + +ioport_constructor a2091_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( a2091_pcb ); +} + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +static MACHINE_CONFIG_FRAGMENT( dmac_hdc ) + MCFG_DMAC_ADD("dmac", 0) + MCFG_DMAC_SCSI_READ_HANDLER(READ8(dmac_hdc_device, dmac_scsi_r)) + MCFG_DMAC_SCSI_WRITE_HANDLER(WRITE8(dmac_hdc_device, dmac_scsi_w)) + MCFG_DMAC_INT_HANDLER(WRITELINE(dmac_hdc_device, dmac_int_w)) + MCFG_DMAC_CFGOUT_HANDLER(WRITELINE(dmac_hdc_device, dmac_cfgout_w)) + MCFG_DEVICE_ADD("scsi", SCSI_PORT, 0) + MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_1) + MCFG_DEVICE_ADD("scsi:wd33c93", WD33C93, 0) + MCFG_LEGACY_SCSI_PORT("scsi") + MCFG_WD33C93_IRQ_CB(DEVWRITELINE("^^", dmac_hdc_device, scsi_irq_w)) +MACHINE_CONFIG_END + +machine_config_constructor dmac_hdc_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( dmac_hdc ); +} + + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( dmac_hdc ) + ROM_REGION16_BE(0x8000, "bootrom", 0) + ROM_DEFAULT_BIOS("v70") + + ROM_SYSTEM_BIOS(0, "v60", "Version 6.0") + ROMX_LOAD("390388-03.u13", 0x0000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("390389-03.u12", 0x0001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("390388-03.u13", 0x4000, 0x2000, CRC(2e77bbff) SHA1(8a098845068f32cfa4d34a278cd290f61d35a52c), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("390389-03.u12", 0x4001, 0x2000, CRC(b0b8cf24) SHA1(fcf4017505f4d441814b45d559c19eab43816b30), ROM_SKIP(1) | ROM_BIOS(1)) + + // changelog v6.1: prevent accesses to location 0 by application programs + ROM_SYSTEM_BIOS(1, "v61", "Version 6.1") + ROMX_LOAD("390721-01.u13", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(2)) + ROMX_LOAD("390722-01.u12", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(2)) + ROMX_LOAD("390721-01.u13", 0x4000, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(2)) + ROMX_LOAD("390722-01.u12", 0x4001, 0x2000, NO_DUMP, ROM_SKIP(1) | ROM_BIOS(2)) + + // changelog v6.6: fixes dual scsi problems with the wd33c93a controller + ROM_SYSTEM_BIOS(2, "v66", "Version 6.6") + ROMX_LOAD("390721-02.u13", 0x0000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(3)) + ROMX_LOAD("390722-02.u12", 0x0001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(3)) + ROMX_LOAD("390721-02.u13", 0x4000, 0x2000, CRC(c0871d25) SHA1(e155f18abb90cf820589c15e70559d3b6b391af8), ROM_SKIP(1) | ROM_BIOS(3)) + ROMX_LOAD("390722-02.u12", 0x4001, 0x2000, CRC(e536bbb2) SHA1(fd7f8a6da18c1b02d07eb990c2467a24183ede12), ROM_SKIP(1) | ROM_BIOS(3)) + + // final commodore released version + ROM_SYSTEM_BIOS(3, "v70", "Version 7.0") + ROMX_LOAD("390721-03.u13", 0x0000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(4)) + ROMX_LOAD("390722-03.u12", 0x0001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(4)) + ROMX_LOAD("390721-03.u13", 0x4000, 0x2000, CRC(2942747a) SHA1(dbd7648e79c753337ff3e4f491de224bf05e6bb6), ROM_SKIP(1) | ROM_BIOS(4)) + ROMX_LOAD("390722-03.u12", 0x4001, 0x2000, CRC(a9ccffed) SHA1(149f5bd52e2d29904e3de483b9ad772448e9278e), ROM_SKIP(1) | ROM_BIOS(4)) + + // third-party upgrade rom, requires a small rom adapter pcb + ROM_SYSTEM_BIOS(4, "g614", "Guru-ROM 6.14") + ROMX_LOAD("gururom_v614.bin", 0x0000, 0x8000, CRC(04e52f93) SHA1(6da21b6f5e8f8837d64507cd8a4d5cdcac4f426b), ROM_GROUPWORD | ROM_BIOS(5)) +ROM_END + +const rom_entry *dmac_hdc_device::device_rom_region() const +{ + return ROM_NAME( dmac_hdc ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// dmac_hdc_device - constructor +//------------------------------------------------- + +dmac_hdc_device::dmac_hdc_device(const machine_config &mconfig, device_type type, const char *tag, + device_t *owner, UINT32 clock, const char *name, const char *shortname) : + device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), + m_int6(false), + m_dmac(*this, "dmac"), + m_wdc(*this, "scsi:wd33c93") +{ +} + +a590_device::a590_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + dmac_hdc_device(mconfig, A590, tag, owner, clock, "CBM A590 HD Controller", "a590"), + device_exp_card_interface(mconfig, *this), + m_dips(*this, "dips"), + m_jp1(*this, "jp1"), + m_jp2(*this, "jp2"), + m_jp4(*this, "jp4") +{ +} + +a2091_device::a2091_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + dmac_hdc_device(mconfig, A2091, tag, owner, clock, "CBM A2091 HD Controller", "a2091"), + device_zorro2_card_interface(mconfig, *this), + m_jp1(*this, "jp1"), + m_jp2(*this, "jp2"), + m_jp3(*this, "jp3"), + m_jp5(*this, "jp5"), + m_jp201(*this, "jp201") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void dmac_hdc_device::device_start() +{ +} + +void a590_device::device_start() +{ + set_zorro_device(); + + // setup dmac + m_dmac->set_address_space(m_slot->m_space); + m_dmac->set_rom(memregion("bootrom")->base()); +} + +void a2091_device::device_start() +{ + set_zorro_device(); + + // setup dmac + m_dmac->set_address_space(m_slot->m_space); + m_dmac->set_rom(memregion("bootrom")->base()); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void dmac_hdc_device::device_reset() +{ +} + +void dmac_hdc_device::resize_ram(int config) +{ + // allocate space for ram + switch (config & 0x0f) + { + case 0x01: + m_ram.resize(0); + m_dmac->ramsz_w(0); + break; + case 0x02: + m_ram.resize(0x080000); + m_dmac->ramsz_w(1); + break; + case 0x04: + m_ram.resize(0x100000); + m_dmac->ramsz_w(2); + break; + case 0x08: + m_ram.resize(0x200000); + m_dmac->ramsz_w(3); + break; + } + + m_dmac->set_ram(m_ram); +} + +void a590_device::device_reset() +{ +} + +void a2091_device::device_reset() +{ +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +WRITE_LINE_MEMBER( a590_device::cfgin_w ) +{ + // make sure we configure ourselves first + m_int6 = m_jp4->read() & 0x01; + resize_ram(m_dips->read() & 0x0f); + + // then tell the dmac to start configuring + m_dmac->configin_w(state); +} + +WRITE_LINE_MEMBER( a2091_device::cfgin_w ) +{ + // make sure we configure ourselves first + m_int6 = m_jp3->read() & 0x01; + resize_ram(m_jp1->read() & 0x0f); + + // then tell the dmac to start configuring + m_dmac->configin_w(state); +} + +READ8_MEMBER( dmac_hdc_device::dmac_scsi_r ) +{ + switch (offset) + { + case 0x48: return m_wdc->read(space, 0); + case 0x49: return m_wdc->read(space, 1); + } + + return 0xff; +} + +WRITE8_MEMBER( dmac_hdc_device::dmac_scsi_w ) +{ + switch (offset) + { + case 0x48: m_wdc->write(space, 0, data); break; + case 0x49: m_wdc->write(space, 1, data); break; + } +} + +WRITE_LINE_MEMBER( dmac_hdc_device::dmac_int_w ) +{ + if (m_int6) + int6_w(state); + else + int2_w(state); +} + +WRITE_LINE_MEMBER( dmac_hdc_device::scsi_irq_w ) +{ + // should be or'ed with xt-ide irq + m_dmac->intx_w(state); +} diff --git a/src/emu/bus/zorro/a590.h b/src/emu/bus/zorro/a590.h new file mode 100644 index 00000000000..4682c72903f --- /dev/null +++ b/src/emu/bus/zorro/a590.h @@ -0,0 +1,135 @@ +/*************************************************************************** + + Commodore A590 / A2091 + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + DMAC based SCSI controller for the Amiga 500 and Zorro-II + +***************************************************************************/ + +#pragma once + +#ifndef __A590_H__ +#define __A590_H__ + +#include "emu.h" +#include "zorro.h" +#include "machine/dmac.h" +#include "machine/wd33c93.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> dmac_hdc_device + +class dmac_hdc_device : public device_t +{ +public: + // construction/destruction + dmac_hdc_device(const machine_config &mconfig, device_type type, const char *tag, + device_t *owner, UINT32 clock, const char *name, const char *shortname); + + // optional information overrides + virtual machine_config_constructor device_mconfig_additions() const; + virtual const rom_entry *device_rom_region() const; + + DECLARE_READ8_MEMBER( dmac_scsi_r ); + DECLARE_WRITE8_MEMBER( dmac_scsi_w ); + DECLARE_WRITE_LINE_MEMBER( dmac_int_w ); + DECLARE_WRITE_LINE_MEMBER( dmac_cfgout_w ) { cfgout_w(state); } + DECLARE_WRITE_LINE_MEMBER( scsi_irq_w ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // to slot + virtual void cfgout_w(int state) = 0; + virtual void int2_w(int state) = 0; + virtual void int6_w(int state) = 0; + + // should be called when the ram size changes + void resize_ram(int config); + + // amiga interrupt target, int 2 or 6 + bool m_int6; + + // sub-devices + required_device<dmac_device> m_dmac; + required_device<wd33c93_device> m_wdc; + + dynamic_buffer m_ram; +}; + +// ======================> a590_device + +class a590_device : public dmac_hdc_device, public device_exp_card_interface +{ +public: + // construction/destruction + a590_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + + // output to slot + virtual void cfgout_w(int state) { m_slot->cfgout_w(state); } + virtual void int2_w(int state) { m_slot->int2_w(state); } + virtual void int6_w(int state) { m_slot->int6_w(state); } + + // input from slot + virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ); + +private: + required_ioport m_dips; + required_ioport m_jp1; + required_ioport m_jp2; + required_ioport m_jp4; +}; + +// ======================> a2091_device + +class a2091_device : public dmac_hdc_device, public device_zorro2_card_interface +{ +public: + // construction/destruction + a2091_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + + // output to slot + virtual void cfgout_w(int state) { m_slot->cfgout_w(state); } + virtual void int2_w(int state) { m_slot->int2_w(state); } + virtual void int6_w(int state) { m_slot->int6_w(state); } + + // input from slot + virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ); + +private: + required_ioport m_jp1; + required_ioport m_jp2; + required_ioport m_jp3; + required_ioport m_jp5; + required_ioport m_jp201; +}; + +// device type definition +extern const device_type A590; +extern const device_type A2091; + +#endif diff --git a/src/emu/bus/zorro/action_replay.c b/src/emu/bus/zorro/action_replay.c new file mode 100644 index 00000000000..890e0081373 --- /dev/null +++ b/src/emu/bus/zorro/action_replay.c @@ -0,0 +1,150 @@ +/*************************************************************************** + + Datel Action Replay + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + Freezer cartridge for Amiga 500 and Amiga 2000 + + Skeleton device, just loads the ROMs and generates the NMI + for now. + + Hardware notes: + - http://www.mways.co.uk/amiga/howtocode/text/actionreplay.php + +***************************************************************************/ + +#include "action_replay.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type ACTION_REPLAY_MK1 = &device_creator<action_replay_mk1_device>; +const device_type ACTION_REPLAY_MK2 = &device_creator<action_replay_mk2_device>; +const device_type ACTION_REPLAY_MK3 = &device_creator<action_replay_mk3_device>; + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( ar_button ) + PORT_START("freeze") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Freeze") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, action_replay_device, freeze, 0) +INPUT_PORTS_END + +ioport_constructor action_replay_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( ar_button ); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +ROM_START( ar_mk1 ) + ROM_REGION(0x10000, "firmware", 0) + ROM_DEFAULT_BIOS("v150") + ROM_SYSTEM_BIOS(0, "v100", "Version 1.00") + ROMX_LOAD("ar1_v100.bin", 0x0000, 0x10000, BAD_DUMP CRC(2d921771) SHA1(1ead9dda2dad29146441f5ef7218375022e01248), ROM_BIOS(1)) + ROM_SYSTEM_BIOS(1, "v150", "Version 1.50") + ROMX_LOAD("ar1_v150.bin", 0x0000, 0x10000, BAD_DUMP CRC(f82c4258) SHA1(843b433b2c56640e045d5fdc854dc6b1a4964e7c), ROM_BIOS(2)) +ROM_END + +const rom_entry *action_replay_mk1_device::device_rom_region() const +{ + return ROM_NAME( ar_mk1 ); +} + +ROM_START( ar_mk2 ) + ROM_REGION(0x20000, "firmware", 0) + ROM_DEFAULT_BIOS("v214") + ROM_SYSTEM_BIOS(0, "v205", "Version 2.05") + ROMX_LOAD("ar2_v205.bin", 0x0000, 0x20000, BAD_DUMP CRC(4051eef8) SHA1(9df22b1d3285b522c223697c83d144d04e961a4a), ROM_BIOS(1)) + ROM_SYSTEM_BIOS(1, "v212", "Version 2.12") + ROMX_LOAD("ar2_v212.bin", 0x0000, 0x20000, BAD_DUMP CRC(d29bdd86) SHA1(76c2900457badf22b742f0af48b78937e8b67694), ROM_BIOS(2)) + ROM_SYSTEM_BIOS(2, "v214", "Version 2.14") + ROMX_LOAD("ar2_v214.bin", 0x0000, 0x20000, BAD_DUMP CRC(1bb3d0a8) SHA1(14b1f5a69efb6f4e2331970e6ca0f33c0f04ac91), ROM_BIOS(3)) +ROM_END + +const rom_entry *action_replay_mk2_device::device_rom_region() const +{ + return ROM_NAME( ar_mk2 ); +} + +ROM_START( ar_mk3 ) + ROM_REGION(0x40000, "firmware", 0) + ROM_DEFAULT_BIOS("v309") + ROM_SYSTEM_BIOS(0, "v309", "Version 3.09") + ROMX_LOAD("ar3_v309.evn", 0x00000, 0x20000, CRC(2b84519f) SHA1(7841873bf009d8341dfa2794b3751bacf86adcc8), ROM_SKIP(1) | ROM_BIOS(1)) + ROMX_LOAD("ar3_v309.odd", 0x00001, 0x20000, CRC(1d35bd56) SHA1(6464be1626b519499e76e4e3409e8016515d48b6), ROM_SKIP(1) | ROM_BIOS(1)) + ROM_SYSTEM_BIOS(1, "v317", "Version 3.17") + ROMX_LOAD("ar3_v314.bin", 0x0000, 0x40000, BAD_DUMP CRC(009f7768) SHA1(0439d6ccc2a0e5c2e83fcf2389dc4d4a440a4c62), ROM_BIOS(2)) +ROM_END + +const rom_entry *action_replay_mk3_device::device_rom_region() const +{ + return ROM_NAME( ar_mk3 ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// action_replay_device - constructor +//------------------------------------------------- + +action_replay_device::action_replay_device(const machine_config &mconfig, device_type type, const char *tag, + device_t *owner, UINT32 clock, const char *name, const char *shortname) : + device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), + device_exp_card_interface(mconfig, *this), + m_button(*this, "freeze") +{ +} + +action_replay_mk1_device::action_replay_mk1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + action_replay_device(mconfig, ACTION_REPLAY_MK1, tag, owner, clock, "Datel Action Replay MK-I", "amiga_ar1") +{ +} + +action_replay_mk2_device::action_replay_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + action_replay_device(mconfig, ACTION_REPLAY_MK1, tag, owner, clock, "Datel Action Replay MK-II", "amiga_ar2") +{ +} + +action_replay_mk3_device::action_replay_mk3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + action_replay_device(mconfig, ACTION_REPLAY_MK1, tag, owner, clock, "Datel Action Replay MK-III", "amiga_ar3") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void action_replay_device::device_start() +{ + set_zorro_device(); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void action_replay_device::device_reset() +{ +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +INPUT_CHANGED_MEMBER( action_replay_device::freeze ) +{ + // pushing the freeze button generates an nmi + m_slot->ipl_w(newval == 1 ? 7 : 0); +} diff --git a/src/emu/bus/zorro/action_replay.h b/src/emu/bus/zorro/action_replay.h new file mode 100644 index 00000000000..f2520575fb7 --- /dev/null +++ b/src/emu/bus/zorro/action_replay.h @@ -0,0 +1,83 @@ +/*************************************************************************** + + Datel Action Replay + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + Freezer cartridge for Amiga 500 and Amiga 2000 + +***************************************************************************/ + +#pragma once + +#ifndef __ACTION_REPLAY_H__ +#define __ACTION_REPLAY_H__ + +#include "emu.h" +#include "zorro.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> action_replay_device + +class action_replay_device : public device_t, public device_exp_card_interface +{ +public: + // construction/destruction + action_replay_device(const machine_config &mconfig, device_type type, const char *tag, + device_t *owner, UINT32 clock, const char *name, const char *shortname); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + + DECLARE_INPUT_CHANGED_MEMBER( freeze ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + required_ioport m_button; +}; + +class action_replay_mk1_device : public action_replay_device +{ +public: + // construction/destruction + action_replay_mk1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual const rom_entry *device_rom_region() const; +}; + +class action_replay_mk2_device : public action_replay_device +{ +public: + // construction/destruction + action_replay_mk2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual const rom_entry *device_rom_region() const; +}; + +class action_replay_mk3_device : public action_replay_device +{ +public: + // construction/destruction + action_replay_mk3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual const rom_entry *device_rom_region() const; +}; + +// device type definition +extern const device_type ACTION_REPLAY_MK1; +extern const device_type ACTION_REPLAY_MK2; +extern const device_type ACTION_REPLAY_MK3; + +#endif diff --git a/src/emu/bus/zorro/cards.c b/src/emu/bus/zorro/cards.c new file mode 100644 index 00000000000..68af08c60a5 --- /dev/null +++ b/src/emu/bus/zorro/cards.c @@ -0,0 +1,31 @@ +/*************************************************************************** + + Amiga Zorro Cards + +***************************************************************************/ + +#include "cards.h" + +SLOT_INTERFACE_START( a1000_expansion_cards ) +SLOT_INTERFACE_END + +SLOT_INTERFACE_START( a500_expansion_cards ) + SLOT_INTERFACE("ar1", ACTION_REPLAY_MK1) + SLOT_INTERFACE("ar2", ACTION_REPLAY_MK2) + SLOT_INTERFACE("ar3", ACTION_REPLAY_MK3) + SLOT_INTERFACE("a590", A590) +SLOT_INTERFACE_END + +SLOT_INTERFACE_START( a2000_expansion_cards ) + SLOT_INTERFACE("ar1", ACTION_REPLAY_MK1) + SLOT_INTERFACE("ar2", ACTION_REPLAY_MK2) + SLOT_INTERFACE("ar3", ACTION_REPLAY_MK3) +SLOT_INTERFACE_END + +SLOT_INTERFACE_START( zorro2_cards ) + SLOT_INTERFACE("a2091", A2091) +SLOT_INTERFACE_END + +SLOT_INTERFACE_START( zorro3_cards ) + SLOT_INTERFACE("a2091", A2091) +SLOT_INTERFACE_END diff --git a/src/emu/bus/zorro/cards.h b/src/emu/bus/zorro/cards.h new file mode 100644 index 00000000000..6c34f9394fb --- /dev/null +++ b/src/emu/bus/zorro/cards.h @@ -0,0 +1,38 @@ +/*************************************************************************** + + Amiga Zorro Cards + + There are different card types and layouts: + + * 86-pin expansion slot + - A1000 + - A500 (rotated slot) + - A2000/B2000 (internal slot) + * Zorro-II + - A2000 + - B2000 + * Zorro-III + - A3000, A4000 + + For details see zorro.h. Zorro-II cards can be inserted into + Zorro-III slots. + +***************************************************************************/ + +#pragma once + +#ifndef __CARDS_H__ +#define __CARDS_H__ + +#include "emu.h" +#include "a590.h" +#include "action_replay.h" + +SLOT_INTERFACE_EXTERN( a1000_expansion_cards ); +SLOT_INTERFACE_EXTERN( a500_expansion_cards ); +SLOT_INTERFACE_EXTERN( a2000_expansion_cards ); + +SLOT_INTERFACE_EXTERN( zorro2_cards ); +SLOT_INTERFACE_EXTERN( zorro3_cards ); + +#endif // __CARDS_H__ diff --git a/src/emu/bus/zorro/zorro.c b/src/emu/bus/zorro/zorro.c new file mode 100644 index 00000000000..91918c2ffea --- /dev/null +++ b/src/emu/bus/zorro/zorro.c @@ -0,0 +1,358 @@ +/*************************************************************************** + + Amiga Zorro Slots + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + 86-pin Expansion Slot (Zorro-I), Zorro-II, Zorro-III + +***************************************************************************/ + +#include "zorro.h" + + +//************************************************************************** +// ZORRO SLOT DEVICE +//************************************************************************** + +const device_type ZORRO_SLOT = &device_creator<zorro_slot_device>; + +//------------------------------------------------- +// zorro_slot_device - constructor +//------------------------------------------------- + +zorro_slot_device::zorro_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, ZORRO_SLOT, "Zorro slot", tag, owner, clock, "zorro_slot", __FILE__), + device_slot_interface(mconfig, *this), + m_zorro_tag(NULL) +{ +} + +zorro_slot_device::zorro_slot_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_slot_interface(mconfig, *this), + m_zorro_tag(NULL) +{ +} + +void zorro_slot_device::set_zorro_slot(device_t &device, device_t *owner, const char *zorro_tag) +{ + zorro_slot_device &zorro_card = dynamic_cast<zorro_slot_device &>(device); + zorro_card.m_owner = owner; + zorro_card.m_zorro_tag = zorro_tag; +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void zorro_slot_device::device_start() +{ + device_zorro_card_interface *dev = dynamic_cast<device_zorro_card_interface *>(get_card_device()); + + if (dev) + { + zorro_device *m_zorro_bus = downcast<zorro_device *>(m_owner->subdevice(m_zorro_tag)); + m_zorro_bus->add_card(dev); + } +} + + +//************************************************************************** +// BASE ZORRO BUS DEVICE +//************************************************************************** + +//------------------------------------------------- +// exp_slot_device - constructor +//------------------------------------------------- + +zorro_device::zorro_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_space(NULL), + m_cputag(NULL), + m_ovr_handler(*this), + m_int2_handler(*this), + m_int6_handler(*this) +{ +} + +//------------------------------------------------- +// set_cputag - set cpu we are attached to +//------------------------------------------------- + +void zorro_device::set_cputag(device_t &device, const char *tag) +{ + zorro_device &zorro = downcast<zorro_device &>(device); + zorro.m_cputag = tag; +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void zorro_device::device_start() +{ + // get address space + device_t *cpu = machine().device(m_cputag); + m_space = &cpu->memory().space(AS_PROGRAM); + + // resolve callbacks + m_ovr_handler.resolve_safe(); + m_int2_handler.resolve_safe(); + m_int6_handler.resolve_safe(); +} + +// from slot device +WRITE_LINE_MEMBER( zorro_device::ovr_w ) { m_ovr_handler(state); } +WRITE_LINE_MEMBER( zorro_device::int2_w ) { m_int2_handler(state); } +WRITE_LINE_MEMBER( zorro_device::int6_w ) { m_int6_handler(state); } + + +//************************************************************************** +// EXPANSION SLOT DEVICE +//************************************************************************** + +const device_type EXP_SLOT = &device_creator<exp_slot_device>; + +//------------------------------------------------- +// exp_slot_device - constructor +//------------------------------------------------- + +exp_slot_device::exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + zorro_device(mconfig, EXP_SLOT, "86-pin expansion slot", tag, owner, clock, "exp_slot", __FILE__), + m_ipl_handler(*this), + m_dev(NULL) +{ +} + +exp_slot_device::exp_slot_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + zorro_device(mconfig, type, name, tag, owner, clock, shortname, source), + m_ipl_handler(*this), + m_dev(NULL) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void exp_slot_device::device_start() +{ + // resolve callbacks + m_ipl_handler.resolve_safe(); + + // call base device start + zorro_device::device_start(); +} + +//------------------------------------------------- +// add_card - add new card to our bus +//------------------------------------------------- + +void exp_slot_device::add_card(device_zorro_card_interface *card) +{ + m_dev = downcast<device_exp_card_interface *>(card); +} + +// from slot device +void exp_slot_device::ipl_w(int interrupt) { m_ipl_handler(0, interrupt, 0xff); } + +// from host +void exp_slot_device::fc_w(int code) { if (m_dev) m_dev->fc_w(code); } + + +//************************************************************************** +// ZORRO2 DEVICE +//************************************************************************** + +const device_type ZORRO2 = &device_creator<zorro2_device>; + +//------------------------------------------------- +// zorro2_device - constructor +//------------------------------------------------- + +zorro2_device::zorro2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + zorro_device(mconfig, ZORRO2, "Zorro-II bus", tag, owner, clock, "zorro2", __FILE__), + m_eint1_handler(*this), + m_eint4_handler(*this), + m_eint5_handler(*this), + m_eint7_handler(*this), + m_autoconfig_device(NULL) +{ +} + +zorro2_device::zorro2_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + zorro_device(mconfig, type, name, tag, owner, clock, shortname, source), + m_eint1_handler(*this), + m_eint4_handler(*this), + m_eint5_handler(*this), + m_eint7_handler(*this), + m_autoconfig_device(NULL) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void zorro2_device::device_start() +{ + // resolve callbacks + m_eint1_handler.resolve_safe(); + m_eint4_handler.resolve_safe(); + m_eint5_handler.resolve_safe(); + m_eint7_handler.resolve_safe(); + + // call base device start + zorro_device::device_start(); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void zorro2_device::device_reset() +{ + // initiate autoconfig + m_autoconfig_device = m_dev.first(); + + // if we have a device, start the autoconfig chain + if (m_autoconfig_device) + m_autoconfig_device->cfgin_w(0); +} + +//------------------------------------------------- +// add_card - add new card to our bus +//------------------------------------------------- + +void zorro2_device::add_card(device_zorro_card_interface *card) +{ + device_zorro2_card_interface *zorro2_card = downcast<device_zorro2_card_interface *>(card); + card->set_zorro_bus(this); + m_dev.append(*zorro2_card); +} + +// from slot device +WRITE_LINE_MEMBER( zorro2_device::eint1_w ) { m_eint1_handler(state); } +WRITE_LINE_MEMBER( zorro2_device::eint4_w ) { m_eint4_handler(state); } +WRITE_LINE_MEMBER( zorro2_device::eint5_w ) { m_eint5_handler(state); } +WRITE_LINE_MEMBER( zorro2_device::eint7_w ) { m_eint7_handler(state); } + +WRITE_LINE_MEMBER( zorro2_device::cfgout_w ) +{ + m_autoconfig_device = m_autoconfig_device->next(); + + // if there is still a device in the chain, tell it to configure itself + if (m_autoconfig_device) + m_autoconfig_device->cfgin_w(0); +} + +// from host +void zorro2_device::fc_w(int code) +{ + device_zorro2_card_interface *entry = m_dev.first(); + + while (entry) + { + entry->fc_w(code); + entry = entry->next(); + } +} + + +//************************************************************************** +// ZORRO INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_zorro_card_interface - constructor +//------------------------------------------------- + +device_zorro_card_interface::device_zorro_card_interface(const machine_config &mconfig, device_t &device) : + device_slot_card_interface(mconfig, device), + m_zorro(NULL) +{ +} + +//------------------------------------------------- +// ~device_zorro_card_interface - destructor +//------------------------------------------------- + +device_zorro_card_interface::~device_zorro_card_interface() +{ +} + +void device_zorro_card_interface::set_zorro_bus(zorro_device *device) +{ + m_zorro = device; +} + +void device_zorro_card_interface::fc_w(int code) +{ +} + +WRITE_LINE_MEMBER( device_zorro_card_interface::cfgin_w ) +{ +} + + +//************************************************************************** +// EXPANSION CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_exp_card_interface - constructor +//------------------------------------------------- + +device_exp_card_interface::device_exp_card_interface(const machine_config &mconfig, device_t &device) : + device_zorro_card_interface(mconfig, device), + m_slot(NULL) +{ +} + +//------------------------------------------------- +// ~device_exp_card_interface - destructor +//------------------------------------------------- + +device_exp_card_interface::~device_exp_card_interface() +{ +} + +void device_exp_card_interface::set_zorro_device() +{ + m_slot = dynamic_cast<exp_slot_device *>(m_zorro); +} + + +//************************************************************************** +// ZORRO-II CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_zorro2_interface - constructor +//------------------------------------------------- + +device_zorro2_card_interface::device_zorro2_card_interface(const machine_config &mconfig, device_t &device) : + device_zorro_card_interface(mconfig, device), + m_next(NULL), + m_slot(NULL) +{ +} + +//------------------------------------------------- +// ~device_zorro2_interface - destructor +//------------------------------------------------- + +device_zorro2_card_interface::~device_zorro2_card_interface() +{ +} + +void device_zorro2_card_interface::set_zorro_device() +{ + m_slot = dynamic_cast<zorro2_device *>(m_zorro); +} diff --git a/src/emu/bus/zorro/zorro.h b/src/emu/bus/zorro/zorro.h new file mode 100644 index 00000000000..d018b217374 --- /dev/null +++ b/src/emu/bus/zorro/zorro.h @@ -0,0 +1,443 @@ +/*************************************************************************** + + Amiga Zorro Slots + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + 86-pin Expansion Slot (Zorro-I), Zorro-II, Zorro-III + + 86-pin Expansion Slot + + 2 Ground 1 Ground + 4 Ground 3 Ground + 6 +5VDC 5 +5VDC + 8 -5VDC 7 N/C + 10 +12VDC 9 N/C *1 + 12 CFGIN 11 N/C *2 + 14 /C3 Clock 13 Ground + 16 /C1 Clock 15 CDAC + 18 XRDY 17 /OVR + 20 N/C *3 19 /INT2 + 22 /INT6 21 A5 + 24 A4 23 A6 + 26 A3 25 Ground + 28 A7 27 A2 + 30 A8 29 A1 + 32 A9 31 FC0 + 34 A10 33 FC1 + 36 A11 35 FC2 + 38 A12 37 Ground + 40 /IPL0 39 A13 + 42 /IPL1 41 A14 + 44 /IPL2 43 A15 + 46 /BEER 45 A16 + 48 /VPA 47 A17 + 50 E Clock 49 Ground + 52 A18 51 /VMA + 54 A19 53 /RST + 56 A20 55 /HLT + 58 A21 57 A22 + 60 /BR *4 59 A23 + 62 /BGACK 61 Ground + 64 /BG *5 63 D15 + 66 /DTACK 65 D14 + 68 R/W 67 D13 + 70 /LDS 69 D12 + 72 /UDS 71 D11 + 74 /AS 73 Ground + 76 D10 75 D0 + 78 D9 77 D1 + 80 D8 79 D2 + 82 D7 81 D3 + 84 D6 83 D4 + 86 D5 85 Ground + + *1 28 MHz Clock on A2000 and B2000 + *2 /COPCFG on B2000 + *3 /PALOPE on A1000, /BOSS on B2000 + *4 /CBR on B2000 + *5 /CBG on B2000 + + Zorro-II (differences only) + + 7 /OWN + 9 /SLAVEn + 11 /CFGOUTn + 12 /CFGINn + 20 -12VDC + 40 /EINT7 + 42 /EINT5 + 44 /EINT4 + 60 /BRn + 64 /BGn + + 88 Ground 87 Ground + 90 Ground 89 Ground + 92 7 MHz 91 Ground + 94 /BURST 93 DOE + 96 /EINT1 95 /BG *5 + 98 N/C 97 N/C + 100 Ground 99 Ground + + *6 /GBG on B2000 + + Zorro-III + + The Zorro-III is a multiplexed Zorro-II bus with address- and + data phases. Signals changes as follows: + + 17 /CINH + 18 /MTCR + 29 /LOCK + 30 AD8 (D0) + 32 AD9 (D1) + 34 AD10 (D2) + 36 AD11 (D3) + 38 AD12 (D4) + 39 AD13 (D5) + 40 Reserved + 41 AD14 (D6) + 42 Reserved + 43 AD15 (D7) + 44 Reserved + 45 AD16 (D8) + 47 AD17 (D9) + 48 /MTACK + 51 /DS0 + 52 AD18 (D10) + 54 AD19 (D11) + 56 AD20 (D12) + 57 AD22 (D14) + 58 AD21 (D13) + 59 AD23 (D15) + 63 AD31 + 65 AD30 + 67 AD29 + 69 AD28 + 70 /DS2 + 71 AD27 + 72 /DS3 + 74 /CCS + 75 SD0 (D16) + 76 AD26 + 77 SD1 (D17) + 78 AD25 + 79 SD2 (D18) + 80 AD24 + 81 SD3 (D19) + 82 SD7 (D23) + 83 SD4 (D20) + 84 SD6 (D22) + 86 SD5 (D21) + 91 Sense Z3 + 94 /IORST + 95 /BCLR + 97 /FCS + 98 /DS1 + + +***************************************************************************/ + +#pragma once + +#ifndef __ZORRO_H__ +#define __ZORRO_H__ + +#include "emu.h" + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_ZORRO_SLOT_ADD(_zorrotag, _tag, _slot_intf, _def_slot) \ + MCFG_DEVICE_ADD(_tag, ZORRO_SLOT, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \ + zorro_slot_device::set_zorro_slot(*device, owner, _zorrotag); + +// ======================> expansion slot + +#define MCFG_EXPANSION_SLOT_ADD(_cputag, _slot_intf, _def_slot) \ + MCFG_DEVICE_ADD("exp", EXP_SLOT, 0) \ + zorro_device::set_cputag(*device, _cputag); \ + MCFG_ZORRO_SLOT_ADD("exp", "slot", _slot_intf, _def_slot) + +// callbacks +#define MCFG_EXPANSION_SLOT_OVR_HANDLER(_devcb) \ + devcb = &zorro_device::set_ovr_handler(*device, DEVCB2_##_devcb); + +#define MCFG_EXPANSION_SLOT_INT2_HANDLER(_devcb) \ + devcb = &zorro_device::set_int2_handler(*device, DEVCB2_##_devcb); + +#define MCFG_EXPANSION_SLOT_INT6_HANDLER(_devcb) \ + devcb = &zorro_device::set_int6_handler(*device, DEVCB2_##_devcb); + +#define MCFG_EXPANSION_SLOT_IPL_HANDLER(_devcb) \ + devcb = &exp_slot_device::set_ipl_handler(*device, DEVCB2_##_devcb); + +// ======================> zorro 2 bus + +#define MCFG_ZORRO2_ADD(_cputag) \ + MCFG_DEVICE_ADD("zorrobus", ZORRO2, 0) \ + zorro_device::set_cputag(*device, _cputag); + +#define MCFG_ZORRO2_SLOT_ADD(_tag, _slot_intf, _def_slot) \ + MCFG_ZORRO_SLOT_ADD("zorrobus", _tag, _slot_intf, _def_slot) + +#define MCFG_ZORRO2_OVR_HANDLER(_devcb) \ + devcb = &zorro_device::set_ovr_handler(*device, DEVCB2_##_devcb); + +#define MCFG_ZORRO2_INT2_HANDLER(_devcb) \ + devcb = &zorro_device::set_int2_handler(*device, DEVCB2_##_devcb); + +#define MCFG_ZORRO2_INT6_HANDLER(_devcb) \ + devcb = &zorro_device::set_int6_handler(*device, DEVCB2_##_devcb); + +#define MCFG_ZORRO2_EINT1_HANDLER(_devcb) \ + devcb = &zorro2_device::set_eint1_handler(*device, DEVCB2_##_devcb); + +#define MCFG_ZORRO2_EINT4_HANDLER(_devcb) \ + devcb = &zorro2_device::set_eint4_handler(*device, DEVCB2_##_devcb); + +#define MCFG_ZORRO2_EINT5_HANDLER(_devcb) \ + devcb = &zorro2_device::set_eint5_handler(*device, DEVCB2_##_devcb); + +#define MCFG_ZORRO2_EINT7_HANDLER(_devcb) \ + devcb = &zorro2_device::set_eint7_handler(*device, DEVCB2_##_devcb); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// forward declaration of card interfaces +class device_zorro_card_interface; +class device_exp_card_interface; +class device_zorro2_card_interface; + +// ======================> zorro slot device + +class zorro_slot_device : public device_t, public device_slot_interface +{ +public: + // construction/destruction + zorro_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + zorro_slot_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + // device-level overrides + virtual void device_start(); + + // inline configuration + static void set_zorro_slot(device_t &device, device_t *owner, const char *zorro_tag); + +protected: + // configuration + const char *m_zorro_tag; +}; + +// device type definition +extern const device_type ZORRO_SLOT; + +// ======================> base zorro bus device + +class zorro_device : public device_t +{ +public: + // construction/destruction + zorro_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + // static configuration helpers + static void set_cputag(device_t &device, const char *tag); + + template<class _Object> static devcb2_base &set_int2_handler(device_t &device, _Object object) + { return downcast<zorro_device &>(device).m_int2_handler.set_callback(object); } + template<class _Object> static devcb2_base &set_int6_handler(device_t &device, _Object object) + { return downcast<zorro_device &>(device).m_int6_handler.set_callback(object); } + template<class _Object> static devcb2_base &set_ovr_handler(device_t &device, _Object object) + { return downcast<zorro_device &>(device).m_ovr_handler.set_callback(object); } + + virtual void add_card(device_zorro_card_interface *card) = 0; + + // interface (from slot device) + virtual DECLARE_WRITE_LINE_MEMBER( cfgout_w ) {}; + + DECLARE_WRITE_LINE_MEMBER( int2_w ); + DECLARE_WRITE_LINE_MEMBER( int6_w ); + DECLARE_WRITE_LINE_MEMBER( ovr_w ); + + // interface (from host) + virtual void fc_w(int code) = 0; + + // access to the host space + address_space *m_space; + +protected: + // device-level overrides + virtual void device_start(); + +private: + const char *m_cputag; + + devcb2_write_line m_ovr_handler; + devcb2_write_line m_int2_handler; + devcb2_write_line m_int6_handler; +}; + +// ======================> expansion slot device + +class exp_slot_device : public zorro_device +{ +public: + // construction/destruction + exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + exp_slot_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + template<class _Object> static devcb2_base &set_ipl_handler(device_t &device, _Object object) + { return downcast<exp_slot_device &>(device).m_ipl_handler.set_callback(object); } + + // the expansion slot can only have a single card + virtual void add_card(device_zorro_card_interface *card); + + // interface (from slot device) + void ipl_w(int interrupt); + + // interface (from host) + virtual void fc_w(int code); + +protected: + // device-level overrides + virtual void device_start(); + +private: + devcb2_write8 m_ipl_handler; + + device_exp_card_interface *m_dev; +}; + +// device type definition +extern const device_type EXP_SLOT; + +// ======================> zorro2 slot device + +class zorro2_device : public zorro_device +{ +public: + // construction/destruction + zorro2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + zorro2_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + template<class _Object> static devcb2_base &set_eint1_handler(device_t &device, _Object object) + { return downcast<zorro2_device &>(device).m_eint1_handler.set_callback(object); } + template<class _Object> static devcb2_base &set_eint4_handler(device_t &device, _Object object) + { return downcast<zorro2_device &>(device).m_eint4_handler.set_callback(object); } + template<class _Object> static devcb2_base &set_eint5_handler(device_t &device, _Object object) + { return downcast<zorro2_device &>(device).m_eint5_handler.set_callback(object); } + template<class _Object> static devcb2_base &set_eint7_handler(device_t &device, _Object object) + { return downcast<zorro2_device &>(device).m_eint7_handler.set_callback(object); } + + // device-level overrides + virtual void device_reset(); + + // the zorro2 bus supports multiple cards + virtual void add_card(device_zorro_card_interface *card); + + // interface (from slot device) + virtual DECLARE_WRITE_LINE_MEMBER( cfgout_w ); + + DECLARE_WRITE_LINE_MEMBER( eint1_w ); + DECLARE_WRITE_LINE_MEMBER( eint4_w ); + DECLARE_WRITE_LINE_MEMBER( eint5_w ); + DECLARE_WRITE_LINE_MEMBER( eint7_w ); + + // interface (from host) + virtual void fc_w(int code); + +protected: + // device-level overrides + virtual void device_start(); + +private: + devcb2_write_line m_eint1_handler; + devcb2_write_line m_eint4_handler; + devcb2_write_line m_eint5_handler; + devcb2_write_line m_eint7_handler; + + simple_list<device_zorro2_card_interface> m_dev; + + // the device which is currently configuring + device_zorro2_card_interface *m_autoconfig_device; +}; + +// device type definition +extern const device_type ZORRO2; + + +// ======================> base zorro card interface + +class device_zorro_card_interface : public device_slot_card_interface +{ +public: + // construction/destruction + device_zorro_card_interface(const machine_config &mconfig, device_t &device); + virtual ~device_zorro_card_interface(); + + virtual void set_zorro_device() = 0; + + void set_zorro_bus(zorro_device *device); + + // interface (from device) + void cfgout_w(int state) { m_zorro->cfgout_w(state); } + + // interface (from host) + virtual void fc_w(int code); + virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ); + +protected: + zorro_device *m_zorro; +}; + +// ======================> expansion slot card interface + +class device_exp_card_interface : public device_zorro_card_interface +{ +public: + // construction/destruction + device_exp_card_interface(const machine_config &mconfig, device_t &device); + virtual ~device_exp_card_interface(); + + virtual void set_zorro_device(); + +protected: + exp_slot_device *m_slot; +}; + +// ======================> zorro2 card interface + +class device_zorro2_card_interface : public device_zorro_card_interface +{ +public: + // construction/destruction + device_zorro2_card_interface(const machine_config &mconfig, device_t &device); + virtual ~device_zorro2_card_interface(); + + virtual void set_zorro_device(); + + device_zorro2_card_interface *next() const { return m_next; } + device_zorro2_card_interface *m_next; + +protected: + zorro2_device *m_slot; +}; + + +// include this here so that you don't need to include it into every +// driver that uses zorro slots +#include "cards.h" + + +#endif // __ZORRO_H__ diff --git a/src/emu/machine/6525tpi.c b/src/emu/machine/6525tpi.c index 2d83a49527b..4589ff23ea7 100644 --- a/src/emu/machine/6525tpi.c +++ b/src/emu/machine/6525tpi.c @@ -535,6 +535,12 @@ WRITE8_MEMBER( tpi6525_device::write ) } } +void tpi6525_device::port_line_w(UINT8 &port, int line, int state) +{ + port &= ~(1 << line); + port |= state << line; +} + /* this should probably be done better, needed for amigacd.c */ UINT8 tpi6525_device::get_ddr_a() diff --git a/src/emu/machine/6525tpi.h b/src/emu/machine/6525tpi.h index 6132fa45c18..a6bcea1f3c1 100644 --- a/src/emu/machine/6525tpi.h +++ b/src/emu/machine/6525tpi.h @@ -66,6 +66,15 @@ public: DECLARE_WRITE8_MEMBER( pb_w ); DECLARE_WRITE8_MEMBER( pc_w ); + WRITE_LINE_MEMBER( pb0_w ) { port_line_w(m_in_b, 0, state); } + WRITE_LINE_MEMBER( pb1_w ) { port_line_w(m_in_b, 1, state); } + WRITE_LINE_MEMBER( pb2_w ) { port_line_w(m_in_b, 2, state); } + WRITE_LINE_MEMBER( pb3_w ) { port_line_w(m_in_b, 3, state); } + WRITE_LINE_MEMBER( pb4_w ) { port_line_w(m_in_b, 4, state); } + WRITE_LINE_MEMBER( pb5_w ) { port_line_w(m_in_b, 5, state); } + WRITE_LINE_MEMBER( pb6_w ) { port_line_w(m_in_b, 6, state); } + WRITE_LINE_MEMBER( pb7_w ) { port_line_w(m_in_b, 7, state); } + UINT8 get_ddr_a(); UINT8 get_ddr_b(); UINT8 get_ddr_c(); @@ -104,6 +113,9 @@ private: void set_interrupt(); void clear_interrupt(); + + // helper function to write a single line + static void port_line_w(UINT8 &port, int line, int state); }; extern const device_type TPI6525; diff --git a/src/emu/machine/akiko.c b/src/emu/machine/akiko.c new file mode 100644 index 00000000000..c9eb0a30114 --- /dev/null +++ b/src/emu/machine/akiko.c @@ -0,0 +1,925 @@ +/*************************************************************************** + + Akiko + + ASIC used in the Amiga CD32. Commodore Part number 391563-01. + + - CD-ROM controller + - Builtin 1KB NVRAM + - Chunky to planar converter + - 2x CIA chips + +***************************************************************************/ + +#include "akiko.h" +#include "includes/amiga.h" +#include "imagedev/chd_cd.h" +#include "coreutil.h" + + +//************************************************************************** +// CONSTANTS / MACROS +//************************************************************************** + +#define LOG_AKIKO 0 +#define LOG_AKIKO_CD 0 + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type AKIKO = &device_creator<akiko_device>; + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +static MACHINE_CONFIG_FRAGMENT( akiko ) +MACHINE_CONFIG_END + +machine_config_constructor akiko_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( akiko ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// akiko_device - constructor +//------------------------------------------------- + +akiko_device::akiko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, AKIKO, "CBM AKIKO", tag, owner, clock, "akiko", __FILE__), + m_c2p_input_index(0), + m_c2p_output_index(0), + m_i2c_scl_out(0), + m_i2c_scl_dir(0), + m_i2c_sda_out(0), + m_i2c_sda_dir(0), + m_cdrom_track_index(0), + m_cdrom_lba_start(0), + m_cdrom_lba_end(0), + m_cdrom_lba_cur(0), + m_cdrom_readmask(0), + m_cdrom_readreqmask(0), + m_cdrom_dmacontrol(0), + m_cdrom_numtracks(0), + m_cdrom_speed(0), + m_cdrom_cmd_start(0), + m_cdrom_cmd_end(0), + m_cdrom_cmd_resp(0), + m_cdda(NULL), + m_cdrom(NULL), + m_cdrom_toc(NULL), + m_dma_timer(NULL), + m_frame_timer(NULL), + m_cdrom_is_device(0), + m_scl_w(*this), + m_sda_r(*this), + m_sda_w(*this) +{ + for (int i = 0; i < 8; i++) + { + m_c2p_input_buffer[i] = 0; + m_c2p_output_buffer[i] = 0; + } + + for (int i = 0; i < 2; i++) + { + m_cdrom_status[i] = 0; + m_cdrom_address[i] = 0; + } +} + + +//------------------------------------------------- +// set_cputag - set cpu tag for cpu we working on +//------------------------------------------------- + +void akiko_device::set_cputag(device_t &device, const char *tag) +{ + akiko_device &akiko = downcast<akiko_device &>(device); + akiko.m_cputag = tag; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void akiko_device::device_start() +{ + // resolve callbacks + m_scl_w.resolve_safe(); + m_sda_r.resolve_safe(1); + m_sda_w.resolve_safe(); + + m_c2p_input_index = 0; + m_c2p_output_index = 0; + + m_i2c_scl_out = 0; + m_i2c_scl_dir = 0; + m_i2c_sda_out = 0; + m_i2c_sda_dir = 0; + + m_cdrom_status[0] = m_cdrom_status[1] = 0; + m_cdrom_address[0] = m_cdrom_address[1] = 0; + m_cdrom_track_index = 0; + m_cdrom_lba_start = 0; + m_cdrom_lba_end = 0; + m_cdrom_lba_cur = 0; + m_cdrom_readmask = 0; + m_cdrom_readreqmask = 0; + m_cdrom_dmacontrol = 0; + m_cdrom_numtracks = 0; + m_cdrom_speed = 0; + m_cdrom_cmd_start = 0; + m_cdrom_cmd_end = 0; + m_cdrom_cmd_resp = 0; + + device_t *cpu = machine().device(m_cputag); + m_space = &cpu->memory().space(AS_PROGRAM); + + m_cdrom_toc = NULL; + m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(akiko_device::dma_proc), this)); + m_frame_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(akiko_device::frame_proc), this)); + m_cdda = machine().device<cdda_device>("cdda"); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void akiko_device::device_reset() +{ + cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom"); + + if (cddevice != NULL) + { + // MESS case + m_cdrom = cddevice->get_cdrom_file(); + m_cdrom_is_device = 1; + } + else + { + // MAME case + m_cdrom = cdrom_open(get_disk_handle(machine(), ":cdrom")); + m_cdrom_is_device = 0; + } + + /* create the TOC table */ + if ( m_cdrom != NULL && cdrom_get_last_track(m_cdrom) ) + { + UINT8 *p; + int i, addrctrl = cdrom_get_adr_control( m_cdrom, 0 ); + UINT32 discend; + + discend = cdrom_get_track_start(m_cdrom,cdrom_get_last_track(m_cdrom)-1); + discend += cdrom_get_toc(m_cdrom)->tracks[cdrom_get_last_track(m_cdrom)-1].frames; + discend = lba_to_msf(discend); + + m_cdrom_numtracks = cdrom_get_last_track(m_cdrom)+3; + + m_cdrom_toc = auto_alloc_array(machine(), UINT8, 13*m_cdrom_numtracks); + memset( m_cdrom_toc, 0, 13*m_cdrom_numtracks); + + p = m_cdrom_toc; + p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4); + p[3] = 0xa0; /* first track */ + p[8] = 1; + p += 13; + p[1] = 0x01; + p[3] = 0xa1; /* last track */ + p[8] = cdrom_get_last_track(m_cdrom); + p += 13; + p[1] = 0x01; + p[3] = 0xa2; /* disc end */ + p[8] = (discend >> 16 ) & 0xff; + p[9] = (discend >> 8 ) & 0xff; + p[10] = discend & 0xff; + p += 13; + + for( i = 0; i < cdrom_get_last_track(m_cdrom); i++ ) + { + UINT32 trackpos = cdrom_get_track_start(m_cdrom,i); + + trackpos = lba_to_msf(trackpos); + addrctrl = cdrom_get_adr_control( m_cdrom, i ); + + p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4); + p[3] = dec_2_bcd( i+1 ); + p[8] = (trackpos >> 16 ) & 0xff; + p[9] = (trackpos >> 8 ) & 0xff; + p[10] = trackpos & 0xff; + + p += 13; + } + } + +} + +//------------------------------------------------- +// device_stop - device-specific stop +//------------------------------------------------- + +void akiko_device::device_stop() +{ + if (!m_cdrom_is_device) + { + if( m_cdrom ) + { + cdrom_close(m_cdrom); + m_cdrom = (cdrom_file *)NULL; + } + } +} + +void akiko_device::nvram_write(UINT32 data) +{ + m_i2c_scl_out = BIT(data, 31); + m_i2c_sda_out = BIT(data, 30); + m_i2c_scl_dir = BIT(data, 15); + m_i2c_sda_dir = BIT(data, 14); + + m_scl_w(m_i2c_scl_out); + m_sda_w(m_i2c_sda_out); +} + +UINT32 akiko_device::nvram_read() +{ + UINT32 v = 0; + + if (m_i2c_scl_dir) + v |= m_i2c_scl_out << 31; + + if (m_i2c_sda_dir) + v |= m_i2c_sda_out << 30; + else + v |= m_sda_r() << 30; + + v |= m_i2c_scl_dir << 15; + v |= m_i2c_sda_dir << 14; + + return v; +} + +/************************************* + * + * Akiko Chunky to Planar converter + * + ************************************/ + +void akiko_device::c2p_write(UINT32 data) +{ + m_c2p_input_buffer[m_c2p_input_index] = data; + m_c2p_input_index++; + m_c2p_input_index &= 7; + m_c2p_output_index = 0; +} + +UINT32 akiko_device::c2p_read() +{ + UINT32 val; + + if ( m_c2p_output_index == 0 ) + { + int i; + + for ( i = 0; i < 8; i++ ) + m_c2p_output_buffer[i] = 0; + + for (i = 0; i < 8 * 32; i++) + { + if (m_c2p_input_buffer[7 - (i >> 5)] & (1 << (i & 31))) + m_c2p_output_buffer[i & 7] |= 1 << (i >> 3); + } + } + m_c2p_input_index = 0; + val = m_c2p_output_buffer[m_c2p_output_index]; + m_c2p_output_index++; + m_c2p_output_index &= 7; + return val; +} + +static const char *const akiko_reg_names[] = +{ + /*0*/ "ID", + /*1*/ "CDROM STATUS 1", + /*2*/ "CDROM_STATUS 2", + /*3*/ "???", + /*4*/ "CDROM ADDRESS 1", + /*5*/ "CDROM ADDRESS 2", + /*6*/ "CDROM COMMAND 1", + /*7*/ "CDROM COMMAND 2", + /*8*/ "CDROM READMASK", + /*9*/ "CDROM DMACONTROL", + /*A*/ "???", + /*B*/ "???", + /*C*/ "NVRAM", + /*D*/ "???", + /*E*/ "C2P" +}; + +static const char* get_akiko_reg_name(int reg) +{ + if (reg < 0xf ) + { + return akiko_reg_names[reg]; + } + else + { + return "???"; + } +} + +/************************************* + * + * Akiko CDROM Controller + * + ************************************/ + +void akiko_device::cdda_stop() +{ + if (m_cdda != NULL) + { + m_cdda->stop_audio(); + m_frame_timer->reset( ); + } +} + +void akiko_device::cdda_play(UINT32 lba, UINT32 num_blocks) +{ + if (m_cdda != NULL) + { + m_cdda->start_audio(lba, num_blocks); + m_frame_timer->adjust( attotime::from_hz( 75 ) ); + } +} + +void akiko_device::cdda_pause(int pause) +{ + if (m_cdda != NULL) + { + if (m_cdda->audio_active() && m_cdda->audio_paused() != pause ) + { + m_cdda->pause_audio(pause); + + if ( pause ) + { + m_frame_timer->reset( ); + } + else + { + m_frame_timer->adjust( attotime::from_hz( 75 ) ); + } + } + } +} + +UINT8 akiko_device::cdda_getstatus(UINT32 *lba) +{ + if ( lba ) *lba = 0; + + if (m_cdda != NULL) + { + if (m_cdda->audio_active()) + { + if ( lba ) *lba = m_cdda->get_audio_lba(); + + if (m_cdda->audio_paused()) + { + return 0x12; /* audio paused */ + } + else + { + return 0x11; /* audio in progress */ + } + } + else if (m_cdda->audio_ended()) + { + return 0x13; /* audio ended */ + } + } + + return 0x15; /* no audio status */ +} + +void akiko_device::set_cd_status(UINT32 status) +{ + amiga_state *amiga = machine().driver_data<amiga_state>(); + + m_cdrom_status[0] |= status; + + if ( m_cdrom_status[0] & m_cdrom_status[1] ) + { + if (LOG_AKIKO_CD) + logerror("Akiko CD IRQ\n"); + + amiga->custom_chip_w(REG_INTREQ, INTENA_SETCLR | INTENA_PORTS); + } +} + +TIMER_CALLBACK_MEMBER(akiko_device::frame_proc) +{ + (void)param; + + if (m_cdda != NULL) + { + UINT8 s = cdda_getstatus(NULL); + + if ( s == 0x11 ) + { + set_cd_status(0x80000000); /* subcode ready */ + } + + m_frame_timer->adjust( attotime::from_hz( 75 ) ); + } +} + +static UINT32 lba_from_triplet( UINT8 *triplet ) +{ + UINT32 r; + + r = bcd_2_dec(triplet[0]) * (60*75); + r += bcd_2_dec(triplet[1]) * 75; + r += bcd_2_dec(triplet[2]); + + return r; +} + +TIMER_CALLBACK_MEMBER(akiko_device::dma_proc) +{ + UINT8 buf[2352]; + int index; + + if ( (m_cdrom_dmacontrol & 0x04000000) == 0 ) + return; + + if ( m_cdrom_readreqmask == 0 ) + return; + + index = (m_cdrom_lba_cur - m_cdrom_lba_start) & 0x0f; + + if ( m_cdrom_readreqmask & ( 1 << index ) ) + { + amiga_state *amiga = machine().driver_data<amiga_state>(); + UINT32 track = cdrom_get_track( m_cdrom, m_cdrom_lba_cur ); + UINT32 datasize = cdrom_get_toc( m_cdrom )->tracks[track].datasize; + UINT32 subsize = cdrom_get_toc( m_cdrom )->tracks[track].subsize; + int i; + + UINT32 curmsf = lba_to_msf( m_cdrom_lba_cur ); + memset( buf, 0, 16 ); + + buf[3] = m_cdrom_lba_cur - m_cdrom_lba_start; + memset( &buf[4], 0xff, 8 ); + + buf[12] = (curmsf >> 16) & 0xff; + buf[13] = (curmsf >> 8) & 0xff; + buf[14] = curmsf & 0xff; + buf[15] = 0x01; /* mode1 */ + + datasize = 2048; + if ( !cdrom_read_data( m_cdrom, m_cdrom_lba_cur, &buf[16], CD_TRACK_MODE1 ) ) + { + logerror( "AKIKO: Read error trying to read sector %08x!\n", m_cdrom_lba_cur ); + return; + } + + if ( subsize ) + { + if ( !cdrom_read_subcode( m_cdrom, m_cdrom_lba_cur, &buf[16+datasize] ) ) + { + logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", m_cdrom_lba_cur ); + return; + } + } + + if (LOG_AKIKO_CD) logerror( "DMA: sector %d - address %08x\n", m_cdrom_lba_cur, m_cdrom_address[0] + (index*4096) ); + + for( i = 0; i < 2352; i += 2 ) + { + UINT16 data; + + data = buf[i]; + data <<= 8; + data |= buf[i+1]; + + (*amiga->m_chip_ram_w)( amiga, m_cdrom_address[0] + (index*4096) + i, data ); + } + + m_cdrom_readmask |= ( 1 << index ); + m_cdrom_readreqmask &= ~( 1 << index ); + m_cdrom_lba_cur++; + } + + if ( m_cdrom_readreqmask == 0 ) + set_cd_status(0x04000000); + else + m_dma_timer->adjust( attotime::from_usec( CD_SECTOR_TIME / m_cdrom_speed ) ); +} + +void akiko_device::start_dma() +{ + if ( m_cdrom_readreqmask == 0 ) + return; + + if ( m_cdrom_lba_start > m_cdrom_lba_end ) + return; + + if ( m_cdrom_speed == 0 ) + return; + + m_cdrom_lba_cur = m_cdrom_lba_start; + + m_dma_timer->adjust( attotime::from_usec( CD_SECTOR_TIME / m_cdrom_speed ) ); +} + +void akiko_device::setup_response( int len, UINT8 *r1 ) +{ + int resp_addr = m_cdrom_address[1]; + UINT8 resp_csum = 0xff; + UINT8 resp_buffer[32]; + int i; + + memset( resp_buffer, 0, sizeof( resp_buffer ) ); + + for( i = 0; i < len; i++ ) + { + resp_buffer[i] = r1[i]; + resp_csum -= resp_buffer[i]; + } + + resp_buffer[len++] = resp_csum; + + for( i = 0; i < len; i++ ) + { + m_space->write_byte( resp_addr + ((m_cdrom_cmd_resp + i) & 0xff), resp_buffer[i] ); + } + + m_cdrom_cmd_resp = (m_cdrom_cmd_resp+len) & 0xff; + + set_cd_status(0x10000000); /* new data available */ +} + +TIMER_CALLBACK_MEMBER( akiko_device::cd_delayed_cmd ) +{ + UINT8 resp[32]; + UINT8 cddastatus; + + if ( m_cdrom_status[0] & 0x10000000 ) + return; + + cddastatus = cdda_getstatus(NULL); + + if ( cddastatus == 0x11 || cddastatus == 0x12 ) + return; + + memset( resp, 0, sizeof( resp ) ); + resp[0] = param; + + param &= 0x0f; + + if ( param == 0x05 ) + { + if (LOG_AKIKO_CD) logerror( "AKIKO: Completing Command %d\n", param ); + + resp[0] = 0x06; + + if ( m_cdrom == NULL || m_cdrom_numtracks == 0 ) + { + resp[1] = 0x80; + setup_response( 15, resp ); + } + else + { + resp[1] = 0x00; + memcpy( &resp[2], &m_cdrom_toc[13*m_cdrom_track_index], 13 ); + + m_cdrom_track_index = ( m_cdrom_track_index + 1 ) % m_cdrom_numtracks; + + setup_response( 15, resp ); + } + } +} + +void akiko_device::update_cdrom() +{ + UINT8 resp[32], cmdbuf[32]; + + if ( m_cdrom_status[0] & 0x10000000 ) + return; + + while ( m_cdrom_cmd_start != m_cdrom_cmd_end ) + { + UINT32 cmd_addr = m_cdrom_address[1] + 0x200 + m_cdrom_cmd_start; + int cmd = m_space->read_byte( cmd_addr ); + + memset( resp, 0, sizeof( resp ) ); + resp[0] = cmd; + + cmd &= 0x0f; + + if (LOG_AKIKO_CD) logerror( "CDROM command: %02X\n", cmd ); + + if ( cmd == 0x02 ) /* pause audio */ + { + resp[1] = 0x00; + + if ( cdda_getstatus(NULL) == 0x11 ) + resp[1] = 0x08; + + cdda_pause(1); + + m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff; + + setup_response( 2, resp ); + } + else if ( cmd == 0x03 ) /* unpause audio (and check audiocd playing status) */ + { + resp[1] = 0x00; + + if ( cdda_getstatus(NULL) == 0x11 ) + resp[1] = 0x08; + + cdda_pause(0); + + m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff; + + setup_response( 2, resp ); + } + else if ( cmd == 0x04 ) /* seek/read/play cd multi command */ + { + int i; + UINT32 startpos, endpos; + + for( i = 0; i < 13; i++ ) + { + cmdbuf[i] = m_space->read_byte( cmd_addr ); + cmd_addr &= 0xffffff00; + cmd_addr += ( m_cdrom_cmd_start + i + 1 ) & 0xff; + } + + m_cdrom_cmd_start = (m_cdrom_cmd_start+13) & 0xff; + + if ( m_cdrom == NULL || m_cdrom_numtracks == 0 ) + { + resp[1] = 0x80; + setup_response( 2, resp ); + } + else + { + startpos = lba_from_triplet( &cmdbuf[1] ); + endpos = lba_from_triplet( &cmdbuf[4] ); + + cdda_stop(); + + resp[1] = 0x00; + + if ( cmdbuf[7] == 0x80 ) + { + if (LOG_AKIKO_CD) logerror( "%s:AKIKO CD: Data read - start lba: %08x - end lba: %08x\n", machine().describe_context(), startpos, endpos ); + m_cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1; + m_cdrom_lba_start = startpos; + m_cdrom_lba_end = endpos; + + resp[1] = 0x02; + } + else if ( cmdbuf[10] & 0x04 ) + { + logerror( "AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos ); + cdda_play(startpos, endpos - startpos); + resp[1] = 0x08; + } + else + { + if (LOG_AKIKO_CD) logerror( "AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos ); + m_cdrom_track_index = 0; + + for( i = 0; i < cdrom_get_last_track(m_cdrom); i++ ) + { + if ( startpos <= cdrom_get_track_start( m_cdrom, i ) ) + { + /* reset to 0 */ + m_cdrom_track_index = i + 2; + m_cdrom_track_index %= m_cdrom_numtracks; + break; + } + } + } + + setup_response( 2, resp ); + } + } + else if ( cmd == 0x05 ) /* read toc */ + { + m_cdrom_cmd_start = (m_cdrom_cmd_start+3) & 0xff; + + machine().scheduler().timer_set( attotime::from_msec(1), timer_expired_delegate(FUNC(akiko_device::cd_delayed_cmd ), this), resp[0]); + + break; + } + else if ( cmd == 0x06 ) /* read subq */ + { + UINT32 lba; + + resp[1] = 0x00; + + (void)cdda_getstatus(&lba); + + if ( lba > 0 ) + { + UINT32 disk_pos; + UINT32 track_pos; + UINT32 track; + int addrctrl; + + track = cdrom_get_track(m_cdrom, lba); + addrctrl = cdrom_get_adr_control(m_cdrom, track); + + resp[2] = 0x00; + resp[3] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4); + resp[4] = dec_2_bcd(track+1); + resp[5] = 0; /* index */ + + disk_pos = lba_to_msf(lba); + track_pos = lba_to_msf(lba - cdrom_get_track_start(m_cdrom, track)); + + /* track position */ + resp[6] = (track_pos >> 16) & 0xff; + resp[7] = (track_pos >> 8) & 0xff; + resp[8] = track_pos & 0xff; + + /* disk position */ + resp[9] = (disk_pos >> 24) & 0xff; + resp[10] = (disk_pos >> 16) & 0xff; + resp[11] = (disk_pos >> 8) & 0xff; + resp[12] = disk_pos & 0xff; + } + else + { + resp[1] = 0x80; + } + + setup_response( 15, resp ); + } + else if ( cmd == 0x07 ) /* check door status */ + { + resp[1] = 0x01; + + m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff; + + if ( m_cdrom == NULL || m_cdrom_numtracks == 0 ) + resp[1] = 0x80; + + setup_response( 20, resp ); + break; + } + else + { + break; + } + } +} + +READ32_MEMBER( akiko_device::read ) +{ + UINT32 retval; + + if ( LOG_AKIKO && offset < (0x30/4) ) + { + logerror( "Reading AKIKO reg %0x [%s] at PC=%06x\n", offset, get_akiko_reg_name(offset), m_space->device().safe_pc() ); + } + + switch( offset ) + { + case 0x00/4: /* ID */ + if ( m_cdrom != NULL ) m_cdda->set_cdrom(m_cdrom); + return 0x0000cafe; + + case 0x04/4: /* CDROM STATUS 1 */ + return m_cdrom_status[0]; + + case 0x08/4: /* CDROM STATUS 2 */ + return m_cdrom_status[1]; + + case 0x10/4: /* CDROM ADDRESS 1 */ + return m_cdrom_address[0]; + + case 0x14/4: /* CDROM ADDRESS 2 */ + return m_cdrom_address[1]; + + case 0x18/4: /* CDROM COMMAND 1 */ + update_cdrom(); + retval = m_cdrom_cmd_start; + retval <<= 8; + retval |= m_cdrom_cmd_resp; + retval <<= 8; + return retval; + + case 0x1C/4: /* CDROM COMMAND 2 */ + update_cdrom(); + retval = m_cdrom_cmd_end; + retval <<= 16; + return retval; + + case 0x20/4: /* CDROM DMA SECTOR READ MASK */ + retval = m_cdrom_readmask << 16; + return retval; + + case 0x24/4: /* CDROM DMA ENABLE? */ + retval = m_cdrom_dmacontrol; + return retval; + + case 0x30/4: /* NVRAM */ + return nvram_read(); + + case 0x38/4: /* C2P */ + return c2p_read(); + + default: + break; + } + + return 0; +} + +WRITE32_MEMBER( akiko_device::write ) +{ + if ( LOG_AKIKO && offset < (0x30/4) ) + { + logerror( "Writing AKIKO reg %0x [%s] with %08x at PC=%06x\n", offset, get_akiko_reg_name(offset), data, m_space->device().safe_pc() ); + } + + switch( offset ) + { + case 0x04/4: /* CDROM STATUS 1 */ + m_cdrom_status[0] = data; + break; + + case 0x08/4: /* CDROM STATUS 2 */ + m_cdrom_status[1] = data; + m_cdrom_status[0] &= data; + break; + + case 0x10/4: /* CDROM ADDRESS 1 */ + m_cdrom_address[0] = data; + break; + + case 0x14/4: /* CDROM ADDRESS 2 */ + m_cdrom_address[1] = data; + break; + + case 0x18/4: /* CDROM COMMAND 1 */ + if ( ACCESSING_BITS_16_23 ) + m_cdrom_cmd_start = ( data >> 16 ) & 0xff; + + if ( ACCESSING_BITS_8_15 ) + m_cdrom_cmd_resp = ( data >> 8 ) & 0xff; + + update_cdrom(); + break; + + case 0x1C/4: /* CDROM COMMAND 2 */ + if ( ACCESSING_BITS_16_23 ) + m_cdrom_cmd_end = ( data >> 16 ) & 0xff; + + update_cdrom(); + break; + + case 0x20/4: /* CDROM DMA SECTOR READ REQUEST WRITE */ + if (LOG_AKIKO_CD) logerror( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask ); + if ( ACCESSING_BITS_16_31 ) + { + m_cdrom_readreqmask = (data >> 16); + m_cdrom_readmask = 0; + } + break; + + case 0x24/4: /* CDROM DMA ENABLE? */ + if (LOG_AKIKO_CD) logerror( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask ); + if ( ( m_cdrom_dmacontrol ^ data ) & 0x04000000 ) + { + if ( data & 0x04000000 ) + start_dma(); + } + m_cdrom_dmacontrol = data; + break; + + case 0x30/4: + nvram_write(data); + break; + + case 0x38/4: + c2p_write(data); + break; + + default: + break; + } +} diff --git a/src/emu/machine/akiko.h b/src/emu/machine/akiko.h new file mode 100644 index 00000000000..47fa22fee19 --- /dev/null +++ b/src/emu/machine/akiko.h @@ -0,0 +1,153 @@ +/*************************************************************************** + + Akiko + + Used in the Amiga CD32 + + - CD-ROM controller + - Builtin 1KB NVRAM + - Chunky to planar converter + +***************************************************************************/ + +#pragma once + +#ifndef __AKIKO_H__ +#define __AKIKO_H__ + +#include "emu.h" +#include "cdrom.h" +#include "sound/cdda.h" + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_AKIKO_ADD(_tag, _cputag) \ + MCFG_DEVICE_ADD(_tag, AKIKO, 0) \ + akiko_device::set_cputag(*device, _cputag); + +#define MCFG_AKIKO_SCL_HANDLER(_devcb) \ + devcb = &akiko_device::set_scl_handler(*device, DEVCB2_##_devcb); + +#define MCFG_AKIKO_SDA_READ_HANDLER(_devcb) \ + devcb = &akiko_device::set_sda_read_handler(*device, DEVCB2_##_devcb); + +#define MCFG_AKIKO_SDA_WRITE_HANDLER(_devcb) \ + devcb = &akiko_device::set_sda_write_handler(*device, DEVCB2_##_devcb); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> akiko_device + +class akiko_device : public device_t +{ +public: + akiko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + ~akiko_device() {} + + // callbacks + template<class _Object> static devcb2_base &set_scl_handler(device_t &device, _Object object) + { return downcast<akiko_device &>(device).m_scl_w.set_callback(object); } + + template<class _Object> static devcb2_base &set_sda_read_handler(device_t &device, _Object object) + { return downcast<akiko_device &>(device).m_sda_r.set_callback(object); } + + template<class _Object> static devcb2_base &set_sda_write_handler(device_t &device, _Object object) + { return downcast<akiko_device &>(device).m_sda_w.set_callback(object); } + + DECLARE_READ32_MEMBER( read ); + DECLARE_WRITE32_MEMBER( write ); + + // inline configuration + static void set_cputag(device_t &device, const char *tag); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_stop(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + +private: + // 1X CDROM sector time in msec (300KBps) + static const int CD_SECTOR_TIME = (1000/((150*1024)/2048)); + + // internal state + address_space *m_space; + + // chunky to planar converter + UINT32 m_c2p_input_buffer[8]; + UINT32 m_c2p_output_buffer[8]; + UINT32 m_c2p_input_index; + UINT32 m_c2p_output_index; + + // i2c bus + int m_i2c_scl_out; + int m_i2c_scl_dir; + int m_i2c_sda_out; + int m_i2c_sda_dir; + + // cdrom + UINT32 m_cdrom_status[2]; + UINT32 m_cdrom_address[2]; + UINT32 m_cdrom_track_index; + UINT32 m_cdrom_lba_start; + UINT32 m_cdrom_lba_end; + UINT32 m_cdrom_lba_cur; + UINT16 m_cdrom_readmask; + UINT16 m_cdrom_readreqmask; + UINT32 m_cdrom_dmacontrol; + UINT32 m_cdrom_numtracks; + UINT8 m_cdrom_speed; + UINT8 m_cdrom_cmd_start; + UINT8 m_cdrom_cmd_end; + UINT8 m_cdrom_cmd_resp; + + cdda_device *m_cdda; + cdrom_file *m_cdrom; + + UINT8 *m_cdrom_toc; + + emu_timer *m_dma_timer; + emu_timer *m_frame_timer; + + int m_cdrom_is_device; + + void nvram_write(UINT32 data); + UINT32 nvram_read(); + + void c2p_write(UINT32 data); + UINT32 c2p_read(); + + void cdda_stop(); + void cdda_play(UINT32 lba, UINT32 num_blocks); + void cdda_pause(int pause); + UINT8 cdda_getstatus(UINT32 *lba); + void set_cd_status(UINT32 status); + + TIMER_CALLBACK_MEMBER( frame_proc ); + TIMER_CALLBACK_MEMBER( dma_proc ); + + void start_dma(); + void setup_response( int len, UINT8 *r1 ); + + TIMER_CALLBACK_MEMBER( cd_delayed_cmd ); + void update_cdrom(); + + // i2c interface + devcb2_write_line m_scl_w; + devcb2_read_line m_sda_r; + devcb2_write_line m_sda_w; + + const char *m_cputag; +}; + +// device type definition +extern const device_type AKIKO; + +#endif diff --git a/src/emu/machine/amigafdc.c b/src/emu/machine/amigafdc.c index 2349a3b7ce0..334c2032a11 100644 --- a/src/emu/machine/amigafdc.c +++ b/src/emu/machine/amigafdc.c @@ -63,8 +63,7 @@ void amiga_fdc::dma_done() { amiga_state *state = machine().driver_data<amiga_state>(); dma_state = DMA_IDLE; - address_space &space = *state->m_maincpu_program_space; - state->amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKBLK, 0xffff); + state->custom_chip_w(REG_INTREQ, INTENA_SETCLR | INTENA_DSKBLK); } void amiga_fdc::dma_write(UINT16 value) @@ -202,8 +201,7 @@ void amiga_fdc::live_run(attotime limit) cur_live.bit_counter = 0; } dskbyt |= 0x1000; - address_space &space = *state->m_maincpu_program_space; - state->amiga_custom_w(space, REG_INTREQ, 0x8000 | INTENA_DSKSYN, 0xffff); + state->custom_chip_w(REG_INTREQ, INTENA_SETCLR | INTENA_DSKSYN); } else dskbyt &= ~0x1000; @@ -412,6 +410,7 @@ UINT8 amiga_fdc::ciaapra_r() if(!floppy->dskchg_r()) ret &= ~0x04; } + return ret; } diff --git a/src/emu/machine/autoconfig.c b/src/emu/machine/autoconfig.c new file mode 100644 index 00000000000..3c93efa6cff --- /dev/null +++ b/src/emu/machine/autoconfig.c @@ -0,0 +1,167 @@ +/*************************************************************************** + + Amiga Autoconfig + +***************************************************************************/ + +#include "autoconfig.h" + + +//************************************************************************** +// CONSTANTS & MACROS +//************************************************************************** + +#define VERBOSE 1 + + +//************************************************************************** +// CONSTRUCTOR +//************************************************************************** + +amiga_autoconfig::amiga_autoconfig() +{ + memset(m_cfg, 0xff, sizeof(m_cfg)); + + // interrupt status register, not inverted + m_cfg[0x20] = 0; + m_cfg[0x21] = 0; +} + +amiga_autoconfig::~amiga_autoconfig() +{ +} + + +//************************************************************************** +// AUTOCONFIG INFO SETTERS +//************************************************************************** + +void amiga_autoconfig::autoconfig_board_type(board_type type) +{ + m_cfg[0x00] &= 0x3000; + m_cfg[0x00] |= (type << 2) << 12; +} + +void amiga_autoconfig::autoconfig_board_size(board_size size) +{ + m_cfg[0x01] &= 0x8000; + m_cfg[0x01] |= (size << 0) << 12; +} + +void amiga_autoconfig::autoconfig_rom_vector_valid(bool state) +{ + m_cfg[0x00] &= 0xe000; + m_cfg[0x00] |= (state ? 0x01 : 0x00) << 12; +} + +void amiga_autoconfig::autoconfig_link_into_memory(bool state) +{ + m_cfg[0x00] &= 0xd000; + m_cfg[0x00] |= (state ? 0x02 : 0x00) << 12; +} + +void amiga_autoconfig::autoconfig_multi_device(bool state) +{ + m_cfg[0x01] &= 0x7000; + m_cfg[0x01] |= (state ? 0x08 : 0x00) << 12; +} + +void amiga_autoconfig::autoconfig_8meg_preferred(bool state) +{ + m_cfg[0x04] &= 0x7000; + m_cfg[0x04] |= (state ? 0x08 : 0x00) << 12; +} + +void amiga_autoconfig::autoconfig_can_shutup(bool state) +{ + m_cfg[0x04] &= 0xb000; + m_cfg[0x04] |= (state ? 0x04 : 0x00) << 12; +} + +void amiga_autoconfig::autoconfig_product(UINT8 data) +{ + m_cfg[0x02] = ~((data & 0xf0) >> 4) << 12; + m_cfg[0x03] = ~((data & 0x0f) >> 0) << 12; +} + +void amiga_autoconfig::autoconfig_manufacturer(UINT16 data) +{ + m_cfg[0x08] = ~((data & 0xf000) >> 12) << 12; + m_cfg[0x09] = ~((data & 0x0f00) >> 8) << 12; + m_cfg[0x0a] = ~((data & 0x00f0) >> 4) << 12; + m_cfg[0x0b] = ~((data & 0x000f) >> 0) << 12; +} + +void amiga_autoconfig::autoconfig_serial(UINT32 data) +{ + m_cfg[0x0c] = ~((data & 0xf0000000) >> 28) << 12; + m_cfg[0x0d] = ~((data & 0x0f000000) >> 24) << 12; + m_cfg[0x0e] = ~((data & 0x00f00000) >> 20) << 12; + m_cfg[0x0f] = ~((data & 0x000f0000) >> 16) << 12; + m_cfg[0x10] = ~((data & 0x0000f000) >> 12) << 12; + m_cfg[0x11] = ~((data & 0x00000f00) >> 8) << 12; + m_cfg[0x12] = ~((data & 0x000000f0) >> 4) << 12; + m_cfg[0x13] = ~((data & 0x0000000f) >> 0) << 12; +} + +void amiga_autoconfig::autoconfig_rom_vector(UINT16 data) +{ + m_cfg[0x14] = ~((data & 0xf000) >> 12) << 12; + m_cfg[0x15] = ~((data & 0x0f00) >> 8) << 12; + m_cfg[0x16] = ~((data & 0x00f0) >> 4) << 12; + m_cfg[0x17] = ~((data & 0x000f) >> 0) << 12; +} + + +//************************************************************************** +// MEMORY INTERFACE +//************************************************************************** + +READ16_MEMBER( amiga_autoconfig::autoconfig_read ) +{ + UINT16 data = m_cfg[offset] | 0x0fff; + + if (VERBOSE && !space.debugger_access()) + logerror("autoconfig_read %04x @ %02x [mask = %04x]\n", data, offset, mem_mask); + + return data; +} + +WRITE16_MEMBER( amiga_autoconfig::autoconfig_write ) +{ + if (VERBOSE && !space.debugger_access()) + logerror("autoconfig_write %04x @ %02x [mask = %04x]\n", data, offset, mem_mask); + + switch (offset) + { + case 0x20: + // user-definable + break; + + case 0x21: + // bit 0 = interrupt enable + // bit 1 = user-definable + // bit 2 = local reset + // bit 3 = user-definable + break; + + case 0x24: + // base address register + m_cfg[0x24] = data & 0xf000; + autoconfig_base_address((m_cfg[0x24] << 8) | (m_cfg[0x25] << 4)); + break; + + case 0x25: + // latch low-nibble + m_cfg[0x25] = data & 0xf000; + break; + + case 0x26: + // shut-up register + autoconfig_base_address(0); + break; + + case 0x27: + break; + } +} diff --git a/src/emu/machine/autoconfig.h b/src/emu/machine/autoconfig.h new file mode 100644 index 00000000000..5183f474af9 --- /dev/null +++ b/src/emu/machine/autoconfig.h @@ -0,0 +1,72 @@ +/*************************************************************************** + + Amiga Autoconfig + +***************************************************************************/ + +#pragma once + +#ifndef __AUTOCONFIG_H__ +#define __AUTOCONFIG_H__ + +#include "emu.h" + +class amiga_autoconfig +{ +public: + amiga_autoconfig(); + virtual ~amiga_autoconfig(); + + // read from autoconfig space + DECLARE_READ16_MEMBER( autoconfig_read ); + + // write to autoconfig space + DECLARE_WRITE16_MEMBER( autoconfig_write ); + +protected: + enum board_type + { + BOARD_TYPE_ZORRO3 = 2, + BOARD_TYPE_ZORRO2 = 3 + }; + + enum board_size + { + BOARD_SIZE_8M = 0, + BOARD_SIZE_64K = 1, + BOARD_SIZE_128K = 2, + BOARD_SIZE_256K = 3, + BOARD_SIZE_512K = 4, + BOARD_SIZE_1M = 5, + BOARD_SIZE_2M = 6, + BOARD_SIZE_4M = 7 + }; + + // board type & size + void autoconfig_board_type(board_type type); + void autoconfig_board_size(board_size size); + + // various flags + void autoconfig_rom_vector_valid(bool state); + void autoconfig_link_into_memory(bool state); + void autoconfig_multi_device(bool state); + void autoconfig_8meg_preferred(bool state); + void autoconfig_can_shutup(bool state); + + // product number, manufacturer number, serial number + void autoconfig_product(UINT8 data); + void autoconfig_manufacturer(UINT16 data); + void autoconfig_serial(UINT32 data); + + // rom vector + void autoconfig_rom_vector(UINT16 data); + + // called once we have received a valid base address from the host system + virtual void autoconfig_base_address(offs_t address) = 0; + +private: + // configuration information about our autoconfig board, 256 nibbles + UINT16 m_cfg[0x40]; +}; + +#endif // __AUTOCONFIG_H__ diff --git a/src/emu/machine/cr511b.c b/src/emu/machine/cr511b.c new file mode 100644 index 00000000000..0a4ee90bf80 --- /dev/null +++ b/src/emu/machine/cr511b.c @@ -0,0 +1,123 @@ +/*************************************************************************** + + CR-511-B CD-ROM drive + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + CD-ROM drive with a custom MKE/Panasonic interface as used in the + Commodore CDTV and early SoundBlaster cards. + +***************************************************************************/ + +#include "cr511b.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type CR511B = &device_creator<cr511b_device>; + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +static MACHINE_CONFIG_FRAGMENT( cr511b ) + MCFG_CDROM_ADD("cdrom") + MCFG_CDROM_INTERFACE("cdrom") + MCFG_SOUND_ADD("cdda", CDDA, 0) + MCFG_SOUND_ROUTE(0, ":lspeaker", 1.0) + MCFG_SOUND_ROUTE(1, ":rspeaker", 1.0) +MACHINE_CONFIG_END + +machine_config_constructor cr511b_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( cr511b ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// cr511b_device - constructor +//------------------------------------------------- + +cr511b_device::cr511b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, CR511B, "CR-511-B CD-ROM drive", tag, owner, clock, "cr511b", __FILE__), + m_cdrom(*this, "cdrom"), + m_cdda(*this, "cdda"), + m_stch_handler(*this), + m_sten_handler(*this), + m_drq_handler(*this), + m_dten_handler(*this), + m_scor_handler(*this), + m_xaen_handler(*this), + m_frame_timer(NULL), + m_motor(false), + m_enabled(-1), + m_cmd(-1) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void cr511b_device::device_start() +{ + // resolve callbacks + m_stch_handler.resolve_safe(); + m_sten_handler.resolve_safe(); + m_drq_handler.resolve_safe(); + m_dten_handler.resolve_safe(); + m_scor_handler.resolve_safe(); + m_xaen_handler.resolve_safe(); + + m_frame_timer = timer_alloc(0, NULL); + m_frame_timer->adjust(attotime::never); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void cr511b_device::device_reset() +{ +} + +//------------------------------------------------- +// device_timer - device-specific timer events +//------------------------------------------------- + +void cr511b_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) +{ +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +READ8_MEMBER( cr511b_device::read ) +{ + return 0xff; +} + +WRITE8_MEMBER ( cr511b_device::write ) +{ + +} + +WRITE_LINE_MEMBER( cr511b_device::enable_w ) +{ + m_enabled = state; +} + +WRITE_LINE_MEMBER( cr511b_device::cmd_w ) +{ + m_cmd = state; +} diff --git a/src/emu/machine/cr511b.h b/src/emu/machine/cr511b.h new file mode 100644 index 00000000000..5def8947fc9 --- /dev/null +++ b/src/emu/machine/cr511b.h @@ -0,0 +1,152 @@ +/*************************************************************************** + + CR-511-B CD-ROM drive + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + CD-ROM drive with a custom MKE/Panasonic interface as used in the + Commodore CDTV and early SoundBlaster cards. + + 1 _RESET 2 GND + 3 EFFK 4 SCCK + 5 SBCP 6 SCOR + 7 GND 8 GND + 9 C16M 10 GND + 11 _XAEN 12 GND + 13 EMPASIS 14 D0 + 15 LRCK 16 DSCK + 17 _MUTE 18 GND + 19 _BUSY 20 _STCH + 21 _ENABLE 22 DRQ + 23 _HWR 24 GND + 25 _DTEN 26 _HRD + 27 _STEN 28 _CMD + 29 _EOP 30 GND + 31 DB7 32 GND + 33 DB6 34 DB5 + 35 DB4 36 GND + 37 DB3 38 DB2 + 39 DB1 40 DB0 + +***************************************************************************/ + +#pragma once + +#ifndef __CR511B_H__ +#define __CR511B_H__ + +#include "emu.h" +#include "imagedev/chd_cd.h" +#include "sound/cdda.h" + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_CR511B_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, CR511B, 0) \ + +#define MCFG_CR511B_STCH_HANDLER(_devcb) \ + devcb = &cr511b_device::set_stch_handler(*device, DEVCB2_##_devcb); + +#define MCFG_CR511B_STEN_HANDLER(_devcb) \ + devcb = &cr511b_device::set_sten_handler(*device, DEVCB2_##_devcb); + +#define MCFG_CR511B_DRQ_HANDLER(_devcb) \ + devcb = &cr511b_device::set_drq_handler(*device, DEVCB2_##_devcb); + +#define MCFG_CR511B_DTEN_HANDLER(_devcb) \ + devcb = &cr511b_device::set_dten_handler(*device, DEVCB2_##_devcb); + +#define MCFG_CR511B_SCOR_HANDLER(_devcb) \ + devcb = &cr511b_device::set_scor_handler(*device, DEVCB2_##_devcb); + +#define MCFG_CR511B_XAEN_HANDLER(_devcb) \ + devcb = &cr511b_device::set_xaen_handler(*device, DEVCB2_##_devcb); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> cr511b_device + +class cr511b_device : public device_t +{ +public: + // construction/destruction + cr511b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // callbacks + template<class _Object> static devcb2_base &set_stch_handler(device_t &device, _Object object) + { return downcast<cr511b_device &>(device).m_stch_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_sten_handler(device_t &device, _Object object) + { return downcast<cr511b_device &>(device).m_sten_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_drq_handler(device_t &device, _Object object) + { return downcast<cr511b_device &>(device).m_drq_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_dten_handler(device_t &device, _Object object) + { return downcast<cr511b_device &>(device).m_dten_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_scor_handler(device_t &device, _Object object) + { return downcast<cr511b_device &>(device).m_scor_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_xaen_handler(device_t &device, _Object object) + { return downcast<cr511b_device &>(device).m_xaen_handler.set_callback(object); } + + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER ( write ); + + DECLARE_WRITE_LINE_MEMBER( enable_w ); + DECLARE_WRITE_LINE_MEMBER( cmd_w ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + +private: + enum + { + STATUS_DOOR_CLOSED = 0x80, + STATUS_MEDIA = 0x40, + STATUS_MOTOR = 0x20, + STATUS_ERROR = 0x10, + STATUS_SUCCESS = 0x08, + STATUS_PLAYING = 0x04, + STATUS_DOOR_LOCKED = 0x02, + STATUS_READY = 0x01 + }; + + required_device<cdrom_image_device> m_cdrom; + required_device<cdda_device> m_cdda; + + devcb2_write_line m_stch_handler; + devcb2_write_line m_sten_handler; + devcb2_write_line m_drq_handler; + devcb2_write_line m_dten_handler; + devcb2_write_line m_scor_handler; + devcb2_write_line m_xaen_handler; + + emu_timer *m_frame_timer; + + bool m_motor; + + // state of lines + int m_enabled; + int m_cmd; + + // data transfer + UINT8 m_sector_buffer[CD_MAX_SECTOR_DATA]; +}; + +// device type definition +extern const device_type CR511B; + +#endif diff --git a/src/emu/machine/dmac.c b/src/emu/machine/dmac.c new file mode 100644 index 00000000000..7f2f674a793 --- /dev/null +++ b/src/emu/machine/dmac.c @@ -0,0 +1,467 @@ +/*************************************************************************** + + DMAC + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + DMA controller used in Amiga systems + +BOARDS: + CBM A590/A2091 HD controller: Prod=514/3($202/$3) (@$e90000 64K) + CBM A2052/58. RAM I 590/2091.RAM Prod=514/10($202/$a) (@$200000 2meg mem) + +***************************************************************************/ + +#include "dmac.h" + + +//************************************************************************** +// CONSTANTS / MACROS +//************************************************************************** + +#define VERBOSE 1 + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type DMAC = &device_creator<dmac_device>; + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// dmac_device - constructor +//------------------------------------------------- + +dmac_device::dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, DMAC, "DMAC DMA Controller", tag, owner, clock, "dmac", __FILE__), + amiga_autoconfig(), + m_cfgout_handler(*this), + m_int_handler(*this), + m_xdack_handler(*this), + m_scsi_read_handler(*this), + m_scsi_write_handler(*this), + m_io_read_handler(*this), + m_io_write_handler(*this), + m_space(NULL), + m_rom(NULL), + m_ram(NULL), + m_ram_size(-1), + m_configured(false), + m_rst(-1), + m_cntr(0), + m_istr(0), + m_wtc(0), + m_acr(0), + m_dma_active(false) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void dmac_device::device_start() +{ + // resolve callbacks + m_cfgout_handler.resolve_safe(); + m_int_handler.resolve_safe(); + m_xdack_handler.resolve_safe(); + m_scsi_read_handler.resolve_safe(0); + m_scsi_write_handler.resolve_safe(); + m_io_read_handler.resolve_safe(0); + m_io_write_handler.resolve_safe(); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void dmac_device::device_reset() +{ + // fifo empty + m_istr |= ISTR_FE_FLG; +} + +void dmac_device::autoconfig_base_address(offs_t address) +{ + if (VERBOSE) + logerror("%s('%s'): autoconfig_base_address received: 0x%06x\n", shortname(), basetag(), address); + + if (!m_configured && m_ram_size > 0) + { + if (VERBOSE) + logerror("-> installing ram (%d bytes)\n", m_ram_size); + + // install access to the ram space + if (address) + m_space->install_ram(address, address + (m_ram_size - 1), m_ram); + + // prepare autoconfig for main device + autoconfig_board_size(BOARD_SIZE_64K); + autoconfig_product(0x03); // or 0x02 for rev 1 + autoconfig_rom_vector(0x2000); + autoconfig_rom_vector_valid(true); + autoconfig_link_into_memory(false); + autoconfig_multi_device(false); + + // first device configured + m_configured = true; + } + else + { + if (VERBOSE) + logerror("-> installing dmac\n"); + + // internal dmac registers + m_space->install_readwrite_handler(address, address + 0xff, + read16_delegate(FUNC(dmac_device::register_read), this), + write16_delegate(FUNC(dmac_device::register_write), this), 0xffff); + + // install access to the rom space + if (m_rom) + { + m_space->install_rom(address + 0x2000, address + 0x7fff, m_rom + 0x2000); + m_space->install_rom(address + 0x8000, address + 0xffff, m_rom); + } + + // stop responding to autoconfig + m_space->unmap_readwrite(0xe80000, 0xe8007f); + + // we're done + m_cfgout_handler(0); + } +} + +void dmac_device::check_interrupts() +{ + // interrupts enabled? + if (m_cntr & CNTR_INTEN) + { + // any interrupts pending? + if (m_istr & ISTR_INT_MASK) + m_istr |= ISTR_INT_P; + } + else + m_istr &= ~ISTR_INT_P; + + // finally update interrupt line + m_int_handler((m_istr & ISTR_INT_P) ? 1 : 0); +} + +void dmac_device::stop_dma() +{ + m_dma_active = false; + m_istr &= ~ISTR_E_INT; + check_interrupts(); +} + +void dmac_device::start_dma() +{ + m_dma_active = true; +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +READ16_MEMBER( dmac_device::register_read ) +{ + UINT16 data = 0xffff; + + // autoconfig handles this + if (offset < 0x20) + return autoconfig_read(space, offset, mem_mask); + + switch (offset) + { + case 0x20: + data = m_istr; + + // reading clears fifo status (?) + m_istr &= ~0x0f; + check_interrupts(); + + if (VERBOSE) + logerror("%s('%s'): read istr %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + break; + + case 0x21: + data = m_cntr; + + if (VERBOSE) + logerror("%s('%s'): read cntr %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + break; + + case 0x48: + case 0x49: + case 0x50: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5e: + case 0x5f: + data = m_scsi_read_handler(offset); + + if (VERBOSE) + logerror("%s('%s'): read scsi data @ %02x %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask); + + break; + + case 0x70: + if (VERBOSE) + logerror("%s('%s'): read dma start strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + start_dma(); + break; + + case 0x71: + if (VERBOSE) + logerror("%s('%s'): read dma stop strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + stop_dma(); + break; + + case 0x72: + if (VERBOSE) + logerror("%s('%s'): read clear irq strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + // clear all interrupts + m_istr &= ~ISTR_INT_MASK; + check_interrupts(); + break; + + case 0x74: + if (VERBOSE) + logerror("%s('%s'): read flush fifo strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_istr |= ISTR_FE_FLG; + break; + + default: + if (VERBOSE) + logerror("%s('%s'): register_read %04x @ %02x [mask = %04x]\n", shortname(), basetag(), data, offset, mem_mask); + } + + return data; +} + +WRITE16_MEMBER( dmac_device::register_write ) +{ + switch (offset) + { + case 0x21: + if (VERBOSE) + logerror("%s('%s'): write cntr %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_cntr = data; + check_interrupts(); + break; + + case 0x40: + if (VERBOSE) + logerror("%s('%s'): write wtc hi %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_wtc &= 0x0000ffff; + m_wtc |= ((UINT32) data) << 16; + break; + + case 0x41: + if (VERBOSE) + logerror("%s('%s'): write wtc lo %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_wtc &= 0xffff0000; + m_wtc |= data; + break; + + case 0x42: + if (VERBOSE) + logerror("%s('%s'): write acr hi %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_acr &= 0x0000ffff; + m_acr |= ((UINT32) data) << 16; + break; + + case 0x43: + if (VERBOSE) + logerror("%s('%s'): write acr lo %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_acr &= 0xffff0000; + m_acr |= data; + break; + + case 0x47: + if (VERBOSE) + logerror("%s('%s'): write dawr %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + break; + + case 0x48: + case 0x49: + case 0x50: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5e: + case 0x5f: + if (VERBOSE) + logerror("%s('%s'): write scsi data @ %02x %04x [mask = %04x]\n", shortname(), basetag(), offset, data, mem_mask); + + m_scsi_write_handler(offset, data, 0xff); + break; + + case 0x70: + if (VERBOSE) + logerror("%s('%s'): write dma start strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + start_dma(); + break; + + case 0x71: + if (VERBOSE) + logerror("%s('%s'): write dma stop strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + stop_dma(); + break; + + case 0x72: + if (VERBOSE) + logerror("%s('%s'): write clear irq strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + // clear all interrupts + m_istr &= ~ISTR_INT_MASK; + check_interrupts(); + break; + + case 0x74: + if (VERBOSE) + logerror("%s('%s'): write flush fifo strobe %04x [mask = %04x]\n", shortname(), basetag(), data, mem_mask); + + m_istr |= ISTR_FE_FLG; + break; + + default: + if (VERBOSE) + logerror("%s('%s'): write %04x @ %02x [mask = %04x]\n", shortname(), basetag(), data, offset, mem_mask); + } +} + +// this signal tells us to expose our autoconfig values +WRITE_LINE_MEMBER( dmac_device::configin_w ) +{ + if (VERBOSE) + logerror("%s('%s'): configin_w (%d)\n", shortname(), basetag(), state); + + if (state == 0 && !m_configured) + { + // common autoconfig values + autoconfig_board_type(BOARD_TYPE_ZORRO2); + autoconfig_manufacturer(0x0202); + autoconfig_serial(0x00000000); + autoconfig_8meg_preferred(false); + autoconfig_can_shutup(true); + + // if we have ram, configure it first + if (m_ram_size > 0) + { + // product id 10 + autoconfig_product(0x0a); + + // board size + switch (m_ram_size) + { + case 0x080000: autoconfig_board_size(BOARD_SIZE_512K); break; + case 0x100000: autoconfig_board_size(BOARD_SIZE_1M); break; + case 0x200000: autoconfig_board_size(BOARD_SIZE_2M); break; + } + + // no rom and link into free memory + autoconfig_rom_vector_valid(false); + autoconfig_link_into_memory(true); + + // the main device follows + autoconfig_multi_device(true); + } + else + { + // just setup autoconfig for the main device + autoconfig_board_size(BOARD_SIZE_64K); + autoconfig_product(0x03); // or 0x02 for rev 1 + autoconfig_rom_vector(0x2000); + autoconfig_rom_vector_valid(true); + autoconfig_link_into_memory(false); + + // no more devices after this + autoconfig_multi_device(false); + } + + // install autoconfig handler + m_space->install_readwrite_handler(0xe80000, 0xe8007f, + read16_delegate(FUNC(amiga_autoconfig::autoconfig_read), static_cast<amiga_autoconfig *>(this)), + write16_delegate(FUNC(amiga_autoconfig::autoconfig_write), static_cast<amiga_autoconfig *>(this)), 0xffff); + } +} + +// this sets the ram size depending on the line voltage +WRITE_LINE_MEMBER( dmac_device::ramsz_w ) +{ + if (VERBOSE) + logerror("%s('%s'): ramsz_w (%d)\n", shortname(), basetag(), state); + + switch (state) + { + case 0: m_ram_size = 0x000000; break; + case 1: m_ram_size = 0x080000; break; + case 2: m_ram_size = 0x100000; break; + case 3: m_ram_size = 0x200000; break; + } +} + +// reset the device +WRITE_LINE_MEMBER( dmac_device::rst_w ) +{ + if (VERBOSE) + logerror("%s('%s'): rst_w (%d)\n", shortname(), basetag(), state); + + if (m_rst == 1 && state == 0) + device_reset(); + + m_rst = state; +} + +// external interrupt +WRITE_LINE_MEMBER( dmac_device::intx_w ) +{ + if (VERBOSE) + logerror("%s('%s'): intx_w (%d)\n", shortname(), basetag(), state); + + if (state) + m_istr |= ISTR_INTS; + else + m_istr &= ~ISTR_INTS; + + check_interrupts(); +} + +// data request +WRITE_LINE_MEMBER( dmac_device::xdreq_w ) +{ + if (VERBOSE) + logerror("%s('%s'): xdreq_w (%d)\n", shortname(), basetag(), state); + + if (m_dma_active) + { + + } +} diff --git a/src/emu/machine/dmac.h b/src/emu/machine/dmac.h new file mode 100644 index 00000000000..ce3849d9ea5 --- /dev/null +++ b/src/emu/machine/dmac.h @@ -0,0 +1,173 @@ +/*************************************************************************** + + DMAC + + license: MAME, GPL-2.0+ + copyright-holders: Dirk Best + + DMA controller used in Amiga systems + +***************************************************************************/ + +#pragma once + +#ifndef __DMAC_H__ +#define __DMAC_H__ + +#include "emu.h" +#include "autoconfig.h" + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_DMAC_ADD(_tag, _clock) \ + MCFG_DEVICE_ADD(_tag, DMAC, _clock) \ + +#define MCFG_DMAC_CFGOUT_HANDLER(_devcb) \ + devcb = &dmac_device::set_cfgout_handler(*device, DEVCB2_##_devcb); + +#define MCFG_DMAC_INT_HANDLER(_devcb) \ + devcb = &dmac_device::set_int_handler(*device, DEVCB2_##_devcb); + +#define MCFG_DMAC_XDACK_HANDLER(_devcb) \ + devcb = &dmac_device::set_xdack_handler(*device, DEVCB2_##_devcb); + +#define MCFG_DMAC_SCSI_READ_HANDLER(_devcb) \ + devcb = &dmac_device::set_scsi_read_handler(*device, DEVCB2_##_devcb); + +#define MCFG_DMAC_SCSI_WRITE_HANDLER(_devcb) \ + devcb = &dmac_device::set_scsi_write_handler(*device, DEVCB2_##_devcb); + +#define MCFG_DMAC_IO_READ_HANDLER(_devcb) \ + devcb = &dmac_device::set_io_read_handler(*device, DEVCB2_##_devcb); + +#define MCFG_DMAC_IO_WRITE_HANDLER(_devcb) \ + devcb = &dmac_device::set_io_write_handler(*device, DEVCB2_##_devcb); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> dmac_device + +class dmac_device : public device_t, public amiga_autoconfig +{ +public: + // construction/destruction + dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // callbacks + template<class _Object> static devcb2_base &set_cfgout_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_cfgout_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_int_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_int_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_xdack_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_xdack_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_scsi_read_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_scsi_read_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_scsi_write_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_scsi_write_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_io_read_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_io_read_handler.set_callback(object); } + + template<class _Object> static devcb2_base &set_io_write_handler(device_t &device, _Object object) + { return downcast<dmac_device &>(device).m_io_write_handler.set_callback(object); } + + void set_address_space(address_space *space) { m_space = space; }; + void set_rom(UINT8 *rom) { m_rom = rom; }; + void set_ram(UINT8 *ram) { m_ram = ram; }; + + // input lines + DECLARE_WRITE_LINE_MEMBER( configin_w ); + DECLARE_WRITE_LINE_MEMBER( ramsz_w ); + DECLARE_WRITE_LINE_MEMBER( rst_w ); + DECLARE_WRITE_LINE_MEMBER( intx_w ); + DECLARE_WRITE_LINE_MEMBER( xdreq_w ); + + // dmac register access + DECLARE_READ16_MEMBER( register_read ); + DECLARE_WRITE16_MEMBER( register_write ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // amiga_autoconfig overrides + virtual void autoconfig_base_address(offs_t address); + +private: + + // control register flags + enum + { + CNTR_TCEN = 0x80, // terminal count enable + CNTR_PREST = 0x40, // peripheral reset + CNTR_PDMD = 0x20, // peripheral device mode select (1=scsi, 0=xt) + CNTR_INTEN = 0x10, // interrupt enable + CNTR_DDIR = 0x08 // device direction (1=rd host, wr to peripheral) + }; + + // interrupt status register + enum + { + ISTR_INTX = 0x100, // xt interrupt pending + ISTR_INT_F = 0x080, // interrupt follow + ISTR_INTS = 0x040, // scsi peripheral interrupt + ISTR_E_INT = 0x020, // end-of-process interrupt + ISTR_INT_P = 0x010, // interrupt pending + ISTR_UE_INT = 0x008, // under-run fifo error interrupt + ISTR_OE_INT = 0x004, // over-run fifo error interrupt + ISTR_FF_FLG = 0x002, // fifo-full flag + ISTR_FE_FLG = 0x001 // fifo-empty flag + }; + + static const int ISTR_INT_MASK = 0x1fc; + + // callbacks + devcb2_write_line m_cfgout_handler; + devcb2_write_line m_int_handler; + devcb2_write_line m_xdack_handler; + devcb2_read8 m_scsi_read_handler; + devcb2_write8 m_scsi_write_handler; + devcb2_read8 m_io_read_handler; + devcb2_write8 m_io_write_handler; + + address_space *m_space; + UINT8 *m_rom; + UINT8 *m_ram; + int m_ram_size; + + // autoconfig state + bool m_configured; + + // state of lines + int m_rst; + + // register + UINT16 m_cntr; // control register + UINT16 m_istr; // interrupt status register + UINT32 m_wtc; // word transfer count + UINT32 m_acr; // address control register + + bool m_dma_active; + + void check_interrupts(); + void start_dma(); + void stop_dma(); +}; + + +// device type definition +extern const device_type DMAC; + + +#endif /* __DMAC_H__ */ diff --git a/src/emu/machine/machine.mak b/src/emu/machine/machine.mak index 18897309000..de303b9dfa7 100644 --- a/src/emu/machine/machine.mak +++ b/src/emu/machine/machine.mak @@ -16,6 +16,46 @@ MACHINEOBJ = $(EMUOBJ)/machine #------------------------------------------------- # +#@src/emu/machine/akiko.h,MACHINES += AKIKO +#------------------------------------------------- + +ifneq ($(filter AKIKO,$(MACHINES)),) +MACHINEOBJS += $(MACHINEOBJ)/akiko.o +endif + + +#------------------------------------------------- +# +#@src/emu/machine/autoconfig.h,MACHINES += AUTOCONFIG +#------------------------------------------------- + +ifneq ($(filter AUTOCONFIG,$(MACHINES)),) +MACHINEOBJS += $(MACHINEOBJ)/autoconfig.o +endif + + +#------------------------------------------------- +# +#@src/emu/machine/cr511b.h,MACHINES += CR511B +#------------------------------------------------- + +ifneq ($(filter CR511B,$(MACHINES)),) +MACHINEOBJS += $(MACHINEOBJ)/cr511b.o +endif + + +#------------------------------------------------- +# +#@src/emu/machine/dmac.h,MACHINES += DMAC +#------------------------------------------------- + +ifneq ($(filter DMAC,$(MACHINES)),) +MACHINEOBJS += $(MACHINEOBJ)/dmac.o +endif + + +#------------------------------------------------- +# #@src/emu/machine/40105.h,MACHINES += CMOS40105 #------------------------------------------------- diff --git a/src/emu/sound/amiga.c b/src/emu/sound/amiga.c new file mode 100644 index 00000000000..c4c9f045352 --- /dev/null +++ b/src/emu/sound/amiga.c @@ -0,0 +1,240 @@ +/*************************************************************************** + + Amiga audio hardware + +***************************************************************************/ + +#include "amiga.h" +#include "includes/amiga.h" + + +//************************************************************************** +// CONSTANTS / MACROS +//************************************************************************** + +#define VERBOSE 0 +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type AMIGA = &device_creator<amiga_sound_device>; + + +//************************************************************************* +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// amiga_sound_device - constructor +//------------------------------------------------- + +amiga_sound_device::amiga_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, AMIGA, "Amiga Paula", tag, owner, clock, "amiga_paula", __FILE__), + device_sound_interface(mconfig, *this), + m_stream(NULL) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void amiga_sound_device::device_start() +{ + // initialize channels + for (int i = 0; i < 4; i++) + { + m_channel[i].index = i; + m_channel[i].irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(amiga_sound_device::signal_irq), this)); + } + + // create the stream + m_stream = machine().sound().stream_alloc(*this, 0, 4, clock() / CLOCK_DIVIDER); +} + + +//************************************************************************* +// IMPLEMENTATION +//************************************************************************** + +//------------------------------------------------- +// signal_irq - irq signaling +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER( amiga_sound_device::signal_irq ) +{ + amiga_state *state = machine().driver_data<amiga_state>(); + + state->custom_chip_w(REG_INTREQ, INTENA_SETCLR | (0x80 << param)); +} + +//------------------------------------------------- +// dma_reload +//------------------------------------------------- + +void amiga_sound_device::dma_reload(audio_channel *chan) +{ + amiga_state *state = machine().driver_data<amiga_state>(); + + chan->curlocation = CUSTOM_REG_LONG(REG_AUD0LCH + chan->index * 8); + chan->curlength = CUSTOM_REG(REG_AUD0LEN + chan->index * 8); + chan->irq_timer->adjust(attotime::from_hz(15750), chan->index); + + LOG(("dma_reload(%d): offs=%05X len=%04X\n", chan->index, chan->curlocation, chan->curlength)); +} + +//------------------------------------------------- +// data_w - manual mode data writer +//------------------------------------------------- + +void amiga_sound_device::data_w(int which, UINT16 data) +{ + m_channel[which].manualmode = true; +} + +//------------------------------------------------- +// update - stream updater +//------------------------------------------------- + +void amiga_sound_device::update() +{ + m_stream->update(); +} + +//------------------------------------------------- +// sound_stream_update - handle a stream update +//------------------------------------------------- + +void amiga_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + amiga_state *state = machine().driver_data<amiga_state>(); + int channum, sampoffs = 0; + + // if all DMA off, disable all channels + if (!(CUSTOM_REG(REG_DMACON) & 0x0200)) + { + m_channel[0].dma_enabled = + m_channel[1].dma_enabled = + m_channel[2].dma_enabled = + m_channel[3].dma_enabled = false; + + // clear the sample data to 0 + for (channum = 0; channum < 4; channum++) + memset(outputs[channum], 0, sizeof(stream_sample_t) * samples); + return; + } + + samples *= CLOCK_DIVIDER; + + // update the DMA states on each channel and reload if fresh + for (channum = 0; channum < 4; channum++) + { + audio_channel *chan = &m_channel[channum]; + if (!chan->dma_enabled && ((CUSTOM_REG(REG_DMACON) >> channum) & 1)) + dma_reload(chan); + chan->dma_enabled = (CUSTOM_REG(REG_DMACON) >> channum) & 1; + } + + // loop until done + while (samples > 0) + { + int nextper, nextvol; + int ticks = samples; + + // determine the number of ticks we can do in this chunk + if (ticks > m_channel[0].curticks) + ticks = m_channel[0].curticks; + if (ticks > m_channel[1].curticks) + ticks = m_channel[1].curticks; + if (ticks > m_channel[2].curticks) + ticks = m_channel[2].curticks; + if (ticks > m_channel[3].curticks) + ticks = m_channel[3].curticks; + + // loop over channels + nextper = nextvol = -1; + for (channum = 0; channum < 4; channum++) + { + int volume = (nextvol == -1) ? CUSTOM_REG(REG_AUD0VOL + channum * 8) : nextvol; + int period = (nextper == -1) ? CUSTOM_REG(REG_AUD0PER + channum * 8) : nextper; + audio_channel *chan = &m_channel[channum]; + stream_sample_t sample; + int i; + + // normalize the volume value + volume = (volume & 0x40) ? 64 : (volume & 0x3f); + volume *= 4; + + // are we modulating the period of the next channel? + if ((CUSTOM_REG(REG_ADKCON) >> channum) & 0x10) + { + nextper = CUSTOM_REG(REG_AUD0DAT + channum * 8); + nextvol = -1; + sample = 0; + } + + // are we modulating the volume of the next channel? + else if ((CUSTOM_REG(REG_ADKCON) >> channum) & 0x01) + { + nextper = -1; + nextvol = CUSTOM_REG(REG_AUD0DAT + channum * 8); + sample = 0; + } + + // otherwise, we are generating data + else + { + nextper = nextvol = -1; + sample = chan->latched * volume; + } + + // fill the buffer with the sample + for (i = 0; i < ticks; i += CLOCK_DIVIDER) + outputs[channum][(sampoffs + i) / CLOCK_DIVIDER] = sample; + + // account for the ticks; if we hit 0, advance + chan->curticks -= ticks; + if (chan->curticks == 0) + { + // reset the clock and ensure we're above the minimum ticks + chan->curticks = period; + if (chan->curticks < 124) + chan->curticks = 124; + + // move forward one byte; if we move to an even byte, fetch new + if (chan->dma_enabled || chan->manualmode) + chan->curlocation++; + if (chan->dma_enabled && !(chan->curlocation & 1)) + { + CUSTOM_REG(REG_AUD0DAT + channum * 8) = (*state->m_chip_ram_r)(state, chan->curlocation); + if (chan->curlength != 0) + chan->curlength--; + + // if we run out of data, reload the dma + if (chan->curlength == 0) + dma_reload(chan); + } + + // latch the next byte of the sample + if (!(chan->curlocation & 1)) + chan->latched = CUSTOM_REG(REG_AUD0DAT + channum * 8) >> 8; + else + chan->latched = CUSTOM_REG(REG_AUD0DAT + channum * 8) >> 0; + + // if we're in manual mode, signal an interrupt once we latch the low byte + if (!chan->dma_enabled && chan->manualmode && (chan->curlocation & 1)) + { + signal_irq(NULL, channum); + chan->manualmode = false; + } + } + } + + // bump ourselves forward by the number of ticks + sampoffs += ticks; + samples -= ticks; + } +} diff --git a/src/emu/sound/amiga.h b/src/emu/sound/amiga.h new file mode 100644 index 00000000000..56e092b248f --- /dev/null +++ b/src/emu/sound/amiga.h @@ -0,0 +1,63 @@ +/*************************************************************************** + + Amiga audio hardware + +***************************************************************************/ + +#pragma once + +#ifndef __SOUND_AMIGA_H__ +#define __SOUND_AMIGA_H__ + +#include "emu.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> amiga_sound_device + +class amiga_sound_device : public device_t, public device_sound_interface +{ +public: + amiga_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + ~amiga_sound_device() {} + + void update(); + void data_w(int which, UINT16 data); + +protected: + // device-level overrides + virtual void device_start(); + + // sound stream update overrides + virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); + +private: + static const int CLOCK_DIVIDER = 16; + + struct audio_channel + { + emu_timer *irq_timer; + UINT32 curlocation; + UINT16 curlength; + UINT16 curticks; + UINT8 index; + bool dma_enabled; + bool manualmode; + INT8 latched; + }; + + void dma_reload(audio_channel *chan); + + // internal state + audio_channel m_channel[4]; + sound_stream *m_stream; + + TIMER_CALLBACK_MEMBER( signal_irq ); +}; + +extern const device_type AMIGA; + +#endif // __SOUND_AMIGA_H__ diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index 070534c8e09..6a6a0cf0d0d 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -101,6 +101,17 @@ endif #------------------------------------------------- +# Amiga audio hardware +#@src/emu/sound/amiga.h,SOUNDS += AMIGA +#------------------------------------------------- + +ifneq ($(filter AMIGA,$(SOUNDS)),) +SOUNDOBJS += $(SOUNDOBJ)/amiga.o +endif + + + +#------------------------------------------------- # Bally Astrocade sound system #@src/emu/sound/astrocde.h,SOUNDS += ASTROCADE #------------------------------------------------- |