From 7aee0e681ec8d375a7d5203d5fe79d8878b0ab32 Mon Sep 17 00:00:00 2001 From: arbee Date: Sun, 12 Mar 2023 19:00:58 -0400 Subject: maciici.cpp: Moved the Macintosh IIci and IIsi to their own driver. [R. Belmont] mac.cpp: Condensed to single-file driver, began cleanup and simplification of the code. [R. Belmont] --- src/mame/apple/mac.cpp | 1487 +++++++++++++++++++++++++++++--------------- src/mame/apple/mac.h | 280 --------- src/mame/apple/mac_m.cpp | 1129 --------------------------------- src/mame/apple/mac_v.cpp | 229 ------- src/mame/apple/maciici.cpp | 1171 ++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 6 +- 6 files changed, 2167 insertions(+), 2135 deletions(-) delete mode 100644 src/mame/apple/mac.h delete mode 100644 src/mame/apple/mac_m.cpp delete mode 100644 src/mame/apple/mac_v.cpp create mode 100644 src/mame/apple/maciici.cpp diff --git a/src/mame/apple/mac.cpp b/src/mame/apple/mac.cpp index 55ab3bb1707..9297c19b633 100644 --- a/src/mame/apple/mac.cpp +++ b/src/mame/apple/mac.cpp @@ -2,288 +2,1003 @@ // copyright-holders: Nathan Woods, Raphael Nabet, R. Belmont, O. Galibert /**************************************************************************** - drivers/mac.cpp - Macintosh II family emulation + mac.cpp + Macintosh II ("Becks, Cabernet, Ikki, Little Big Mac, Paris, Reno, Uzi, Milwaukee") + Macintosh II FDHD (Codenames not known) + Macintosh IIx ("Spock, Stratos") + Macintosh IIcx ("Atlantic, Cobra, Aurora") + Macintosh SE/30 ("Fafnir, Green Jade") - TODO: - - Move RBV machines (IIci/IIsi) to separate driver? - - Rewrite this driver in the newer (maclc3/maciivx/maclc) style as macii.cpp? + Driver by R. Belmont and O. Galibert, based on work by Nathan Woods, Ernesto Corvi, and Raphael Nabet ****************************************************************************/ #include "emu.h" -#include "mac.h" +#include "adbmodem.h" #include "macadb.h" +#include "macrtc.h" +#include "macscsi.h" #include "mactoolbox.h" #include "bus/nscsi/devices.h" +#include "bus/macpds/macpds.h" +#include "bus/nubus/nubus.h" #include "bus/nubus/cards.h" +#include "bus/rs232/rs232.h" #include "cpu/m68000/m68020.h" #include "cpu/m68000/m68030.h" -#include "cpu/m6805/m6805.h" +#include "cpu/m68000/m68kmusashi.h" +#include "machine/6522via.h" +#include "machine/applefdintf.h" #include "machine/iwm.h" +#include "machine/ncr5380.h" +#include "machine/nscsi_bus.h" +#include "machine/ram.h" #include "machine/swim1.h" -#include "machine/swim2.h" +#include "machine/timer.h" +#include "machine/z80scc.h" +#include "sound/asc.h" -#include "layout/generic.h" +#include "emupal.h" +#include "screen.h" #include "softlist_dev.h" #include "speaker.h" #include "formats/ap_dsk35.h" +#define C15M (15.6672_MHz_XTAL) +#define C7M (C15M/2) -#define C32M (31.3344_MHz_XTAL) -#define C15M (C32M/2) -#define C7M (C32M/4) +// video parameters for classic Macs +#define MAC_H_VIS (512) +#define MAC_V_VIS (342) +#define MAC_H_TOTAL (704) // (512+192) +#define MAC_V_TOTAL (370) // (342+28) -// do this here - screen_update is called each scanline when stepping in the -// debugger, which means you can't escape the VIA2 IRQ handler -// -// RBV/MDU bits in IER/IFR: -// -// CA1: any slot interrupt = 0x02 -// CA2: SCSI interrupt = 0x01 -// CB1: ASC interrupt = 0x10 +#define MACII_USE_ADBMODEM (0) -WRITE_LINE_MEMBER(mac_state::mac_rbv_vbl) -{ - if (!state) - return; +// Mac driver data - m_rbv_regs[2] &= ~0x40; // set vblank signal - m_rbv_vbltime = 10; +class mac_state:public driver_device +{ +public: + mac_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_via1(*this, "via6522_0"), + m_via2(*this, "via6522_1"), + m_asc(*this, "asc"), + m_adbmodem(*this, "adbmodem"), + m_macadb(*this, "macadb"), + m_ram(*this, RAM_TAG), + m_scc(*this, "scc"), + m_ncr5380(*this, "scsi:7:ncr5380"), + m_scsihelp(*this, "scsihelp"), + m_fdc(*this, "fdc"), + m_floppy(*this, "fdc:%d", 0U), + m_rtc(*this, "rtc"), + m_vram(*this,"vram"), + m_via2_ca1_hack(0), + m_screen(*this, "screen"), + m_palette(*this, "palette") + { + m_rom_size = 0; + m_rom_ptr = nullptr; + m_cur_floppy = nullptr; + } -// printf("RBV: raising VBL!\n"); + void macii(machine_config &config); + void maciihmu(machine_config &config); + void maciihd(machine_config &config); + void maciix(machine_config &config); + void maciicx(machine_config &config); + void macse30(machine_config &config); + + void init_maciifdhd(); + void init_macse30(); + void init_macii(); + void init_maciix(); + void init_maciicx(); + + /* tells which model is being emulated (set by macxxx_init) */ + enum model_t + { + MODEL_MAC_II, // Mac II class 68020/030 machines + MODEL_MAC_II_FDHD, + MODEL_MAC_IIX, + MODEL_MAC_IICX, + MODEL_MAC_SE30 + }; + + model_t m_model; + +private: + required_device m_maincpu; + required_device m_via1; + required_device m_via2; + required_device m_asc; + optional_device m_adbmodem; + required_device m_macadb; + required_device m_ram; + required_device m_scc; + required_device m_ncr5380; + required_device m_scsihelp; + required_device m_fdc; + required_device_array m_floppy; + required_device m_rtc; + + virtual void machine_start() override; + virtual void machine_reset() override; + + uint32_t m_overlay = 0; + + uint32_t m_via2_vbl = 0; + uint32_t m_se30_vbl_enable = 0; + uint8_t m_nubus_irq_state = 0; + + emu_timer *m_overlay_timeout = nullptr; + TIMER_CALLBACK_MEMBER(overlay_timeout_func); + uint32_t rom_switch_r(offs_t offset); + + int m_adb_irq_pending = 0; + int m_screen_buffer = 0; + int ca1_data = 0; + + // ADB refresh timer, independent of anything else going on + emu_timer *m_adbupdate_timer = nullptr; + + WRITE_LINE_MEMBER(adb_irq_w) { m_adb_irq_pending = state; } + + // this is shared among all video setups with vram + optional_shared_ptr m_vram; + + // interrupts + int m_scc_interrupt = false, m_via_interrupt = false, m_via2_interrupt = false, m_scsi_interrupt = false, m_last_taken_interrupt = false; + + // defined in machine/mac.c + void set_memory_overlay(int overlay); + void scc_mouse_irq( int x, int y ); + void nubus_slot_interrupt(uint8_t slot, uint32_t state); + DECLARE_WRITE_LINE_MEMBER(set_scc_interrupt); + void set_via_interrupt(int value); + void set_via2_interrupt(int value); + void field_interrupts(); + void vblank_irq(); + void update_volume(); + + void mac_via_sync(); + uint16_t mac_via_r(offs_t offset); + void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t mac_via2_r(offs_t offset); + void mac_via2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint16_t mac_iwm_r(offs_t offset, uint16_t mem_mask = ~0); + void mac_iwm_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + u16 mac_scc_r(offs_t offset); + void mac_scc_w(offs_t offset, u16 data); + uint16_t macplus_scsi_r(offs_t offset, uint16_t mem_mask = ~0); + void macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + uint32_t macii_scsi_drq_r(offs_t offset, uint32_t mem_mask = ~0); + void macii_scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); + void scsi_berr_w(uint8_t data); + + template DECLARE_WRITE_LINE_MEMBER(nubus_irq_w); + + DECLARE_WRITE_LINE_MEMBER(mac_scsi_irq); + DECLARE_WRITE_LINE_MEMBER(mac_asc_irq); + + void macii_map(address_map &map); + void macse30_map(address_map &map); + + int m_via2_ca1_hack = 0; + optional_device m_screen; + optional_device m_palette; + + uint32_t m_rom_size = 0; + uint32_t *m_rom_ptr = nullptr; + + emu_timer *m_scanline_timer = nullptr; + + floppy_image_device *m_cur_floppy = nullptr; + + void phases_w(uint8_t phases); + void devsel_w(uint8_t devsel); + + uint32_t screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + TIMER_CALLBACK_MEMBER(mac_adbrefresh_tick); + TIMER_CALLBACK_MEMBER(mac_scanline_tick); + DECLARE_WRITE_LINE_MEMBER(mac_adb_via_out_cb2); + uint8_t mac_via_in_a(); + uint8_t mac_via_in_b(); + void mac_via_out_a(uint8_t data); + void mac_via_out_b(uint8_t data); + uint8_t mac_via2_in_a(); + uint8_t mac_via2_in_b(); + void mac_via2_out_a(uint8_t data); + void mac_via2_out_b(uint8_t data); + void mac_state_load(); + DECLARE_WRITE_LINE_MEMBER(mac_via_irq); + DECLARE_WRITE_LINE_MEMBER(mac_via2_irq); + void mac_driver_init(model_t model); + void mac_install_memory(offs_t memory_begin, offs_t memory_end, offs_t memory_size, void *memory_data, int is_rom); +}; + +uint32_t mac_state::screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + uint32_t const video_base = (m_screen_buffer ? 0x8000 : 0) + (MAC_H_VIS / 8); + uint16_t const *const video_ram = (const uint16_t *)&m_vram[video_base / 4]; - if (m_rbv_regs[0x12] & 0x40) + for (int y = 0; y < MAC_V_VIS; y++) { - rbv_recalc_irqs(); + uint16_t *const line = &bitmap.pix(y); + + for (int x = 0; x < MAC_H_VIS; x += 16) + { + uint16_t const word = video_ram[((y * MAC_H_VIS) / 16) + ((x / 16) ^ 1)]; + for (int b = 0; b < 16; b++) + { + line[x + b] = (word >> (15 - b)) & 0x0001; + } + } } + return 0; } -uint32_t mac_state::rbv_ramdac_r() +void mac_state::mac_install_memory(offs_t memory_begin, offs_t memory_end, + offs_t memory_size, void *memory_data, int is_rom) { - return 0; + address_space &space = m_maincpu->space(AS_PROGRAM); + offs_t memory_mirror; + + memory_size = std::min(memory_size, (memory_end + 1 - memory_begin)); + memory_mirror = (memory_end - memory_begin) & ~(memory_size - 1); + + if (!is_rom) + { + space.install_ram(memory_begin, memory_end & ~memory_mirror, memory_mirror, memory_data); + } + else + { + space.unmap_write(memory_begin, memory_end); + space.install_rom(memory_begin, memory_end & ~memory_mirror, memory_mirror, memory_data); + } } -void mac_state::rbv_ramdac_w(offs_t offset, uint32_t data) +/* + Interrupt handling +*/ + +void mac_state::field_interrupts() { - if (!offset) + int take_interrupt = -1; + + if (m_scc_interrupt) { - m_rbv_clutoffs = data>>24; - m_rbv_count = 0; + take_interrupt = 4; } - else + else if (m_via2_interrupt) + { + take_interrupt = 2; + } + else if (m_via_interrupt) + { + take_interrupt = 1; + } + + if (m_last_taken_interrupt > -1) { - m_rbv_colors[m_rbv_count++] = data>>24; + m_maincpu->set_input_line(m_last_taken_interrupt, CLEAR_LINE); + m_last_taken_interrupt = -1; + } + + if (take_interrupt > -1) + { + m_maincpu->set_input_line(take_interrupt, ASSERT_LINE); + m_last_taken_interrupt = take_interrupt; + } +} + +WRITE_LINE_MEMBER(mac_state::set_scc_interrupt) +{ + m_scc_interrupt = state; + this->field_interrupts(); +} + +void mac_state::set_via_interrupt(int value) +{ + m_via_interrupt = value; + this->field_interrupts(); +} + +void mac_state::set_via2_interrupt(int value) +{ + m_via2_interrupt = value; + this->field_interrupts(); +} - if (m_rbv_count == 3) +WRITE_LINE_MEMBER(mac_state::mac_asc_irq) +{ + m_via2->write_cb1(state ^ 1); +} + +void mac_state::set_memory_overlay(int overlay) +{ + offs_t memory_size; + uint8_t *memory_data; + int is_rom; + + /* normalize overlay */ + overlay = overlay ? true : false; + + if (overlay != m_overlay) + { + /* set up either main RAM area or ROM mirror at 0x000000-0x3fffff */ + if (overlay) { - // for portrait display, force monochrome by using the blue channel - if (m_montype.read_safe(2) == 1) - { - m_palette->set_pen_color(m_rbv_clutoffs, rgb_t(m_rbv_colors[2], m_rbv_colors[2], m_rbv_colors[2])); - m_rbv_palette[m_rbv_clutoffs] = rgb_t(m_rbv_colors[2], m_rbv_colors[2], m_rbv_colors[2]); - m_rbv_clutoffs++; - m_rbv_count = 0; - } - else - { - m_palette->set_pen_color(m_rbv_clutoffs, rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2])); - m_rbv_palette[m_rbv_clutoffs] = rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2]); - m_rbv_clutoffs++; - m_rbv_count = 0; - } + /* ROM mirror */ + memory_size = m_rom_size; + memory_data = reinterpret_cast(m_rom_ptr); + is_rom = true; } + else + { + /* RAM */ + memory_size = m_ram->size(); + memory_data = m_ram->pointer(); + is_rom = false; + } + + /* install the memory */ + mac_install_memory(0x00000000, 0x3fffffff, memory_size, memory_data, is_rom); + + m_overlay = overlay; } } -void mac_state::rbv_recalc_irqs() +uint32_t mac_state::rom_switch_r(offs_t offset) { - // check slot interrupts and bubble them down to IFR - uint8_t slot_irqs = (~m_rbv_regs[2]) & 0x78; - slot_irqs &= (m_rbv_regs[0x12] & 0x78); - - if (slot_irqs) + // disable the overlay + if (m_overlay) { - m_rbv_regs[3] |= 2; // any slot + set_memory_overlay(0); } - else // no slot irqs, clear the pending bit + + // printf("rom_switch_r: offset %08x ROM_size -1 = %08x, masked = %08x\n", offset, m_rom_size-1, offset & ((m_rom_size - 1)>>2)); + + return m_rom_ptr[offset & ((m_rom_size - 1) >> 2)]; +} + +/* ************************************************************************* + * SCSI + * *************************************************************************/ + +/* + +From http://www.mac.m68k-linux.org/devel/plushw.php + +The address of each register is computed as follows: + + $580drn + + where r represents the register number (from 0 through 7), + n determines whether it a read or write operation + (0 for reads, or 1 for writes), and + d determines whether the DACK signal to the NCR 5380 is asserted. + (0 for not asserted, 1 is for asserted) + +Here's an example of the address expressed in binary: + + 0101 1000 0000 00d0 0rrr 000n + +Note: Asserting the DACK signal applies only to write operations to + the output data register and read operations from the input + data register. + + Symbolic Memory + Location Location NCR 5380 Internal Register + + scsiWr+sODR+dackWr $580201 Output Data Register with DACK + scsiWr+sODR $580001 Output Data Register + scsiWr+sICR $580011 Initiator Command Register + scsiWr+sMR $580021 Mode Register + scsiWr+sTCR $580031 Target Command Register + scsiWr+sSER $580041 Select Enable Register + scsiWr+sDMAtx $580051 Start DMA Send + scsiWr+sTDMArx $580061 Start DMA Target Receive + scsiWr+sIDMArx $580071 Start DMA Initiator Receive + + scsiRd+sIDR+dackRd $580260 Current SCSI Data with DACK + scsiRd+sCDR $580000 Current SCSI Data + scsiRd+sICR $580010 Initiator Command Register + scsiRd+sMR $580020 Mode Registor + scsiRd+sTCR $580030 Target Command Register + scsiRd+sCSR $580040 Current SCSI Bus Status + scsiRd+sBSR $580050 Bus and Status Register + scsiRd+sIDR $580060 Input Data Register + scsiRd+sRESET $580070 Reset Parity/Interrupt + */ + +uint16_t mac_state::macplus_scsi_r(offs_t offset, uint16_t mem_mask) +{ + int reg = (offset >> 3) & 0xf; + + // logerror("macplus_scsi_r: offset %x mask %x\n", offset, mem_mask); + + bool pseudo_dma = (reg == 6) && (offset == 0x130); + + return m_scsihelp->read_wrapper(pseudo_dma, reg) << 8; +} + +uint32_t mac_state::macii_scsi_drq_r(offs_t offset, uint32_t mem_mask) +{ + switch (mem_mask) { - m_rbv_regs[3] &= ~2; // any slot + case 0xff000000: + return m_scsihelp->read_wrapper(true, 6) << 24; + + case 0xffff0000: + return (m_scsihelp->read_wrapper(true, 6) << 24) | (m_scsihelp->read_wrapper(true, 6) << 16); + + case 0xffffffff: + return (m_scsihelp->read_wrapper(true, 6) << 24) | (m_scsihelp->read_wrapper(true, 6) << 16) | (m_scsihelp->read_wrapper(true, 6) << 8) | m_scsihelp->read_wrapper(true, 6); + + default: + logerror("macii_scsi_drq_r: unknown mem_mask %08x\n", mem_mask); } - uint8_t ifr = (m_rbv_regs[3] & m_rbv_ier) & 0x1b; //m_rbv_regs[0x13]); + return 0; +} -// printf("ifr = %02x (reg3 %02x reg13 %02x)\n", ifr, m_rbv_regs[3], m_rbv_regs[0x13]); - if (ifr != 0) +void mac_state::macii_scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (mem_mask) { - m_rbv_regs[3] = ifr | 0x80; - m_rbv_ifr = ifr | 0x80; + case 0xff000000: + m_scsihelp->write_wrapper(true, 0, data >> 24); + break; + + case 0xffff0000: + m_scsihelp->write_wrapper(true, 0, data >> 24); + m_scsihelp->write_wrapper(true, 0, data >> 16); + break; + + case 0xffffffff: + m_scsihelp->write_wrapper(true, 0, data >> 24); + m_scsihelp->write_wrapper(true, 0, data >> 16); + m_scsihelp->write_wrapper(true, 0, data >> 8); + m_scsihelp->write_wrapper(true, 0, data & 0xff); + break; -// printf("VIA2 raise\n"); - set_via2_interrupt(1); + default: + logerror("macii_scsi_drq_w: unknown mem_mask %08x\n", mem_mask); + break; } +} + +void mac_state::macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + int reg = (offset >> 3) & 0xf; + + // logerror("macplus_scsi_w: data %x offset %x mask %x (PC=%x)\n", data, offset, mem_mask, m_maincpu->pc()); + + bool pseudo_dma = (reg == 0) && (offset == 0x100); + + m_scsihelp->write_wrapper(pseudo_dma, reg, data >> 8); +} + +WRITE_LINE_MEMBER(mac_state::mac_scsi_irq) +{ +} + +void mac_state::scsi_berr_w(uint8_t data) +{ + m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero); +} + +/* ************************************************************************* + * SCC + * + * Serial Communications Controller + * *************************************************************************/ +u16 mac_state::mac_scc_r(offs_t offset) +{ + u16 result = m_scc->dc_ab_r(offset); + return (result << 8) | result; +} + +void mac_state::mac_scc_w(offs_t offset, u16 data) +{ + m_scc->dc_ab_w(offset, data >> 8); +} + +/* ********************************** * + * IWM Code specific to the Mac Plus * + * ********************************** */ + +uint16_t mac_state::mac_iwm_r(offs_t offset, uint16_t mem_mask) +{ + /* The first time this is called is in a floppy test, which goes from + * $400104 to $400126. After that, all access to the floppy goes through + * the disk driver in the MacOS + * + * I just thought this would be on interest to someone trying to further + * this driver along + */ + + uint16_t result = m_fdc->read(offset >> 8); + + if (!machine().side_effects_disabled()) + m_maincpu->adjust_icount(-5); + + return (result << 8) | result; +} + +void mac_state::mac_iwm_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7) + m_fdc->write((offset >> 8), data & 0xff); else + m_fdc->write((offset >> 8), data >> 8); + + if (!machine().side_effects_disabled()) + m_maincpu->adjust_icount(-5); +} + +WRITE_LINE_MEMBER(mac_state::mac_adb_via_out_cb2) +{ + // printf("VIA OUT CB2 = %x\n", state); +#if !MACII_USE_ADBMODEM + if (m_macadb) { -// printf("VIA2 lower\n"); - set_via2_interrupt(0); + m_macadb->adb_data_w(state); } +#endif } -uint8_t mac_state::mac_rbv_r(offs_t offset) +/* ************************************************************************* + * VIA + * ************************************************************************* + * + * + * PORT A + * + * bit 7 R SCC Wait/Request + * bit 6 W Main/Alternate screen buffer select + * bit 5 W Floppy Disk Line Selection + * bit 4 W Overlay/Normal memory mapping + * bit 3 W Main/Alternate sound buffer + * bit 2-0 W Sound Volume + * + * + * PORT B + * + * bit 7 W Sound enable + * bit 6 R Video beam in display + * bit 5 (pre-ADB) R Mouse Y2 + * (ADB) W ADB ST1 + * bit 4 (pre-ADB) R Mouse X2 + * (ADB) W ADB ST0 + * bit 3 (pre-ADB) R Mouse button (active low) + * (ADB) R ADB INT + * bit 2 W Real time clock enable + * bit 1 W Real time clock data clock + * bit 0 RW Real time clock data + * + */ + +#define PA6 0x40 +#define PA4 0x10 +#define PA2 0x04 +#define PA1 0x02 + +uint8_t mac_state::mac_via_in_a() { - int data = 0; + // printf("%s VIA1 IN_A\n", machine().describe_context().c_str()); - if (offset < 0x100) + switch (m_model) { - data = m_rbv_regs[offset]; + case MODEL_MAC_II: + case MODEL_MAC_II_FDHD: + case MODEL_MAC_IIX: + return 0x81; // bit 0 must be set on most Macs to avoid attempting to boot from AppleTalk - if (offset == 0x10) - { - data &= ~0x38; - data |= (m_montype.read_safe(2)<<3); -// printf("%s rbv_r montype: %02x\n", machine().describe_context().c_str(), data); - } + case MODEL_MAC_SE30: + return 0x81 | PA6; + + case MODEL_MAC_IICX: + return 0x81 | PA6; + + default: + return 0x80; + } +} + +uint8_t mac_state::mac_via_in_b() +{ + int val = 0; + +#if !MACII_USE_ADBMODEM + val |= m_macadb->get_adb_state() << 4; +#endif + + if (!m_adb_irq_pending) + { + val |= 0x08; + } + + val |= m_rtc->data_r(); + + // printf("%s VIA1 IN_B_II = %02x\n", machine().describe_context().c_str(), val); + + return val; +} + +void mac_state::mac_via_out_a(uint8_t data) +{ + // printf("%s VIA1 OUT A: %02x\n", machine().describe_context().c_str(), data); + + m_screen_buffer = (data & 0x40) >> 6; + if (m_cur_floppy) + m_cur_floppy->ss_w((data & 0x20) >> 5); +} + +void mac_state::mac_via_out_b(uint8_t data) +{ + // printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data); + + if (m_model == MODEL_MAC_SE30) + { + // 0x40 = 0 means enable vblank on SE/30 + m_se30_vbl_enable = (data & 0x40) ? 0 : 1; - // bit 7 of these registers always reads as 0 on RBV - if ((offset == 0x12) || (offset == 0x13)) + // clear the interrupt if we disabled it + if (!m_se30_vbl_enable) { - data &= ~0x80; + nubus_slot_interrupt(0xe, 0); } } + +#if MACII_USE_ADBMODEM + m_adbmodem->set_via_state((data & 0x30) >> 4); +#else + m_macadb->mac_adb_newaction((data & 0x30) >> 4); +#endif + + m_rtc->ce_w((data & 0x04) >> 2); + m_rtc->data_w(data & 0x01); + m_rtc->clk_w((data >> 1) & 0x01); +} + +WRITE_LINE_MEMBER(mac_state::mac_via_irq) +{ + /* interrupt the 68k (level 1) */ + set_via_interrupt(state); +} + +void mac_state::mac_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 + // the whole access takes half a (via) cycle and ends when synced + // with the main cpu again. + + // Get the main cpu time + u64 cycle = m_maincpu->total_cycles(); + + // Get the number of the cycle the via is in at that time + u64 via_cycle = cycle * m_via1->clock() / m_maincpu->clock(); + + // The access is going to start at via_cycle+1 and end at + // via_cycle+1.5, compute what that means in maincpu cycles (the + // +1 rounds up, since the clocks are too different to ever be + // synced). + u64 main_cycle = (via_cycle * 2 + 3) * m_maincpu->clock() / (2 * m_via1->clock()) + 1; + + // Finally adjust the main cpu icount as needed. + m_maincpu->adjust_icount(-int(main_cycle - cycle)); +} + +uint16_t mac_state::mac_via_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + mac_via_sync(); + + uint16_t data; + + offset >>= 8; + offset &= 0x0f; + + data = m_via1->read(offset); + + return (data & 0xff) | (data << 8); +} + +void mac_state::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + mac_via_sync(); + + offset >>= 8; + offset &= 0x0f; + + if (ACCESSING_BITS_0_7) + m_via1->write(offset, data & 0xff); + if (ACCESSING_BITS_8_15) + m_via1->write(offset, (data >> 8) & 0xff); +} + +/* ************************************************************************* + * VIA 2 (on Mac IIs, PowerBooks > 100, and PowerMacs) + * *************************************************************************/ + +WRITE_LINE_MEMBER(mac_state::mac_via2_irq) +{ + set_via2_interrupt(state); +} + +uint16_t mac_state::mac_via2_r(offs_t offset) +{ + int data; + + if (!machine().side_effects_disabled()) + mac_via_sync(); + + offset >>= 8; + offset &= 0x0f; + + data = m_via2->read(offset); + + return (data & 0xff) | (data << 8); +} + +void mac_state::mac_via2_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + mac_via_sync(); + + offset >>= 8; + offset &= 0x0f; + + if (ACCESSING_BITS_0_7) + m_via2->write(offset, data & 0xff); + if (ACCESSING_BITS_8_15) + m_via2->write(offset, (data >> 8) & 0xff); +} + +uint8_t mac_state::mac_via2_in_a() +{ + return 0xc0 | m_nubus_irq_state; +} + +uint8_t mac_state::mac_via2_in_b() +{ + if ((m_model == MODEL_MAC_SE30) || (m_model == MODEL_MAC_IIX)) + { + return 0x87; // bits 3 and 6 are tied low on SE/30 + } + + return 0xcf; // indicate no NuBus transaction error +} + +void mac_state::mac_via2_out_a(uint8_t data) +{ +} + +void mac_state::mac_via2_out_b(uint8_t data) +{ + // chain 60.15 Hz to VIA1 + m_via1->write_ca1(data >> 7); + + if (m_model == MODEL_MAC_II) + { + m68000_musashi_device *m68k = downcast(m_maincpu.target()); + m68k->set_hmmu_enable((data & 0x8) ? M68K_HMMU_DISABLE : M68K_HMMU_ENABLE_II); + } +} + +void mac_state::machine_start() +{ + if (m_screen) + { + this->m_scanline_timer = timer_alloc(FUNC(mac_state::mac_scanline_tick), this); + this->m_scanline_timer->adjust(m_screen->time_until_pos(0, 0)); + } else { - offset >>= 9; + m_adbupdate_timer = timer_alloc(FUNC(mac_state::mac_adbrefresh_tick), this); + m_adbupdate_timer->adjust(attotime::from_hz(70)); + } - switch (offset) - { - case 13: // IFR -// printf("Read IER = %02x (PC=%x) 2=%02x\n", m_rbv_ier, m_maincpu->pc(), m_rbv_regs[2]); - data = m_rbv_ifr; - break; - - case 14: // IER -// printf("Read IFR = %02x (PC=%x) 2=%02x\n", m_rbv_ifr, m_maincpu->pc(), m_rbv_regs[2]); - data = m_rbv_ier; - break; - - default: - logerror("rbv_r: Unknown extended RBV VIA register %d access\n", offset); - break; - } + save_item(NAME(m_nubus_irq_state)); + save_item(NAME(m_se30_vbl_enable)); + save_item(NAME(m_adb_irq_pending)); + save_item(NAME(ca1_data)); + save_item(NAME(m_scc_interrupt)); + save_item(NAME(m_via_interrupt)); + save_item(NAME(m_via2_interrupt)); + save_item(NAME(m_scsi_interrupt)); + save_item(NAME(m_last_taken_interrupt)); + save_item(NAME(m_via2_ca1_hack)); +} + +void mac_state::machine_reset() +{ + m_last_taken_interrupt = -1; + + /* setup the memory overlay */ + m_overlay = -1; // insure no match + this->set_memory_overlay(1); + + if (m_overlay_timeout != (emu_timer *)nullptr) + { + m_overlay_timeout->adjust(m_maincpu->cycles_to_attotime(8)); + } + + /* setup videoram */ + this->m_screen_buffer = 1; + + m_via2_ca1_hack = 1; + m_via2->write_ca1(1); + m_via2->write_cb1(1); + + m_scsi_interrupt = 0; + + m_via2_vbl = 0; + m_se30_vbl_enable = 0; + m_nubus_irq_state = 0xff; + m_last_taken_interrupt = 0; +} + +void mac_state::mac_state_load() +{ + int overlay = m_overlay; + m_overlay = -1; + set_memory_overlay(overlay); +} + +TIMER_CALLBACK_MEMBER(mac_state::overlay_timeout_func) +{ + if (m_overlay != -1) + { + set_memory_overlay(0); // kill the overlay } -// printf("rbv_r: %x = %02x (PC=%x)\n", offset, data, m_maincpu->pc()); + // we're a one-time-only thing + m_overlay_timeout->adjust(attotime::never); +} + +void mac_state::mac_driver_init(model_t model) +{ + m_overlay = 1; + m_scsi_interrupt = 0; + m_model = model; + m_scc_interrupt = 0; + m_via_interrupt = 0; + m_via2_interrupt = 0; + + m_rom_size = memregion("bootrom")->bytes(); + m_rom_ptr = reinterpret_cast(memregion("bootrom")->base()); + + m_overlay = -1; + set_memory_overlay(1); + + memset(m_ram->pointer(), 0, m_ram->size()); + + m_overlay_timeout = timer_alloc(FUNC(mac_state::overlay_timeout_func), this); - return data; + /* save state stuff */ + machine().save().register_postload(save_prepost_delegate(FUNC(mac_state::mac_state_load), this)); } -void mac_state::mac_rbv_w(offs_t offset, uint8_t data) +#define MAC_DRIVER_INIT(label, model) \ + void mac_state::init_##label() \ + { \ + mac_driver_init(model); \ + } + +MAC_DRIVER_INIT(macii, MODEL_MAC_II) +MAC_DRIVER_INIT(macse30, MODEL_MAC_SE30) +MAC_DRIVER_INIT(maciicx, MODEL_MAC_IICX) +MAC_DRIVER_INIT(maciifdhd, MODEL_MAC_II_FDHD) +MAC_DRIVER_INIT(maciix, MODEL_MAC_IIX) + +void mac_state::nubus_slot_interrupt(uint8_t slot, uint32_t state) { - if (offset < 0x100) + static const uint8_t masks[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; + uint8_t mask = 0x3f; + + slot -= 9; + + if (state) + { + m_nubus_irq_state &= ~masks[slot]; + } + else + { + m_nubus_irq_state |= masks[slot]; + } + + if ((m_nubus_irq_state & mask) != mask) { -// if (offset == 0x10) -// printf("rbv_w: %02x to offset %x (PC=%x)\n", data, offset, m_maincpu->pc()); - switch (offset) + // HACK: sometimes we miss an ack (possible misbehavior in the VIA?) + if (m_via2_ca1_hack == 0) { - case 0x02: - data &= 0x40; - m_rbv_regs[offset] &= ~data; - rbv_recalc_irqs(); - break; - - case 0x03: // write here to ack - if (data & 0x80) // 1 bits write 1s - { - m_rbv_regs[offset] |= data & 0x7f; - m_rbv_ifr |= data & 0x7f; - } - else // 1 bits write 0s - { - m_rbv_regs[offset] &= ~(data & 0x7f); - m_rbv_ifr &= ~(data & 0x7f); - } - rbv_recalc_irqs(); - break; - - case 0x10: - if (data != 0) - { - m_rbv_immed10wr = 1; - } - m_rbv_regs[offset] = data; - break; - - case 0x12: - if (data & 0x80) // 1 bits write 1s - { - m_rbv_regs[offset] |= data & 0x7f; - } - else // 1 bits write 0s - { - m_rbv_regs[offset] &= ~(data & 0x7f); - } - rbv_recalc_irqs(); - break; - - case 0x13: - if (data & 0x80) // 1 bits write 1s - { - m_rbv_regs[offset] |= data & 0x7f; - - if (data == 0xff) m_rbv_regs[offset] = 0x1f; // I don't know why this is special, but the IIci ROM's POST demands it - } - else // 1 bits write 0s - { - m_rbv_regs[offset] &= ~(data & 0x7f); - } - break; - - default: - m_rbv_regs[offset] = data; - break; + m_via2->write_ca1(1); } + m_via2_ca1_hack = 0; + m_via2->write_ca1(0); } else { - offset >>= 9; + m_via2_ca1_hack = 1; + m_via2->write_ca1(1); + } +} - switch (offset) +void mac_state::vblank_irq() +{ + /* handle ADB keyboard/mouse */ + m_macadb->adb_vblank(); + + // handle SE/30 vblank IRQ + if (m_model == MODEL_MAC_SE30) + { + if (m_se30_vbl_enable) { - case 13: // IFR -// printf("%02x to IFR (PC=%x)\n", data, m_maincpu->pc()); - if (data & 0x80) - { - data = 0x7f; - } - rbv_recalc_irqs(); - break; - - case 14: // IER -// printf("%02x to IER (PC=%x)\n", data, m_maincpu->pc()); - if (data & 0x80) // 1 bits write 1s - { - m_rbv_ier |= data & 0x7f; - } - else // 1 bits write 0s - { - m_rbv_ier &= ~(data & 0x7f); - } - rbv_recalc_irqs(); - break; - - default: - logerror("rbv_w: Unknown extended RBV VIA register %d access\n", offset); - break; + m_via2_vbl ^= 1; + if (!m_via2_vbl) + { + this->nubus_slot_interrupt(0xe, 1); + } } } } -uint16_t mac_state::mac_config_r() +TIMER_CALLBACK_MEMBER(mac_state::mac_adbrefresh_tick) +{ + vblank_irq(); + m_adbupdate_timer->adjust(attotime::from_hz(70)); +} + +TIMER_CALLBACK_MEMBER(mac_state::mac_scanline_tick) +{ + const int scanline = m_screen->vpos(); + if (scanline == 0) + { + vblank_irq(); + } + const int next_scanline = (scanline + 1) % MAC_V_TOTAL; + m_scanline_timer->adjust(m_screen->time_until_pos(next_scanline), next_scanline); +} + +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w) { - return 0xffff; // returns nonzero if no PDS RAM expansion, 0 if present + nubus_slot_interrupt(Slot, state); +} + +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w<9>); +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w<0xa>); +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w<0xb>); +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w<0xc>); +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w<0xd>); +template WRITE_LINE_MEMBER(mac_state::nubus_irq_w<0xe>); + +void mac_state::phases_w(uint8_t phases) +{ + if (m_cur_floppy) + m_cur_floppy->seek_phase_w(phases); +} + +void mac_state::devsel_w(uint8_t devsel) +{ + if (devsel == 1) + m_cur_floppy = m_floppy[0]->get_device(); + else if (devsel == 2) + m_cur_floppy = m_floppy[1]->get_device(); + else + m_cur_floppy = nullptr; + m_fdc->set_floppy(m_cur_floppy); + if (m_cur_floppy) + m_cur_floppy->ss_w((m_via1->read_pa() & 0x20) >> 5); } /*************************************************************************** @@ -297,7 +1012,7 @@ void mac_state::macii_map(address_map &map) // MMU remaps I/O without the F map(0x50000000, 0x50001fff).rw(FUNC(mac_state::mac_via_r), FUNC(mac_state::mac_via_w)).mirror(0x00f00000); map(0x50002000, 0x50003fff).rw(FUNC(mac_state::mac_via2_r), FUNC(mac_state::mac_via2_w)).mirror(0x00f00000); - map(0x50004000, 0x50005fff).rw(FUNC(mac_state::mac_scc_r), FUNC(mac_state::mac_scc_2_w)).mirror(0x00f00000); + map(0x50004000, 0x50005fff).rw(FUNC(mac_state::mac_scc_r), FUNC(mac_state::mac_scc_w)).mirror(0x00f00000); map(0x50006000, 0x50006003).w(FUNC(mac_state::macii_scsi_drq_w)).mirror(0x00f00000); map(0x50006060, 0x50006063).r(FUNC(mac_state::macii_scsi_drq_r)).mirror(0x00f00000); map(0x50010000, 0x50011fff).rw(FUNC(mac_state::macplus_scsi_r), FUNC(mac_state::macii_scsi_w)).mirror(0x00f00000); @@ -307,35 +1022,9 @@ void mac_state::macii_map(address_map &map) map(0x50040000, 0x50041fff).rw(FUNC(mac_state::mac_via_r), FUNC(mac_state::mac_via_w)).mirror(0x00f00000); } -void mac_state::maciici_map(address_map &map) -{ - map(0x40000000, 0x4007ffff).r(FUNC(mac_state::rom_switch_r)).mirror(0x0ff80000); - - map(0x50000000, 0x50001fff).rw(FUNC(mac_state::mac_via_r), FUNC(mac_state::mac_via_w)).mirror(0x00f00000); - map(0x50004000, 0x50005fff).rw(FUNC(mac_state::mac_scc_r), FUNC(mac_state::mac_scc_2_w)).mirror(0x00f00000); - map(0x50006000, 0x50007fff).rw(FUNC(mac_state::macii_scsi_drq_r), FUNC(mac_state::macii_scsi_drq_w)).mirror(0x00f00000); - map(0x50010000, 0x50011fff).rw(FUNC(mac_state::macplus_scsi_r), FUNC(mac_state::macii_scsi_w)).mirror(0x00f00000); - map(0x50012000, 0x50013fff).rw(FUNC(mac_state::macii_scsi_drq_r), FUNC(mac_state::macii_scsi_drq_w)).mirror(0x00f00000); - map(0x50014000, 0x50015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000); - map(0x50016000, 0x50017fff).rw(FUNC(mac_state::mac_iwm_r), FUNC(mac_state::mac_iwm_w)).mirror(0x00f00000); - map(0x50024000, 0x50024007).w(FUNC(mac_state::rbv_ramdac_w)).mirror(0x00f00000); - map(0x50026000, 0x50027fff).rw(FUNC(mac_state::mac_rbv_r), FUNC(mac_state::mac_rbv_w)).mirror(0x00f00000); - map(0x50040000, 0x50041fff).rw(FUNC(mac_state::mac_via_r), FUNC(mac_state::mac_via_w)).mirror(0x00f00000); -} - void mac_state::macse30_map(address_map &map) { - map(0x40000000, 0x4003ffff).rom().region("bootrom", 0).mirror(0x0ffc0000); - - map(0x50000000, 0x50001fff).rw(FUNC(mac_state::mac_via_r), FUNC(mac_state::mac_via_w)).mirror(0x00f00000); - map(0x50002000, 0x50003fff).rw(FUNC(mac_state::mac_via2_r), FUNC(mac_state::mac_via2_w)).mirror(0x00f00000); - map(0x50004000, 0x50005fff).rw(FUNC(mac_state::mac_scc_r), FUNC(mac_state::mac_scc_2_w)).mirror(0x00f00000); - map(0x50006000, 0x50007fff).rw(FUNC(mac_state::macii_scsi_drq_r), FUNC(mac_state::macii_scsi_drq_w)).mirror(0x00f00000); - map(0x50010000, 0x50011fff).rw(FUNC(mac_state::macplus_scsi_r), FUNC(mac_state::macii_scsi_w)).mirror(0x00f00000); - map(0x50012000, 0x50013fff).rw(FUNC(mac_state::macii_scsi_drq_r), FUNC(mac_state::macii_scsi_drq_w)).mirror(0x00f00000); - map(0x50014000, 0x50015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000); - map(0x50016000, 0x50017fff).rw(FUNC(mac_state::mac_iwm_r), FUNC(mac_state::mac_iwm_w)).mirror(0x00f00000); - map(0x50040000, 0x50041fff).rw(FUNC(mac_state::mac_via_r), FUNC(mac_state::mac_via_w)).mirror(0x00f00000); // mirror + macii_map(map); map(0xfe000000, 0xfe00ffff).ram().share("vram"); map(0xfee00000, 0xfee0ffff).ram().share("vram").mirror(0x000f0000); @@ -346,65 +1035,57 @@ void mac_state::macse30_map(address_map &map) MACHINE DRIVERS ***************************************************************************/ -void mac_state::add_base_devices(machine_config &config, bool rtc, int woz_version) +void mac_state::macii(machine_config &config) { - if (rtc) - { - RTC3430042(config, m_rtc, XTAL(32'768)); - m_rtc->cko_cb().set(m_via1, FUNC(via6522_device::write_ca2)); - } + M68020PMMU(config, m_maincpu, C15M); + m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::macii_map); + m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); - switch (woz_version) { - case 0: - IWM(config, m_fdc, C15M); - m_fdc->devsel_cb().set(FUNC(mac_state::devsel_w)); - break; - case 1: - SWIM1(config, m_fdc, C15M); - m_fdc->devsel_cb().set(FUNC(mac_state::devsel_w)); - break; - case 2: - SWIM2(config, m_fdc, C15M); - m_fdc->hdsel_cb().set(FUNC(mac_state::hdsel_w)); - m_fdc->devsel_cb().set(FUNC(mac_state::devsel_w)); - break; - } + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + ASC(config, m_asc, C15M, asc_device::asc_type::ASC); + m_asc->irqf_callback().set(FUNC(mac_state::mac_asc_irq)); + m_asc->add_route(0, "lspeaker", 1.0); + m_asc->add_route(1, "rspeaker", 1.0); + + RTC3430042(config, m_rtc, XTAL(32'768)); + m_rtc->cko_cb().set(m_via1, FUNC(via6522_device::write_ca2)); + IWM(config, m_fdc, C15M); + m_fdc->devsel_cb().set(FUNC(mac_state::devsel_w)); m_fdc->phases_cb().set(FUNC(mac_state::phases_w)); - m_fdc->sel35_cb().set(FUNC(mac_state::sel35_w)); + applefdintf_device::add_35(config, m_floppy[0]); + applefdintf_device::add_35_nc(config, m_floppy[1]); - if (woz_version == 0) - { - applefdintf_device::add_35(config, m_floppy[0]); - applefdintf_device::add_35_nc(config, m_floppy[1]); - } - else - { - applefdintf_device::add_35_hd(config, m_floppy[0]); - applefdintf_device::add_35_nc(config, m_floppy[1]); + 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(FUNC(mac_state::set_scc_interrupt)); + 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)); - SOFTWARE_LIST(config, "flop35hd_list").set_original("mac_hdflop"); - } + 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)); - SCC8530(config, m_scc, C7M); - m_scc->intrq_callback().set(FUNC(mac_state::set_scc_interrupt)); -} + 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)); -void mac_state::add_scsi(machine_config &config, bool cdrom) -{ NSCSI_BUS(config, "scsi"); 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 ? "cdrom" : 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("ncr5380", NCR53C80).machine_config([this](device_t *device) { + NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR53C80).machine_config([this](device_t *device) + { ncr53c80_device &adapter = downcast(*device); adapter.irq_handler().set(*this, FUNC(mac_state::mac_scsi_irq)); - adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w)); - }); + adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w)); }); MAC_SCSI_HELPER(config, m_scsihelp); m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read)); @@ -415,98 +1096,36 @@ void mac_state::add_scsi(machine_config &config, bool cdrom) m_scsihelp->timeout_error_callback().set(FUNC(mac_state::scsi_berr_w)); SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd"); -} -void mac_state::add_via1_adb(machine_config &config, bool macii) -{ + nubus_device &nubus(NUBUS(config, "nubus", 0)); + nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.out_irq9_callback().set(FUNC(mac_state::nubus_irq_w<9>)); + nubus.out_irqa_callback().set(FUNC(mac_state::nubus_irq_w<0xa>)); + nubus.out_irqb_callback().set(FUNC(mac_state::nubus_irq_w<0xb>)); + nubus.out_irqc_callback().set(FUNC(mac_state::nubus_irq_w<0xc>)); + nubus.out_irqd_callback().set(FUNC(mac_state::nubus_irq_w<0xd>)); + nubus.out_irqe_callback().set(FUNC(mac_state::nubus_irq_w<0xe>)); + NUBUS_SLOT(config, "nb9", "nubus", mac_nubus_cards, "mdc824"); + NUBUS_SLOT(config, "nba", "nubus", mac_nubus_cards, nullptr); + NUBUS_SLOT(config, "nbb", "nubus", mac_nubus_cards, nullptr); + NUBUS_SLOT(config, "nbc", "nubus", mac_nubus_cards, nullptr); + NUBUS_SLOT(config, "nbd", "nubus", mac_nubus_cards, nullptr); + NUBUS_SLOT(config, "nbe", "nubus", mac_nubus_cards, nullptr); + R65NC22(config, m_via1, C7M/10); m_via1->readpa_handler().set(FUNC(mac_state::mac_via_in_a)); - if (macii) - m_via1->readpb_handler().set(FUNC(mac_state::mac_via_in_b_ii)); - else - m_via1->readpb_handler().set(FUNC(mac_state::mac_via_in_b)); + m_via1->readpb_handler().set(FUNC(mac_state::mac_via_in_b)); m_via1->writepa_handler().set(FUNC(mac_state::mac_via_out_a)); - m_via1->writepb_handler().set(FUNC(mac_state::mac_via_out_b_bbadb)); + m_via1->writepb_handler().set(FUNC(mac_state::mac_via_out_b)); m_via1->cb2_handler().set(FUNC(mac_state::mac_adb_via_out_cb2)); m_via1->irq_handler().set(FUNC(mac_state::mac_via_irq)); -} -void mac_state::add_via2(machine_config &config) -{ R65NC22(config, m_via2, C7M/10); m_via2->readpa_handler().set(FUNC(mac_state::mac_via2_in_a)); m_via2->readpb_handler().set(FUNC(mac_state::mac_via2_in_b)); m_via2->writepa_handler().set(FUNC(mac_state::mac_via2_out_a)); m_via2->writepb_handler().set(FUNC(mac_state::mac_via2_out_b)); m_via2->irq_handler().set(FUNC(mac_state::mac_via2_irq)); -} - -void mac_state::add_asc(machine_config &config, asc_device::asc_type type) -{ - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - ASC(config, m_asc, C15M, type); - m_asc->irqf_callback().set(FUNC(mac_state::mac_asc_irq)); - m_asc->add_route(0, "lspeaker", 1.0); - m_asc->add_route(1, "rspeaker", 1.0); -} - -void mac_state::add_nubus(machine_config &config, bool bank1, bool bank2) -{ - nubus_device &nubus(NUBUS(config, "nubus", 0)); - nubus.set_space(m_maincpu, AS_PROGRAM); - nubus.out_irq9_callback().set(FUNC(mac_state::nubus_irq_9_w)); - nubus.out_irqa_callback().set(FUNC(mac_state::nubus_irq_a_w)); - nubus.out_irqb_callback().set(FUNC(mac_state::nubus_irq_b_w)); - nubus.out_irqc_callback().set(FUNC(mac_state::nubus_irq_c_w)); - nubus.out_irqd_callback().set(FUNC(mac_state::nubus_irq_d_w)); - nubus.out_irqe_callback().set(FUNC(mac_state::nubus_irq_e_w)); - if (bank1) - { - NUBUS_SLOT(config, "nb9", "nubus", mac_nubus_cards, "mdc824"); - NUBUS_SLOT(config, "nba", "nubus", mac_nubus_cards, nullptr); - NUBUS_SLOT(config, "nbb", "nubus", mac_nubus_cards, nullptr); - } - if (bank2) - { - NUBUS_SLOT(config, "nbc", "nubus", mac_nubus_cards, nullptr); - NUBUS_SLOT(config, "nbd", "nubus", mac_nubus_cards, nullptr); - NUBUS_SLOT(config, "nbe", "nubus", mac_nubus_cards, nullptr); - } -} - -template void mac_state::add_nubus_pds(machine_config &config, const char *slot_tag, T &&opts) -{ - nubus_device &nubus(NUBUS(config, "pds", 0)); - nubus.set_space(m_maincpu, AS_PROGRAM); - nubus.out_irq9_callback().set(FUNC(mac_state::nubus_irq_9_w)); - nubus.out_irqa_callback().set(FUNC(mac_state::nubus_irq_a_w)); - nubus.out_irqb_callback().set(FUNC(mac_state::nubus_irq_b_w)); - nubus.out_irqc_callback().set(FUNC(mac_state::nubus_irq_c_w)); - nubus.out_irqd_callback().set(FUNC(mac_state::nubus_irq_d_w)); - nubus.out_irqe_callback().set(FUNC(mac_state::nubus_irq_e_w)); - NUBUS_SLOT(config, slot_tag, "pds", std::forward(opts), nullptr); -} - -void mac_state::macii(machine_config &config, bool cpu, asc_device::asc_type asc_type, bool nubus, bool nubus_bank1, bool nubus_bank2, int woz_version) -{ - if (cpu) - { - M68020PMMU(config, m_maincpu, C15M); - m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::macii_map); - m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); - } - - PALETTE(config, m_palette).set_entries(256); - - add_asc(config, asc_type); - add_base_devices(config, true, woz_version); - add_scsi(config, true); - if (nubus) - add_nubus(config, nubus_bank1, nubus_bank2); - - add_via1_adb(config, true); - add_via2(config); #if MACII_USE_ADBMODEM ADBMODEM(config, m_adbmodem, C7M); @@ -537,58 +1156,52 @@ void mac_state::macii(machine_config &config, bool cpu, asc_device::asc_type asc void mac_state::maciihmu(machine_config &config) { - macii(config, false); + macii(config); - M68020HMMU(config, m_maincpu, C15M); + M68020HMMU(config.replace(), m_maincpu, C15M); m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::macii_map); m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); } void mac_state::maciihd(machine_config &config) { - macii(config, true); + macii(config); + // Mac II FDHD = Mac II with a SWIM1 instead of IWM SWIM1(config.replace(), m_fdc, C15M); m_fdc->phases_cb().set(FUNC(mac_state::phases_w)); - m_fdc->sel35_cb().set(FUNC(mac_state::sel35_w)); m_fdc->devsel_cb().set(FUNC(mac_state::devsel_w)); applefdintf_device::add_35_hd(config, m_floppy[0]); applefdintf_device::add_35_hd(config, m_floppy[1]); - SOFTWARE_LIST(config, "flop35hd_list").set_original("mac_hdflop"); } -void mac_state::maciix(machine_config &config, bool nubus_bank1, bool nubus_bank2) +void mac_state::maciix(machine_config &config) { - macii(config, false, asc_device::asc_type::ASC, true, nubus_bank1, nubus_bank2); + maciihd(config); - M68030(config, m_maincpu, C15M); + // IIx = Mac II FDHD with a 68030 instead of the 020 + M68030(config.replace(), m_maincpu, C15M); m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::macii_map); m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); - - SWIM1(config.replace(), m_fdc, C15M); - m_fdc->phases_cb().set(FUNC(mac_state::phases_w)); - m_fdc->sel35_cb().set(FUNC(mac_state::sel35_w)); - m_fdc->devsel_cb().set(FUNC(mac_state::devsel_w)); - - applefdintf_device::add_35_hd(config, m_floppy[0]); - applefdintf_device::add_35_hd(config, m_floppy[1]); - - SOFTWARE_LIST(config, "flop35hd_list").set_original("mac_hdflop"); - - m_ram->set_default_size("2M"); - m_ram->set_extra_options("8M,32M,64M,96M,128M"); } -void mac_state::maciicx(machine_config &config) // IIcx is a IIx with only slots 9/a/b +void mac_state::maciicx(machine_config &config) { - maciix(config, true, false); + maciix(config); + + // IIcx = IIx with 3 fewer slots + config.device_remove("nbc"); + config.device_remove("nbd"); + config.device_remove("nbe"); } void mac_state::macse30(machine_config &config) { - M68030(config, m_maincpu, C15M); + maciicx(config); + + // SE/30 = IIx with no slots and built-in video m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::macse30_map); m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); @@ -604,126 +1217,25 @@ void mac_state::macse30(machine_config &config) PALETTE(config, m_palette, palette_device::MONOCHROME_INVERTED); - add_base_devices(config, true, 1); - add_asc(config, asc_device::asc_type::ASC); - add_scsi(config); - - add_nubus_pds(config, "pds030", mac_pds030_cards); - - add_via1_adb(config, false); - add_via2(config); - -#if MACII_USE_ADBMODEM - ADBMODEM(config, m_adbmodem, C7M); - m_adbmodem->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); - m_adbmodem->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); - m_adbmodem->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); - m_adbmodem->irq_callback().set(FUNC(mac_state::adb_irq_w)); - m_via1->cb2_handler().set(m_adbmodem, FUNC(adbmodem_device::set_via_data)); - config.set_perfect_quantum(m_maincpu); -#endif - - MACADB(config, m_macadb, C15M); -#if !MACII_USE_ADBMODEM - m_macadb->set_mcu_mode(false); - m_macadb->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); - m_macadb->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); - m_macadb->adb_irq_callback().set(FUNC(mac_state::adb_irq_w)); -#else - m_macadb->adb_data_callback().set(m_adbmodem, FUNC(adbmodem_device::set_adb_line)); -#endif - - RAM(config, m_ram); - m_ram->set_default_size("2M"); - m_ram->set_extra_options("8M,16M,32M,48M,64M,96M,128M"); - - SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop"); -} - -void mac_state::maciici(machine_config &config) -{ - macii(config, false, asc_device::asc_type::ASC, true, false, true, 1); - - M68030(config, m_maincpu, 25000000); - m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::maciici_map); - m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480); - m_screen->set_size(640, 870); - m_screen->set_visarea(0, 640-1, 0, 480-1); - m_screen->set_screen_update(FUNC(mac_state::screen_update_macrbv)); - m_screen->screen_vblank().set(FUNC(mac_state::mac_rbv_vbl)); - config.set_default_layout(layout_monitors); - - /* internal ram */ - m_ram->set_default_size("2M"); - m_ram->set_extra_options("4M,8M,16M,32M,48M,64M,128M"); -} - -void mac_state::maciisi(machine_config &config) -{ - M68030(config, m_maincpu, 20000000); - m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::maciici_map); - m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); - - PALETTE(config, m_palette).set_entries(256); - - add_asc(config, asc_device::asc_type::ASC); - add_base_devices(config, true, 1); - add_scsi(config, true); - - add_via1_adb(config, true); - add_via2(config); + config.device_remove("nb9"); + config.device_remove("nba"); + config.device_remove("nbb"); + config.device_remove("nubus"); - RAM(config, m_ram); - m_ram->set_default_size("2M"); - m_ram->set_extra_options("8M,32M,64M,96M,128M"); - - SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop"); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480); - m_screen->set_size(640, 870); - m_screen->set_visarea(0, 640-1, 0, 480-1); - m_screen->set_screen_update(FUNC(mac_state::screen_update_macrbv)); - m_screen->screen_vblank().set(FUNC(mac_state::mac_rbv_vbl)); - config.set_default_layout(layout_monitors); - - m_ram->set_default_size("2M"); - m_ram->set_extra_options("4M,8M,16M,32M,48M,64M,128M"); - - MACADB(config, m_macadb, C15M); - - m_via1->writepb_handler().set(FUNC(mac_state::mac_via_out_b_egadb)); - EGRET(config, m_egret, EGRET_344S0100); - m_egret->reset_callback().set(FUNC(mac_state::egret_reset_w)); - m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); - m_egret->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); - m_egret->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); - m_macadb->adb_data_callback().set(m_egret, FUNC(egret_device::set_adb_line)); - config.set_perfect_quantum(m_maincpu); + nubus_device &nubus(NUBUS(config, "pds", 0)); + nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.out_irq9_callback().set(FUNC(mac_state::nubus_irq_w<9>)); + nubus.out_irqa_callback().set(FUNC(mac_state::nubus_irq_w<0xa>)); + nubus.out_irqb_callback().set(FUNC(mac_state::nubus_irq_w<0xb>)); + nubus.out_irqc_callback().set(FUNC(mac_state::nubus_irq_w<0xc>)); + nubus.out_irqd_callback().set(FUNC(mac_state::nubus_irq_w<0xd>)); + nubus.out_irqe_callback().set(FUNC(mac_state::nubus_irq_w<0xe>)); + NUBUS_SLOT(config, "pds030", "pds", mac_pds030_cards, nullptr); } static INPUT_PORTS_START( macadb ) INPUT_PORTS_END -INPUT_PORTS_START( maciici ) - PORT_START("MONTYPE") - PORT_CONFNAME(0x0f, 0x06, "Connected monitor") - PORT_CONFSETTING( 0x01, "15\" Portrait Display (640x870)") - PORT_CONFSETTING( 0x02, "12\" RGB (512x384)") - PORT_CONFSETTING( 0x06, "13\" RGB (640x480)") -INPUT_PORTS_END - -/*************************************************************************** - - Game driver(s) - - The Mac driver uses a convention of placing the BIOS in "bootrom" - -***************************************************************************/ - ROM_START( macii ) ROM_REGION32_BE(0x40000, "bootrom", 0) ROM_SYSTEM_BIOS(0, "default", "rev. B") @@ -763,19 +1275,6 @@ ROM_START( macse30 ) ROM_LOAD( "se30vrom.uk6", 0x000000, 0x002000, CRC(b74c3463) SHA1(584201cc67d9452b2488f7aaaf91619ed8ce8f03) ) ROM_END -ROM_START( maciici ) - ROM_REGION32_BE(0x80000, "bootrom", 0) - ROM_LOAD32_BYTE( "341-0736.um12", 0x000000, 0x020000, CRC(7a1906e6) SHA1(3e39c80b52f40798502fcbdfc97b315545c4c4d3) ) - ROM_LOAD32_BYTE( "341-0735.um11", 0x000001, 0x020000, CRC(a8942189) SHA1(be9f653cab04c304d7ee8d4ec312c23ff5d47efc) ) - ROM_LOAD32_BYTE( "342-0734.um10", 0x000002, 0x020000, CRC(07f56402) SHA1(e11ca97181faf26cd0d05bd639d65998805c7822) ) - ROM_LOAD32_BYTE( "342-0733.um9", 0x000003, 0x020000, CRC(20c28451) SHA1(fecf849c9ac9717c18c13184e24a471888028e46) ) -ROM_END - -ROM_START( maciisi ) - ROM_REGION32_BE(0x80000, "bootrom", 0) - ROM_LOAD( "36b7fb6c.rom", 0x000000, 0x080000, CRC(f304d973) SHA1(f923de4125aae810796527ff6e25364cf1d54eec) ) -ROM_END - /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */ COMP( 1987, macii, 0, 0, macii, macadb, mac_state, init_macii, "Apple Computer", "Macintosh II", MACHINE_SUPPORTS_SAVE ) COMP( 1987, maciihmu, macii, 0, maciihmu, macadb, mac_state, init_macii, "Apple Computer", "Macintosh II (w/o 68851 MMU)", MACHINE_SUPPORTS_SAVE ) @@ -783,5 +1282,3 @@ COMP( 1988, mac2fdhd, 0, 0, maciihd, macadb, mac_state, init_maci COMP( 1988, maciix, mac2fdhd, 0, maciix, macadb, mac_state, init_maciix, "Apple Computer", "Macintosh IIx", MACHINE_SUPPORTS_SAVE ) COMP( 1989, macse30, mac2fdhd, 0, macse30, macadb, mac_state, init_macse30, "Apple Computer", "Macintosh SE/30", MACHINE_SUPPORTS_SAVE ) COMP( 1989, maciicx, mac2fdhd, 0, maciicx, macadb, mac_state, init_maciicx, "Apple Computer", "Macintosh IIcx", MACHINE_SUPPORTS_SAVE ) -COMP( 1989, maciici, 0, 0, maciici, maciici, mac_state, init_maciici, "Apple Computer", "Macintosh IIci", MACHINE_SUPPORTS_SAVE ) -COMP( 1990, maciisi, 0, 0, maciisi, maciici, mac_state, init_maciisi, "Apple Computer", "Macintosh IIsi", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/apple/mac.h b/src/mame/apple/mac.h deleted file mode 100644 index 37c08a9003a..00000000000 --- a/src/mame/apple/mac.h +++ /dev/null @@ -1,280 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont -/***************************************************************************** - * - * mac.h - * - * Macintosh II driver declarations - * - ****************************************************************************/ -#ifndef MAME_APPLE_MAC_H -#define MAME_APPLE_MAC_H - -#pragma once - -#include "machine/8530scc.h" -#include "machine/6522via.h" -#include "machine/ncr5380.h" -#include "machine/nscsi_bus.h" -#include "machine/ram.h" -#include "machine/timer.h" -#include "adbmodem.h" -#include "egret.h" -#include "macadb.h" -#include "bus/nubus/nubus.h" -#include "bus/macpds/macpds.h" -#include "machine/applefdintf.h" -#include "macrtc.h" -#include "macscsi.h" -#include "sound/asc.h" -#include "cpu/m68000/m68kmusashi.h" -#include "emupal.h" -#include "screen.h" - -#define MAC_SCREEN_NAME "screen" - -// model helpers -#define ADB_IS_BITBANG_CLASS ((m_model >= MODEL_MAC_II && m_model <= MODEL_MAC_IICI) || (m_model == MODEL_MAC_SE30)) -#define ADB_IS_EGRET (m_model == MODEL_MAC_IISI) - -// video parameters for classic Macs -#define MAC_H_VIS (512) -#define MAC_V_VIS (342) -#define MAC_H_TOTAL (704) // (512+192) -#define MAC_V_TOTAL (370) // (342+28) - -#define MACII_USE_ADBMODEM (0) - -// Mac driver data - -class mac_state:public driver_device -{ -public: - mac_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_via1(*this, "via6522_0"), - m_via2(*this, "via6522_1"), - m_asc(*this, "asc"), - m_egret(*this, EGRET_TAG), - m_adbmodem(*this, "adbmodem"), - m_macadb(*this, "macadb"), - m_ram(*this, RAM_TAG), - m_scc(*this, "scc"), - m_ncr5380(*this, "scsi:7:ncr5380"), - m_scsihelp(*this, "scsihelp"), - m_fdc(*this, "fdc"), - m_floppy(*this, "fdc:%d", 0U), - m_rtc(*this, "rtc"), - m_montype(*this, "MONTYPE"), - m_main_buffer(true), - m_vram(*this,"vram"), - m_via2_ca1_hack(0), - m_screen(*this, "screen"), - m_palette(*this, "palette") - { - m_rom_size = 0; - m_rom_ptr = nullptr; - m_cur_floppy = nullptr; - } - - void add_scsi(machine_config &config, bool cdrom = false); - void add_base_devices(machine_config &config, bool rtc = true, int woz_version = 0); - void add_asc(machine_config &config, asc_device::asc_type type = asc_device::asc_type::ASC); - void add_nubus(machine_config &config, bool bank1 = true, bool bank2 = true); - template void add_nubus_pds(machine_config &config, const char *slot_tag, T &&opts); - void add_via1_adb(machine_config &config, bool macii); - void add_via2(machine_config &config); - void add_egret(machine_config &config, int type); - - void maciisi(machine_config &config); - void maciici(machine_config &config); - void maciix(machine_config &config, bool nubus_bank1 = true, bool nubus_bank2 = true); - void maciicx(machine_config &config); - void macse30(machine_config &config); - void macii(machine_config &config, bool cpu = true, asc_device::asc_type asc_type = asc_device::asc_type::ASC, - bool nubus = true, bool nubus_bank1 = true, bool nubus_bank2 = true, int woz_version = 0); - void maciihmu(machine_config &config); - void maciihd(machine_config &config); - - void init_maciifdhd(); - void init_macse30(); - void init_macii(); - void init_maciici(); - void init_maciix(); - void init_maciisi(); - void init_maciicx(); - - /* tells which model is being emulated (set by macxxx_init) */ - enum model_t - { - MODEL_MAC_II, // Mac II class 68020/030 machines - MODEL_MAC_II_FDHD, - MODEL_MAC_IIX, - MODEL_MAC_IICX, - MODEL_MAC_IICI, - MODEL_MAC_IISI, - MODEL_MAC_SE30 - }; - - model_t m_model; - -private: - required_device m_maincpu; - required_device m_via1; - optional_device m_via2; - optional_device m_asc; - optional_device m_egret; - optional_device m_adbmodem; - optional_device m_macadb; - required_device m_ram; - required_device m_scc; - required_device m_ncr5380; - required_device m_scsihelp; - required_device m_fdc; - required_device_array m_floppy; - optional_device m_rtc; - optional_ioport m_montype; - - virtual void machine_start() override; - virtual void machine_reset() override; - - uint32_t m_overlay = 0; - - uint32_t m_via2_vbl = 0; - uint32_t m_se30_vbl_enable = 0; - uint8_t m_nubus_irq_state = 0; - - emu_timer *m_overlay_timeout = nullptr; - TIMER_CALLBACK_MEMBER(overlay_timeout_func); - uint32_t rom_switch_r(offs_t offset); - - bool m_main_buffer = false; - int m_adb_irq_pending = 0; - int m_screen_buffer = 0; - int ca1_data = 0; - - // 60.15 Hz timer for RBV/V8/Eagle/VASP/etc. - emu_timer *m_6015_timer = nullptr; - - // ADB refresh timer, independent of anything else going on - emu_timer *m_adbupdate_timer = nullptr; - - WRITE_LINE_MEMBER(adb_irq_w) { m_adb_irq_pending = state; } - - // RBV and friends (V8, etc) - uint8_t m_rbv_regs[256]{}, m_rbv_ier = 0, m_rbv_ifr = 0, m_rbv_montype = 0, m_rbv_vbltime = 0; - uint32_t m_rbv_colors[3]{}, m_rbv_count = 0, m_rbv_clutoffs = 0, m_rbv_immed10wr = 0; - uint32_t m_rbv_palette[256]{}; - emu_timer *m_vbl_timer = nullptr, *m_cursor_timer = nullptr; - uint16_t m_cursor_line = 0; - - // this is shared among all video setups with vram - optional_shared_ptr m_vram; - - // interrupts - int m_scc_interrupt = false, m_via_interrupt = false, m_via2_interrupt = false, m_scsi_interrupt = false, m_last_taken_interrupt = false; - - // defined in machine/mac.c - void v8_resize(); - void set_memory_overlay(int overlay); - void scc_mouse_irq( int x, int y ); - void nubus_slot_interrupt(uint8_t slot, uint32_t state); - DECLARE_WRITE_LINE_MEMBER(set_scc_interrupt); - void set_via_interrupt(int value); - void set_via2_interrupt(int value); - void field_interrupts(); - void vblank_irq(); - void rbv_recalc_irqs(); - void update_volume(); - - void mac_via_sync(); - uint16_t mac_via_r(offs_t offset); - void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t mac_via2_r(offs_t offset); - void mac_via2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t mac_autovector_r(offs_t offset); - void mac_autovector_w(offs_t offset, uint16_t data); - uint16_t mac_iwm_r(offs_t offset, uint16_t mem_mask = ~0); - void mac_iwm_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint16_t mac_scc_r(offs_t offset); - void mac_scc_w(offs_t offset, uint16_t data); - void mac_scc_2_w(offs_t offset, uint16_t data); - uint16_t macplus_scsi_r(offs_t offset, uint16_t mem_mask = ~0); - void macplus_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - void macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - uint32_t macii_scsi_drq_r(offs_t offset, uint32_t mem_mask = ~0); - void macii_scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); - void scsi_berr_w(uint8_t data); - - uint32_t rbv_ramdac_r(); - void rbv_ramdac_w(offs_t offset, uint32_t data); - uint8_t mac_rbv_r(offs_t offset); - void mac_rbv_w(offs_t offset, uint8_t data); - - uint16_t mac_config_r(); - - DECLARE_WRITE_LINE_MEMBER(nubus_irq_9_w); - DECLARE_WRITE_LINE_MEMBER(nubus_irq_a_w); - DECLARE_WRITE_LINE_MEMBER(nubus_irq_b_w); - DECLARE_WRITE_LINE_MEMBER(nubus_irq_c_w); - DECLARE_WRITE_LINE_MEMBER(nubus_irq_d_w); - DECLARE_WRITE_LINE_MEMBER(nubus_irq_e_w); - - DECLARE_WRITE_LINE_MEMBER(egret_reset_w); - - DECLARE_WRITE_LINE_MEMBER(mac_scsi_irq); - DECLARE_WRITE_LINE_MEMBER(mac_asc_irq); - - void macii_map(address_map &map); - void maciici_map(address_map &map); - void macse30_map(address_map &map); - - int m_via2_ca1_hack = 0; - optional_device m_screen; - optional_device m_palette; - - uint32_t m_rom_size = 0; - uint32_t *m_rom_ptr = nullptr; - - emu_timer *m_scanline_timer = nullptr; - - floppy_image_device *m_cur_floppy = nullptr; - - uint8_t m_pm_req = 0, m_pm_state = 0, m_pm_dptr = 0, m_pm_cmd = 0; - - void phases_w(uint8_t phases); - void sel35_w(int sel35); - void devsel_w(uint8_t devsel); - void hdsel_w(int hdsel); - - void macrbv_reset(); - uint32_t screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - uint32_t screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - uint32_t screen_update_macrbvvram(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - - DECLARE_WRITE_LINE_MEMBER(mac_rbv_vbl); - TIMER_CALLBACK_MEMBER(mac_6015_tick); - TIMER_CALLBACK_MEMBER(mac_adbrefresh_tick); - TIMER_CALLBACK_MEMBER(mac_scanline_tick); - DECLARE_WRITE_LINE_MEMBER(mac_adb_via_out_cb2); - uint8_t mac_via_in_a(); - uint8_t mac_via_in_b(); - uint8_t mac_via_in_b_ii(); - void mac_via_out_a(uint8_t data); - void mac_via_out_b(uint8_t data); - void mac_via_out_b_bbadb(uint8_t data); - void mac_via_out_b_egadb(uint8_t data); - uint8_t mac_via2_in_a(); - uint8_t mac_via2_in_b(); - void mac_via2_out_a(uint8_t data); - void mac_via2_out_b(uint8_t data); - void mac_state_load(); - DECLARE_WRITE_LINE_MEMBER(mac_via_irq); - DECLARE_WRITE_LINE_MEMBER(mac_via2_irq); - void set_scc_waitrequest(int waitrequest); - void mac_driver_init(model_t model); - void mac_install_memory(offs_t memory_begin, offs_t memory_end, offs_t memory_size, void *memory_data, int is_rom); -}; - -#endif // MAME_APPLE_MAC_H diff --git a/src/mame/apple/mac_m.cpp b/src/mame/apple/mac_m.cpp deleted file mode 100644 index 1362a279b06..00000000000 --- a/src/mame/apple/mac_m.cpp +++ /dev/null @@ -1,1129 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont -/**************************************************************************** - - mac_m.cpp - - Mac II series hardware - - Nate Woods - Ernesto Corvi - Raphael Nabet - R. Belmont - - Mac Model Feature Summary: - CPU FDC Kbd/Mouse PRAM Video - - Mac II 020 IWM MacII ADB ext NuBus card - - Mac IIx 030 SWIM MacII ADB ext NuBus card - - Mac SE/30 030 SWIM MacII ADB ext Internal fake NuBus card - - Mac IIcx 030 SWIM MacII ADB ext NuBus card - - Mac IIci 030 SWIM MacII ADB ext Internal "RBV" type - - Mac IIsi 030 SWIM Egret ADB n/a Internal "RBV" type - - Notes: - - On the SE and most later Macs, the first access to ROM turns off the overlay. - However, the Mac II/IIx/IIcx (and others?) have the old-style VIA overlay control bit! - - The Mac II can have either a 68551 PMMU fitted or an Apple custom that handles 24 vs. 32 - bit addressing mode. The ROM is *not* 32-bit clean so Mac OS normally runs in 24 bit mode, - but A/UX can run 32. - - There are 5 known kinds of host-side ADB hardware: - * "Mac II ADB" used in the SE, II, IIx, IIcx, SE/30, IIci, Quadra 610, Quadra 650, Quadra 700, - Quadra 800, Centris 610 and Centris 650. This is a bit-banger using the VIA and a simple PIC. - * "PMU ADB" used in the Mac Portable and all 680x0-based PowerBooks. - * "Egret ADB" used in the IIsi, IIvi, IIvx, Classic II, LC, LC II, LC III, Performa 460, - and Performa 600. This is a 68HC05 with a different internal ROM than CUDA. - * "IOP ADB" (ADB driven by a 6502 coprocessor, similar to Lisa) used in the IIfx, - Quadra 900, and Quadra 950. - * "Cuda ADB" (Apple's CUDA chip, which is a 68HC05 MCU) used in the Color Classic, LC 520, - LC 55x, LC 57x, LC 58x, Quadra 630, Quadra 660AV, Quadra 840AV, PowerMac 6100/7100/8100, - IIci, and PowerMac 5200. - - TODO: - - Call the RTC timer - -****************************************************************************/ - -#include "emu.h" -#include "mac.h" - -#define INTS_RBV ((m_model == MODEL_MAC_IICI) || (m_model == MODEL_MAC_IISI)) - -#ifdef MAME_DEBUG -#define LOG_ADB 0 -#define LOG_VIA 0 -#define LOG_MAC_IWM 0 -#define LOG_GENERAL 0 -#define LOG_KEYBOARD 0 -#define LOG_MEMORY 0 -#else -#define LOG_ADB 0 -#define LOG_VIA 0 -#define LOG_MAC_IWM 0 -#define LOG_GENERAL 0 -#define LOG_KEYBOARD 0 -#define LOG_MEMORY 0 -#endif - -void mac_state::mac_install_memory(offs_t memory_begin, offs_t memory_end, - offs_t memory_size, void *memory_data, int is_rom) -{ - address_space& space = m_maincpu->space(AS_PROGRAM); - offs_t memory_mirror; - - memory_size = std::min(memory_size, (memory_end + 1 - memory_begin)); - memory_mirror = (memory_end - memory_begin) & ~(memory_size - 1); - - if (!is_rom) - { - space.install_ram(memory_begin, memory_end & ~memory_mirror, memory_mirror, memory_data); - } - else - { - space.unmap_write(memory_begin, memory_end); - space.install_rom(memory_begin, memory_end & ~memory_mirror, memory_mirror, memory_data); - } - - if (LOG_MEMORY) - { - printf("mac_install_memory(): range=[0x%06x...0x%06x] mirror=0x%06x ptr=0x%p\n", - memory_begin, memory_end, memory_mirror, memory_data); - } -} - - - -/* - Interrupt handling -*/ - -void mac_state::field_interrupts() -{ - int take_interrupt = -1; - - if (m_scc_interrupt) - { - take_interrupt = 4; - } - else if (m_via2_interrupt) - { - take_interrupt = 2; - } - else if (m_via_interrupt) - { - take_interrupt = 1; - } - - if (m_last_taken_interrupt > -1) - { - m_maincpu->set_input_line(m_last_taken_interrupt, CLEAR_LINE); - m_last_taken_interrupt = -1; - } - - if (take_interrupt > -1) - { - m_maincpu->set_input_line(take_interrupt, ASSERT_LINE); - m_last_taken_interrupt = take_interrupt; - } -} - -WRITE_LINE_MEMBER(mac_state::set_scc_interrupt) -{ - m_scc_interrupt = state; - this->field_interrupts(); -} - -void mac_state::set_via_interrupt(int value) -{ - m_via_interrupt = value; - this->field_interrupts(); -} - - -void mac_state::set_via2_interrupt(int value) -{ - m_via2_interrupt = value; - this->field_interrupts(); -} - -WRITE_LINE_MEMBER(mac_state::mac_asc_irq) -{ - if (INTS_RBV) - { - if (state == ASSERT_LINE) - { - m_rbv_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt - rbv_recalc_irqs(); - } - else - { - m_rbv_regs[3] &= ~0x10; - rbv_recalc_irqs(); - } - } - else - { - m_via2->write_cb1(state^1); - } -} - -void mac_state::mac_autovector_w(offs_t offset, uint16_t data) -{ - if (LOG_GENERAL) - logerror("mac_autovector_w: offset=0x%08x data=0x%04x\n", offset, data); - - /* This should throw an exception */ - - /* Not yet implemented */ -} - -uint16_t mac_state::mac_autovector_r(offs_t offset) -{ - if (LOG_GENERAL) - logerror("mac_autovector_r: offset=0x%08x\n", offset); - - /* This should throw an exception */ - - /* Not yet implemented */ - return 0; -} - -void mac_state::set_scc_waitrequest(int waitrequest) -{ - if (LOG_GENERAL) - logerror("set_scc_waitrequest: waitrequest=%i\n", waitrequest); - - /* Not Yet Implemented */ -} - -void mac_state::set_memory_overlay(int overlay) -{ - offs_t memory_size; - uint8_t *memory_data; - int is_rom; - - /* normalize overlay */ - overlay = overlay ? true : false; - - if (overlay != m_overlay) - { - /* set up either main RAM area or ROM mirror at 0x000000-0x3fffff */ - if (overlay) - { - /* ROM mirror */ - memory_size = m_rom_size; - memory_data = reinterpret_cast(m_rom_ptr); - is_rom = true; - } - else - { - /* RAM */ - memory_size = m_ram->size(); - memory_data = m_ram->pointer(); - is_rom = false; - } - - /* install the memory */ - if ((m_model == MODEL_MAC_IICI) || (m_model == MODEL_MAC_IISI)) - { - // ROM is OK to flood to 3fffffff - if (is_rom) - { - mac_install_memory(0x00000000, 0x3fffffff, memory_size, memory_data, is_rom); - } - else // RAM: be careful not to populate ram B with a mirror or the ROM will get confused - { - mac_install_memory(0x00000000, memory_size-1, memory_size, memory_data, is_rom); - // switch ROM region to direct access instead of through rom_switch_r - mac_install_memory(0x40000000, 0x4007ffff, memory_size, memory_data, is_rom); - } - } - else if ((m_model >= MODEL_MAC_II) && (m_model <= MODEL_MAC_SE30)) - { - mac_install_memory(0x00000000, 0x3fffffff, memory_size, memory_data, is_rom); - } - else - { - mac_install_memory(0x00000000, 0x003fffff, memory_size, memory_data, is_rom); - } - - m_overlay = overlay; - - if (LOG_GENERAL) - logerror("mac_set_memory_overlay: overlay=%i\n", overlay); - } -} - -uint32_t mac_state::rom_switch_r(offs_t offset) -{ - // disable the overlay - if (m_overlay) - { - set_memory_overlay(0); - } - - //printf("rom_switch_r: offset %08x ROM_size -1 = %08x, masked = %08x\n", offset, m_rom_size-1, offset & ((m_rom_size - 1)>>2)); - - return m_rom_ptr[offset & ((m_rom_size - 1)>>2)]; -} - -/* ************************************************************************* - * SCSI - * *************************************************************************/ - -/* - -From http://www.mac.m68k-linux.org/devel/plushw.php - -The address of each register is computed as follows: - - $580drn - - where r represents the register number (from 0 through 7), - n determines whether it a read or write operation - (0 for reads, or 1 for writes), and - d determines whether the DACK signal to the NCR 5380 is asserted. - (0 for not asserted, 1 is for asserted) - -Here's an example of the address expressed in binary: - - 0101 1000 0000 00d0 0rrr 000n - -Note: Asserting the DACK signal applies only to write operations to - the output data register and read operations from the input - data register. - - Symbolic Memory - Location Location NCR 5380 Internal Register - - scsiWr+sODR+dackWr $580201 Output Data Register with DACK - scsiWr+sODR $580001 Output Data Register - scsiWr+sICR $580011 Initiator Command Register - scsiWr+sMR $580021 Mode Register - scsiWr+sTCR $580031 Target Command Register - scsiWr+sSER $580041 Select Enable Register - scsiWr+sDMAtx $580051 Start DMA Send - scsiWr+sTDMArx $580061 Start DMA Target Receive - scsiWr+sIDMArx $580071 Start DMA Initiator Receive - - scsiRd+sIDR+dackRd $580260 Current SCSI Data with DACK - scsiRd+sCDR $580000 Current SCSI Data - scsiRd+sICR $580010 Initiator Command Register - scsiRd+sMR $580020 Mode Registor - scsiRd+sTCR $580030 Target Command Register - scsiRd+sCSR $580040 Current SCSI Bus Status - scsiRd+sBSR $580050 Bus and Status Register - scsiRd+sIDR $580060 Input Data Register - scsiRd+sRESET $580070 Reset Parity/Interrupt - */ - -uint16_t mac_state::macplus_scsi_r(offs_t offset, uint16_t mem_mask) -{ - int reg = (offset>>3) & 0xf; - -// logerror("macplus_scsi_r: offset %x mask %x\n", offset, mem_mask); - - bool pseudo_dma = (reg == 6) && (offset == 0x130); - - return m_scsihelp->read_wrapper(pseudo_dma, reg)<<8; -} - -uint32_t mac_state::macii_scsi_drq_r(offs_t offset, uint32_t mem_mask) -{ - switch (mem_mask) - { - case 0xff000000: - return m_scsihelp->read_wrapper(true, 6)<<24; - - case 0xffff0000: - return (m_scsihelp->read_wrapper(true, 6)<<24) | (m_scsihelp->read_wrapper(true, 6)<<16); - - case 0xffffffff: - return (m_scsihelp->read_wrapper(true, 6)<<24) | (m_scsihelp->read_wrapper(true, 6)<<16) | (m_scsihelp->read_wrapper(true, 6)<<8) | m_scsihelp->read_wrapper(true, 6); - - default: - logerror("macii_scsi_drq_r: unknown mem_mask %08x\n", mem_mask); - } - - return 0; -} - -void mac_state::macii_scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch (mem_mask) - { - case 0xff000000: - m_scsihelp->write_wrapper(true, 0, data>>24); - break; - - case 0xffff0000: - m_scsihelp->write_wrapper(true, 0, data>>24); - m_scsihelp->write_wrapper(true, 0, data>>16); - break; - - case 0xffffffff: - m_scsihelp->write_wrapper(true, 0, data>>24); - m_scsihelp->write_wrapper(true, 0, data>>16); - m_scsihelp->write_wrapper(true, 0, data>>8); - m_scsihelp->write_wrapper(true, 0, data&0xff); - break; - - default: - logerror("macii_scsi_drq_w: unknown mem_mask %08x\n", mem_mask); - break; - } -} - -void mac_state::macplus_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - int reg = (offset>>3) & 0xf; - -// logerror("macplus_scsi_w: data %x offset %x mask %x\n", data, offset, mem_mask); - - bool pseudo_dma = (reg == 0) && (offset == 0x100); - - m_scsihelp->write_wrapper(pseudo_dma, reg, data); -} - -void mac_state::macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - int reg = (offset>>3) & 0xf; - -// logerror("macplus_scsi_w: data %x offset %x mask %x (PC=%x)\n", data, offset, mem_mask, m_maincpu->pc()); - - bool pseudo_dma = (reg == 0) && (offset == 0x100); - - m_scsihelp->write_wrapper(pseudo_dma, reg, data>>8); -} - -WRITE_LINE_MEMBER(mac_state::mac_scsi_irq) -{ -} - -void mac_state::scsi_berr_w(uint8_t data) -{ - m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero); -} - -/* ************************************************************************* - * SCC - * - * Serial Communications Controller - * *************************************************************************/ -uint16_t mac_state::mac_scc_r(offs_t offset) -{ - if (!machine().side_effects_disabled()) - mac_via_sync(); - - uint16_t result; - - result = m_scc->reg_r(offset); - return (result << 8) | result; -} - -void mac_state::mac_scc_w(offs_t offset, uint16_t data) -{ - mac_via_sync(); - m_scc->reg_w(offset, data); -} - -void mac_state::mac_scc_2_w(offs_t offset, uint16_t data) -{ - mac_via_sync(); - m_scc->reg_w(offset, data >> 8); -} - -/* ********************************** * - * IWM Code specific to the Mac Plus * - * ********************************** */ - -uint16_t mac_state::mac_iwm_r(offs_t offset, uint16_t mem_mask) -{ - /* The first time this is called is in a floppy test, which goes from - * $400104 to $400126. After that, all access to the floppy goes through - * the disk driver in the MacOS - * - * I just thought this would be on interest to someone trying to further - * this driver along - */ - - uint16_t result = m_fdc->read(offset >> 8); - - if (!machine().side_effects_disabled()) - m_maincpu->adjust_icount(-5); - - if (LOG_MAC_IWM) - printf("%s mac_iwm_r: offset=0x%08x mem_mask %04x = %02x\n", machine().describe_context().c_str(), offset, mem_mask, result); - - return (result << 8) | result; -} - -void mac_state::mac_iwm_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - if (LOG_MAC_IWM) - printf("mac_iwm_w: offset=0x%08x data=0x%04x mask %04x (PC=%x)\n", offset, data, mem_mask, m_maincpu->pc()); - - if (ACCESSING_BITS_0_7) - m_fdc->write((offset >> 8), data & 0xff); - else - m_fdc->write((offset >> 8), data>>8); - - if (!machine().side_effects_disabled()) - m_maincpu->adjust_icount(-5); -} - -WRITE_LINE_MEMBER(mac_state::mac_adb_via_out_cb2) -{ - //printf("VIA OUT CB2 = %x\n", state); - if (ADB_IS_EGRET) - { - m_egret->set_via_data(state & 1); - } -#if !MACII_USE_ADBMODEM - else - { - if (m_macadb) - { - m_macadb->adb_data_w(state); - } - } -#endif -} - -/* ************************************************************************* - * VIA - * ************************************************************************* - * - * - * PORT A - * - * bit 7 R SCC Wait/Request - * bit 6 W Main/Alternate screen buffer select - * bit 5 W Floppy Disk Line Selection - * bit 4 W Overlay/Normal memory mapping - * bit 3 W Main/Alternate sound buffer - * bit 2-0 W Sound Volume - * - * - * PORT B - * - * bit 7 W Sound enable - * bit 6 R Video beam in display - * bit 5 (pre-ADB) R Mouse Y2 - * (ADB) W ADB ST1 - * bit 4 (pre-ADB) R Mouse X2 - * (ADB) W ADB ST0 - * bit 3 (pre-ADB) R Mouse button (active low) - * (ADB) R ADB INT - * bit 2 W Real time clock enable - * bit 1 W Real time clock data clock - * bit 0 RW Real time clock data - * - */ - -#define PA6 0x40 -#define PA4 0x10 -#define PA2 0x04 -#define PA1 0x02 - -uint8_t mac_state::mac_via_in_a() -{ -// printf("%s VIA1 IN_A\n", machine().describe_context().c_str()); - - switch (m_model) - { - case MODEL_MAC_II: - case MODEL_MAC_II_FDHD: - case MODEL_MAC_IIX: - return 0x81; // bit 0 must be set on most Macs to avoid attempting to boot from AppleTalk - - case MODEL_MAC_SE30: - return 0x81 | PA6; - - case MODEL_MAC_IICI: - return 0x81 | PA6 | PA2 | PA1; - - case MODEL_MAC_IISI: - return 0x81 | PA4 | PA2 | PA1; - - case MODEL_MAC_IICX: - return 0x81 | PA6; - - default: - return 0x80; - } -} - -uint8_t mac_state::mac_via_in_b() -{ - int val = 0; - /* video beam in display (! VBLANK && ! HBLANK basically) */ - if (m_screen->vpos() >= MAC_V_VIS) - val |= 0x40; - - if (ADB_IS_BITBANG_CLASS) - { - #if !MACII_USE_ADBMODEM - val |= m_macadb->get_adb_state() << 4; - #endif - - if (!m_adb_irq_pending) - { - val |= 0x08; - } - - val |= m_rtc->data_r(); - } - else if (ADB_IS_EGRET) - { - val |= m_egret->get_xcvr_session()<<3; - } - -// printf("%s VIA1 IN_B = %02x\n", machine().describe_context().c_str(), val); - - return val; -} - -uint8_t mac_state::mac_via_in_b_ii() -{ - int val = 0; - - if (ADB_IS_BITBANG_CLASS) - { -#if !MACII_USE_ADBMODEM - val |= m_macadb->get_adb_state() << 4; -#endif - - if (!m_adb_irq_pending) - { - val |= 0x08; - } - - val |= m_rtc->data_r(); - } - else if (ADB_IS_EGRET) - { - val |= m_egret->get_xcvr_session()<<3; - } - -// printf("%s VIA1 IN_B_II = %02x\n", machine().describe_context().c_str(), val); - - return val; -} - -void mac_state::mac_via_out_a(uint8_t data) -{ -// printf("%s VIA1 OUT A: %02x\n", machine().describe_context().c_str(), data); - - set_scc_waitrequest((data & 0x80) >> 7); - m_screen_buffer = (data & 0x40) >> 6; - if (m_cur_floppy) - m_cur_floppy->ss_w((data & 0x20) >> 5); -} - -void mac_state::mac_via_out_b(uint8_t data) -{ -// printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data); - m_rtc->ce_w((data & 0x04)>>2); - m_rtc->data_w(data & 0x01); - m_rtc->clk_w((data >> 1) & 0x01); -} - -void mac_state::mac_via_out_b_bbadb(uint8_t data) -{ -// printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data); - - if (m_model == MODEL_MAC_SE30) - { - // 0x40 = 0 means enable vblank on SE/30 - m_se30_vbl_enable = (data & 0x40) ? 0 : 1; - - // clear the interrupt if we disabled it - if (!m_se30_vbl_enable) - { - nubus_slot_interrupt(0xe, 0); - } - } - -#if MACII_USE_ADBMODEM - m_adbmodem->set_via_state((data & 0x30) >> 4); -#else - m_macadb->mac_adb_newaction((data & 0x30) >> 4); -#endif - - m_rtc->ce_w((data & 0x04)>>2); - m_rtc->data_w(data & 0x01); - m_rtc->clk_w((data >> 1) & 0x01); -} - -void mac_state::mac_via_out_b_egadb(uint8_t data) -{ -// printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data); - - #if LOG_ADB - printf("%s 68K: New Egret state: SS %d VF %d\n", machine().describe_context().c_str(), (data>>5)&1, (data>>4)&1); - #endif - m_egret->set_via_full((data&0x10) ? 1 : 0); - m_egret->set_sys_session((data&0x20) ? 1 : 0); -} - -WRITE_LINE_MEMBER(mac_state::mac_via_irq) -{ - /* interrupt the 68k (level 1) */ - set_via_interrupt(state); -} - -void mac_state::mac_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 - // the whole access takes half a (via) cycle and ends when synced - // with the main cpu again. - - // Get the main cpu time - u64 cycle = m_maincpu->total_cycles(); - - // Get the number of the cycle the via is in at that time - u64 via_cycle = cycle * m_via1->clock() / m_maincpu->clock(); - - // The access is going to start at via_cycle+1 and end at - // via_cycle+1.5, compute what that means in maincpu cycles (the - // +1 rounds up, since the clocks are too different to ever be - // synced). - u64 main_cycle = (via_cycle*2+3) * m_maincpu->clock() / (2*m_via1->clock()) + 1; - - // Finally adjust the main cpu icount as needed. - m_maincpu->adjust_icount(-int(main_cycle - cycle)); -} - -uint16_t mac_state::mac_via_r(offs_t offset) -{ - if (!machine().side_effects_disabled()) - mac_via_sync(); - - uint16_t data; - - offset >>= 8; - offset &= 0x0f; - - if (LOG_VIA) - logerror("mac_via_r: offset=0x%02x\n", offset); - data = m_via1->read(offset); - - return (data & 0xff) | (data << 8); -} - -void mac_state::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - mac_via_sync(); - - offset >>= 8; - offset &= 0x0f; - - if (LOG_VIA) - logerror("mac_via_w: offset=0x%02x data=0x%08x\n", offset, data); - - if (ACCESSING_BITS_0_7) - m_via1->write(offset, data & 0xff); - if (ACCESSING_BITS_8_15) - m_via1->write(offset, (data >> 8) & 0xff); -} - -/* ************************************************************************* - * VIA 2 (on Mac IIs, PowerBooks > 100, and PowerMacs) - * *************************************************************************/ - -WRITE_LINE_MEMBER(mac_state::mac_via2_irq) -{ - set_via2_interrupt(state); -} - -uint16_t mac_state::mac_via2_r(offs_t offset) -{ - int data; - - offset >>= 8; - offset &= 0x0f; - - data = m_via2->read(offset); - - if (LOG_VIA) - logerror("mac_via2_r: offset=0x%02x = %02x (PC=%x)\n", offset*2, data, m_maincpu->pc()); - - return (data & 0xff) | (data << 8); -} - -void mac_state::mac_via2_w(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - offset >>= 8; - offset &= 0x0f; - - if (LOG_VIA) - logerror("mac_via2_w: offset=%x data=0x%08x mask=%x (PC=%x)\n", offset, data, mem_mask, m_maincpu->pc()); - - if (ACCESSING_BITS_0_7) - m_via2->write(offset, data & 0xff); - if (ACCESSING_BITS_8_15) - m_via2->write(offset, (data >> 8) & 0xff); -} - - -uint8_t mac_state::mac_via2_in_a() -{ - return 0xc0 | m_nubus_irq_state; -} - -uint8_t mac_state::mac_via2_in_b() -{ -// logerror("%s VIA2 IN B\n", machine().describe_context()); - - if ((m_model == MODEL_MAC_SE30) || (m_model == MODEL_MAC_IIX)) - { - return 0x87; // bits 3 and 6 are tied low on SE/30 - } - - return 0xcf; // indicate no NuBus transaction error -} - -void mac_state::mac_via2_out_a(uint8_t data) -{ -// logerror("%s VIA2 OUT A: %02x\n", machine().describe_context(), data); -} - -void mac_state::mac_via2_out_b(uint8_t data) -{ -// logerror("%s VIA2 OUT B: %02x\n", machine().describe_context(), data); - - // chain 60.15 Hz to VIA1 - m_via1->write_ca1(data>>7); - - if (m_model == MODEL_MAC_II) - { - m68000_musashi_device *m68k = downcast(m_maincpu.target()); - m68k->set_hmmu_enable((data & 0x8) ? M68K_HMMU_DISABLE : M68K_HMMU_ENABLE_II); - } -} - -// This signal is generated internally on RBV, V8, VASP, Eagle, etc. -TIMER_CALLBACK_MEMBER(mac_state::mac_6015_tick) -{ - m_via1->write_ca1(0); - m_via1->write_ca1(1); -} - -/* ************************************************************************* - * Main - * *************************************************************************/ - -void mac_state::machine_start() -{ - if (m_screen) - { - this->m_scanline_timer = timer_alloc(FUNC(mac_state::mac_scanline_tick), this); - this->m_scanline_timer->adjust(m_screen->time_until_pos(0, 0)); - } - else - { - m_adbupdate_timer = timer_alloc(FUNC(mac_state::mac_adbrefresh_tick), this); - m_adbupdate_timer->adjust(attotime::from_hz(70)); - } - - m_6015_timer = timer_alloc(FUNC(mac_state::mac_6015_tick), this); - m_6015_timer->adjust(attotime::never); - - save_item(NAME(m_nubus_irq_state)); - save_item(NAME(m_se30_vbl_enable)); - save_item(NAME(m_adb_irq_pending)); - save_item(NAME(ca1_data)); - if ((m_model == MODEL_MAC_IICI) || (m_model == MODEL_MAC_IISI)) - { - save_item(NAME(m_rbv_regs)); - save_item(NAME(m_rbv_ier)); - save_item(NAME(m_rbv_ifr)); - save_item(NAME(m_rbv_colors)); - save_item(NAME(m_rbv_count)); - save_item(NAME(m_rbv_clutoffs)); - save_item(NAME(m_rbv_palette)); - } - save_item(NAME(m_scc_interrupt)); - save_item(NAME(m_via_interrupt)); - save_item(NAME(m_via2_interrupt)); - save_item(NAME(m_scsi_interrupt)); - save_item(NAME(m_last_taken_interrupt)); - save_item(NAME(m_via2_ca1_hack)); -} - -void mac_state::machine_reset() -{ - if (ADB_IS_EGRET) - { - m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - } - - // stop 60.15 Hz timer - m_6015_timer->adjust(attotime::never); - - if ((m_model == MODEL_MAC_IICI) || (m_model == MODEL_MAC_IISI)) - { - m_rbv_vbltime = 0; - macrbv_reset(); - } - - // start 60.15 Hz timer for most systems - if ((m_model >= MODEL_MAC_IICI) && (m_model <= MODEL_MAC_IISI)) - { - m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15)); - } - - m_last_taken_interrupt = -1; - - /* setup the memory overlay */ - m_overlay = -1; // insure no match - this->set_memory_overlay(1); - - if (m_overlay_timeout != (emu_timer *)nullptr) - { - m_overlay_timeout->adjust(m_maincpu->cycles_to_attotime(8)); - } - - /* setup videoram */ - this->m_screen_buffer = 1; - - m_via2_ca1_hack = 1; - m_via2->write_ca1(1); - m_via2->write_cb1(1); - - m_scsi_interrupt = 0; - - m_via2_vbl = 0; - m_se30_vbl_enable = 0; - m_nubus_irq_state = 0xff; - m_last_taken_interrupt = 0; -} - -WRITE_LINE_MEMBER(mac_state::egret_reset_w) -{ - if (state == ASSERT_LINE) - { - set_memory_overlay(0); - set_memory_overlay(1); - } - - m_maincpu->set_input_line(INPUT_LINE_HALT, state); - m_maincpu->set_input_line(INPUT_LINE_RESET, state); -} - -void mac_state::mac_state_load() -{ - int overlay; - overlay = m_overlay; - m_overlay = -1; - set_memory_overlay(overlay); -} - - -TIMER_CALLBACK_MEMBER(mac_state::overlay_timeout_func) -{ - if (m_overlay != -1) - { - set_memory_overlay(0); // kill the overlay - } - - // we're a one-time-only thing - m_overlay_timeout->adjust(attotime::never); -} - -void mac_state::mac_driver_init(model_t model) -{ - m_overlay = 1; - m_scsi_interrupt = 0; - m_model = model; - m_scc_interrupt = 0; - m_via_interrupt = 0; - m_via2_interrupt = 0; - - m_rom_size = memregion("bootrom")->bytes(); - m_rom_ptr = reinterpret_cast(memregion("bootrom")->base()); - - m_overlay = -1; - set_memory_overlay(1); - - memset(m_ram->pointer(), 0, m_ram->size()); - - if ((m_model >= MODEL_MAC_II) && (m_model <= MODEL_MAC_SE30)) - { - m_overlay_timeout = timer_alloc(FUNC(mac_state::overlay_timeout_func), this); - } - else - { - m_overlay_timeout = (emu_timer *)nullptr; - } - - /* save state stuff */ - machine().save().register_postload(save_prepost_delegate(FUNC(mac_state::mac_state_load), this)); -} - -#define MAC_DRIVER_INIT(label, model) \ -void mac_state::init_##label() \ -{ \ - mac_driver_init(model); \ -} - -MAC_DRIVER_INIT(maciici, MODEL_MAC_IICI) -MAC_DRIVER_INIT(maciisi, MODEL_MAC_IISI) -MAC_DRIVER_INIT(macii, MODEL_MAC_II) -MAC_DRIVER_INIT(macse30, MODEL_MAC_SE30) -MAC_DRIVER_INIT(maciicx, MODEL_MAC_IICX) -MAC_DRIVER_INIT(maciifdhd, MODEL_MAC_II_FDHD) -MAC_DRIVER_INIT(maciix, MODEL_MAC_IIX) - -void mac_state::nubus_slot_interrupt(uint8_t slot, uint32_t state) -{ - static const uint8_t masks[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }; - uint8_t mask = 0x3f; - - slot -= 9; - - if (state) - { - m_nubus_irq_state &= ~masks[slot]; - } - else - { - m_nubus_irq_state |= masks[slot]; - } - - if (!INTS_RBV) - { - if ((m_nubus_irq_state & mask) != mask) - { - // HACK: sometimes we miss an ack (possible misbehavior in the VIA?) - if (m_via2_ca1_hack == 0) - { - m_via2->write_ca1(1); - } - m_via2_ca1_hack = 0; - m_via2->write_ca1(0); - } - else - { - m_via2_ca1_hack = 1; - m_via2->write_ca1(1); - } - } - - if (INTS_RBV) - { - m_rbv_regs[2] &= ~0x38; - m_rbv_regs[2] |= (m_nubus_irq_state & 0x38); - rbv_recalc_irqs(); - } -} - -void mac_state::vblank_irq() -{ - /* handle ADB keyboard/mouse */ - if (m_macadb) - { - m_macadb->adb_vblank(); - } - - // handle SE/30 vblank IRQ - if (m_model == MODEL_MAC_SE30) - { - if (m_se30_vbl_enable) - { - m_via2_vbl ^= 1; - if (!m_via2_vbl) - { - this->nubus_slot_interrupt(0xe, 1); - } - } - } -} - -TIMER_CALLBACK_MEMBER(mac_state::mac_adbrefresh_tick) -{ - vblank_irq(); - m_adbupdate_timer->adjust(attotime::from_hz(70)); -} - -TIMER_CALLBACK_MEMBER(mac_state::mac_scanline_tick) -{ - int scanline; - - if (m_rbv_vbltime > 0) - { - m_rbv_vbltime--; - - if (m_rbv_vbltime == 0) - { - m_rbv_regs[2] |= 0x40; - rbv_recalc_irqs(); - } - } - - scanline = m_screen->vpos(); - if (scanline == MAC_V_VIS) - vblank_irq(); - - int next_scanline = (scanline+1) % MAC_V_TOTAL; - m_scanline_timer->adjust(m_screen->time_until_pos(next_scanline), next_scanline); -} - -WRITE_LINE_MEMBER(mac_state::nubus_irq_9_w) -{ - nubus_slot_interrupt(9, state); -} - -WRITE_LINE_MEMBER(mac_state::nubus_irq_a_w) -{ - nubus_slot_interrupt(0xa, state); -} - -WRITE_LINE_MEMBER(mac_state::nubus_irq_b_w) -{ - nubus_slot_interrupt(0xb, state); -} - -WRITE_LINE_MEMBER(mac_state::nubus_irq_c_w) -{ - nubus_slot_interrupt(0xc, state); -} - -WRITE_LINE_MEMBER(mac_state::nubus_irq_d_w) -{ - nubus_slot_interrupt(0xd, state); -} - -WRITE_LINE_MEMBER(mac_state::nubus_irq_e_w) -{ - nubus_slot_interrupt(0xe, state); -} - -void mac_state::phases_w(uint8_t phases) -{ - if(m_cur_floppy) - m_cur_floppy->seek_phase_w(phases); -} - -void mac_state::sel35_w(int sel35) -{ - logerror("fdc mac sel35 %d\n", sel35); -} - -void mac_state::devsel_w(uint8_t devsel) -{ - if(devsel == 1) - m_cur_floppy = m_floppy[0]->get_device(); - else if(devsel == 2) - m_cur_floppy = m_floppy[1]->get_device(); - else - m_cur_floppy = nullptr; - m_fdc->set_floppy(m_cur_floppy); - if(m_cur_floppy) - m_cur_floppy->ss_w((m_via1->read_pa() & 0x20) >> 5); -} - -void mac_state::hdsel_w(int hdsel) -{ -} diff --git a/src/mame/apple/mac_v.cpp b/src/mame/apple/mac_v.cpp deleted file mode 100644 index 8110adae765..00000000000 --- a/src/mame/apple/mac_v.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont -/*************************************************************************** - - mac_v.cpp - Macintosh video hardware - - Emulates the video hardware for systems with RBV and SE/30 video - - ---------------------------------------------------------------------- - Monitor sense codes - - Apple assigns 3 pins for monitor IDs. These allow 8 possible codes: - - 000 - color 2-Page Display (21") - 001 - monochrome Full Page display (15") - 010 - color 512x384 (12") - 011 - monochrome 2 Page display (21") - 100 - NTSC - 101 - color Full Page display (15") - 110 - High-Resolution Color (13" 640x480) or use "type 6" extended codes - 111 - No monitor connected or use "type 7" extended codes - - For extended codes, you drive one of the 3 pins at a time and read the 2 - undriven pins. See http://support.apple.com/kb/TA21618?viewlocale=en_US - for details. - -Extended codes: - - Sense 2 Low Sense 1 Low Sense 0 Low - 1 & 0 2 & 0 2 & 1 - -Multiple Scan 14" 00 00 11 -Multiple Scan 16" 00 10 11 -Multiple Scan 21" 10 00 11 -PAL Encoder 00 00 00 -NTSC Encoder 01 01 00 -VGA/Super VGA 01 01 11 -RGB 16" 10 11 01 -PAL Monitor 11 00 00 -RGB 19" 11 10 10 -Radius color TPD 11 00 01 (TPD = Two Page Display) -Radius mono TPD 11 01 00 -Apple TPD 11 01 01 -Apple color FPD 01 11 10 (FPD = Full Page Display) - -***************************************************************************/ - -#include "emu.h" -#include "sound/asc.h" -#include "mac.h" -#include "machine/ram.h" -#include "render.h" - -uint32_t mac_state::screen_update_macse30(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - uint32_t const video_base = (m_screen_buffer ? 0x8000 : 0) + (MAC_H_VIS/8); - uint16_t const *const video_ram = (const uint16_t *) &m_vram[video_base/4]; - - for (int y = 0; y < MAC_V_VIS; y++) - { - uint16_t *const line = &bitmap.pix(y); - - for (int x = 0; x < MAC_H_VIS; x += 16) - { - uint16_t const word = video_ram[((y * MAC_H_VIS)/16) + ((x/16)^1)]; - for (int b = 0; b < 16; b++) - { - line[x + b] = (word >> (15 - b)) & 0x0001; - } - } - } - return 0; -} - -// IIci/IIsi RAM-Based Video (RBV) - -void mac_state::macrbv_reset() -{ - int htotal, vtotal; - double framerate; - int view; - - memset(m_rbv_regs, 0, sizeof(m_rbv_regs)); - - m_rbv_count = 0; - m_rbv_clutoffs = 0; - m_rbv_immed10wr = 0; - - m_rbv_regs[2] = 0x7f; - m_rbv_regs[3] = 0; - - view = 0; - - m_rbv_montype = m_montype.read_safe(2); - rectangle visarea; - switch (m_rbv_montype) - { - case 1: // 15" portrait display - visarea.set(0, 640-1, 0, 870-1); - htotal = 832; - vtotal = 918; - framerate = 75.0; - view = 1; - break; - - case 2: // 12" RGB - visarea.set(0, 512-1, 0, 384-1); - htotal = 640; - vtotal = 407; - framerate = 60.15; - break; - - case 6: // 13" RGB - default: - visarea.set(0, 640-1, 0, 480-1); - htotal = 800; - vtotal = 525; - framerate = 59.94; - break; - } - -// logerror("RBV reset: monitor is %dx%d @ %f Hz\n", visarea.width(), visarea.height(), framerate); - m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate)); - render_target *target = machine().render().first_target(); - target->set_view(view); -} - -uint32_t mac_state::screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - uint8_t const *vram8 = (uint8_t *)m_ram->pointer(); - int hres, vres; - - switch (m_rbv_montype) - { - case 1: // 15" portrait display - hres = 640; - vres = 870; - break; - - case 2: // 12" RGB - hres = 512; - vres = 384; - break; - - case 6: // 13" RGB - default: - hres = 640; - vres = 480; - break; - } - - switch (m_rbv_regs[0x10] & 7) - { - case 0: // 1bpp - { - for (int y = 0; y < vres; y++) - { - uint32_t *scanline = &bitmap.pix(y); - for (int x = 0; x < hres; x+=8) - { - uint8_t const pixels = vram8[(y * (hres/8)) + ((x/8)^3)]; - - *scanline++ = m_rbv_palette[0xfe|(pixels>>7)]; - *scanline++ = m_rbv_palette[0xfe|((pixels>>6)&1)]; - *scanline++ = m_rbv_palette[0xfe|((pixels>>5)&1)]; - *scanline++ = m_rbv_palette[0xfe|((pixels>>4)&1)]; - *scanline++ = m_rbv_palette[0xfe|((pixels>>3)&1)]; - *scanline++ = m_rbv_palette[0xfe|((pixels>>2)&1)]; - *scanline++ = m_rbv_palette[0xfe|((pixels>>1)&1)]; - *scanline++ = m_rbv_palette[0xfe|(pixels&1)]; - } - } - } - break; - - case 1: // 2bpp - { - for (int y = 0; y < vres; y++) - { - uint32_t *scanline = &bitmap.pix(y); - for (int x = 0; x < hres/4; x++) - { - uint8_t const pixels = vram8[(y * (hres/4)) + (BYTE4_XOR_BE(x))]; - - *scanline++ = m_rbv_palette[0xfc|((pixels>>6)&3)]; - *scanline++ = m_rbv_palette[0xfc|((pixels>>4)&3)]; - *scanline++ = m_rbv_palette[0xfc|((pixels>>2)&3)]; - *scanline++ = m_rbv_palette[0xfc|(pixels&3)]; - } - } - } - break; - - case 2: // 4bpp - { - for (int y = 0; y < vres; y++) - { - uint32_t *scanline = &bitmap.pix(y); - - for (int x = 0; x < hres/2; x++) - { - uint8_t const pixels = vram8[(y * (hres/2)) + (BYTE4_XOR_BE(x))]; - - *scanline++ = m_rbv_palette[0xf0|(pixels>>4)]; - *scanline++ = m_rbv_palette[0xf0|(pixels&0xf)]; - } - } - } - break; - - case 3: // 8bpp - { - for (int y = 0; y < vres; y++) - { - uint32_t *scanline = &bitmap.pix(y); - - for (int x = 0; x < hres; x++) - { - uint8_t const pixels = vram8[(y * hres) + (BYTE4_XOR_BE(x))]; - *scanline++ = m_rbv_palette[pixels]; - } - } - } - } - - return 0; -} - diff --git a/src/mame/apple/maciici.cpp b/src/mame/apple/maciici.cpp new file mode 100644 index 00000000000..6ff8c7139ce --- /dev/null +++ b/src/mame/apple/maciici.cpp @@ -0,0 +1,1171 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/**************************************************************************** + + maciici.cpp + Mac IIci ("Cobra II, Aurora, Aurora25/16, Pacific, Atlantic") + Mac IIsi ("Erickson, Rafiki, Hobie Cat") + + By R. Belmont + + These are the RBV/MDU (RAM Based Video/Memory Decode Unit) near-twins. + IIci cost-reduced the IIcx and added on-board video. + IIsi cost-reduced the IIci with a slower CPU and Egret ADB instead of + the PIC ADB modem and Apple RTC/PRAM chip. + +****************************************************************************/ + +#include "emu.h" + +#include "egret.h" +#include "macadb.h" +#include "macrtc.h" +#include "macscsi.h" +#include "mactoolbox.h" + +#include "bus/nscsi/devices.h" +#include "bus/nubus/nubus.h" +#include "bus/nubus/cards.h" +#include "bus/rs232/rs232.h" +#include "cpu/m68000/m68030.h" +#include "machine/applefdintf.h" +#include "machine/ram.h" +#include "machine/swim1.h" +#include "machine/timer.h" +#include "machine/6522via.h" +#include "machine/ncr5380.h" +#include "machine/nscsi_bus.h" +#include "machine/z80scc.h" +#include "sound/asc.h" + +#include "emupal.h" +#include "render.h" +#include "screen.h" +#include "softlist_dev.h" +#include "speaker.h" + +namespace { + +static constexpr u32 C7M = 7833600; +static constexpr u32 C15M = (C7M * 2); + +class maciici_state : public driver_device +{ +public: + maciici_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_via1(*this, "via1"), + m_macadb(*this, "macadb"), + m_ram(*this, RAM_TAG), + m_asc(*this, "asc"), + m_scsibus1(*this, "scsi"), + m_ncr5380(*this, "scsi:7:ncr5380"), + m_scsihelp(*this, "scsihelp"), + m_fdc(*this, "fdc"), + m_floppy(*this, "fdc:%d", 0U), + m_scc(*this, "scc"), + m_montype(*this, "MONTYPE"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_rtc(*this, "rtc"), + m_egret(*this, "egret") + { + } + + void maciici(machine_config &config); + void maciisi(machine_config &config); + void maciici_map(address_map &map); + +private: + required_device m_maincpu; + required_device m_via1; + required_device m_macadb; + required_device m_ram; + required_device m_asc; + required_device m_scsibus1; + required_device m_ncr5380; + required_device m_scsihelp; + required_device m_fdc; + required_device_array m_floppy; + required_device m_scc; + required_ioport m_montype; + required_device m_screen; + required_device m_palette; + optional_device m_rtc; + optional_device m_egret; + + virtual void machine_start() override; + virtual void machine_reset() override; + + emu_timer *m_6015_timer = nullptr; + emu_timer *m_scanline_timer = nullptr; + + u8 m_rbv_regs[256]{}, m_rbv_ier = 0, m_rbv_ifr = 0, m_rbv_montype = 0, m_rbv_vbltime = 0; + u32 m_rbv_colors[3]{}, m_rbv_count = 0, m_rbv_clutoffs = 0, m_rbv_immed10wr = 0; + u32 m_rbv_palette[256]{}; + + uint32_t screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + void rbv_reset(); + void rbv_recalc_irqs(); + uint32_t rbv_ramdac_r(); + void rbv_ramdac_w(offs_t offset, uint32_t data); + uint8_t rbv_r(offs_t offset); + void rbv_w(offs_t offset, uint8_t data); + void nubus_slot_interrupt(uint8_t slot, uint32_t state); + + WRITE_LINE_MEMBER(mac_asc_irq); + DECLARE_WRITE_LINE_MEMBER(scc_irq_w); + void set_via2_interrupt(int value); + void field_interrupts(); + + uint32_t m_overlay = 0; + u32 *m_rom_ptr = nullptr; + u32 m_rom_size = 0; + int m_scc_interrupt = false, m_via_interrupt = false, m_via2_interrupt = false, m_last_taken_interrupt = false; + int m_adb_irq_pending = 0; + uint8_t m_nubus_irq_state = 0; + + DECLARE_WRITE_LINE_MEMBER(mac_rbv_vbl); + TIMER_CALLBACK_MEMBER(mac_6015_tick); + TIMER_CALLBACK_MEMBER(mac_scanline_tick); + + DECLARE_WRITE_LINE_MEMBER(nubus_irq_c_w); + DECLARE_WRITE_LINE_MEMBER(nubus_irq_d_w); + DECLARE_WRITE_LINE_MEMBER(nubus_irq_e_w); + WRITE_LINE_MEMBER(adb_irq_w) { m_adb_irq_pending = state; } + + uint16_t via_r(offs_t offset); + void via_w(offs_t offset, uint16_t data, uint16_t mem_mask); + uint8_t via_in_a(); + uint8_t via_in_a_iisi(); + uint8_t via_in_b(); + uint8_t via_in_b_iisi(); + void via_out_a(uint8_t data); + void via_out_b(uint8_t data); + void via_out_b_iisi(uint8_t data); + void via_sync(); + DECLARE_WRITE_LINE_MEMBER(via_irq); + WRITE_LINE_MEMBER(via_out_cb2); + WRITE_LINE_MEMBER(via_out_cb2_iisi); + + uint32_t rom_switch_r(offs_t offset); + + u16 scc_r(offs_t offset) + { + u16 result = m_scc->dc_ab_r(offset); + return (result << 8) | result; + } + void scc_w(offs_t offset, u16 data) + { + m_scc->dc_ab_w(offset, data >> 8); + } + + u16 scsi_r(offs_t offset, u16 mem_mask = ~0); + void scsi_w(offs_t offset, u16 data, u16 mem_mask = ~0); + u32 scsi_drq_r(offs_t offset, u32 mem_mask = ~0); + void scsi_drq_w(offs_t offset, u32 data, u32 mem_mask = ~0); + + void scsi_berr_w(u8 data) + { + m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero); + } + + WRITE_LINE_MEMBER(egret_reset_w) + { + m_maincpu->set_input_line(INPUT_LINE_HALT, state); + m_maincpu->set_input_line(INPUT_LINE_RESET, state); + } + + floppy_image_device *m_cur_floppy = nullptr; + int m_hdsel; + void phases_w(uint8_t phases); + void devsel_w(uint8_t devsel); + + uint16_t iwm_r(offs_t offset, u16 mem_mask) + { + if (!machine().side_effects_disabled()) + { + m_maincpu->adjust_icount(-5); + } + + u16 result = m_fdc->read((offset >> 8) & 0xf); + return result << 8; + } + + void iwm_w(offs_t offset, u16 data, u16 mem_mask) + { + if (ACCESSING_BITS_0_7) + m_fdc->write((offset >> 8) & 0xf, data & 0xff); + else + m_fdc->write((offset >> 8) & 0xf, data >> 8); + } +}; + +TIMER_CALLBACK_MEMBER(maciici_state::mac_6015_tick) +{ + m_via1->write_ca1(0); + m_via1->write_ca1(1); + + m_macadb->adb_vblank(); +} + +TIMER_CALLBACK_MEMBER(maciici_state::mac_scanline_tick) +{ + int scanline = m_screen->vpos(); + + if (m_rbv_vbltime > 0) + { + m_rbv_vbltime--; + + if (m_rbv_vbltime == 0) + { + m_rbv_regs[2] |= 0x40; + rbv_recalc_irqs(); + } + } + + int next_scanline = (scanline + 1) % 370; // TODO: fix + m_scanline_timer->adjust(m_screen->time_until_pos(next_scanline), next_scanline); +} + +void maciici_state::machine_start() +{ + m_6015_timer = timer_alloc(FUNC(maciici_state::mac_6015_tick), this); + m_6015_timer->adjust(attotime::never); + + m_scanline_timer = timer_alloc(FUNC(maciici_state::mac_scanline_tick), this); + m_scanline_timer->adjust(m_screen->time_until_pos(0, 0)); + + m_rom_ptr = (u32 *)memregion("bootrom")->base(); + m_rom_size = memregion("bootrom")->bytes(); + + m_last_taken_interrupt = -1; + + save_item(NAME(m_rbv_regs)); + save_item(NAME(m_rbv_ier)); + save_item(NAME(m_rbv_ifr)); + save_item(NAME(m_rbv_colors)); + save_item(NAME(m_rbv_count)); + save_item(NAME(m_rbv_clutoffs)); + save_item(NAME(m_rbv_palette)); +} + +void maciici_state::machine_reset() +{ + m_rbv_vbltime = 0; + rbv_reset(); + m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15)); + + // main cpu shouldn't start until Egret wakes it up + if (m_egret) + { + m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); + } + + // put ROM mirror at 0 + address_space &space = m_maincpu->space(AS_PROGRAM); + const u32 memory_size = std::min((u32)0x3fffff, m_rom_size); + const u32 memory_end = memory_size - 1; + offs_t memory_mirror = memory_end & ~(memory_size - 1); + + space.unmap_write(0x00000000, memory_end); + space.install_rom(0x00000000, memory_end & ~memory_mirror, memory_mirror, m_rom_ptr); + m_overlay = true; +} + +uint32_t maciici_state::rom_switch_r(offs_t offset) +{ + // disable the overlay + if (m_overlay) + { + address_space &space = m_maincpu->space(AS_PROGRAM); + const u32 memory_end = m_ram->size() - 1; + void *memory_data = m_ram->pointer(); + offs_t memory_mirror = memory_end & ~memory_end; + + space.install_ram(0x00000000, memory_end & ~memory_mirror, memory_mirror, memory_data); + m_overlay = false; + } + + // printf("rom_switch_r: offset %08x ROM_size -1 = %08x, masked = %08x\n", offset, m_rom_size-1, offset & ((m_rom_size - 1)>>2)); + + return m_rom_ptr[offset & ((m_rom_size - 1) >> 2)]; +} + +void maciici_state::field_interrupts() +{ + int take_interrupt = -1; + + if (m_scc_interrupt) + { + take_interrupt = 4; + } + else if (m_via2_interrupt) + { + take_interrupt = 2; + } + else if (m_via_interrupt) + { + take_interrupt = 1; + } + + if (m_last_taken_interrupt > -1) + { + m_maincpu->set_input_line(m_last_taken_interrupt, CLEAR_LINE); + m_last_taken_interrupt = -1; + } + + if (take_interrupt > -1) + { + m_maincpu->set_input_line(take_interrupt, ASSERT_LINE); + m_last_taken_interrupt = take_interrupt; + } +} + +WRITE_LINE_MEMBER(maciici_state::mac_asc_irq) +{ + if (state == ASSERT_LINE) + { + m_rbv_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt + rbv_recalc_irqs(); + } + else + { + m_rbv_regs[3] &= ~0x10; + rbv_recalc_irqs(); + } +} + +WRITE_LINE_MEMBER(maciici_state::via_irq) +{ + m_via_interrupt = state; + field_interrupts(); +} + +WRITE_LINE_MEMBER(maciici_state::scc_irq_w) +{ + m_scc_interrupt = state; + field_interrupts(); +} + +void maciici_state::set_via2_interrupt(int value) +{ + m_via2_interrupt = value; + field_interrupts(); +} + +WRITE_LINE_MEMBER(maciici_state::nubus_irq_c_w) +{ + nubus_slot_interrupt(0xc, state); +} + +WRITE_LINE_MEMBER(maciici_state::nubus_irq_d_w) +{ + nubus_slot_interrupt(0xd, state); +} + +WRITE_LINE_MEMBER(maciici_state::nubus_irq_e_w) +{ + nubus_slot_interrupt(0xe, state); +} + +void maciici_state::nubus_slot_interrupt(uint8_t slot, uint32_t state) +{ + static const uint8_t masks[8] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80}; + + slot -= 9; + + if (state) + { + m_nubus_irq_state &= ~masks[slot]; + } + else + { + m_nubus_irq_state |= masks[slot]; + } + + m_rbv_regs[2] &= ~0x38; + m_rbv_regs[2] |= (m_nubus_irq_state & 0x38); + rbv_recalc_irqs(); +} + +// do this here - screen_update is called each scanline when stepping in the +// debugger, which means you can't escape the VIA2 IRQ handler +// +// RBV/MDU bits in IER/IFR: +// +// CA1: any slot interrupt = 0x02 +// CA2: SCSI interrupt = 0x01 +// CB1: ASC interrupt = 0x10 + +WRITE_LINE_MEMBER(maciici_state::mac_rbv_vbl) +{ + if (!state) + return; + + m_rbv_regs[2] &= ~0x40; // set vblank signal + m_rbv_vbltime = 10; + + // printf("RBV: raising VBL!\n"); + + if (m_rbv_regs[0x12] & 0x40) + { + rbv_recalc_irqs(); + } +} + +uint32_t maciici_state::rbv_ramdac_r() +{ + return 0; +} + +void maciici_state::rbv_ramdac_w(offs_t offset, uint32_t data) +{ + if (!offset) + { + m_rbv_clutoffs = data >> 24; + m_rbv_count = 0; + } + else + { + m_rbv_colors[m_rbv_count++] = data >> 24; + + if (m_rbv_count == 3) + { + // for portrait display, force monochrome by using the blue channel + if (m_montype->read() == 1) + { + m_palette->set_pen_color(m_rbv_clutoffs, rgb_t(m_rbv_colors[2], m_rbv_colors[2], m_rbv_colors[2])); + m_rbv_palette[m_rbv_clutoffs] = rgb_t(m_rbv_colors[2], m_rbv_colors[2], m_rbv_colors[2]); + m_rbv_clutoffs++; + m_rbv_count = 0; + } + else + { + m_palette->set_pen_color(m_rbv_clutoffs, rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2])); + m_rbv_palette[m_rbv_clutoffs] = rgb_t(m_rbv_colors[0], m_rbv_colors[1], m_rbv_colors[2]); + m_rbv_clutoffs++; + m_rbv_count = 0; + } + } + } +} + +void maciici_state::rbv_recalc_irqs() +{ + // check slot interrupts and bubble them down to IFR + uint8_t slot_irqs = (~m_rbv_regs[2]) & 0x78; + slot_irqs &= (m_rbv_regs[0x12] & 0x78); + + if (slot_irqs) + { + m_rbv_regs[3] |= 2; // any slot + } + else // no slot irqs, clear the pending bit + { + m_rbv_regs[3] &= ~2; // any slot + } + + uint8_t ifr = (m_rbv_regs[3] & m_rbv_ier) & 0x1b; // m_rbv_regs[0x13]); + + // printf("ifr = %02x (reg3 %02x reg13 %02x)\n", ifr, m_rbv_regs[3], m_rbv_regs[0x13]); + if (ifr != 0) + { + m_rbv_regs[3] = ifr | 0x80; + m_rbv_ifr = ifr | 0x80; + + // printf("VIA2 raise\n"); + set_via2_interrupt(1); + } + else + { + // printf("VIA2 lower\n"); + set_via2_interrupt(0); + } +} + +uint8_t maciici_state::rbv_r(offs_t offset) +{ + int data = 0; + + if (offset < 0x100) + { + data = m_rbv_regs[offset]; + + if (offset == 0x10) + { + data &= ~0x38; + data |= (m_montype->read() << 3); + // printf("%s rbv_r montype: %02x\n", machine().describe_context().c_str(), data); + } + + // bit 7 of these registers always reads as 0 on RBV + if ((offset == 0x12) || (offset == 0x13)) + { + data &= ~0x80; + } + } + else + { + offset >>= 9; + + switch (offset) + { + case 13: // IFR + // printf("Read IER = %02x (PC=%x) 2=%02x\n", m_rbv_ier, m_maincpu->pc(), m_rbv_regs[2]); + data = m_rbv_ifr; + break; + + case 14: // IER + // printf("Read IFR = %02x (PC=%x) 2=%02x\n", m_rbv_ifr, m_maincpu->pc(), m_rbv_regs[2]); + data = m_rbv_ier; + break; + + default: + logerror("rbv_r: Unknown extended RBV VIA register %d access\n", offset); + break; + } + } + + // printf("rbv_r: %x = %02x (PC=%x)\n", offset, data, m_maincpu->pc()); + + return data; +} + +void maciici_state::rbv_w(offs_t offset, uint8_t data) +{ + if (offset < 0x100) + { + // if (offset == 0x10) + // printf("rbv_w: %02x to offset %x (PC=%x)\n", data, offset, m_maincpu->pc()); + switch (offset) + { + case 0x02: + data &= 0x40; + m_rbv_regs[offset] &= ~data; + rbv_recalc_irqs(); + break; + + case 0x03: // write here to ack + if (data & 0x80) // 1 bits write 1s + { + m_rbv_regs[offset] |= data & 0x7f; + m_rbv_ifr |= data & 0x7f; + } + else // 1 bits write 0s + { + m_rbv_regs[offset] &= ~(data & 0x7f); + m_rbv_ifr &= ~(data & 0x7f); + } + rbv_recalc_irqs(); + break; + + case 0x10: + if (data != 0) + { + m_rbv_immed10wr = 1; + } + m_rbv_regs[offset] = data; + break; + + case 0x12: + if (data & 0x80) // 1 bits write 1s + { + m_rbv_regs[offset] |= data & 0x7f; + } + else // 1 bits write 0s + { + m_rbv_regs[offset] &= ~(data & 0x7f); + } + rbv_recalc_irqs(); + break; + + case 0x13: + if (data & 0x80) // 1 bits write 1s + { + m_rbv_regs[offset] |= data & 0x7f; + + if (data == 0xff) + m_rbv_regs[offset] = 0x1f; // I don't know why this is special, but the IIci ROM's POST demands it + } + else // 1 bits write 0s + { + m_rbv_regs[offset] &= ~(data & 0x7f); + } + break; + + default: + m_rbv_regs[offset] = data; + break; + } + } + else + { + offset >>= 9; + + switch (offset) + { + case 13: // IFR + // printf("%02x to IFR (PC=%x)\n", data, m_maincpu->pc()); + if (data & 0x80) + { + data = 0x7f; + } + rbv_recalc_irqs(); + break; + + case 14: // IER + // printf("%02x to IER (PC=%x)\n", data, m_maincpu->pc()); + if (data & 0x80) // 1 bits write 1s + { + m_rbv_ier |= data & 0x7f; + } + else // 1 bits write 0s + { + m_rbv_ier &= ~(data & 0x7f); + } + rbv_recalc_irqs(); + break; + + default: + logerror("rbv_w: Unknown extended RBV VIA register %d access\n", offset); + break; + } + } +} + +void maciici_state::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 + // the whole access takes half a (via) cycle and ends when synced + // with the main cpu again. + + // Get the main cpu time + u64 cycle = m_maincpu->total_cycles(); + + // Get the number of the cycle the via is in at that time + u64 via_cycle = cycle * m_via1->clock() / m_maincpu->clock(); + + // The access is going to start at via_cycle+1 and end at + // via_cycle+1.5, compute what that means in maincpu cycles (the + // +1 rounds up, since the clocks are too different to ever be + // synced). + u64 main_cycle = (via_cycle * 2 + 3) * m_maincpu->clock() / (2 * m_via1->clock()) + 1; + + // Finally adjust the main cpu icount as needed. + m_maincpu->adjust_icount(-int(main_cycle - cycle)); +} + +uint16_t maciici_state::via_r(offs_t offset) +{ + uint16_t data; + + offset >>= 8; + offset &= 0x0f; + + if (!machine().side_effects_disabled()) + via_sync(); + + data = m_via1->read(offset); + + return (data & 0xff) | (data << 8); +} + +void maciici_state::via_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + offset >>= 8; + offset &= 0x0f; + + via_sync(); + + if (ACCESSING_BITS_0_7) + m_via1->write(offset, data & 0xff); + if (ACCESSING_BITS_8_15) + m_via1->write(offset, (data >> 8) & 0xff); +} + +uint8_t maciici_state::via_in_a() +{ + return 0xc7; // IIci: PA6 | PA2 | PA1 +} + +uint8_t maciici_state::via_in_a_iisi() +{ + return 0x97; // IIci: PA4 | PA2 | PA1 +} + +uint8_t maciici_state::via_in_b() +{ + u8 val = m_macadb->get_adb_state() << 4; + + if (!m_adb_irq_pending) + { + val |= 0x08; + } + + val |= m_rtc->data_r(); + + return val; +} + +uint8_t maciici_state::via_in_b_iisi() +{ + return m_egret->get_xcvr_session() << 3; +} + +void maciici_state::via_out_a(uint8_t data) +{ + int hdsel = BIT(data, 5); + if (hdsel != m_hdsel) + { + if (m_cur_floppy) + { + m_cur_floppy->ss_w(hdsel); + } + } + m_hdsel = hdsel; +} + +void maciici_state::via_out_b(uint8_t data) +{ + // printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data); + m_macadb->mac_adb_newaction((data & 0x30) >> 4); + + m_rtc->ce_w((data & 0x04) >> 2); + m_rtc->data_w(data & 0x01); + m_rtc->clk_w((data >> 1) & 0x01); +} + +void maciici_state::via_out_b_iisi(uint8_t data) +{ + m_egret->set_via_full((data & 0x10) ? 1 : 0); + m_egret->set_sys_session((data & 0x20) ? 1 : 0); +} + +WRITE_LINE_MEMBER(maciici_state::via_out_cb2) +{ + m_macadb->adb_data_w(state); +} + +WRITE_LINE_MEMBER(maciici_state::via_out_cb2_iisi) +{ + m_egret->set_via_data(state & 1); +} + +/*************************************************************************** + ADDRESS MAPS +***************************************************************************/ + +void maciici_state::maciici_map(address_map &map) +{ + map(0x40000000, 0x4007ffff).r(FUNC(maciici_state::rom_switch_r)).mirror(0x0ff80000); + + map(0x50000000, 0x50001fff).rw(FUNC(maciici_state::via_r), FUNC(maciici_state::via_w)).mirror(0x00f00000); + map(0x50004000, 0x50005fff).rw(FUNC(maciici_state::scc_r), FUNC(maciici_state::scc_w)).mirror(0x00f00000); + map(0x50006000, 0x50007fff).rw(FUNC(maciici_state::scsi_drq_r), FUNC(maciici_state::scsi_drq_w)).mirror(0x00f00000); + map(0x50010000, 0x50011fff).rw(FUNC(maciici_state::scsi_r), FUNC(maciici_state::scsi_w)).mirror(0x00f00000); + map(0x50012000, 0x50013fff).rw(FUNC(maciici_state::scsi_drq_r), FUNC(maciici_state::scsi_drq_w)).mirror(0x00f00000); + map(0x50014000, 0x50015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000); + map(0x50016000, 0x50017fff).rw(FUNC(maciici_state::iwm_r), FUNC(maciici_state::iwm_w)).mirror(0x00f00000); + map(0x50024000, 0x50024007).w(FUNC(maciici_state::rbv_ramdac_w)).mirror(0x00f00000); + map(0x50026000, 0x50027fff).rw(FUNC(maciici_state::rbv_r), FUNC(maciici_state::rbv_w)).mirror(0x00f00000); + map(0x50040000, 0x50041fff).rw(FUNC(maciici_state::via_r), FUNC(maciici_state::via_w)).mirror(0x00f00000); +} + +u16 maciici_state::scsi_r(offs_t offset, u16 mem_mask) +{ + const int reg = (offset >> 3) & 0xf; + const bool pseudo_dma = (reg == 6) && (offset == 0x130); + + return m_scsihelp->read_wrapper(pseudo_dma, reg) << 8; +} + +void maciici_state::scsi_w(offs_t offset, u16 data, u16 mem_mask) +{ + const int reg = (offset >> 3) & 0xf; + const bool pseudo_dma = (reg == 0) && (offset == 0x100); + + m_scsihelp->write_wrapper(pseudo_dma, reg, data >> 8); +} + +u32 maciici_state::scsi_drq_r(offs_t offset, u32 mem_mask) +{ + switch (mem_mask) + { + case 0xff000000: + return m_scsihelp->read_wrapper(true, 6) << 24; + + case 0xffff0000: + return (m_scsihelp->read_wrapper(true, 6) << 24) | (m_scsihelp->read_wrapper(true, 6) << 16); + + case 0xffffffff: + return (m_scsihelp->read_wrapper(true, 6) << 24) | (m_scsihelp->read_wrapper(true, 6) << 16) | (m_scsihelp->read_wrapper(true, 6) << 8) | m_scsihelp->read_wrapper(true, 6); + + default: + logerror("scsi_drq_r: unknown mem_mask %08x\n", mem_mask); + } + + return 0; +} + +void maciici_state::scsi_drq_w(offs_t offset, u32 data, u32 mem_mask) +{ + switch (mem_mask) + { + case 0xff000000: + m_scsihelp->write_wrapper(true, 0, data >> 24); + break; + + case 0xffff0000: + m_scsihelp->write_wrapper(true, 0, data >> 24); + m_scsihelp->write_wrapper(true, 0, data >> 16); + break; + + case 0xffffffff: + m_scsihelp->write_wrapper(true, 0, data >> 24); + m_scsihelp->write_wrapper(true, 0, data >> 16); + m_scsihelp->write_wrapper(true, 0, data >> 8); + m_scsihelp->write_wrapper(true, 0, data & 0xff); + break; + + default: + logerror("scsi_drq_w: unknown mem_mask %08x\n", mem_mask); + break; + } +} + +void maciici_state::phases_w(uint8_t phases) +{ + if (m_cur_floppy) + m_cur_floppy->seek_phase_w(phases); +} + +void maciici_state::devsel_w(uint8_t devsel) +{ + if (devsel == 1) + m_cur_floppy = m_floppy[0]->get_device(); + else if (devsel == 2) + m_cur_floppy = m_floppy[1]->get_device(); + else + m_cur_floppy = nullptr; + + m_fdc->set_floppy(m_cur_floppy); + if (m_cur_floppy) + m_cur_floppy->ss_w(m_hdsel); +} + +// IIci/IIsi RAM-Based Video (RBV) + +void maciici_state::rbv_reset() +{ + int htotal, vtotal; + double framerate; + + memset(m_rbv_regs, 0, sizeof(m_rbv_regs)); + + m_rbv_count = 0; + m_rbv_clutoffs = 0; + m_rbv_immed10wr = 0; + + m_rbv_regs[2] = 0x7f; + m_rbv_regs[3] = 0; + + m_rbv_montype = m_montype->read(); + rectangle visarea; + switch (m_rbv_montype) + { + case 1: // 15" portrait display + visarea.set(0, 640 - 1, 0, 870 - 1); + htotal = 832; + vtotal = 918; + framerate = 75.0; + break; + + case 2: // 12" RGB + visarea.set(0, 512 - 1, 0, 384 - 1); + htotal = 640; + vtotal = 407; + framerate = 60.15; + break; + + case 6: // 13" RGB + default: + visarea.set(0, 640 - 1, 0, 480 - 1); + htotal = 800; + vtotal = 525; + framerate = 59.94; + break; + } + + // logerror("RBV reset: monitor is %dx%d @ %f Hz\n", visarea.width(), visarea.height(), framerate); + m_screen->configure(htotal, vtotal, visarea, HZ_TO_ATTOSECONDS(framerate)); +} + +uint32_t maciici_state::screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + uint8_t const *vram8 = (uint8_t *)m_ram->pointer(); + int hres, vres; + + switch (m_rbv_montype) + { + case 1: // 15" portrait display + hres = 640; + vres = 870; + break; + + case 2: // 12" RGB + hres = 512; + vres = 384; + break; + + case 6: // 13" RGB + default: + hres = 640; + vres = 480; + break; + } + + switch (m_rbv_regs[0x10] & 7) + { + case 0: // 1bpp + { + for (int y = 0; y < vres; y++) + { + uint32_t *scanline = &bitmap.pix(y); + for (int x = 0; x < hres; x += 8) + { + uint8_t const pixels = vram8[(y * (hres / 8)) + ((x / 8) ^ 3)]; + + *scanline++ = m_rbv_palette[0xfe | (pixels >> 7)]; + *scanline++ = m_rbv_palette[0xfe | ((pixels >> 6) & 1)]; + *scanline++ = m_rbv_palette[0xfe | ((pixels >> 5) & 1)]; + *scanline++ = m_rbv_palette[0xfe | ((pixels >> 4) & 1)]; + *scanline++ = m_rbv_palette[0xfe | ((pixels >> 3) & 1)]; + *scanline++ = m_rbv_palette[0xfe | ((pixels >> 2) & 1)]; + *scanline++ = m_rbv_palette[0xfe | ((pixels >> 1) & 1)]; + *scanline++ = m_rbv_palette[0xfe | (pixels & 1)]; + } + } + } + break; + + case 1: // 2bpp + { + for (int y = 0; y < vres; y++) + { + uint32_t *scanline = &bitmap.pix(y); + for (int x = 0; x < hres / 4; x++) + { + uint8_t const pixels = vram8[(y * (hres / 4)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0xfc | ((pixels >> 6) & 3)]; + *scanline++ = m_rbv_palette[0xfc | ((pixels >> 4) & 3)]; + *scanline++ = m_rbv_palette[0xfc | ((pixels >> 2) & 3)]; + *scanline++ = m_rbv_palette[0xfc | (pixels & 3)]; + } + } + } + break; + + case 2: // 4bpp + { + for (int y = 0; y < vres; y++) + { + uint32_t *scanline = &bitmap.pix(y); + + for (int x = 0; x < hres / 2; x++) + { + uint8_t const pixels = vram8[(y * (hres / 2)) + (BYTE4_XOR_BE(x))]; + + *scanline++ = m_rbv_palette[0xf0 | (pixels >> 4)]; + *scanline++ = m_rbv_palette[0xf0 | (pixels & 0xf)]; + } + } + } + break; + + case 3: // 8bpp + { + for (int y = 0; y < vres; y++) + { + uint32_t *scanline = &bitmap.pix(y); + + for (int x = 0; x < hres; x++) + { + uint8_t const pixels = vram8[(y * hres) + (BYTE4_XOR_BE(x))]; + *scanline++ = m_rbv_palette[pixels]; + } + } + } + } + + return 0; +} + +/*************************************************************************** + DEVICE CONFIG +***************************************************************************/ + +INPUT_PORTS_START( maciici ) + PORT_START("MONTYPE") + PORT_CONFNAME(0x0f, 0x06, "Connected monitor") + PORT_CONFSETTING( 0x01, "15\" Portrait Display (640x870)") + PORT_CONFSETTING( 0x02, "12\" RGB (512x384)") + PORT_CONFSETTING( 0x06, "13\" RGB (640x480)") +INPUT_PORTS_END + +/*************************************************************************** + MACHINE DRIVERS +***************************************************************************/ +void maciici_state::maciici(machine_config &config) +{ + M68030(config, m_maincpu, 25000000); + m_maincpu->set_addrmap(AS_PROGRAM, &maciici_state::maciici_map); + m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); + + RTC3430042(config, m_rtc, XTAL(32'768)); + m_rtc->cko_cb().set(m_via1, FUNC(via6522_device::write_ca2)); + + SWIM1(config, m_fdc, C15M); + m_fdc->devsel_cb().set(FUNC(maciici_state::devsel_w)); + m_fdc->phases_cb().set(FUNC(maciici_state::phases_w)); + + applefdintf_device::add_35_hd(config, m_floppy[0]); + applefdintf_device::add_35_nc(config, m_floppy[1]); + + SOFTWARE_LIST(config, "flop35hd_list").set_original("mac_hdflop"); + + 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(FUNC(maciici_state::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)); + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + ASC(config, m_asc, C15M, asc_device::asc_type::ASC); + m_asc->irqf_callback().set(FUNC(maciici_state::mac_asc_irq)); + m_asc->add_route(0, "lspeaker", 1.0); + m_asc->add_route(1, "rspeaker", 1.0); + + R65NC22(config, m_via1, C7M / 10); + m_via1->readpa_handler().set(FUNC(maciici_state::via_in_a)); + m_via1->readpb_handler().set(FUNC(maciici_state::via_in_b)); + m_via1->writepa_handler().set(FUNC(maciici_state::via_out_a)); + m_via1->writepb_handler().set(FUNC(maciici_state::via_out_b)); + m_via1->cb2_handler().set(FUNC(maciici_state::via_out_cb2)); + m_via1->irq_handler().set(FUNC(maciici_state::via_irq)); + + NSCSI_BUS(config, "scsi"); + 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("ncr5380", NCR53C80).machine_config([this](device_t *device) + { + ncr53c80_device &adapter = downcast(*device); + adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w)); }); + + MAC_SCSI_HELPER(config, m_scsihelp); + m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read)); + m_scsihelp->scsi_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::write)); + m_scsihelp->scsi_dma_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_r)); + m_scsihelp->scsi_dma_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_w)); + m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT); + m_scsihelp->timeout_error_callback().set(FUNC(maciici_state::scsi_berr_w)); + + SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd"); + + RAM(config, m_ram); + m_ram->set_default_size("2M"); + m_ram->set_extra_options("8M,32M,64M,96M,128M"); + + SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop"); + + PALETTE(config, m_palette).set_entries(256); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480); + m_screen->set_size(640, 870); + m_screen->set_visarea(0, 640 - 1, 0, 480 - 1); + m_screen->set_screen_update(FUNC(maciici_state::screen_update_macrbv)); + m_screen->screen_vblank().set(FUNC(maciici_state::mac_rbv_vbl)); + + /* internal ram */ + m_ram->set_default_size("2M"); + m_ram->set_extra_options("4M,8M,16M,32M,48M,64M,128M"); + + nubus_device &nubus(NUBUS(config, "nubus", 0)); + nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.out_irqc_callback().set(FUNC(maciici_state::nubus_irq_c_w)); + nubus.out_irqd_callback().set(FUNC(maciici_state::nubus_irq_d_w)); + nubus.out_irqe_callback().set(FUNC(maciici_state::nubus_irq_e_w)); + + NUBUS_SLOT(config, "nbc", "nubus", mac_nubus_cards, nullptr); + NUBUS_SLOT(config, "nbd", "nubus", mac_nubus_cards, nullptr); + NUBUS_SLOT(config, "nbe", "nubus", mac_nubus_cards, nullptr); + + MACADB(config, m_macadb, C15M); + m_macadb->set_mcu_mode(false); + m_macadb->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); + m_macadb->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); + m_macadb->adb_irq_callback().set(FUNC(maciici_state::adb_irq_w)); +} + +void maciici_state::maciisi(machine_config &config) +{ + maciici(config); + + M68030(config.replace(), m_maincpu, 20000000); + m_maincpu->set_addrmap(AS_PROGRAM, &maciici_state::maciici_map); + m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override"); + + MACADB(config.replace(), m_macadb, C15M); + + m_via1->readpa_handler().set(FUNC(maciici_state::via_in_a_iisi)); + m_via1->readpb_handler().set(FUNC(maciici_state::via_in_b_iisi)); + m_via1->writepb_handler().set(FUNC(maciici_state::via_out_b_iisi)); + m_via1->cb2_handler().set(FUNC(maciici_state::via_out_cb2_iisi)); + + EGRET(config, m_egret, EGRET_344S0100); + m_egret->reset_callback().set(FUNC(maciici_state::egret_reset_w)); + m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); + m_egret->via_clock_callback().set(m_via1, FUNC(via6522_device::write_cb1)); + m_egret->via_data_callback().set(m_via1, FUNC(via6522_device::write_cb2)); + m_macadb->adb_data_callback().set(m_egret, FUNC(egret_device::set_adb_line)); + config.set_perfect_quantum(m_maincpu); +} + +ROM_START( maciici ) + ROM_REGION32_BE(0x80000, "bootrom", 0) + ROM_LOAD32_BYTE( "341-0736.um12", 0x000000, 0x020000, CRC(7a1906e6) SHA1(3e39c80b52f40798502fcbdfc97b315545c4c4d3) ) + ROM_LOAD32_BYTE( "341-0735.um11", 0x000001, 0x020000, CRC(a8942189) SHA1(be9f653cab04c304d7ee8d4ec312c23ff5d47efc) ) + ROM_LOAD32_BYTE( "342-0734.um10", 0x000002, 0x020000, CRC(07f56402) SHA1(e11ca97181faf26cd0d05bd639d65998805c7822) ) + ROM_LOAD32_BYTE( "342-0733.um9", 0x000003, 0x020000, CRC(20c28451) SHA1(fecf849c9ac9717c18c13184e24a471888028e46) ) +ROM_END + +ROM_START( maciisi ) + ROM_REGION32_BE(0x80000, "bootrom", 0) + ROM_LOAD( "36b7fb6c.rom", 0x000000, 0x080000, CRC(f304d973) SHA1(f923de4125aae810796527ff6e25364cf1d54eec) ) +ROM_END + +} // anonymous namespace + +COMP(1989, maciici, 0, 0, maciici, maciici, maciici_state, empty_init, "Apple Computer", "Macintosh IIci", MACHINE_SUPPORTS_SAVE) +COMP(1990, maciisi, 0, 0, maciisi, maciici, maciici_state, empty_init, "Apple Computer", "Macintosh IIsi", MACHINE_SUPPORTS_SAVE) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 76394994dc7..dda50eab15f 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -822,10 +822,8 @@ lwriter2nt // Apple LaserWriter II NT @source:apple/mac.cpp mac2fdhd // 1988 Apple Macintosh II (FDHD) macii // 1987 Apple Macintosh II -maciici // 1989 Apple Macintosh IIci maciicx // 1989 Apple Macintosh IIcx maciihmu // 1987 Apple Macintosh II (w/o 68851 MMU) -maciisi // 1990 Apple Macintosh IIsi maciix // 1988 Apple Macintosh IIx macse30 // 1989 Apple Macintosh SE/30 @@ -840,6 +838,10 @@ macsefd // 1988 Apple Macintosh SE (FDHD) unitron // 1985 Unitron utrn1024 // 1986 Unitron 1024 +@source:apple/maciici.cpp +maciici // 1989 Apple Macintosh IIci +maciisi // 1990 Apple Macintosh IIsi + @source:apple/maciifx.cpp maciifx // 1990 Apple Macintosh IIfx -- cgit v1.2.3