From 93c88bf03fbad65e46af3afcab72783c99786d85 Mon Sep 17 00:00:00 2001 From: arbee Date: Fri, 28 Jul 2023 20:44:08 -0400 Subject: apple/dafb.cpp: Add support for the MEMCjr variant of DAFB. [R. Belmont] apple/djmemc.cpp: Add support for the cost-reduced MEMCjr variant. [R. Belmont] apple/iosb.cpp: Add support for the PrimeTime variant. [R. Belmont] New working systems ------------------- Apple Macintosh Quadra 605 [R. Belmont] New working clones ------------------ Apple Macintosh LC 475 [R. Belmont] Apple Macintosh LC 575 [R. Belmont] --- src/mame/apple/dafb.cpp | 210 ++++++++++++++++++++++++++++++++- src/mame/apple/dafb.h | 38 +++++- src/mame/apple/djmemc.cpp | 102 ++++++++++++++-- src/mame/apple/djmemc.h | 37 ++++-- src/mame/apple/iosb.cpp | 195 +++++++++++++++++++------------ src/mame/apple/iosb.h | 57 +++++++-- src/mame/apple/macquadra605.cpp | 253 ++++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 5 + 8 files changed, 784 insertions(+), 113 deletions(-) mode change 100644 => 100755 src/mame/apple/dafb.cpp create mode 100644 src/mame/apple/macquadra605.cpp diff --git a/src/mame/apple/dafb.cpp b/src/mame/apple/dafb.cpp old mode 100644 new mode 100755 index 29b98d9ded6..36bfe37d491 --- a/src/mame/apple/dafb.cpp +++ b/src/mame/apple/dafb.cpp @@ -17,6 +17,7 @@ MEMC - DAFB II without the Turbo SCSI logic, in the djMEMC and MEMCjr memory controllers. (returns version 3) Used in LC 475, LC 575, Quadra 605, Quadra 610, Quadra 650, and Quadra 800. This version uses a DP8534 timing generator instead of the DP8531 and an AC842a DAC instead of AC842. + Valkyrie - This video used in the LC/Performa/Quadra 630 and LC580 is stated by the developer note to be very similar to DAFB. DaMFB - DAFB II with a PowerPC bus interface instead of 68040. Used in the HPV card for the PowerMac 6100/7100/8100. Platinum - DAFB II with 4 MB VRAM support and a blitter bolted on. @@ -55,6 +56,7 @@ DEFINE_DEVICE_TYPE(DAFB, dafb_device, "macdafb", "Apple DAFB video") DEFINE_DEVICE_TYPE(DAFB_MEMC, dafb_memc_device, "macdafb_memc", "Apple DAFB II video (djMEMC integrated)") +DEFINE_DEVICE_TYPE(DAFB_MEMCJR, dafb_memcjr_device, "macdafb_memcjr", "Apple DAFB II video (MEMCjr integrated)") //------------------------------------------------- // ADDRESS_MAP @@ -107,6 +109,20 @@ dafb_memc_device::dafb_memc_device(const machine_config &mconfig, const char *ta { } +dafb_memcjr_device::dafb_memcjr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + dafb_base(mconfig, DAFB_MEMC, tag, owner, clock), + m_pcbr1(0), + m_last_clock(0), + m_clock_shift(0), + m_bit_clock(0), + m_M(1), + m_N(1), + m_P(1), + m_mclk(30'000'000), + m_pclk(30'000'000) +{ +} + void dafb_base::device_start() { m_vram = std::make_unique(m_vram_size); @@ -180,11 +196,35 @@ static INPUT_PORTS_START(monitor_config) PORT_CONFSETTING(ext(3, 0, 0), "PAL (640\u00d7480, 768\u00d7576)") INPUT_PORTS_END +// djMEMC and MEMCjr versions of DAFB don't support convolution and therefore don't support NTSC/PAL modes +// (the firmware does try since the DAFB driver is shared, but it doesn't work) +static INPUT_PORTS_START(monitor_config_noconv) + PORT_START("monitor") + PORT_CONFNAME(0x7f, 6, "Monitor type") + PORT_CONFSETTING(0x00, u8"Mac 21\" Color Display (1152\u00d7870)") // "RGB 2 Page" or "Kong" + PORT_CONFSETTING(0x01, u8"Mac Portrait Display (B&W 15\" 640\u00d7870)") // "Full Page" or "Portrait" + PORT_CONFSETTING(0x02, u8"Mac RGB Display (12\" 512\u00d7384)") // "Rubik" (modified IIgs AppleColor RGB) + PORT_CONFSETTING(0x03, u8"Mac Two-Page Display (B&W 21\" 1152\u00d7870)") // "2 Page" + PORT_CONFSETTING(0x06, u8"Mac Hi-Res Display (12-14\" 640\u00d7480)") // "High Res" + PORT_CONFSETTING(ext(1, 1, 3), "640x480 VGA") + PORT_CONFSETTING(ext(2, 3, 1), "832x624 16\" RGB") // "Goldfish" or "16 inch RGB" +INPUT_PORTS_END + ioport_constructor dafb_base::device_input_ports() const { return INPUT_PORTS_NAME(monitor_config); } +ioport_constructor dafb_memc_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(monitor_config_noconv); +} + +ioport_constructor dafb_memcjr_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(monitor_config_noconv); +} + u32 dafb_base::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { auto const vram8 = util::big_endian_cast(&m_vram[0]) + m_base; @@ -303,6 +343,21 @@ u32 dafb_base::dafb_r(offs_t offset) { switch (offset<<2) { + case 0: // framebuffer base, bits 20-9 + return (m_base >> 9) & 0xfff; + + case 4: // framebuffer base, bits 8-5 + return (m_base >> 5) & 0xf; + + case 8: // framebuffer stride, in 32-bit words + return m_stride >> 2; + + case 0xc: // timing control + return m_timing_control; + + case 0x10: // DAFB config + return m_config; + case 0x1c: // inverse of monitor sense { u8 mon = m_monitor_config->read(); @@ -365,7 +420,7 @@ void dafb_base::dafb_w(offs_t offset, u32 data) break; case 8: - m_stride = data<<2; // stride in DWORDs + m_stride = data<<2; // stride in 32-bit words LOG("Stride = %d\n", m_stride); break; @@ -661,7 +716,6 @@ void dafb_base::ramdac_w(offs_t offset, u32 data) switch (offset << 2) { case 0: - LOGMASKED(LOG_RAMDAC, "Address to %d\n", data & 0xff); m_pal_address = data & 0xff; m_pal_idx = 0; break; @@ -741,8 +795,8 @@ void dafb_base::recalc_mode() m_vres = (m_vertical_params[VFP] >> 1) - (m_vertical_params[VAL] >> 1); // these are in half-line units for interlace // Quadra 700 programs the wrong base for the 512x384 mode and is off-by-1 on the vertical res. - // Maybe that monitor wasn't really intended to be supported? - if (m_hres == 512) + // Maybe that monitor wasn't really intended to be supported? Quadra 800 and Quadra 605 do program it correctly. + if ((m_hres == 512) && (m_dafb_version == 1)) { m_base = 0x1000; m_vres = 384; @@ -766,6 +820,7 @@ void dafb_base::recalc_mode() else { m_hres *= clockdiv; + m_htotal *= clockdiv; } // if we're interlaced, bump the vertical back to double @@ -775,7 +830,8 @@ void dafb_base::recalc_mode() m_vtotal <<= 1; } - LOGMASKED(LOG_SWATCH, "hres %d vres %d htotal %d vtotal %d\n", m_hres, m_vres, m_htotal, m_vtotal); + const double refresh = (double)m_pixel_clock / (double)(m_htotal * m_vtotal); + LOGMASKED(LOG_SWATCH, "hres %d vres %d htotal %d vtotal %d refresh %f stride %d mode %d\n", m_hres, m_vres, m_htotal, m_vtotal, refresh, m_stride, m_mode); if ((m_hres != 0) && (m_vres != 0)) { rectangle visarea(0, m_hres - 1, 0, m_vres - 1); @@ -995,6 +1051,7 @@ template void dafb_device::turboscsi_drq_w<1>(int state); void dafb_memc_device::device_start() { m_vram_size = 0x100000; // all 5 MEMC machines can only have 1 MB VRAM + m_dafb_version = 3; dafb_base::device_start(); } @@ -1113,3 +1170,146 @@ void dafb_memc_device::ramdac_w(offs_t offset, u32 data) break; } } + +// ************************************************************************ +// dafb_memcjr_device overrides/additions +// ************************************************************************ +void dafb_memcjr_device::device_start() +{ + m_vram_size = 0x100000; // all 3 MEMCjr machines can only have 1 MB VRAM + m_dafb_version = 3; + dafb_base::device_start(); +} + +// MEMC's DAFB uses the "Gazelle" clock chip, which Apple describes as +// a modified version of the Sierra Semiconductor SC11412. I am unable +// to find a datasheet for the Sierra version, but the Apple documentation +// suffices for Gazelle. +u8 dafb_memcjr_device::clockgen_r(offs_t offset) +{ + return 0; +} + +void dafb_memcjr_device::clockgen_w(offs_t offset, u8 data) +{ + //printf("clockgen_w offset %x data %02x last_clock %02x\n", offset, data, m_last_clock); + switch (offset) + { + // The 20-bit parameter word is shifted in 1 bit at a time. + // bit 0 = data + // bit 1 = clock (bit latched on rising edge) + // bit 3 = chip enable + // clock = (N / (M * P)) * 31334400 + case 0xc3: + if ((BIT(data, 1)) && !(BIT(m_last_clock, 1))) + { + m_clock_shift >>= 1; + m_clock_shift |= BIT(data, 0) ? (1 << 19) : 0; + m_bit_clock++; + if (m_bit_clock == 20) + { + m_bit_clock = 0; + + const int clock_select = BIT(m_clock_shift, 0) ^ 1; + const int p_select = (m_clock_shift >> 4) & 3; + + m_P = (1 << p_select); + m_N = (m_clock_shift >> 6) & 0x7f; + m_M = (m_clock_shift >> 13) & 0x7f; + LOGMASKED(LOG_CLOCKGEN, "Gazelle: M = %d %02x, N = %d %02x P = %d\n", m_M, m_M, m_N, m_N, m_P); + + const double divisor = ((double)m_N / ((double)m_M * (double)m_P)); + if (clock_select) + { + m_pclk = (u32)(31334400.0f * divisor); + m_pixel_clock = m_pclk; + LOGMASKED(LOG_CLOCKGEN, "Gazelle: P clock %d\n", m_pclk); + } + else + { + m_mclk = (u32)(31334400.0f * divisor); + LOGMASKED(LOG_CLOCKGEN, "Gazelle: M clock %d\n", m_pclk); + } + + m_clock_shift = 0; + m_bit_clock = 0; + } + } + m_last_clock = data; + break; + } +} + +// This is an Anrelope which is a further revised AC842a +u32 dafb_memcjr_device::ramdac_r(offs_t offset) +{ + switch (offset << 2) + { + case 0x20: + if ((m_pal_address == 1) && ((m_ac842_pbctrl & 0x06) == 0x06)) + { + return m_pcbr1; + } + else + { + return dafb_base::ramdac_r(offset); + } + + default: + return dafb_base::ramdac_r(offset); + } +} + +void dafb_memcjr_device::ramdac_w(offs_t offset, u32 data) +{ + switch (offset << 2) + { + case 0x20: + if ((m_pal_address == 1) && ((m_ac842_pbctrl & 0x06) == 0x06)) + { + LOGMASKED(LOG_RAMDAC, "%02x to Antelope PCBR1\n", data); + m_pcbr1 = (data & 0xf0) | 0x02; // Antelope version ID + } + else + { + LOGMASKED(LOG_RAMDAC, "%02x to Antelope PCBR0, & 0x1c = %02x\n", data, data & 0x1c); + m_ac842_pbctrl = data; + if (((m_pcbr1 & 0xc0) == 0xc0) && ((data & 0x06) == 0x06)) + { + m_mode = 5; // 16 bpp (x555) + } + else + { + switch (data & 0x1c) + { + case 0x00: + m_mode = 0; // 1bpp + break; + + case 0x08: + m_mode = 1; // 2bpp + break; + + case 0x10: + m_mode = 2; // 4bpp + break; + + case 0x18: + m_mode = 3; // 8bpp + break; + + case 0x1c: + m_mode = 4; // 24bpp + break; + } + } + recalc_mode(); + } + break; + + default: + dafb_base::ramdac_w(offset, data); + break; + } +} + diff --git a/src/mame/apple/dafb.h b/src/mame/apple/dafb.h index 326bcba948d..744582a36d1 100644 --- a/src/mame/apple/dafb.h +++ b/src/mame/apple/dafb.h @@ -25,12 +25,6 @@ public: auto dafb_irq() { return m_irq.bind(); } -protected: - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_add_mconfig(machine_config &config) override; - virtual ioport_constructor device_input_ports() const override; - u32 dafb_r(offs_t offset); void dafb_w(offs_t offset, u32 data); u32 swatch_r(offs_t offset); @@ -39,6 +33,13 @@ protected: virtual void ramdac_w(offs_t offset, u32 data); virtual u8 clockgen_r(offs_t offset); virtual void clockgen_w(offs_t offset, u8 data); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + void recalc_ints(); void recalc_mode(); @@ -133,6 +134,7 @@ public: protected: virtual void device_start() override; + virtual ioport_constructor device_input_ports() const override; virtual u8 clockgen_r(offs_t offset) override; virtual void clockgen_w(offs_t offset, u8 data) override; @@ -145,7 +147,31 @@ private: u64 m_clock_params; }; +class dafb_memcjr_device: public dafb_base +{ +public: + dafb_memcjr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual void device_start() override; + virtual ioport_constructor device_input_ports() const override; + + virtual u8 clockgen_r(offs_t offset) override; + virtual void clockgen_w(offs_t offset, u8 data) override; + virtual u32 ramdac_r(offs_t offset) override; + virtual void ramdac_w(offs_t offset, u32 data) override; + +private: + u8 m_pcbr1; + u8 m_last_clock; + u32 m_clock_shift; + s32 m_bit_clock; + u8 m_M, m_N, m_P; + u32 m_mclk, m_pclk; +}; + DECLARE_DEVICE_TYPE(DAFB, dafb_device) DECLARE_DEVICE_TYPE(DAFB_MEMC, dafb_memc_device) +DECLARE_DEVICE_TYPE(DAFB_MEMCJR, dafb_memcjr_device) #endif /* MAME_APPLE_DAFB_H */ diff --git a/src/mame/apple/djmemc.cpp b/src/mame/apple/djmemc.cpp index f9fa6d68f3f..ddc7c512030 100644 --- a/src/mame/apple/djmemc.cpp +++ b/src/mame/apple/djmemc.cpp @@ -1,11 +1,11 @@ // license:BSD-3-Clause // copyright-holders:R. Belmont /* - Apple "djMEMC" memory controller + Apple "djMEMC" and "MEMCjr" memory controllers Emulation by R. Belmont - djMEMC contains the following: - - A memory controller for up to 640 MiB of RAM + djMEMC and MEMCjr contain the following: + - A memory controller for up to 640 MiB of RAM (10 banks of 64 MiB for djMEMC or 5 banks of 128 MiB for MEMCjr) - The usual Mac ROM/RAM switch so at boot the processor has vectors at 0 - DAFB II video, minus the "Turbo SCSI" feature, which has moved to IOSB */ @@ -18,6 +18,7 @@ //************************************************************************** DEFINE_DEVICE_TYPE(DJMEMC, djmemc_device, "djmemc", "Apple djMEMC memory controller") +DEFINE_DEVICE_TYPE(MEMCJR, memcjr_device, "memcjr", "Apple MEMCjr memory controller") //------------------------------------------------- // ADDRESS_MAP @@ -25,7 +26,7 @@ DEFINE_DEVICE_TYPE(DJMEMC, djmemc_device, "djmemc", "Apple djMEMC memory control void djmemc_device::map(address_map &map) { - map(0x40000000, 0x400fffff).r(FUNC(djmemc_device::rom_switch_r)).mirror(0x0ff00000); + map(0x40000000, 0x400fffff).r(FUNC(djmemc_device::rom_switch_r)).mirror(0x0ff00000).nopw(); map(0xf9000000, 0xf91fffff).rw(m_video, FUNC(dafb_device::vram_r), FUNC(dafb_device::vram_w)); map(0xf9800000, 0xf98003ff).m(m_video, FUNC(dafb_device::map)); } @@ -44,16 +45,27 @@ void djmemc_device::device_add_mconfig(machine_config &config) // djmemc_device - constructor //------------------------------------------------- -djmemc_device::djmemc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, DJMEMC, tag, owner, clock), - m_maincpu(*this, finder_base::DUMMY_TAG), +djmemc_device::djmemc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), m_video(*this, "video"), + m_maincpu(*this, finder_base::DUMMY_TAG), m_rom(*this, finder_base::DUMMY_TAG), m_irq(*this), m_overlay(false) { } +djmemc_device::djmemc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + djmemc_device(mconfig, DJMEMC, tag, owner, clock) +{ +} + +memcjr_device::memcjr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + djmemc_device(mconfig, MEMCJR, tag, owner, clock), + m_dafb_holding(0) +{ +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -110,3 +122,79 @@ void djmemc_device::vbl_w(int state) m_irq(state); } +// memcjr_device ------------------------------------------------------------------- + +void memcjr_device::device_add_mconfig(machine_config &config) +{ + DAFB_MEMCJR(config, m_video); + m_video->dafb_irq().set(FUNC(memcjr_device::vbl_w)); +} + +void memcjr_device::device_start() +{ + djmemc_device::device_start(); + + save_item(NAME(m_dafb_holding)); +} + +void memcjr_device::map(address_map &map) +{ + map(0x40000000, 0x400fffff).r(FUNC(memcjr_device::rom_switch_r)).mirror(0x0ff00000).nopw(); + map(0x5000e000, 0x5000ffff).rw(FUNC(memcjr_device::memcjr_r), FUNC(memcjr_device::memcjr_w)).mirror(0x00fc0000); + map(0xf9000000, 0xf91fffff).rw(m_video, FUNC(dafb_device::vram_r), FUNC(dafb_device::vram_w)); + map(0xf9800000, 0xf98003ff).m(m_video, FUNC(dafb_device::map)); + map(0xf9800000, 0xf98001ff).rw(FUNC(memcjr_device::dafb_holding_r), FUNC(memcjr_device::dafb_holding_w)); +} + +u32 memcjr_device::dafb_holding_r(offs_t offset) +{ + u32 result; + + if (offset < (0x100>>2)) + { + result = m_video->dafb_r(offset); + } + else + { + result = m_video->swatch_r(offset - (0x100>>2)); + } + + m_dafb_holding = (result >> 6) & 0x3f; + + return result & 0x3f; +} + +void memcjr_device::dafb_holding_w(offs_t offset, u32 data) +{ +// printf("%04x (%04x) to DAFB @ %04x\n", (data & 0x3f) | m_dafb_holding, data & 0xfff, offset<<2); + if (offset < (0x100>>2)) + { + m_video->dafb_w(offset, (data & 0x3f) | m_dafb_holding); + } + else + { + m_video->swatch_w(offset - (0x100>>2), (data & 0x3f) | m_dafb_holding); + } + m_dafb_holding = 0; +} + +u32 memcjr_device::memcjr_r(offs_t offset) +{ + //printf("memcjr_r @ %x\n", offset<<2); + if (offset == (0x7c>>2)) + { + return m_dafb_holding >> 6; + } + + return 0; +} + +void memcjr_device::memcjr_w(offs_t offset, u32 data) +{ + //printf("memcjr_w: %08x to %x\n", data, offset<<2); + if (offset == (0x7c>>2)) + { + m_dafb_holding = (data & 0x3f) << 6; + // printf("holding = %x\n", m_dafb_holding); + } +} diff --git a/src/mame/apple/djmemc.h b/src/mame/apple/djmemc.h index 500fe373f41..a1292cf15ff 100644 --- a/src/mame/apple/djmemc.h +++ b/src/mame/apple/djmemc.h @@ -14,15 +14,10 @@ class djmemc_device : public device_t { public: // construction/destruction - djmemc_device(const machine_config &mconfig, const char *tag, device_t *owner) - : djmemc_device(mconfig, tag, owner, (uint32_t)0) - { - } - djmemc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // interface routines - void map(address_map &map); + virtual void map(address_map &map); template void set_maincpu_tag(T &&... args) { m_maincpu.set_tag(std::forward(args)...); } template void set_rom_tag(T &&... args) { m_rom.set_tag(std::forward(args)...); } @@ -31,14 +26,20 @@ public: auto write_irq() { return m_irq.bind(); } protected: + djmemc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + // device-level overrides virtual void device_start() override; virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; + u32 rom_switch_r(offs_t offset); + void vbl_w(int state); + + required_device m_video; + private: required_device m_maincpu; - required_device m_video; required_region_ptr m_rom; devcb_write_line m_irq; @@ -46,13 +47,31 @@ private: bool m_overlay; u32 *m_ram_ptr, *m_rom_ptr; u32 m_ram_size, m_rom_size; +}; - u32 rom_switch_r(offs_t offset); +class memcjr_device : public djmemc_device +{ +public: + // construction/destruction + memcjr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - void vbl_w(int state); + virtual void map(address_map &map) override; + +protected: + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + +private: + u32 dafb_holding_r(offs_t offset); + void dafb_holding_w(offs_t offset, u32 data); + u32 memcjr_r(offs_t offset); + void memcjr_w(offs_t offset, u32 data); + + u16 m_dafb_holding; }; // device type definition DECLARE_DEVICE_TYPE(DJMEMC, djmemc_device) +DECLARE_DEVICE_TYPE(MEMCJR, memcjr_device) #endif // MAME_APPLE_DJMEMC_H diff --git a/src/mame/apple/iosb.cpp b/src/mame/apple/iosb.cpp index e9d93a7dc82..bbee1cff200 100644 --- a/src/mame/apple/iosb.cpp +++ b/src/mame/apple/iosb.cpp @@ -1,13 +1,13 @@ // license:BSD-3-Clause // copyright-holders:R. Belmont /* - Apple "IOSB" I/O ASIC + Apple "IOSB" and "PrimeTime" I/O ASICs Emulation by R. Belmont IOSB stands for "I/O Subsystem Buffer". The chip was originally called "BIOS" ("Buffered I/O Subsystem"), but they flipped the order around, presumably to avoid the obvious IBM PC reference. - IOSB contains the following: + IOSB and PrimeTime contain the following: - A full VIA (VIA1) and a "pseudo-VIA" for VIA2. This is not the standard pseudo-VIA found in chips like RBV, V8, or Sonora; it acts exactly like a real VIA, just without timers or a shift register. - A SWIM2 floppy controller @@ -15,7 +15,12 @@ - The "Turbo SCSI" logic from the standalone versions of DAFB and DAFB II - Support logic for various external subsystems (ADB, SCC, SONIC Ethernet) - The "PrimeTime" I/O ASIC is similar, and "PrimeTime II" adds an ATA controller. + IOSB and PrimeTime are similar to Sonora, but replace the RBV/V8/VASP/Sonora pseudo-VIA with a + real VIA core that has the timers disabled and some IER and PCR bits hard-wired to specific values. + The pseudo-VIA returns in AMIC on the PDM-class PowerMacs and goes away forever in the TNT-class. + + PrimeTime swaps the GI/Microchip ADB modem interface for the standard Cuda hookup found in Sonora, + and doesn't bring out the 4 VIA ID pins. PrimeTime II is similar. */ #include "emu.h" @@ -37,21 +42,22 @@ static constexpr u32 C15M = (C7M * 2); // DEVICE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(IOSB, iosb_device, "iosb", "Apple IOSB system ASIC") +DEFINE_DEVICE_TYPE(IOSB, iosb_device, "iosb", "Apple IOSB I/O ASIC") +DEFINE_DEVICE_TYPE(PRIMETIME, primetime_device, "primetime", "Apple PrimeTime I/O ASIC") //------------------------------------------------- // ADDRESS_MAP //------------------------------------------------- -void iosb_device::map(address_map &map) +void iosb_base::map(address_map &map) { - map(0x00000000, 0x00001fff).rw(FUNC(iosb_device::mac_via_r), FUNC(iosb_device::mac_via_w)).mirror(0x00fc0000); - map(0x00002000, 0x00003fff).rw(FUNC(iosb_device::mac_via2_r), FUNC(iosb_device::mac_via2_w)).mirror(0x00f00000); - map(0x00010000, 0x000100ff).rw(FUNC(iosb_device::turboscsi_r), FUNC(iosb_device::turboscsi_w)).mirror(0x00fc0000); - map(0x00010100, 0x00010103).rw(FUNC(iosb_device::turboscsi_dma_r), FUNC(iosb_device::turboscsi_dma_w)).select(0x00fc0000); + map(0x00000000, 0x00001fff).rw(FUNC(iosb_base::mac_via_r), FUNC(iosb_base::mac_via_w)).mirror(0x00fc0000); + map(0x00002000, 0x00003fff).rw(FUNC(iosb_base::mac_via2_r), FUNC(iosb_base::mac_via2_w)).mirror(0x00f00000); + map(0x00010000, 0x000100ff).rw(FUNC(iosb_base::turboscsi_r), FUNC(iosb_base::turboscsi_w)).mirror(0x00fc0000); + map(0x00010100, 0x00010103).rw(FUNC(iosb_base::turboscsi_dma_r), FUNC(iosb_base::turboscsi_dma_w)).select(0x00fc0000); map(0x00014000, 0x00015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000); - map(0x00018000, 0x00019fff).rw(FUNC(iosb_device::iosb_regs_r), FUNC(iosb_device::iosb_regs_w)).mirror(0x00f00000); - map(0x0001e000, 0x0001ffff).rw(FUNC(iosb_device::swim_r), FUNC(iosb_device::swim_w)).mirror(0x00f00000); + map(0x00018000, 0x00019fff).rw(FUNC(iosb_base::iosb_regs_r), FUNC(iosb_base::iosb_regs_w)).mirror(0x00f00000); + map(0x0001e000, 0x0001ffff).rw(FUNC(iosb_base::swim_r), FUNC(iosb_base::swim_w)).mirror(0x00f00000); // IOSB always gives an ID of "0x2BAD", the VIA I/O pins determine the rest map(0x0fff0000, 0x0fffffff).lr32(NAME([](offs_t offset) { return 0xa55a2bad; })); @@ -61,45 +67,50 @@ void iosb_device::map(address_map &map) // device_add_mconfig - add device configuration //------------------------------------------------- -void iosb_device::device_add_mconfig(machine_config &config) +void iosb_base::device_add_mconfig(machine_config &config) { R65NC22(config, m_via1, C7M / 10); - m_via1->readpa_handler().set(FUNC(iosb_device::via_in_a)); - m_via1->readpb_handler().set(FUNC(iosb_device::via_in_b)); - m_via1->writepa_handler().set(FUNC(iosb_device::via_out_a)); - m_via1->writepb_handler().set(FUNC(iosb_device::via_out_b)); - m_via1->cb1_handler().set(FUNC(iosb_device::via_out_cb1)); - m_via1->cb2_handler().set(FUNC(iosb_device::via_out_cb2)); - m_via1->irq_handler().set(FUNC(iosb_device::via1_irq)); + m_via1->readpa_handler().set(FUNC(iosb_base::via_in_a)); + m_via1->readpb_handler().set(FUNC(iosb_base::via_in_b)); + m_via1->writepa_handler().set(FUNC(iosb_base::via_out_a)); + m_via1->writepb_handler().set(FUNC(iosb_base::via_out_b)); + m_via1->cb1_handler().set(FUNC(iosb_base::via_out_cb1)); + m_via1->cb2_handler().set(FUNC(iosb_base::via_out_cb2)); + m_via1->irq_handler().set(FUNC(iosb_base::via1_irq)); R65NC22(config, m_via2, C7M / 10); - m_via2->readpa_handler().set(FUNC(iosb_device::via2_in_a)); - m_via2->irq_handler().set(FUNC(iosb_device::via2_irq)); + m_via2->readpa_handler().set(FUNC(iosb_base::via2_in_a)); + m_via2->irq_handler().set(FUNC(iosb_base::via2_irq)); SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); ASC(config, m_asc, C15M, asc_device::asc_type::SONORA); m_asc->add_route(0, "lspeaker", 1.0); m_asc->add_route(1, "rspeaker", 1.0); - m_asc->irqf_callback().set(FUNC(iosb_device::asc_irq)); + m_asc->irqf_callback().set(FUNC(iosb_base::asc_irq)); SWIM2(config, m_fdc, C15M); - m_fdc->devsel_cb().set(FUNC(iosb_device::devsel_w)); - m_fdc->phases_cb().set(FUNC(iosb_device::phases_w)); + m_fdc->devsel_cb().set(FUNC(iosb_base::devsel_w)); + m_fdc->phases_cb().set(FUNC(iosb_base::phases_w)); applefdintf_device::add_35_hd(config, m_floppy[0]); applefdintf_device::add_35_nc(config, m_floppy[1]); +} + +void iosb_device::device_add_mconfig(machine_config &config) +{ + iosb_base::device_add_mconfig(config); RTC3430042(config, m_rtc, XTAL(32'768)); m_rtc->cko_cb().set(m_via1, FUNC(via6522_device::write_ca2)); } //------------------------------------------------- -// iosb_device - constructor +// iosb_base - constructor //------------------------------------------------- -iosb_device::iosb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, IOSB, tag, owner, clock), +iosb_base::iosb_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), m_adb_st(*this), m_cb1(*this), m_cb2(*this), @@ -112,7 +123,6 @@ iosb_device::iosb_device(const machine_config &mconfig, const char *tag, device_ m_via1(*this, "via1"), m_via2(*this, "via2"), m_asc(*this, "asc"), - m_rtc(*this,"rtc"), m_fdc(*this, "fdc"), m_floppy(*this, "fdc:%d", 0U), m_cur_floppy(nullptr), @@ -131,15 +141,29 @@ iosb_device::iosb_device(const machine_config &mconfig, const char *tag, device_ std::fill(std::begin(m_iosb_regs), std::end(m_iosb_regs), 0); } +iosb_device::iosb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + iosb_base(mconfig, IOSB, tag, owner, clock), + m_rtc(*this,"rtc") +{ +} + +primetime_device::primetime_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + iosb_base(mconfig, PRIMETIME, tag, owner, clock), + write_pb4(*this), + write_pb5(*this), + read_pb3(*this, 0) +{ +} + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- -void iosb_device::device_start() +void iosb_base::device_start() { m_maincpu->set_emmu_enable(true); - m_6015_timer = timer_alloc(FUNC(iosb_device::mac_6015_tick), this); + m_6015_timer = timer_alloc(FUNC(iosb_base::mac_6015_tick), this); m_6015_timer->adjust(attotime::never); save_item(NAME(m_via_interrupt)); @@ -156,7 +180,7 @@ void iosb_device::device_start() // device_reset - device-specific reset //------------------------------------------------- -void iosb_device::device_reset() +void iosb_base::device_reset() { // start 60.15 Hz timer m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15)); @@ -177,13 +201,13 @@ void iosb_device::device_reset() m_via2->write(14, 0x80); } -TIMER_CALLBACK_MEMBER(iosb_device::mac_6015_tick) +TIMER_CALLBACK_MEMBER(iosb_base::mac_6015_tick) { m_via1->write_ca1(CLEAR_LINE); m_via1->write_ca1(ASSERT_LINE); } -uint8_t iosb_device::via_in_a() +uint8_t iosb_base::via_in_a() { u8 result = m_pa1() << 1; result |= m_pa2() << 2; @@ -192,22 +216,22 @@ uint8_t iosb_device::via_in_a() return result; } -uint8_t iosb_device::via_in_b() +uint8_t iosb_base::via_in_b() { - return (m_adb_interrupt ? 0 : 8) | m_rtc->data_r(); + return m_adb_interrupt ? 0 : 8; } -void iosb_device::via_out_cb1(int state) +void iosb_base::via_out_cb1(int state) { m_cb1(state & 1); } -void iosb_device::via_out_cb2(int state) +void iosb_base::via_out_cb2(int state) { m_cb2(state & 1); } -void iosb_device::via_out_a(uint8_t data) +void iosb_base::via_out_a(uint8_t data) { int hdsel = BIT(data, 5); if (hdsel != m_hdsel) @@ -220,28 +244,24 @@ void iosb_device::via_out_a(uint8_t data) m_hdsel = hdsel; } -void iosb_device::via_out_b(uint8_t data) +void iosb_base::via_out_b(uint8_t data) { m_adb_st((data & 0x30) >> 4); - - m_rtc->ce_w((data & 0x04)>>2); - m_rtc->data_w(data & 0x01); - m_rtc->clk_w((data >> 1) & 0x01); } -void iosb_device::via1_irq(int state) +void iosb_base::via1_irq(int state) { m_via_interrupt = state; field_interrupts(); } -void iosb_device::via2_irq(int state) +void iosb_base::via2_irq(int state) { m_via2_interrupt = state; field_interrupts(); } -void iosb_device::field_interrupts() +void iosb_base::field_interrupts() { int take_interrupt = -1; @@ -271,14 +291,14 @@ void iosb_device::field_interrupts() } } -void iosb_device::scc_irq_w(int state) +void iosb_base::scc_irq_w(int state) { m_scc_interrupt = (state == ASSERT_LINE); field_interrupts(); } template -void iosb_device::via2_irq_w(int state) +void iosb_base::via2_irq_w(int state) { m_nubus_irqs = m_via2->read(1); @@ -309,41 +329,41 @@ void iosb_device::via2_irq_w(int state) } } -template void iosb_device::via2_irq_w<0x40>(int state); -template void iosb_device::via2_irq_w<0x20>(int state); -template void iosb_device::via2_irq_w<0x10>(int state); -template void iosb_device::via2_irq_w<0x08>(int state); -template void iosb_device::via2_irq_w<0x01>(int state); +template void iosb_base::via2_irq_w<0x40>(int state); +template void iosb_base::via2_irq_w<0x20>(int state); +template void iosb_base::via2_irq_w<0x10>(int state); +template void iosb_base::via2_irq_w<0x08>(int state); +template void iosb_base::via2_irq_w<0x01>(int state); -u8 iosb_device::via2_in_a() +u8 iosb_base::via2_in_a() { return m_nubus_irqs; } -void iosb_device::scsi_irq_w(int state) +void iosb_base::scsi_irq_w(int state) { m_via2->write_cb2(state ^ 1); m_scsi_irq = state; } -void iosb_device::asc_irq(int state) +void iosb_base::asc_irq(int state) { m_via2->write_cb1(state ^ 1); m_asc_irq = state; } -void iosb_device::cb1_w(int state) +void iosb_base::cb1_w(int state) { m_via1->write_cb1(state); } -void iosb_device::cb2_w(int state) +void iosb_base::cb2_w(int state) { m_via1->write_cb2(state); } -uint16_t iosb_device::mac_via_r(offs_t offset) +uint16_t iosb_base::mac_via_r(offs_t offset) { uint16_t data; @@ -358,7 +378,7 @@ uint16_t iosb_device::mac_via_r(offs_t offset) return (data & 0xff) | (data << 8); } -void iosb_device::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask) +void iosb_base::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask) { offset >>= 8; offset &= 0x0f; @@ -371,7 +391,7 @@ void iosb_device::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask) m_via1->write(offset, (data >> 8) & 0xff); } -u16 iosb_device::mac_via2_r(offs_t offset) +u16 iosb_base::mac_via2_r(offs_t offset) { int data; @@ -393,7 +413,7 @@ u16 iosb_device::mac_via2_r(offs_t offset) return (data & 0xff) | (data << 8); } -void iosb_device::mac_via2_w(offs_t offset, u16 data, u16 mem_mask) +void iosb_base::mac_via2_w(offs_t offset, u16 data, u16 mem_mask) { offset >>= 8; offset &= 0x0f; @@ -427,7 +447,7 @@ void iosb_device::mac_via2_w(offs_t offset, u16 data, u16 mem_mask) m_via2->write(offset, (data >> 8) & 0xff); } -void iosb_device::via_sync() +void iosb_base::via_sync() { // The via runs at 783.36KHz while the main cpu runs at 15MHz or // more, so we need to sync the access with the via clock. Plus @@ -450,7 +470,7 @@ void iosb_device::via_sync() m_maincpu->adjust_icount(-int(main_cycle - cycle)); } -uint16_t iosb_device::swim_r(offs_t offset, u16 mem_mask) +uint16_t iosb_base::swim_r(offs_t offset, u16 mem_mask) { if (!machine().side_effects_disabled()) { @@ -460,7 +480,7 @@ uint16_t iosb_device::swim_r(offs_t offset, u16 mem_mask) u16 result = m_fdc->read((offset >> 8) & 0xf); return result << 8; } -void iosb_device::swim_w(offs_t offset, u16 data, u16 mem_mask) +void iosb_base::swim_w(offs_t offset, u16 data, u16 mem_mask) { if (ACCESSING_BITS_0_7) m_fdc->write((offset >> 8) & 0xf, data & 0xff); @@ -468,13 +488,13 @@ void iosb_device::swim_w(offs_t offset, u16 data, u16 mem_mask) m_fdc->write((offset >> 8) & 0xf, data >> 8); } -void iosb_device::phases_w(uint8_t phases) +void iosb_base::phases_w(uint8_t phases) { if (m_cur_floppy) m_cur_floppy->seek_phase_w(phases); } -void iosb_device::devsel_w(uint8_t devsel) +void iosb_base::devsel_w(uint8_t devsel) { if (devsel == 1) m_cur_floppy = m_floppy[0]->get_device(); @@ -488,7 +508,7 @@ void iosb_device::devsel_w(uint8_t devsel) m_cur_floppy->ss_w(m_hdsel); } -u8 iosb_device::turboscsi_r(offs_t offset) +u8 iosb_base::turboscsi_r(offs_t offset) { if (!machine().side_effects_disabled()) { @@ -497,14 +517,14 @@ u8 iosb_device::turboscsi_r(offs_t offset) return m_ncr->read(offset>>4); } -void iosb_device::turboscsi_w(offs_t offset, u8 data) +void iosb_base::turboscsi_w(offs_t offset, u8 data) { LOGMASKED(LOG_TURBOSCSI, "turboscsi_w: %02x @ %x (PC=%x)\n", data, offset>>4, m_maincpu->pc()); m_maincpu->adjust_icount(-m_scsi_write_cycles); m_ncr->write(offset>>4, data); } -u32 iosb_device::turboscsi_dma_r(offs_t offset, u32 mem_mask) +u32 iosb_base::turboscsi_dma_r(offs_t offset, u32 mem_mask) { if (mem_mask != 0xffffffff && mem_mask != 0xffff0000) { @@ -552,7 +572,7 @@ u32 iosb_device::turboscsi_dma_r(offs_t offset, u32 mem_mask) return m_scsi_dma_result; } -void iosb_device::turboscsi_dma_w(offs_t offset, u32 data, u32 mem_mask) +void iosb_base::turboscsi_dma_w(offs_t offset, u32 data, u32 mem_mask) { if (!machine().side_effects_disabled() && BIT(offset << 1, 18)) { @@ -598,20 +618,20 @@ void iosb_device::turboscsi_dma_w(offs_t offset, u32 data, u32 mem_mask) } } -void iosb_device::scsi_drq_w(int state) +void iosb_base::scsi_drq_w(int state) { LOGMASKED(LOG_SCSIDRQ, "SCSI DRQ %d (was %d)\n", state, m_drq); m_drq = state; m_via2->write_ca2(state); } -u16 iosb_device::iosb_regs_r(offs_t offset) +u16 iosb_base::iosb_regs_r(offs_t offset) { LOGMASKED(LOG_IOSBREGS, "iosb_regs_r: @ %x\n", offset>>7); return m_iosb_regs[offset>>7]; } -void iosb_device::iosb_regs_w(offs_t offset, u16 data, u16 mem_mask) +void iosb_base::iosb_regs_w(offs_t offset, u16 data, u16 mem_mask) { LOGMASKED(LOG_IOSBREGS, "iosb_regs_w: %04x @ %x, mask %04x\n", data, offset>>7, mem_mask); COMBINE_DATA(&m_iosb_regs[offset>>7]); @@ -624,3 +644,30 @@ void iosb_device::iosb_regs_w(offs_t offset, u16 data, u16 mem_mask) LOGMASKED(LOG_TURBOSCSI, "SCSI DMA read cycles %d write cycles %d\n", m_scsi_dma_read_cycles, m_scsi_dma_write_cycles); } } + +// ------------------------------------------- IOSB device +uint8_t iosb_device::via_in_b() +{ + return iosb_base::via_in_b() | m_rtc->data_r(); +} + +void iosb_device::via_out_b(uint8_t data) +{ + iosb_base::via_out_b(data); + + m_rtc->ce_w((data & 0x04)>>2); + m_rtc->data_w(data & 0x01); + m_rtc->clk_w((data >> 1) & 0x01); +} + +// ------------------------------------------- PrimeTime device +uint8_t primetime_device::via_in_b() +{ + return read_pb3() << 3; +} + +void primetime_device::via_out_b(uint8_t data) +{ + write_pb4(BIT(data, 4)); + write_pb5(BIT(data, 5)); +} diff --git a/src/mame/apple/iosb.h b/src/mame/apple/iosb.h index 1c353c4de3b..1483bc0910b 100644 --- a/src/mame/apple/iosb.h +++ b/src/mame/apple/iosb.h @@ -16,18 +16,13 @@ #include "sound/asc.h" #include "speaker.h" -// ======================> iosb_device +// ======================> iosb_base -class iosb_device : public device_t +class iosb_base : public device_t { public: // construction/destruction - iosb_device(const machine_config &mconfig, const char *tag, device_t *owner) - : iosb_device(mconfig, tag, owner, (uint32_t)0) - { - } - - iosb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + iosb_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // interface routines auto write_adb_st() { return m_adb_st.bind(); } // ADB state @@ -67,7 +62,9 @@ protected: virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; -private: + virtual uint8_t via_in_b(); + virtual void via_out_b(uint8_t data); + devcb_write8 m_adb_st; devcb_write_line m_cb1, m_cb2; devcb_read_line m_pa1, m_pa2, m_pa4, m_pa6; @@ -76,10 +73,10 @@ private: required_device m_ncr; required_device m_via1, m_via2; required_device m_asc; - required_device m_rtc; required_device m_fdc; required_device_array m_floppy; +private: emu_timer *m_6015_timer; int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt; floppy_image_device *m_cur_floppy = nullptr; @@ -105,9 +102,7 @@ private: uint8_t via_in_a(); uint8_t via2_in_a(); - uint8_t via_in_b(); void via_out_a(uint8_t data); - void via_out_b(uint8_t data); void field_interrupts(); void via_out_cb1(int state); void via_out_cb2(int state); @@ -122,7 +117,45 @@ private: void swim_w(offs_t offset, u16 data, u16 mem_mask); }; +class iosb_device : public iosb_base +{ +public: + // construction/destruction + iosb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config &config) override; + + virtual uint8_t via_in_b() override; + virtual void via_out_b(uint8_t data) override; + + required_device m_rtc; + +private: +}; + +class primetime_device : public iosb_base +{ +public: + // construction/destruction + primetime_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto pb4_callback() { return write_pb4.bind(); } + auto pb5_callback() { return write_pb5.bind(); } + auto pb3_callback() { return read_pb3.bind(); } + +protected: + virtual uint8_t via_in_b() override; + virtual void via_out_b(uint8_t data) override; + + devcb_write_line write_pb4, write_pb5; + devcb_read_line read_pb3; + +private: +}; + // device type definition DECLARE_DEVICE_TYPE(IOSB, iosb_device) +DECLARE_DEVICE_TYPE(PRIMETIME, primetime_device) #endif // MAME_APPLE_IOSB_H diff --git a/src/mame/apple/macquadra605.cpp b/src/mame/apple/macquadra605.cpp new file mode 100644 index 00000000000..b765530c8d2 --- /dev/null +++ b/src/mame/apple/macquadra605.cpp @@ -0,0 +1,253 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/**************************************************************************** + + drivers/macquadra605.cpp + Mac Quadra 605 ("Aladdin", "Primus") + Mac LC 475 + Mac LC 575 ("Optimus") + + By R. Belmont + + These machines were cost-reduced versions of the "Wombat" (Quadra/Centris 610/650/800) + machines. djMEMC was replaced with a cost-reduced version called MEMCjr, + and IOSB was replaced with PrimeTime, which is mostly compatible. + +****************************************************************************/ + +#include "emu.h" + +#include "cuda.h" +#include "djmemc.h" +#include "iosb.h" +#include "macadb.h" +#include "mactoolbox.h" + +#include "bus/nscsi/devices.h" +#include "bus/rs232/rs232.h" +#include "cpu/m68000/m68040.h" +#include "machine/ncr53c90.h" +#include "machine/nscsi_bus.h" +#include "machine/ram.h" +#include "machine/timer.h" +#include "machine/z80scc.h" + +#include "softlist_dev.h" + +#define C32M 31.3344_MHz_XTAL +#define C15M (C32M/2) +#define C7M (C32M/4) + +namespace { + +class quadra605_state : public driver_device +{ +public: + quadra605_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_memcjr(*this, "memcjr"), + m_primetime(*this, "iosb"), + m_macadb(*this, "macadb"), + m_cuda(*this, "cuda"), + m_scc(*this, "scc"), + m_ram(*this, RAM_TAG), + m_scsibus(*this, "scsi"), + m_ncr1(*this, "scsi:7:ncr53c96") + { + } + + void macqd605(machine_config &config); + void maclc475(machine_config &config); + void maclc575(machine_config &config); + + void quadra605_map(address_map &map); + void lc475_map(address_map &map); + void lc575_map(address_map &map); + + void init_macqd605(); + +private: + required_device m_maincpu; + required_device m_memcjr; + required_device m_primetime; + required_device m_macadb; + required_device m_cuda; + required_device m_scc; + required_device m_ram; + required_device m_scsibus; + required_device m_ncr1; + + virtual void machine_start() override; + virtual void machine_reset() override; + + u16 mac_scc_r(offs_t offset) + { + m_primetime->via_sync(); + u16 result = m_scc->dc_ab_r(offset); + return (result << 8) | result; + } + void mac_scc_2_w(offs_t offset, u16 data) { m_primetime->via_sync(); + m_scc->dc_ab_w(offset, data >> 8); } + + void cuda_reset_w(int state) + { + m_maincpu->set_input_line(INPUT_LINE_HALT, state); + m_maincpu->set_input_line(INPUT_LINE_RESET, state); + } +}; + +void quadra605_state::machine_start() +{ + m_memcjr->set_ram_info((u32 *) m_ram->pointer(), m_ram->size()); +} + +void quadra605_state::machine_reset() +{ + m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); +} + +void quadra605_state::init_macqd605() +{ +} + +/*************************************************************************** + ADDRESS MAPS +***************************************************************************/ +void quadra605_state::quadra605_map(address_map &map) +{ + map(0x00000000, 0xffffffff).m(m_memcjr, FUNC(memcjr_device::map)); + map(0x50000000, 0x5fffffff).m(m_primetime, FUNC(primetime_device::map)); + + map(0x5000c000, 0x5000dfff).rw(FUNC(quadra605_state::mac_scc_r), FUNC(quadra605_state::mac_scc_2_w)).mirror(0x00fc0000); + + map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a2225; })); +} + +void quadra605_state::lc475_map(address_map &map) +{ + quadra605_map(map); + map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a2221; })); +} + +void quadra605_state::lc575_map(address_map &map) +{ + quadra605_map(map); + map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a222e; })); +} + +/*************************************************************************** + DEVICE CONFIG +***************************************************************************/ + +static INPUT_PORTS_START( macadb ) +INPUT_PORTS_END + +/*************************************************************************** + MACHINE DRIVERS +***************************************************************************/ + +void quadra605_state::macqd605(machine_config &config) +{ + M68040(config, m_maincpu, 25_MHz_XTAL); + m_maincpu->set_addrmap(AS_PROGRAM, &quadra605_state::quadra605_map); + m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); + + MEMCJR(config, m_memcjr, 25_MHz_XTAL); + m_memcjr->set_maincpu_tag("maincpu"); + m_memcjr->set_rom_tag("bootrom"); + m_memcjr->write_irq().set(m_primetime, FUNC(primetime_device::via2_irq_w<0x40>)); + + PRIMETIME(config, m_primetime, 25_MHz_XTAL); + m_primetime->set_maincpu_tag("maincpu"); + m_primetime->set_scsi_tag("scsi:7:ncr53c96"); + + SCC85C30(config, m_scc, C7M); + m_scc->configure_channels(3'686'400, 3'686'400, 3'686'400, 3'686'400); + m_scc->out_int_callback().set(m_primetime, FUNC(primetime_device::scc_irq_w)); + m_scc->out_txda_callback().set("printer", FUNC(rs232_port_device::write_txd)); + m_scc->out_txdb_callback().set("modem", FUNC(rs232_port_device::write_txd)); + + rs232_port_device &rs232a(RS232_PORT(config, "printer", default_rs232_devices, nullptr)); + rs232a.rxd_handler().set(m_scc, FUNC(z80scc_device::rxa_w)); + rs232a.dcd_handler().set(m_scc, FUNC(z80scc_device::dcda_w)); + rs232a.cts_handler().set(m_scc, FUNC(z80scc_device::ctsa_w)); + + rs232_port_device &rs232b(RS232_PORT(config, "modem", default_rs232_devices, nullptr)); + rs232b.rxd_handler().set(m_scc, FUNC(z80scc_device::rxb_w)); + rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w)); + rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w)); + + // SCSI bus and devices + NSCSI_BUS(config, m_scsibus); + NSCSI_CONNECTOR(config, "scsi:0", mac_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:1", mac_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:2", mac_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:3", mac_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, "cdrom"); + NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr); + NSCSI_CONNECTOR(config, "scsi:6", mac_scsi_devices, "harddisk"); + NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr53c96", NCR53C96).clock(40_MHz_XTAL).machine_config( + [this] (device_t *device) + { + ncr53c96_device &adapter = downcast(*device); + + adapter.set_busmd(ncr53c96_device::BUSMD_1); + adapter.irq_handler_cb().set(m_primetime, FUNC(primetime_device::scsi_irq_w)); + adapter.drq_handler_cb().set(m_primetime, FUNC(primetime_device::scsi_drq_w)); + }); + + MACADB(config, m_macadb, C15M); + + CUDA(config, m_cuda, CUDA_341S0060); + m_cuda->reset_callback().set(FUNC(quadra605_state::cuda_reset_w)); + m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); + m_cuda->via_clock_callback().set(m_primetime, FUNC(primetime_device::cb1_w)); + m_cuda->via_data_callback().set(m_primetime, FUNC(primetime_device::cb2_w)); + m_macadb->adb_data_callback().set(m_cuda, FUNC(cuda_device::set_adb_line)); + config.set_perfect_quantum(m_maincpu); + + m_primetime->pb3_callback().set(m_cuda, FUNC(cuda_device::get_treq)); + m_primetime->pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack)); + m_primetime->pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip)); + m_primetime->write_cb2().set(m_cuda, FUNC(cuda_device::set_via_data)); + + /* internal ram */ + RAM(config, m_ram); + m_ram->set_default_size("4M"); + m_ram->set_extra_options("8M,16M,32M,64M,96M,128M,192M,256M,320M,384M,512M,640M"); + + SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd"); +} + +void quadra605_state::maclc475(machine_config &config) +{ + macqd605(config); + + m_maincpu->set_addrmap(AS_PROGRAM, &quadra605_state::lc475_map); +} + +void quadra605_state::maclc575(machine_config &config) +{ + macqd605(config); + + M68040(config.replace(), m_maincpu, 33_MHz_XTAL); + m_maincpu->set_addrmap(AS_PROGRAM, &quadra605_state::lc575_map); + m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); + + m_ram->set_default_size("5M"); +} + +ROM_START( macqd605 ) + ROM_REGION32_BE(0x100000, "bootrom", 0) + ROM_LOAD( "ff7439ee.bin", 0x000000, 0x100000, CRC(b8514689) SHA1(1d833125adf553a50f5994746c2c01aa5a1dbbf2) ) +ROM_END + +#define rom_maclc475 rom_macqd605 +#define rom_maclc575 rom_macqd605 + +} // anonymous namespace + +COMP( 1993, macqd605, 0, 0, macqd605, macadb, quadra605_state, init_macqd605, "Apple Computer", "Macintosh Quadra 605", MACHINE_SUPPORTS_SAVE) +COMP( 1993, maclc475, macqd605, 0, maclc475, macadb, quadra605_state, init_macqd605, "Apple Computer", "Macintosh LC/Performa 475", MACHINE_SUPPORTS_SAVE) +COMP( 1994, maclc575, macqd605, 0, maclc575, macadb, quadra605_state, init_macqd605, "Apple Computer", "Macintosh LC/Performa 575", MACHINE_SUPPORTS_SAVE) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index ef05a628708..f9de551a9d5 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -899,6 +899,11 @@ macpb180 // 1992 Apple Macintosh PowerBook 180 macpb180c // 1992 Apple Macintosh PowerBook 180c macpd210 // 1992 Apple Macintosh PowerBook Duo 210 +@source:apple/macquadra605.cpp +macqd605 // 1993 Apple Macintosh Quadra 605 +maclc475 // 1993 Apple Macintosh LC/Performa 475 +maclc575 // 1994 Apple Macintosh LC/Performa 575 + @source:apple/macquadra700.cpp macqd700 // 1991 Apple Macintosh Quadra 700 -- cgit v1.2.3