summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2022-07-17 22:33:22 -0400
committer arbee <rb6502@users.noreply.github.com>2022-07-17 22:33:22 -0400
commit6f2d0788c567c44f264864df410e1628d538a191 (patch)
tree02143eb17beef6201691ac5c1a93db3c1f0b1397 /src
parentd01d1a0029872b51b9e2244e7e00caf658a90a78 (diff)
mac.cpp: moved maciivx and maciivi to their own driver. [R. Belmont]
Diffstat (limited to 'src')
-rw-r--r--src/mame/apple/mac.cpp59
-rw-r--r--src/mame/apple/mac.h13
-rw-r--r--src/mame/apple/mac_m.cpp55
-rw-r--r--src/mame/apple/mac_v.cpp137
-rw-r--r--src/mame/apple/maciivx.cpp401
-rw-r--r--src/mame/apple/vasp.cpp756
-rw-r--r--src/mame/apple/vasp.h108
-rw-r--r--src/mame/mame.lst6
8 files changed, 1281 insertions, 254 deletions
diff --git a/src/mame/apple/mac.cpp b/src/mame/apple/mac.cpp
index adf57c066d9..391080bf2ae 100644
--- a/src/mame/apple/mac.cpp
+++ b/src/mame/apple/mac.cpp
@@ -7,7 +7,6 @@
TODO:
- V8 and friends (LC, LC2, Classic 2, Color Classic) to own driver
- - IIvx / IIvi to own driver
****************************************************************************/
@@ -461,25 +460,6 @@ void mac_state::maclc_map(address_map &map)
map(0xf40000, 0xfbffff).ram().share("vram");
}
-void mac_state::maclc3_map(address_map &map)
-{
- map(0x40000000, 0x400fffff).rom().region("bootrom", 0).mirror(0x0ff00000);
-
- 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, 0x50025fff).w(FUNC(mac_state::ariel_ramdac_w)).mirror(0x00f00000);
- map(0x50026000, 0x50027fff).rw(FUNC(mac_state::mac_rbv_r), FUNC(mac_state::mac_rbv_w)).mirror(0x00f00000);
-
- map(0x5ffffffc, 0x5fffffff).r(FUNC(mac_state::mac_read_id));
-
- map(0x60000000, 0x600fffff).ram().mirror(0x0ff00000).share("vram");
-}
-
void mac_state::macii_map(address_map &map)
{
map(0x40000000, 0x4003ffff).rom().region("bootrom", 0).mirror(0x0ffc0000);
@@ -908,33 +888,6 @@ void mac_state::maccclas(machine_config &config)
m_via1->writepb_handler().set(FUNC(mac_state::mac_via_out_b_cdadb));
}
-void mac_state::maciivx(machine_config &config)
-{
- maclc(config, false, true, asc_device::asc_type::VASP);
-
- M68030(config, m_maincpu, C32M);
- m_maincpu->set_addrmap(AS_PROGRAM, &mac_state::maclc3_map);
- m_maincpu->set_dasm_override(FUNC(mac_state::mac_dasm_override));
-
- MCFG_VIDEO_START_OVERRIDE(mac_state,macv8)
- MCFG_VIDEO_RESET_OVERRIDE(mac_state,macrbv)
-
- m_screen->set_screen_update(FUNC(mac_state::screen_update_macrbvvram));
-
- add_nubus(config, false);
-
- m_ram->set_default_size("4M");
- m_ram->set_extra_options("8M,12M,16M,20M,24M,28M,32M,36M,40M,44M,48M,52M,56M,60M,64M");
-
- m_egret->set_type(EGRET_341S0851);
-}
-
-void mac_state::maciivi(machine_config &config)
-{
- maciivx(config);
- m_maincpu->set_clock(C15M);
-}
-
void mac_state::maciix(machine_config &config, bool nubus_bank1, bool nubus_bank2)
{
macii(config, false, asc_device::asc_type::ASC, true, nubus_bank1, nubus_bank2);
@@ -1161,16 +1114,6 @@ ROM_START( maciisi )
ROM_LOAD( "36b7fb6c.rom", 0x000000, 0x080000, CRC(f304d973) SHA1(f923de4125aae810796527ff6e25364cf1d54eec) )
ROM_END
-ROM_START( maciivx )
- ROM_REGION32_BE(0x100000, "bootrom", 0)
- ROM_LOAD( "4957eb49.rom", 0x000000, 0x100000, CRC(61be06e5) SHA1(560ce203d65178657ad09d03f532f86fa512bb40) )
-ROM_END
-
-ROM_START( maciivi )
- ROM_REGION32_BE(0x100000, "bootrom", 0)
- ROM_LOAD( "4957eb49.rom", 0x000000, 0x100000, CRC(61be06e5) SHA1(560ce203d65178657ad09d03f532f86fa512bb40) )
-ROM_END
-
ROM_START( macclas2 )
ROM_REGION32_BE(0x100000, "bootrom", 0) // 3193670e
//ROM_LOAD( "3193670e.rom", 0x000000, 0x080000, CRC(96d2e1fd) SHA1(50df69c1b6e805e12a405dc610bc2a1471b2eac2) )
@@ -1208,5 +1151,3 @@ COMP( 1990, maciisi, 0, 0, maciisi, maciici, mac_state, init_maci
COMP( 1991, macclas2, 0, 0, macclas2, macadb, mac_state, init_macclassic2, "Apple Computer", "Macintosh Classic II", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
COMP( 1991, maclc2, 0, 0, maclc2, maciici, mac_state, init_maclc2, "Apple Computer", "Macintosh LC II", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND )
COMP( 1993, maccclas, 0, 0, maccclas, macadb, mac_state, init_maclrcclassic, "Apple Computer", "Macintosh Color Classic", MACHINE_NOT_WORKING )
-COMP( 1993, maciivx, 0, 0, maciivx, maciici, mac_state, init_maciivx, "Apple Computer", "Macintosh IIvx", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
-COMP( 1993, maciivi, maciivx, 0, maciivi, maciici, mac_state, init_maciivi, "Apple Computer", "Macintosh IIvi", MACHINE_SUPPORTS_SAVE|MACHINE_IMPERFECT_SOUND )
diff --git a/src/mame/apple/mac.h b/src/mame/apple/mac.h
index 32e6e0ddb29..90aa578ab82 100644
--- a/src/mame/apple/mac.h
+++ b/src/mame/apple/mac.h
@@ -2,9 +2,9 @@
// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont
/*****************************************************************************
*
- * includes/mac.h
+ * mac.h
*
- * Macintosh driver declarations
+ * Macintosh II driver declarations
*
****************************************************************************/
#ifndef MAME_INCLUDES_MAC_H
@@ -93,14 +93,10 @@ public:
void maclc(machine_config &config, bool cpu = true, bool egret = true, asc_device::asc_type asc_type = asc_device::asc_type::V8, int woz_version = 1);
void maciisi(machine_config &config);
void maclc2(machine_config &config, bool egret = true, int woz_version = 1);
- void maclc3(machine_config &config, bool egret = true);
void macpd210(machine_config &config);
void maciici(machine_config &config);
void maciix(machine_config &config, bool nubus_bank1 = true, bool nubus_bank2 = true);
- void maclc520(machine_config &config);
- void maciivx(machine_config &config);
void maccclas(machine_config &config);
- void maciivi(machine_config &config);
void maciicx(machine_config &config);
void macse30(machine_config &config);
void maciifx(machine_config &config);
@@ -113,20 +109,15 @@ public:
void init_maclc2();
void init_maciifdhd();
void init_macse30();
- void init_maciivx();
- void init_maciivi();
void init_macii();
void init_macclassic2();
void init_maciifx();
void init_maclc();
- void init_maclc520();
void init_maciici();
void init_maciix();
void init_maclrcclassic();
void init_maciisi();
void init_maciicx();
- void init_maclc3();
- void init_maclc3plus();
/* tells which model is being emulated (set by macxxx_init) */
enum model_t
diff --git a/src/mame/apple/mac_m.cpp b/src/mame/apple/mac_m.cpp
index f4d8a771f99..ebd30a177dc 100644
--- a/src/mame/apple/mac_m.cpp
+++ b/src/mame/apple/mac_m.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont
/****************************************************************************
- machine/mac.c
+ mac_m.cpp
Mac II series hardware
@@ -20,10 +20,8 @@
- 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
- - Mac IIvx/IIvi 030 SWIM Egret ADB n/a Internal "VASP" type
- Mac LC 020 SWIM Egret ADB n/a Internal "V8" type
- Mac LC II 030 SWIM Egret ADB n/a Internal "V8" type
- - Mac LC III 030 SWIM Egret ADB n/a Internal "Sonora" type
- Mac Classic II 030 SWIM Egret ADB n/a Internal "Eagle" type (V8 clone)
- Mac Color Classic 030 SWIM Cuda ADB n/a Internal "Spice" type (V8 clone)
@@ -320,7 +318,7 @@ void mac_state::set_memory_overlay(int overlay)
}
/* install the memory */
- if (((m_model >= MODEL_MAC_LC) && (m_model <= MODEL_MAC_COLOR_CLASSIC) && ((m_model != MODEL_MAC_LC_III) && (m_model != MODEL_MAC_LC_III_PLUS))) || (m_model == MODEL_MAC_CLASSIC_II))
+ if (((m_model >= MODEL_MAC_LC) && (m_model <= MODEL_MAC_COLOR_CLASSIC)) || (m_model == MODEL_MAC_CLASSIC_II))
{
m_overlay = overlay;
v8_resize();
@@ -345,24 +343,10 @@ void mac_state::set_memory_overlay(int overlay)
space.unmap_write(0x000000, 0x9fffff);
mac_install_memory(0x000000, memory_size-1, memory_size, memory_data, is_rom);
}
- else if ((m_model >= MODEL_MAC_II) && (m_model <= MODEL_MAC_SE30) && (m_model != MODEL_MAC_IIVX) && (m_model != MODEL_MAC_IIVI))
+ else if ((m_model >= MODEL_MAC_II) && (m_model <= MODEL_MAC_SE30))
{
mac_install_memory(0x00000000, 0x3fffffff, memory_size, memory_data, is_rom);
}
- else if ((m_model == MODEL_MAC_IIVX) || (m_model == MODEL_MAC_IIVI) || (m_model == MODEL_MAC_LC_III) || (m_model == MODEL_MAC_LC_III_PLUS) || (m_model >= MODEL_MAC_LC_475 && m_model <= MODEL_MAC_LC_580)) // up to 36 MB
- {
- mac_install_memory(0x00000000, memory_size-1, memory_size, memory_data, is_rom);
-
- if (is_rom)
- {
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x40000000, 0x4fffffff, read32sm_delegate(*this, FUNC(mac_state::rom_switch_r)), 0xffffffff);
- }
- else
- {
- size_t rom_mirror = 0xfffffff ^ (m_rom_size - 1);
- m_maincpu->space(AS_PROGRAM).install_rom(0x40000000, 0x4fffffff & ~rom_mirror, rom_mirror, m_rom_ptr);
- }
- }
else
{
mac_install_memory(0x00000000, 0x003fffff, memory_size, memory_data, is_rom);
@@ -672,8 +656,6 @@ uint8_t mac_state::mac_via_in_a()
case MODEL_MAC_LC:
case MODEL_MAC_LC_II:
- case MODEL_MAC_IIVX:
- case MODEL_MAC_IIVI:
return 0x81 | PA6 | PA4 | PA2;
case MODEL_MAC_IICI:
@@ -1064,15 +1046,7 @@ void mac_state::machine_reset()
if (m_overlay_timeout != (emu_timer *)nullptr)
{
- if ((m_model == MODEL_MAC_LC_III) || (m_model == MODEL_MAC_LC_III_PLUS) || (m_model >= MODEL_MAC_LC_475 && m_model <= MODEL_MAC_LC_580)) // up to 36 MB
- {
- m_overlay_timeout->adjust(attotime::never);
- }
- else if (((m_model >= MODEL_MAC_LC) && (m_model <= MODEL_MAC_COLOR_CLASSIC) && ((m_model != MODEL_MAC_LC_III) && (m_model != MODEL_MAC_LC_III_PLUS))) || (m_model == MODEL_MAC_CLASSIC_II))
- {
- m_overlay_timeout->adjust(attotime::never);
- }
- else if ((m_model >= MODEL_MAC_IIVX) && (m_model <= MODEL_MAC_IIVI))
+ if (((m_model >= MODEL_MAC_LC) && (m_model <= MODEL_MAC_COLOR_CLASSIC)) || (m_model == MODEL_MAC_CLASSIC_II))
{
m_overlay_timeout->adjust(attotime::never);
}
@@ -1138,18 +1112,9 @@ uint32_t mac_state::mac_read_id()
switch (m_model)
{
- case MODEL_MAC_LC_III:
- return 0xa55a0001; // 25 MHz LC III
-
- case MODEL_MAC_LC_III_PLUS:
- return 0xa55a0003; // 33 MHz LC III+
-
case MODEL_MAC_LC_475:
return 0xa55a2221;
- case MODEL_MAC_LC_520:
- return 0xa55a0100;
-
case MODEL_MAC_LC_550:
return 0xa55a0101;
@@ -1177,9 +1142,6 @@ uint32_t mac_state::mac_read_id()
case MODEL_MAC_QUADRA_840AV:
return 0xa55a2830;
- case MODEL_MAC_IIVX:
- return 0xa55a2015;
-
default:
return 0;
}
@@ -1202,8 +1164,8 @@ void mac_state::mac_driver_init(model_t model)
memset(m_ram->pointer(), 0, m_ram->size());
- if ((model == MODEL_MAC_CLASSIC_II) || (model == MODEL_MAC_LC) || (model == MODEL_MAC_COLOR_CLASSIC) || (model >= MODEL_MAC_LC_475 && model <= MODEL_MAC_LC_580) ||
- (model == MODEL_MAC_LC_II) || (model == MODEL_MAC_LC_III) || (model == MODEL_MAC_LC_III_PLUS) || ((m_model >= MODEL_MAC_II) && (m_model <= MODEL_MAC_SE30)))
+ if ((model == MODEL_MAC_CLASSIC_II) || (model == MODEL_MAC_LC) || (model == MODEL_MAC_COLOR_CLASSIC) ||
+ (model == MODEL_MAC_LC_II) || ((m_model >= MODEL_MAC_II) && (m_model <= MODEL_MAC_SE30)))
{
m_overlay_timeout = timer_alloc(FUNC(mac_state::overlay_timeout_func), this);
}
@@ -1224,21 +1186,16 @@ void mac_state::init_##label() \
MAC_DRIVER_INIT(maclc, MODEL_MAC_LC)
MAC_DRIVER_INIT(maclc2, MODEL_MAC_LC_II)
-MAC_DRIVER_INIT(maclc3, MODEL_MAC_LC_III)
-MAC_DRIVER_INIT(maclc3plus, MODEL_MAC_LC_III_PLUS)
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(macclassic2, MODEL_MAC_CLASSIC_II)
MAC_DRIVER_INIT(maclrcclassic, MODEL_MAC_COLOR_CLASSIC)
-MAC_DRIVER_INIT(maciivx, MODEL_MAC_IIVX)
-MAC_DRIVER_INIT(maciivi, MODEL_MAC_IIVI)
MAC_DRIVER_INIT(maciifx, MODEL_MAC_IIFX)
MAC_DRIVER_INIT(maciicx, MODEL_MAC_IICX)
MAC_DRIVER_INIT(maciifdhd, MODEL_MAC_II_FDHD)
MAC_DRIVER_INIT(maciix, MODEL_MAC_IIX)
-MAC_DRIVER_INIT(maclc520, MODEL_MAC_LC_520)
void mac_state::nubus_slot_interrupt(uint8_t slot, uint32_t state)
{
diff --git a/src/mame/apple/mac_v.cpp b/src/mame/apple/mac_v.cpp
index dea55dd698c..bebf10372ef 100644
--- a/src/mame/apple/mac_v.cpp
+++ b/src/mame/apple/mac_v.cpp
@@ -2,16 +2,12 @@
// copyright-holders:Nathan Woods, Raphael Nabet, R. Belmont
/***************************************************************************
- video/mac.c
+ video/mac.cpp
Macintosh video hardware
- Emulates the video hardware for compact Macintosh series (original
- Macintosh (128k, 512k, 512ke), Macintosh Plus, Macintosh SE, Macintosh
- Classic)
-
- Also emulates on-board video for systems with the
- RBV, V8, Eagle, and DAFB chips.
+ Emulates the video hardware for systems with the
+ RBV, V8, and Eagle chips.
----------------------------------------------------------------------
Monitor sense codes
@@ -52,7 +48,6 @@ Apple color FPD 01 11 10 (FPD = Full Page Display)
***************************************************************************/
-
#include "emu.h"
#include "sound/asc.h"
#include "mac.h"
@@ -84,7 +79,7 @@ uint32_t mac_state::screen_update_macse30(screen_device &screen, bitmap_ind16 &b
return 0;
}
-// IIci/IIsi RAM-Based Video (RBV) and children: V8, Eagle, Spice, VASP
+// IIci/IIsi RAM-Based Video (RBV) and children: V8, Eagle, Spice
VIDEO_START_MEMBER(mac_state,macrbv)
{
@@ -272,130 +267,6 @@ uint32_t mac_state::screen_update_macrbv(screen_device &screen, bitmap_rgb32 &bi
return 0;
}
-uint32_t mac_state::screen_update_macrbvvram(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- 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
- {
- auto const vram8 = util::big_endian_cast<uint8_t const>(m_vram.target());
-
- 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 * 2048) + (x / 8)];
-
- *scanline++ = m_rbv_palette[0x7f|(pixels&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<1)&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<2)&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<3)&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<4)&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<5)&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<6)&0x80)];
- *scanline++ = m_rbv_palette[0x7f|((pixels<<7)&0x80)];
- }
- }
- }
- break;
-
- case 1: // 2bpp
- {
- auto const vram8 = util::big_endian_cast<uint8_t const>(m_vram.target());
-
- 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 * 2048) + x];
-
- *scanline++ = m_rbv_palette[0x3f|(pixels&0xc0)];
- *scanline++ = m_rbv_palette[0x3f|((pixels<<2)&0xc0)];
- *scanline++ = m_rbv_palette[0x3f|((pixels<<4)&0xc0)];
- *scanline++ = m_rbv_palette[0x3f|((pixels<<6)&0xc0)];
- }
- }
- }
- break;
-
- case 2: // 4bpp
- {
- auto const vram8 = util::big_endian_cast<uint8_t const>(m_vram.target());
-
- 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 * 2048) + x];
-
- *scanline++ = m_rbv_palette[0x0f|(pixels&0xf0)];
- *scanline++ = m_rbv_palette[0x0f|((pixels<<4)&0xf0)];
- }
- }
- }
- break;
-
- case 3: // 8bpp
- {
- auto const vram8 = util::big_endian_cast<uint8_t const>(m_vram.target());
-
- 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 * 2048) + x];
- *scanline++ = m_rbv_palette[pixels];
- }
- }
- }
- break;
-
- case 4: // 16bpp
- {
- auto const vram16 = util::big_endian_cast<uint16_t const>(m_vram.target());
-
- for (int y = 0; y < vres; y++)
- {
- uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < hres; x++)
- {
- uint16_t const pixels = vram16[(y * 1024) + x];
- *scanline++ = rgb_t(((pixels >> 10) & 0x1f) << 3, ((pixels >> 5) & 0x1f) << 3, (pixels & 0x1f) << 3);
- }
- }
- }
- break;
- }
-
- return 0;
-}
-
uint32_t mac_state::screen_update_macv8(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int hres, vres;
diff --git a/src/mame/apple/maciivx.cpp b/src/mame/apple/maciivx.cpp
new file mode 100644
index 00000000000..7934114483a
--- /dev/null
+++ b/src/mame/apple/maciivx.cpp
@@ -0,0 +1,401 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/****************************************************************************
+
+ maciivx.cpp
+ Mac IIvx
+ Mac IIvi
+
+ By R. Belmont
+
+ These 68030 machines were the last Mac IIs, and had development rushed
+ after then-CEO John Sculley told MacWorld Tokyo that Apple would soon
+ ship machines with a built-in CD-ROM drive.
+
+ They run on the "VASP" system ASIC, which is basically V8 with slightly
+ different video and the RAM size limit lifted to 68 MB.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include "bus/nscsi/devices.h"
+#include "bus/nubus/nubus.h"
+#include "bus/nubus/cards.h"
+#include "bus/rs232/rs232.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/applefdintf.h"
+#include "machine/ncr5380.h"
+#include "machine/nscsi_bus.h"
+#include "machine/ram.h"
+#include "machine/swim1.h"
+#include "machine/timer.h"
+#include "machine/z80scc.h"
+#include "cuda.h"
+#include "egret.h"
+#include "macadb.h"
+#include "macscsi.h"
+#include "vasp.h"
+
+#include "emupal.h"
+#include "screen.h"
+#include "softlist_dev.h"
+
+namespace {
+
+#define C32M (31.3344_MHz_XTAL)
+#define C15M (C32M/2)
+#define C7M (C32M/4)
+
+class maciivx_state : public driver_device
+{
+public:
+ maciivx_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_macadb(*this, "macadb"),
+ m_ram(*this, RAM_TAG),
+ m_vasp(*this, "vasp"),
+ m_fdc(*this, "fdc"),
+ m_floppy(*this, "fdc:%d", 0U),
+ m_scsibus1(*this, "scsi"),
+ m_ncr5380(*this, "scsi:7:ncr5380"),
+ m_scsihelp(*this, "scsihelp"),
+ m_scc(*this, "scc"),
+ m_egret(*this, "egret"),
+ m_cur_floppy(nullptr),
+ m_hdsel(0)
+ {
+ }
+
+ void maciiv_base(machine_config &config);
+ void maciivx(machine_config &config);
+ void maciivi(machine_config &config);
+ void base_map(address_map &map);
+ void maciivx_map(address_map &map);
+ void maciivi_map(address_map &map);
+
+private:
+ required_device<m68030_device> m_maincpu;
+ required_device<macadb_device> m_macadb;
+ required_device<ram_device> m_ram;
+ required_device<vasp_device> m_vasp;
+ required_device<applefdintf_device> m_fdc;
+ required_device_array<floppy_connector, 2> m_floppy;
+ required_device<nscsi_bus_device> m_scsibus1;
+ required_device<ncr5380_device> m_ncr5380;
+ required_device<mac_scsi_helper_device> m_scsihelp;
+ required_device<z80scc_device> m_scc;
+ required_device<egret_device> m_egret;
+
+ virtual void machine_start() override;
+
+ 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(cuda_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 swim_r(offs_t offset, u16 mem_mask);
+ void swim_w(offs_t offset, u16 data, u16 mem_mask);
+ WRITE_LINE_MEMBER(hdsel_w);
+};
+
+void maciivx_state::machine_start()
+{
+ m_vasp->set_ram_info((u32 *) m_ram->pointer(), m_ram->size());
+
+ save_item(NAME(m_hdsel));
+}
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+void maciivx_state::base_map(address_map &map)
+{
+ // RAM, ROM, and base I/O mappings come from VASP
+ map(0x40000000, 0x600fffff).m(m_vasp, FUNC(vasp_device::map));
+
+ map(0x50004000, 0x50005fff).rw(FUNC(maciivx_state::scc_r), FUNC(maciivx_state::scc_w)).mirror(0x00f00000);
+ map(0x50006000, 0x50007fff).rw(FUNC(maciivx_state::scsi_drq_r), FUNC(maciivx_state::scsi_drq_w)).mirror(0x00f00000);
+ map(0x50010000, 0x50011fff).rw(FUNC(maciivx_state::scsi_r), FUNC(maciivx_state::scsi_w)).mirror(0x00f00000);
+ map(0x50012000, 0x50013fff).rw(FUNC(maciivx_state::scsi_drq_r), FUNC(maciivx_state::scsi_drq_w)).mirror(0x00f00000);
+ map(0x50016000, 0x50017fff).rw(FUNC(maciivx_state::swim_r), FUNC(maciivx_state::swim_w)).mirror(0x00f00000);
+}
+
+void maciivx_state::maciivx_map(address_map &map)
+{
+ base_map(map);
+ map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a2015; }));
+}
+
+void maciivx_state::maciivi_map(address_map &map)
+{
+ base_map(map);
+ map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a2016; }));
+}
+
+u16 maciivx_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 maciivx_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 maciivx_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 maciivx_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;
+ }
+}
+
+uint16_t maciivx_state::swim_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 maciivx_state::swim_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);
+}
+
+void maciivx_state::phases_w(uint8_t phases)
+{
+ if (m_cur_floppy)
+ m_cur_floppy->seek_phase_w(phases);
+}
+
+void maciivx_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);
+}
+
+WRITE_LINE_MEMBER(maciivx_state::hdsel_w)
+{
+ if (state != m_hdsel)
+ {
+ if (m_cur_floppy)
+ {
+ m_cur_floppy->ss_w(state);
+ }
+ }
+ m_hdsel = state;
+}
+
+/***************************************************************************
+ DEVICE CONFIG
+***************************************************************************/
+
+static INPUT_PORTS_START( maciivx )
+INPUT_PORTS_END
+
+/***************************************************************************
+ MACHINE DRIVERS
+***************************************************************************/
+
+void maciivx_state::maciiv_base(machine_config &config)
+{
+ RAM(config, m_ram);
+ m_ram->set_default_size("4M");
+ m_ram->set_extra_options("8M,16M,32M,36M,48M,64M,68M");
+
+ 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<ncr53c80_device &>(*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(maciivx_state::scsi_berr_w));
+
+ SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd");
+ 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(m_vasp, FUNC(vasp_device::scc_irq_w));
+ m_scc->out_txda_callback().set("printer", FUNC(rs232_port_device::write_txd));
+ m_scc->out_txdb_callback().set("modem", FUNC(rs232_port_device::write_txd));
+
+ rs232_port_device &rs232a(RS232_PORT(config, "printer", default_rs232_devices, nullptr));
+ rs232a.rxd_handler().set(m_scc, FUNC(z80scc_device::rxa_w));
+ rs232a.dcd_handler().set(m_scc, FUNC(z80scc_device::dcda_w));
+ rs232a.cts_handler().set(m_scc, FUNC(z80scc_device::ctsa_w));
+
+ rs232_port_device &rs232b(RS232_PORT(config, "modem", default_rs232_devices, nullptr));
+ rs232b.rxd_handler().set(m_scc, FUNC(z80scc_device::rxb_w));
+ rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w));
+ rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w));
+
+ VASP(config, m_vasp, C15M);
+ m_vasp->set_maincpu_tag("maincpu");
+ m_vasp->set_rom_tag(":bootrom");
+ m_vasp->hdsel_callback().set(FUNC(maciivx_state::hdsel_w));
+
+ MACADB(config, m_macadb, C15M);
+ m_macadb->set_mcu_mode(true);
+
+ nubus_device &nubus(NUBUS(config, "nubus", 0));
+ nubus.set_space(m_maincpu, AS_PROGRAM);
+ nubus.out_irqc_callback().set(m_vasp, FUNC(vasp_device::slot0_irq_w));
+ nubus.out_irqd_callback().set(m_vasp, FUNC(vasp_device::slot1_irq_w));
+ nubus.out_irqe_callback().set(m_vasp, FUNC(vasp_device::slot2_irq_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);
+
+ SWIM1(config, m_fdc, C15M);
+ m_fdc->devsel_cb().set(FUNC(maciivx_state::devsel_w));
+ m_fdc->phases_cb().set(FUNC(maciivx_state::phases_w));
+
+ applefdintf_device::add_35_hd(config, m_floppy[0]);
+ applefdintf_device::add_35_nc(config, m_floppy[1]);
+}
+
+void maciivx_state::maciivx(machine_config &config)
+{
+ M68030(config, m_maincpu, C32M);
+ m_maincpu->set_addrmap(AS_PROGRAM, &maciivx_state::maciivx_map);
+
+ maciiv_base(config);
+
+ EGRET(config, m_egret, EGRET_341S0851);
+ m_egret->reset_callback().set(FUNC(maciivx_state::cuda_reset_w));
+ m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w));
+ m_egret->via_clock_callback().set(m_vasp, FUNC(vasp_device::cb1_w));
+ m_egret->via_data_callback().set(m_vasp, FUNC(vasp_device::cb2_w));
+ m_macadb->adb_data_callback().set(m_egret, FUNC(egret_device::set_adb_line));
+ config.set_perfect_quantum(m_maincpu);
+
+ m_vasp->pb3_callback().set(m_egret, FUNC(egret_device::get_xcvr_session));
+ m_vasp->pb4_callback().set(m_egret, FUNC(egret_device::set_via_full));
+ m_vasp->pb5_callback().set(m_egret, FUNC(egret_device::set_sys_session));
+ m_vasp->cb2_callback().set(m_egret, FUNC(egret_device::set_via_data));
+}
+
+void maciivx_state::maciivi(machine_config &config)
+{
+ maciivx(config);
+
+ M68030(config.replace(), m_maincpu, C15M);
+ m_maincpu->set_addrmap(AS_PROGRAM, &maciivx_state::maciivi_map);
+}
+
+ROM_START(maciivx)
+ ROM_REGION32_BE(0x100000, "bootrom", 0)
+ ROM_LOAD("4957eb49.rom", 0x000000, 0x100000, CRC(61be06e5) SHA1(560ce203d65178657ad09d03f532f86fa512bb40))
+ROM_END
+
+ROM_START(maciivi)
+ ROM_REGION32_BE(0x100000, "bootrom", 0)
+ ROM_LOAD("4957eb49.rom", 0x000000, 0x100000, CRC(61be06e5) SHA1(560ce203d65178657ad09d03f532f86fa512bb40))
+ROM_END
+
+} // anonymous namespace
+
+COMP(1993, maciivx, 0, 0, maciivx, maciivx, maciivx_state, empty_init, "Apple Computer", "Macintosh IIvx", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND)
+COMP(1993, maciivi, maciivx, 0, maciivi, maciivx, maciivx_state, empty_init, "Apple Computer", "Macintosh IIvi", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND)
diff --git a/src/mame/apple/vasp.cpp b/src/mame/apple/vasp.cpp
new file mode 100644
index 00000000000..43ed98b9e36
--- /dev/null
+++ b/src/mame/apple/vasp.cpp
@@ -0,0 +1,756 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*
+ Apple "VASP Integrated Controller" system ASIC
+ Emulation by R. Belmont
+
+ VASP contains the following:
+ - A memory controller for up to 68 MB (4 MB on the motherboard + one 64 MB SIMM)
+ - A VRAM controller and framebuffer controller, supporting monitor ID selection
+ - A full VIA (VIA1) and a "pseudo-VIA", which is basically a combination GPIO and
+ interrupt controller that looks somewhat like a VIA with no timers and no shift register
+ - An ASC-like 4-channel audio controller
+ - Support logic for various external subsystems (ADB, FDC, NuBus, SCC, SCSI)
+*/
+
+#include "emu.h"
+#include "vasp.h"
+
+#include "formats/ap_dsk35.h"
+#include "layout/generic.h"
+
+static constexpr u32 C7M = 7833600;
+static constexpr u32 C15M = (C7M * 2);
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VASP, vasp_device, "vasp", "Apple VASP system ASIC")
+
+static INPUT_PORTS_START( vasp )
+ 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
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor vasp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( vasp );
+}
+
+//-------------------------------------------------
+// ADDRESS_MAP
+//-------------------------------------------------
+
+void vasp_device::map(address_map &map)
+{
+ map(0x00000000, 0x000fffff).r(FUNC(vasp_device::rom_switch_r)).mirror(0x0ff00000);
+
+ map(0x10000000, 0x10001fff).rw(FUNC(vasp_device::mac_via_r), FUNC(vasp_device::mac_via_w)).mirror(0x00f00000);
+ map(0x10014000, 0x10015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000);
+ map(0x10024000, 0x10025fff).rw(FUNC(vasp_device::dac_r), FUNC(vasp_device::dac_w)).mirror(0x00f00000);
+ map(0x10026000, 0x10027fff).rw(FUNC(vasp_device::pseudovia_r), FUNC(vasp_device::pseudovia_w)).mirror(0x00f00000);
+
+ map(0x20000000, 0x200fffff).ram().mirror(0x0ff00000).rw(FUNC(vasp_device::vram_r), FUNC(vasp_device::vram_w));
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void vasp_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480);
+ m_screen->set_size(1024, 768);
+ m_screen->set_visarea(0, 640 - 1, 0, 480 - 1);
+ m_screen->set_screen_update(FUNC(vasp_device::screen_update));
+ m_screen->screen_vblank().set(FUNC(vasp_device::vbl_w));
+ config.set_default_layout(layout_monitors);
+
+ PALETTE(config, m_palette).set_entries(256);
+
+ R65NC22(config, m_via1, C7M / 10);
+ m_via1->readpa_handler().set(FUNC(vasp_device::via_in_a));
+ m_via1->readpb_handler().set(FUNC(vasp_device::via_in_b));
+ m_via1->writepa_handler().set(FUNC(vasp_device::via_out_a));
+ m_via1->writepb_handler().set(FUNC(vasp_device::via_out_b));
+ m_via1->cb2_handler().set(FUNC(vasp_device::via_out_cb2));
+ m_via1->irq_handler().set(FUNC(vasp_device::via1_irq));
+
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+ ASC(config, m_asc, C15M, asc_device::asc_type::VASP);
+ m_asc->add_route(0, "lspeaker", 1.0);
+ m_asc->add_route(1, "rspeaker", 1.0);
+}
+
+//-------------------------------------------------
+// vasp_device - constructor
+//-------------------------------------------------
+
+vasp_device::vasp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, VASP, tag, owner, clock),
+ write_pb4(*this),
+ write_pb5(*this),
+ write_cb2(*this),
+ write_hdsel(*this),
+ read_pb3(*this),
+ m_maincpu(*this, finder_base::DUMMY_TAG),
+ m_montype(*this, "MONTYPE"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_via1(*this, "via1"),
+ m_asc(*this, "asc"),
+ m_rom(*this, finder_base::DUMMY_TAG),
+ m_overlay(false)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void vasp_device::device_start()
+{
+ m_vram = std::make_unique<u32[]>(0x100000 / sizeof(u32));
+
+ write_pb4.resolve_safe();
+ write_pb5.resolve_safe();
+ write_cb2.resolve_safe();
+ write_hdsel.resolve_safe();
+ read_pb3.resolve_safe(0);
+
+ m_6015_timer = timer_alloc(FUNC(vasp_device::mac_6015_tick), this);
+ m_6015_timer->adjust(attotime::never);
+
+ save_pointer(NAME(m_vram), 0x100000/sizeof(u32));
+ save_item(NAME(m_via_interrupt));
+ save_item(NAME(m_via2_interrupt));
+ save_item(NAME(m_scc_interrupt));
+ save_item(NAME(m_last_taken_interrupt));
+ save_item(NAME(m_pseudovia_regs));
+ save_item(NAME(m_pseudovia_ier));
+ save_item(NAME(m_pseudovia_ifr));
+ save_item(NAME(m_pal_address));
+ save_item(NAME(m_pal_idx));
+ save_item(NAME(m_pal_control));
+ save_item(NAME(m_pal_colkey));
+ save_item(NAME(m_overlay));
+
+ m_rom_ptr = &m_rom[0];
+ m_rom_size = m_rom.length() << 2;
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void vasp_device::device_reset()
+{
+ // start 60.15 Hz timer
+ m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15));
+
+ std::fill_n(m_pseudovia_regs, 256, 0);
+ m_pseudovia_regs[0] = 0x4f;
+ m_pseudovia_regs[1] = 0x06;
+ m_pseudovia_regs[2] = 0x7f;
+ m_pseudovia_regs[3] = 0;
+ m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
+ m_last_taken_interrupt = -1;
+
+ // main cpu shouldn't start until Egret wakes it up
+ m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+
+ m_overlay = true;
+
+ // 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);
+}
+
+u32 vasp_device::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_ptr;
+ offs_t memory_mirror = memory_end & ~memory_end;
+
+ space.install_ram(0x00000000, memory_end & ~memory_mirror, memory_mirror, memory_data);
+ m_overlay = false;
+ }
+
+ return m_rom_ptr[offset & ((m_rom_size - 1) >> 2)];
+}
+
+void vasp_device::set_ram_info(u32 *ram, u32 size)
+{
+ m_ram_ptr = ram;
+ m_ram_size = size;
+}
+
+TIMER_CALLBACK_MEMBER(vasp_device::mac_6015_tick)
+{
+ m_via1->write_ca1(CLEAR_LINE);
+ m_via1->write_ca1(ASSERT_LINE);
+}
+
+uint8_t vasp_device::via_in_a()
+{
+ return 0xd5;
+}
+
+uint8_t vasp_device::via_in_b()
+{
+ return read_pb3() << 3;
+}
+
+WRITE_LINE_MEMBER(vasp_device::via_out_cb2)
+{
+ write_cb2(state & 1);
+}
+
+void vasp_device::via_out_a(uint8_t data)
+{
+ write_hdsel(BIT(data, 5));
+}
+
+void vasp_device::via_out_b(uint8_t data)
+{
+ write_pb4(BIT(data, 4));
+ write_pb5(BIT(data, 5));
+}
+
+WRITE_LINE_MEMBER(vasp_device::via1_irq)
+{
+ m_via_interrupt = state;
+ field_interrupts();
+}
+
+WRITE_LINE_MEMBER(vasp_device::via2_irq)
+{
+ m_via2_interrupt = state;
+ field_interrupts();
+}
+
+void vasp_device::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(vasp_device::scc_irq_w)
+{
+ m_scc_interrupt = (state == ASSERT_LINE);
+ field_interrupts();
+}
+
+WRITE_LINE_MEMBER(vasp_device::vbl_w)
+{
+ if (!state)
+ {
+ return;
+ }
+
+ m_pseudovia_regs[2] &= ~0x40; // set vblank signal
+
+ if (m_pseudovia_regs[0x12] & 0x40)
+ {
+ pseudovia_recalc_irqs();
+ }
+}
+
+WRITE_LINE_MEMBER(vasp_device::slot0_irq_w)
+{
+ if (state)
+ {
+ m_pseudovia_regs[2] &= ~0x08;
+ }
+ else
+ {
+ m_pseudovia_regs[2] |= 0x08;
+ }
+
+ pseudovia_recalc_irqs();
+}
+
+WRITE_LINE_MEMBER(vasp_device::slot1_irq_w)
+{
+ if (state)
+ {
+ m_pseudovia_regs[2] &= ~0x10;
+ }
+ else
+ {
+ m_pseudovia_regs[2] |= 0x10;
+ }
+
+ pseudovia_recalc_irqs();
+}
+
+WRITE_LINE_MEMBER(vasp_device::slot2_irq_w)
+{
+ if (state)
+ {
+ m_pseudovia_regs[2] &= ~0x20;
+ }
+ else
+ {
+ m_pseudovia_regs[2] |= 0x20;
+ }
+
+ pseudovia_recalc_irqs();
+}
+
+void vasp_device::pseudovia_recalc_irqs()
+{
+ // check slot interrupts and bubble them down to IFR
+ uint8_t slot_irqs = (~m_pseudovia_regs[2]) & 0x78;
+ slot_irqs &= (m_pseudovia_regs[0x12] & 0x78);
+
+ if (slot_irqs)
+ {
+ m_pseudovia_regs[3] |= 2; // any slot
+ }
+ else // no slot irqs, clear the pending bit
+ {
+ m_pseudovia_regs[3] &= ~2; // any slot
+ }
+
+ uint8_t ifr = (m_pseudovia_regs[3] & m_pseudovia_ier) & 0x1b;
+
+ if (ifr != 0)
+ {
+ m_pseudovia_regs[3] = ifr | 0x80;
+ m_pseudovia_ifr = ifr | 0x80;
+
+ via2_irq(ASSERT_LINE);
+ }
+ else
+ {
+ via2_irq(CLEAR_LINE);
+ }
+}
+
+uint8_t vasp_device::pseudovia_r(offs_t offset)
+{
+ int data = 0;
+
+ if (offset < 0x100)
+ {
+ data = m_pseudovia_regs[offset];
+
+ if (offset == 0x10)
+ {
+ data &= ~0x38;
+ data |= (m_montype->read() << 3);
+ }
+
+ // bit 7 of these registers always reads as 0 on pseudo-VIAs
+ if ((offset == 0x12) || (offset == 0x13))
+ {
+ data &= ~0x80;
+ }
+ }
+ else
+ {
+ offset >>= 9;
+
+ switch (offset)
+ {
+ case 13: // IFR
+ data = m_pseudovia_ifr;
+ break;
+
+ case 14: // IER
+ data = m_pseudovia_ier;
+ break;
+
+ default:
+ logerror("pseudovia_r: Unknown pseudo-VIA register %d access\n", offset);
+ break;
+ }
+ }
+ return data;
+}
+
+void vasp_device::pseudovia_w(offs_t offset, uint8_t data)
+{
+ if (offset < 0x100)
+ {
+ switch (offset)
+ {
+ case 0x02:
+ m_pseudovia_regs[offset] |= (data & 0x40);
+ pseudovia_recalc_irqs();
+ break;
+
+ case 0x03: // write here to ack
+ if (data & 0x80) // 1 bits write 1s
+ {
+ m_pseudovia_regs[offset] |= data & 0x7f;
+ m_pseudovia_ifr |= data & 0x7f;
+ }
+ else // 1 bits write 0s
+ {
+ m_pseudovia_regs[offset] &= ~(data & 0x7f);
+ m_pseudovia_ifr &= ~(data & 0x7f);
+ }
+ pseudovia_recalc_irqs();
+ break;
+
+ case 0x10:
+ m_pseudovia_regs[offset] = data;
+ break;
+
+ case 0x12:
+ if (data & 0x80) // 1 bits write 1s
+ {
+ m_pseudovia_regs[offset] |= data & 0x7f;
+ }
+ else // 1 bits write 0s
+ {
+ m_pseudovia_regs[offset] &= ~(data & 0x7f);
+ }
+ pseudovia_recalc_irqs();
+ break;
+
+ case 0x13:
+ if (data & 0x80) // 1 bits write 1s
+ {
+ m_pseudovia_regs[offset] |= data & 0x7f;
+
+ if (data == 0xff)
+ m_pseudovia_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_pseudovia_regs[offset] &= ~(data & 0x7f);
+ }
+ break;
+
+ default:
+ m_pseudovia_regs[offset] = data;
+ break;
+ }
+ }
+ else
+ {
+ offset >>= 9;
+
+ switch (offset)
+ {
+ case 13: // IFR
+ if (data & 0x80)
+ {
+ data = 0x7f;
+ }
+ pseudovia_recalc_irqs();
+ break;
+
+ case 14: // IER
+ if (data & 0x80) // 1 bits write 1s
+ {
+ m_pseudovia_ier |= data & 0x7f;
+ }
+ else // 1 bits write 0s
+ {
+ m_pseudovia_ier &= ~(data & 0x7f);
+ }
+ pseudovia_recalc_irqs();
+ break;
+
+ default:
+ logerror("pseudovia_w: Unknown extended pseudo-VIA register %d access\n", offset);
+ break;
+ }
+ }
+}
+
+WRITE_LINE_MEMBER(vasp_device::cb1_w)
+{
+ m_via1->write_cb1(state);
+}
+
+WRITE_LINE_MEMBER(vasp_device::cb2_w)
+{
+ m_via1->write_cb2(state);
+}
+
+uint16_t vasp_device::mac_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 vasp_device::mac_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);
+}
+
+void vasp_device::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));
+}
+
+u32 vasp_device::vram_r(offs_t offset)
+{
+ return m_vram[offset];
+}
+
+void vasp_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_vram[offset]);
+}
+
+u8 vasp_device::dac_r(offs_t offset)
+{
+ switch (offset)
+ {
+ case 2:
+ return m_pal_control;
+
+ default:
+ return 0;
+ }
+}
+
+void vasp_device::dac_w(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_pal_address = data;
+ m_pal_idx = 0;
+ break;
+
+ case 1:
+ switch (m_pal_idx)
+ {
+ case 0:
+ m_palette->set_pen_red_level(m_pal_address, data);
+ break;
+ case 1:
+ m_palette->set_pen_green_level(m_pal_address, data);
+ break;
+ case 2:
+ m_palette->set_pen_blue_level(m_pal_address, data);
+ break;
+ }
+ m_pal_idx++;
+ if (m_pal_idx == 3)
+ {
+ m_pal_idx = 0;
+ m_pal_address++;
+ }
+ break;
+
+ case 2:
+ m_pal_control = data;
+ break;
+
+ case 3:
+ m_pal_colkey = data;
+ break;
+ }
+}
+
+u32 vasp_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ int hres, vres;
+ switch (m_montype->read())
+ {
+ 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;
+ }
+
+ const pen_t *pens = m_palette->pens();
+
+ switch (m_pseudovia_regs[0x10] & 7)
+ {
+ case 0: // 1bpp
+ {
+ auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+
+ 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 * 2048) + (x / 8)];
+
+ *scanline++ = pens[0x7f | (pixels & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 1) & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 2) & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 3) & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 4) & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 5) & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 6) & 0x80)];
+ *scanline++ = pens[0x7f | ((pixels << 7) & 0x80)];
+ }
+ }
+ }
+ break;
+
+ case 1: // 2bpp
+ {
+ auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+
+ 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 * 2048) + x];
+
+ *scanline++ = pens[0x3f | (pixels & 0xc0)];
+ *scanline++ = pens[0x3f | ((pixels << 2) & 0xc0)];
+ *scanline++ = pens[0x3f | ((pixels << 4) & 0xc0)];
+ *scanline++ = pens[0x3f | ((pixels << 6) & 0xc0)];
+ }
+ }
+ }
+ break;
+
+ case 2: // 4bpp
+ {
+ auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+
+ 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 * 2048) + x];
+
+ *scanline++ = pens[0x0f | (pixels & 0xf0)];
+ *scanline++ = pens[0x0f | ((pixels << 4) & 0xf0)];
+ }
+ }
+ }
+ break;
+
+ case 3: // 8bpp
+ {
+ auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+
+ 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 * 2048) + x];
+ *scanline++ = pens[pixels];
+ }
+ }
+ }
+ break;
+
+ case 4: // 16bpp
+ {
+ auto const vram16 = util::big_endian_cast<uint16_t const>(&m_vram[0]);
+
+ for (int y = 0; y < vres; y++)
+ {
+ uint32_t *scanline = &bitmap.pix(y);
+ for (int x = 0; x < hres; x++)
+ {
+ uint16_t const pixels = vram16[(y * 1024) + x];
+ *scanline++ = rgb_t(((pixels >> 10) & 0x1f) << 3, ((pixels >> 5) & 0x1f) << 3, (pixels & 0x1f) << 3);
+ }
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
diff --git a/src/mame/apple/vasp.h b/src/mame/apple/vasp.h
new file mode 100644
index 00000000000..ec1cfb16714
--- /dev/null
+++ b/src/mame/apple/vasp.h
@@ -0,0 +1,108 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+
+#ifndef MAME_APPLE_VASP_H
+#define MAME_APPLE_VASP_H
+
+#pragma once
+
+#include "machine/6522via.h"
+#include "sound/asc.h"
+#include "emupal.h"
+#include "speaker.h"
+#include "screen.h"
+
+// ======================> vasp_device
+
+class vasp_device : public device_t
+{
+public:
+ // construction/destruction
+ vasp_device(const machine_config &mconfig, const char *tag, device_t *owner)
+ : vasp_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ }
+
+ vasp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // interface routines
+ auto pb4_callback() { return write_pb4.bind(); }
+ auto pb5_callback() { return write_pb5.bind(); }
+ auto cb2_callback() { return write_cb2.bind(); }
+ auto hdsel_callback() { return write_hdsel.bind(); }
+ auto pb3_callback() { return read_pb3.bind(); }
+
+ void map(address_map &map);
+
+ template <typename... T> void set_maincpu_tag(T &&... args) { m_maincpu.set_tag(std::forward<T>(args)...); }
+ template <typename... T> void set_rom_tag(T &&... args) { m_rom.set_tag(std::forward<T>(args)...); }
+ void set_ram_info(u32 *ram, u32 size);
+
+ DECLARE_WRITE_LINE_MEMBER(cb1_w);
+ DECLARE_WRITE_LINE_MEMBER(cb2_w);
+ DECLARE_WRITE_LINE_MEMBER(vbl_w);
+ DECLARE_WRITE_LINE_MEMBER(scc_irq_w);
+ DECLARE_WRITE_LINE_MEMBER(slot0_irq_w);
+ DECLARE_WRITE_LINE_MEMBER(slot1_irq_w);
+ DECLARE_WRITE_LINE_MEMBER(slot2_irq_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ devcb_write_line write_pb4, write_pb5, write_cb2, write_hdsel;
+ devcb_read_line read_pb3;
+
+ required_device<cpu_device> m_maincpu;
+ required_ioport m_montype;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_device<via6522_device> m_via1;
+ required_device<asc_device> m_asc;
+ required_region_ptr<u32> m_rom;
+
+ std::unique_ptr<u32[]> m_vram;
+ emu_timer *m_6015_timer;
+ int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt;
+ u8 m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr;
+ u8 m_pal_address, m_pal_idx, m_pal_control, m_pal_colkey;
+ bool m_overlay;
+ u32 *m_ram_ptr, *m_rom_ptr;
+ u32 m_ram_size, m_rom_size;
+
+ u32 rom_switch_r(offs_t offset);
+
+ uint8_t pseudovia_r(offs_t offset);
+ void pseudovia_w(offs_t offset, uint8_t data);
+ void pseudovia_recalc_irqs();
+
+ uint16_t mac_via_r(offs_t offset);
+ void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ uint8_t via_in_a();
+ uint8_t via_in_b();
+ void via_out_a(uint8_t data);
+ void via_out_b(uint8_t data);
+ void via_sync();
+ void field_interrupts();
+ DECLARE_WRITE_LINE_MEMBER(via_out_cb2);
+ DECLARE_WRITE_LINE_MEMBER(via1_irq);
+ DECLARE_WRITE_LINE_MEMBER(via2_irq);
+ TIMER_CALLBACK_MEMBER(mac_6015_tick);
+
+ u32 vram_r(offs_t offset);
+ void vram_w(offs_t offset, u32 data, u32 mem_mask);
+ u8 dac_r(offs_t offset);
+ void dac_w(offs_t offset, u8 data);
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(VASP, vasp_device)
+
+#endif // MAME_APPLE_VASP_H
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 1cb0b584426..0496e9c8bb1 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -20734,13 +20734,15 @@ maciicx // 1989 Apple Macintosh IIcx
maciifx // 1990 Apple Macintosh IIfx
maciihmu // 1987 Apple Macintosh II (w/o 68851 MMU)
maciisi // 1990 Apple Macintosh IIsi
-maciivi // 1993 Apple Macintosh IIvi
-maciivx // 1993 Apple Macintosh IIvx
maciix // 1988 Apple Macintosh IIx
maclc // 1990 Apple Macintosh LC
maclc2 // 1991 Apple Macintosh LC II
macse30 // 1989 Apple Macintosh SE/30
+@source:apple/maciivx.cpp
+maciivx // 1993 Apple Macintosh IIvx
+maciivi // 1993 Apple Macintosh IIvi
+
@source:apple/maclc3.cpp
maclc3 // 1993 Apple Macintosh LC III
maclc520 // 1993 Apple Macintosh LC 520