apple/pseudovia.cpp: Split out the pseudo-VIA device used by RBV, V8, VASP, and Sonora. [R. Belmont]

* This device was previously copy-pasted almost verbatim between those 4 devices,
  and it will be appearing in PowerBooks in the future as well.

apple/mac*.cpp: All 68020 and 68030 Macintoshes that didn't come with an FPU but
 were able to be fitted with one later now gate it behind a configuration switch. [R. Belmont]
* You must completely exit out of the driver to for changes take effect.  This
  may be relaxed in the future.
This commit is contained in:
arbee 2024-10-27 21:59:46 -04:00
parent e2965b559c
commit 94cdc63a80
14 changed files with 571 additions and 768 deletions

View File

@ -68,7 +68,8 @@ public:
m_floppy(*this, "fdc:%d", 0U),
m_scc(*this, "scc"),
m_rtc(*this, "rtc"),
m_egret(*this, "egret")
m_egret(*this, "egret"),
m_config(*this, "config")
{
}
@ -96,6 +97,7 @@ private:
required_device<z80scc_device> m_scc;
optional_device<rtc3430042_device> m_rtc;
optional_device<egret_device> m_egret;
optional_ioport m_config;
void set_via2_interrupt(int value);
void field_interrupts();
@ -203,6 +205,11 @@ void maciici_state::machine_reset()
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
}
if (m_config)
{
m_maincpu->set_fpu_enable(BIT(m_config->read(), 0));
}
// put ROM mirror at 0
address_space &space = m_maincpu->space(AS_PROGRAM);
const u32 memory_size = std::min((u32)0x3fffff, m_rom_size);
@ -502,6 +509,13 @@ void maciici_state::devsel_w(uint8_t devsel)
static INPUT_PORTS_START(maciici)
INPUT_PORTS_END
static INPUT_PORTS_START(maciisi)
PORT_START("config")
PORT_CONFNAME(0x01, 0x00, "FPU")
PORT_CONFSETTING(0x00, "No FPU")
PORT_CONFSETTING(0x01, "FPU Present")
INPUT_PORTS_END
/***************************************************************************
MACHINE DRIVERS
***************************************************************************/
@ -687,4 +701,4 @@ 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)
COMP(1990, maciisi, 0, 0, maciisi, maciisi, maciici_state, empty_init, "Apple Computer", "Macintosh IIsi", MACHINE_SUPPORTS_SAVE)

View File

@ -68,6 +68,7 @@ public:
m_scsihelp(*this, "scsihelp"),
m_scc(*this, "scc"),
m_egret(*this, "egret"),
m_config(*this, "config"),
m_cur_floppy(nullptr),
m_hdsel(0)
{
@ -93,8 +94,10 @@ private:
required_device<mac_scsi_helper_device> m_scsihelp;
required_device<z80scc_device> m_scc;
required_device<egret_device> m_egret;
optional_ioport m_config;
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
u16 scc_r(offs_t offset)
{
@ -139,6 +142,14 @@ void maciivx_state::machine_start()
save_item(NAME(m_hdsel));
}
void maciivx_state::machine_reset()
{
if (m_config)
{
m_maincpu->set_fpu_enable(BIT(m_config->read(), 0));
}
}
/***************************************************************************
ADDRESS MAPS
***************************************************************************/
@ -285,6 +296,13 @@ void maciivx_state::hdsel_w(int state)
static INPUT_PORTS_START( maciivx )
INPUT_PORTS_END
static INPUT_PORTS_START( maciivi )
PORT_START("config")
PORT_CONFNAME(0x01, 0x00, "FPU")
PORT_CONFSETTING(0x00, "No FPU")
PORT_CONFSETTING(0x01, "FPU Present")
INPUT_PORTS_END
/***************************************************************************
MACHINE DRIVERS
***************************************************************************/
@ -424,4 +442,4 @@ ROM_END
} // anonymous namespace
COMP(1993, maciivx, 0, 0, maciivx, maciivx, maciivx_state, empty_init, "Apple Computer", "Macintosh IIvx", MACHINE_SUPPORTS_SAVE)
COMP(1993, maciivi, maciivx, 0, maciivi, maciivx, maciivx_state, empty_init, "Apple Computer", "Macintosh IIvi", MACHINE_SUPPORTS_SAVE)
COMP(1993, maciivi, maciivx, 0, maciivi, maciivi, maciivx_state, empty_init, "Apple Computer", "Macintosh IIvi", MACHINE_SUPPORTS_SAVE)

View File

@ -74,6 +74,7 @@ public:
m_scc(*this, "scc"),
m_egret(*this, "egret"),
m_cuda(*this, "cuda"),
m_config(*this, "config"),
m_cur_floppy(nullptr),
m_hdsel(0)
{
@ -102,8 +103,10 @@ private:
required_device<z80scc_device> m_scc;
optional_device<egret_device> m_egret;
optional_device<cuda_device> m_cuda;
optional_ioport m_config;
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
u16 scc_r(offs_t offset)
{
@ -159,6 +162,14 @@ void maclc_state::machine_start()
save_item(NAME(m_hdsel));
}
void maclc_state::machine_reset()
{
if (m_config)
{
m_maincpu->set_fpu_enable(BIT(m_config->read(), 0));
}
}
/***************************************************************************
ADDRESS MAPS
***************************************************************************/
@ -306,6 +317,14 @@ void maclc_state::hdsel_w(int state)
***************************************************************************/
static INPUT_PORTS_START( maclc )
PORT_START("config")
PORT_CONFNAME(0x01, 0x00, "FPU")
PORT_CONFSETTING(0x00, "No FPU")
PORT_CONFSETTING(0x01, "FPU Present")
INPUT_PORTS_END
// mactv doesn't have a way to add an FPU
static INPUT_PORTS_START( mactv )
INPUT_PORTS_END
/***************************************************************************
@ -386,8 +405,8 @@ void maclc_state::maclc_base(machine_config &config)
nubus.set_space(m_maincpu, AS_PROGRAM);
nubus.set_address_mask(0x80ffffff);
// V8 supports interrupts for slots $C, $D, and $E, but the LC, LC II, and Color Classic
// only hook the slot $E IRQ up to the PDS slot.
nubus.out_irqe_callback().set(m_v8, FUNC(v8_device::slot_irq_w<0x20>));
// only hook the slot $E IRQ up to the PDS slot. ($C/$D/$E are 0/1/2 on the schematics).
nubus.out_irqe_callback().set(m_v8, FUNC(v8_device::slot2_irq_w));
MACADB(config, m_macadb, C15M);
@ -491,6 +510,7 @@ void maclc_state::mactv(machine_config &config)
maclc_base(config);
M68030(config.replace(), m_maincpu, C32M);
m_maincpu->set_fpu_enable(false); // this machine has no FPU and no ability to add one
m_maincpu->set_addrmap(AS_PROGRAM, &maclc_state::maccclassic_map);
m_maincpu->set_dasm_override(std::function(&mac68k_dasm_override), "mac68k_dasm_override");
@ -595,4 +615,4 @@ COMP(1990, maclc, 0, 0, maclc, maclc, maclc_state, empty_init, "Apple Computer
COMP(1991, maclc2, 0, 0, maclc2, maclc, maclc_state, empty_init, "Apple Computer", "Macintosh LC II", MACHINE_SUPPORTS_SAVE)
COMP(1991, macclas2, 0, 0, macclas2, maclc, maclc_state, empty_init, "Apple Computer", "Macintosh Classic II", MACHINE_SUPPORTS_SAVE)
COMP(1993, maccclas, 0, 0, maccclas, maclc, maclc_state, empty_init, "Apple Computer", "Macintosh Color Classic", MACHINE_SUPPORTS_SAVE)
COMP(1994, mactv, 0, 0, mactv, maclc, maclc_state, empty_init, "Apple Computer", "Macintosh TV", MACHINE_SUPPORTS_SAVE)
COMP(1994, mactv, 0, 0, mactv, mactv, maclc_state, empty_init, "Apple Computer", "Macintosh TV", MACHINE_SUPPORTS_SAVE)

View File

@ -64,7 +64,8 @@ public:
m_scsihelp(*this, "scsihelp"),
m_scc(*this, "scc"),
m_egret(*this, "egret"),
m_cuda(*this, "cuda")
m_cuda(*this, "cuda"),
m_config(*this, "config")
{
}
@ -92,8 +93,10 @@ private:
required_device<z80scc_device> m_scc;
optional_device<egret_device> m_egret;
optional_device<cuda_device> m_cuda;
required_ioport m_config;
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
u16 scc_r(offs_t offset)
{
@ -127,6 +130,14 @@ void macvail_state::machine_start()
m_sonora->set_ram_info((u32 *) m_ram->pointer(), m_ram->size());
}
void macvail_state::machine_reset()
{
if (m_config)
{
m_maincpu->set_fpu_enable(BIT(m_config->read(), 0));
}
}
/***************************************************************************
ADDRESS MAPS
***************************************************************************/
@ -232,6 +243,10 @@ void macvail_state::scsi_drq_w(offs_t offset, u32 data, u32 mem_mask)
***************************************************************************/
static INPUT_PORTS_START( macadb )
PORT_START("config")
PORT_CONFNAME(0x01, 0x00, "FPU")
PORT_CONFSETTING(0x00, "No FPU")
PORT_CONFSETTING(0x01, "FPU Present")
INPUT_PORTS_END
/***************************************************************************
@ -313,9 +328,9 @@ void macvail_state::maclc3_base(machine_config &config)
nubus_device &nubus(NUBUS(config, "pds", 0));
nubus.set_space(m_maincpu, AS_PROGRAM);
// LC III style PDS cards have slot IRQs $C, $D, and $E connected
nubus.out_irqc_callback().set(m_sonora, FUNC(sonora_device::slot_irq_w<0x08>));
nubus.out_irqd_callback().set(m_sonora, FUNC(sonora_device::slot_irq_w<0x10>));
nubus.out_irqe_callback().set(m_sonora, FUNC(sonora_device::slot_irq_w<0x20>));
nubus.out_irqc_callback().set(m_sonora, FUNC(sonora_device::slot0_irq_w));
nubus.out_irqd_callback().set(m_sonora, FUNC(sonora_device::slot1_irq_w));
nubus.out_irqe_callback().set(m_sonora, FUNC(sonora_device::slot2_irq_w));
NUBUS_SLOT(config, "lcpds", "pds", mac_pdslc_cards, nullptr);
MACADB(config, m_macadb, C15M);
@ -325,6 +340,7 @@ void macvail_state::maclc3(machine_config &config)
{
maclc3_base(config);
m_maincpu->set_addrmap(AS_PROGRAM, &macvail_state::maclc3_map);
m_maincpu->set_fpu_enable(false); // this machine has no FPU
EGRET(config, m_egret, XTAL(32'768));
m_egret->set_default_bios_tag("341s0851");

View File

@ -0,0 +1,300 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/*
Apple pseudo-VIA device
Emulation by R. Belmont
A "pseudo-VIA" is a 2-port GPIO interface and interrupt controller
with a 6522 compatible-ish register layout. The 6522's timers,
shift register, and data direction registers are all missing.
This first appeared in the Mac IIci's RBV chip, and also showed
up in V8/Eagle/Spice/Tinker Bell, Sonora/Ardbeg, and VASP.
Quadras used a fairly different pseudo-VIA that acts
much closer to a "real" VIA. (And a real 6522 in the
Quadra 700/900/950).
*/
#include "emu.h"
#include "pseudovia.h"
#define LOG_IRQ (1U << 1)
#define VERBOSE (0)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(APPLE_PSEUDOVIA, pseudovia_device, "pseudovia", "Apple pseudo-VIA")
pseudovia_device::pseudovia_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, APPLE_PSEUDOVIA, tag, owner, clock),
m_write_irq(*this),
m_in_a_handler(*this, 0),
m_in_b_handler(*this, 0),
m_in_config_handler(*this, 0),
m_in_video_handler(*this, 0),
m_out_a_handler(*this),
m_out_b_handler(*this),
m_out_config_handler(*this),
m_out_video_handler(*this)
{
}
void pseudovia_device::device_start()
{
save_item(NAME(m_pseudovia_regs));
save_item(NAME(m_pseudovia_ier));
save_item(NAME(m_pseudovia_ifr));
m_pseudovia_ier = m_pseudovia_ifr = 0;
}
void pseudovia_device::device_reset()
{
std::fill_n(m_pseudovia_regs, 256, 0);
m_pseudovia_regs[2] = 0x7f;
}
void pseudovia_device::vbl_irq_w(int state)
{
if (!state)
{
return;
}
m_pseudovia_regs[2] &= ~0x40; // set vblank signal
if (m_pseudovia_regs[0x12] & 0x40)
{
pseudovia_recalc_irqs();
}
}
template <u8 mask>
void pseudovia_device::slot_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~mask;
}
else
{
m_pseudovia_regs[2] |= mask;
}
pseudovia_recalc_irqs();
}
template void pseudovia_device::slot_irq_w<0x40>(int state);
template void pseudovia_device::slot_irq_w<0x20>(int state);
template void pseudovia_device::slot_irq_w<0x10>(int state);
template void pseudovia_device::slot_irq_w<0x08>(int state);
template void pseudovia_device::slot_irq_w<0x04>(int state);
template void pseudovia_device::slot_irq_w<0x02>(int state);
template void pseudovia_device::slot_irq_w<0x01>(int state);
void pseudovia_device::asc_irq_w(int state)
{
if (state == ASSERT_LINE)
{
m_pseudovia_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt
pseudovia_recalc_irqs();
}
else
{
m_pseudovia_regs[3] &= ~0x10;
pseudovia_recalc_irqs();
}
}
void pseudovia_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;
LOGMASKED(LOG_IRQ, "%s: slot_irqs %02x IFR %02x\n", slot_irqs, ifr);
if (ifr != 0)
{
m_pseudovia_regs[3] = ifr | 0x80;
m_pseudovia_ifr = ifr | 0x80;
m_write_irq(ASSERT_LINE);
}
else
{
m_write_irq(CLEAR_LINE);
}
}
uint8_t pseudovia_device::read(offs_t offset)
{
u8 data = 0;
if (offset < 0x100)
{
data = m_pseudovia_regs[offset];
if (offset == 0)
{
data = m_in_b_handler();
}
if (offset == 1)
{
data = m_in_config_handler();
}
if (offset == 0x10)
{
data &= ~0x38;
data |= m_in_video_handler();
}
// 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 1: // Port A
data = m_in_a_handler();
break;
case 13: // IFR
data = m_pseudovia_ifr;
break;
case 14: // IER
data = m_pseudovia_ier;
break;
default:
LOG("pseudovia_r: Unknown pseudo-VIA register %d access\n", offset);
break;
}
}
return data;
}
void pseudovia_device::write(offs_t offset, uint8_t data)
{
if (offset < 0x100)
{
switch (offset)
{
case 0x00:
m_out_b_handler(data);
break;
case 0x01:
m_out_config_handler(data);
break;
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;
m_out_video_handler(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 1: // Port A
m_out_a_handler(data);
break;
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:
LOG("pseudovia_w: Unknown extended pseudo-VIA register %d access\n", offset);
break;
}
}
}

View File

@ -0,0 +1,51 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
#ifndef MAME_APPLE_PSEUDOVIA_H
#define MAME_APPLE_PSEUDOVIA_H
#pragma once
class pseudovia_device : public device_t
{
public:
pseudovia_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// interface routines
auto readpa_handler() { return m_in_a_handler.bind(); }
auto readpb_handler() { return m_in_b_handler.bind(); }
auto readconfig_handler() { return m_in_config_handler.bind(); }
auto readvideo_handler() { return m_in_video_handler.bind(); }
auto writepa_handler() { return m_out_a_handler.bind(); }
auto writepb_handler() { return m_out_b_handler.bind(); }
auto writeconfig_handler() { return m_out_config_handler.bind(); }
auto writevideo_handler() { return m_out_video_handler.bind(); }
auto irq_callback() { return m_write_irq.bind(); }
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
template <u8 mask> void slot_irq_w(int state);
void vbl_irq_w(int state);
void scc_irq_w(int state);
void asc_irq_w(int state);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
devcb_write_line m_write_irq;
devcb_read8 m_in_a_handler, m_in_b_handler, m_in_config_handler, m_in_video_handler;
devcb_write8 m_out_a_handler, m_out_b_handler, m_out_config_handler, m_out_video_handler;
uint8_t m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr;
void pseudovia_recalc_irqs();
};
// device type definition
DECLARE_DEVICE_TYPE(APPLE_PSEUDOVIA, pseudovia_device)
#endif // MAME_APPLE_PSEUDOVIA_H

View File

@ -47,7 +47,7 @@ ioport_constructor rbv_device::device_input_ports() const
void rbv_device::map(address_map &map)
{
map(0x00000000, 0x00000007).rw(FUNC(rbv_device::dac_r), FUNC(rbv_device::dac_w)).mirror(0x00f00000);
map(0x00002000, 0x00003fff).rw(FUNC(rbv_device::pseudovia_r), FUNC(rbv_device::pseudovia_w)).mirror(0x00f00000);
map(0x00002000, 0x00003fff).rw(m_pseudovia, FUNC(pseudovia_device::read), FUNC(pseudovia_device::write)).mirror(0x00f00000);
}
//-------------------------------------------------
@ -61,10 +61,15 @@ void rbv_device::device_add_mconfig(machine_config &config)
m_screen->set_size(1024, 768);
m_screen->set_visarea(0, 640 - 1, 0, 480 - 1);
m_screen->set_screen_update(FUNC(rbv_device::screen_update));
m_screen->screen_vblank().set(FUNC(rbv_device::slot_irq_w<0x40>));
m_screen->screen_vblank().set(m_pseudovia, FUNC(pseudovia_device::slot_irq_w<0x40>));
config.set_default_layout(layout_monitors);
PALETTE(config, m_palette).set_entries(256);
APPLE_PSEUDOVIA(config, m_pseudovia, C15M);
m_pseudovia->readvideo_handler().set(FUNC(rbv_device::via2_video_config_r));
m_pseudovia->writevideo_handler().set(FUNC(rbv_device::via2_video_config_w));
m_pseudovia->irq_callback().set(FUNC(rbv_device::via2_irq_w));
}
//-------------------------------------------------
@ -77,7 +82,8 @@ rbv_device::rbv_device(const machine_config &mconfig, const char *tag, device_t
write_irq(*this),
m_montype(*this, "MONTYPE"),
m_screen(*this, "screen"),
m_palette(*this, "palette")
m_palette(*this, "palette"),
m_pseudovia(*this, "pseudovia")
{
}
@ -90,13 +96,9 @@ void rbv_device::device_start()
m_6015_timer = timer_alloc(FUNC(rbv_device::mac_6015_tick), this);
m_6015_timer->adjust(attotime::never);
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));
m_pseudovia_ier = m_pseudovia_ifr = 0;
m_pal_address = m_pal_idx = 0;
}
@ -108,16 +110,6 @@ void rbv_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_pseudovia_ier = 0;
m_pseudovia_ifr = 0;
m_pseudovia_regs[0x10] = 0x40; // video off
}
void rbv_device::set_ram_info(u32 *ram, u32 size)
@ -135,16 +127,7 @@ TIMER_CALLBACK_MEMBER(rbv_device::mac_6015_tick)
template <u8 mask>
void rbv_device::slot_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~mask;
}
else
{
m_pseudovia_regs[2] |= mask;
}
pseudovia_recalc_irqs();
m_pseudovia->slot_irq_w<mask>(state);
}
template void rbv_device::slot_irq_w<0x40>(int state);
@ -157,16 +140,7 @@ template void rbv_device::slot_irq_w<0x01>(int state);
void rbv_device::asc_irq_w(int state)
{
if (state == ASSERT_LINE)
{
m_pseudovia_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt
pseudovia_recalc_irqs();
}
else
{
m_pseudovia_regs[3] &= ~0x10;
pseudovia_recalc_irqs();
}
m_pseudovia->asc_irq_w(state);
}
void rbv_device::pseudovia_recalc_irqs()
@ -199,6 +173,21 @@ void rbv_device::pseudovia_recalc_irqs()
}
}
u8 rbv_device::via2_video_config_r()
{
return m_montype->read() << 3;
}
void rbv_device::via2_video_config_w(u8 data)
{
m_video_config = data;
}
void rbv_device::via2_irq_w(int state)
{
write_irq(state);
}
uint8_t rbv_device::pseudovia_r(offs_t offset)
{
int data = 0;
@ -403,7 +392,7 @@ u32 rbv_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const
}
// video disabled?
if (m_pseudovia_regs[0x10] & 0x40)
if (m_video_config & 0x40)
{
bitmap.fill(0, cliprect);
return 0;
@ -411,7 +400,7 @@ u32 rbv_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const
const pen_t *pens = m_palette->pens();
switch (m_pseudovia_regs[0x10] & 7)
switch (m_video_config & 7)
{
case 0: // 1bpp
{

View File

@ -6,6 +6,8 @@
#pragma once
#include "pseudovia.h"
#include "emupal.h"
#include "screen.h"
@ -45,17 +47,23 @@ private:
required_ioport m_montype;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<pseudovia_device> m_pseudovia;
emu_timer *m_6015_timer;
u8 m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr;
u8 m_pal_address, m_pal_idx;
u32 *m_ram_ptr;
u32 m_ram_size;
u8 m_video_config;
uint8_t pseudovia_r(offs_t offset);
void pseudovia_w(offs_t offset, uint8_t data);
void pseudovia_recalc_irqs();
u8 via2_video_config_r();
void via2_video_config_w(u8 data);
void via2_irq_w(int state);
TIMER_CALLBACK_MEMBER(mac_6015_tick);
u8 dac_r(offs_t offset);

View File

@ -53,7 +53,7 @@ void sonora_device::map(address_map &map)
map(0x10000000, 0x10001fff).rw(FUNC(sonora_device::mac_via_r), FUNC(sonora_device::mac_via_w)).mirror(0x00fc0000);
map(0x10014000, 0x10015fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write)).mirror(0x00f00000);
map(0x10016000, 0x10017fff).rw(FUNC(sonora_device::swim_r), FUNC(sonora_device::swim_w)).mirror(0x00f00000);
map(0x10026000, 0x10027fff).rw(FUNC(sonora_device::pseudovia_r), FUNC(sonora_device::pseudovia_w)).mirror(0x00f00000);
map(0x10026000, 0x10027fff).rw(m_pseudovia, FUNC(pseudovia_device::read), FUNC(pseudovia_device::write)).mirror(0x00f00000);
map(0x10f24000, 0x10f24003).rw(m_video, FUNC(mac_video_sonora_device::dac_r), FUNC(mac_video_sonora_device::dac_w));
map(0x10f28000, 0x10f28007).rw(m_video, FUNC(mac_video_sonora_device::vctrl_r), FUNC(mac_video_sonora_device::vctrl_w));
@ -67,7 +67,7 @@ void sonora_device::map(address_map &map)
void sonora_device::device_add_mconfig(machine_config &config)
{
MAC_VIDEO_SONORA(config, m_video);
m_video->screen_vblank().set(FUNC(sonora_device::slot_irq_w<0x40>));
m_video->screen_vblank().set(m_pseudovia, FUNC(pseudovia_device::slot_irq_w<0x40>));
R65NC22(config, m_via1, C7M / 10);
m_via1->readpa_handler().set(FUNC(sonora_device::via_in_a));
@ -77,11 +77,13 @@ void sonora_device::device_add_mconfig(machine_config &config)
m_via1->cb2_handler().set(FUNC(sonora_device::via_out_cb2));
m_via1->irq_handler().set(FUNC(sonora_device::via1_irq));
APPLE_PSEUDOVIA(config, m_pseudovia, C15M);
m_pseudovia->irq_callback().set(FUNC(sonora_device::via2_irq));
ASC(config, m_asc, C15M, asc_device::asc_type::SONORA);
m_asc->add_route(0, tag(), 1.0);
m_asc->add_route(1, tag(), 1.0);
m_asc->irqf_callback().set(FUNC(sonora_device::asc_irq));
m_asc->irqf_callback().set(m_pseudovia, FUNC(pseudovia_device::asc_irq_w));
SWIM2(config, m_fdc, C15M);
m_fdc->devsel_cb().set(FUNC(sonora_device::devsel_w));
@ -105,6 +107,7 @@ sonora_device::sonora_device(const machine_config &mconfig, const char *tag, dev
m_maincpu(*this, finder_base::DUMMY_TAG),
m_video(*this, "sonora_video"),
m_via1(*this, "via1"),
m_pseudovia(*this, "pseudovia"),
m_asc(*this, "asc"),
m_fdc(*this, "fdc"),
m_floppy(*this, "fdc:%d", 0U),
@ -133,15 +136,10 @@ void sonora_device::device_start()
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_hdsel));
m_rom_ptr = &m_rom[0];
m_rom_size = m_rom.length() << 2;
m_pseudovia_ier = m_pseudovia_ifr = 0;
}
//-------------------------------------------------
@ -157,8 +155,6 @@ void sonora_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[2] = 0x7f;
m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
m_last_taken_interrupt = -1;
m_hdsel = 0;
@ -298,205 +294,19 @@ void sonora_device::scc_irq_w(int state)
field_interrupts();
}
template <u8 mask>
void sonora_device::slot_irq_w(int state)
void sonora_device::slot0_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~mask;
}
else
{
m_pseudovia_regs[2] |= mask;
}
pseudovia_recalc_irqs();
m_pseudovia->slot_irq_w<0x08>(state);
}
template void sonora_device::slot_irq_w<0x40>(int state);
template void sonora_device::slot_irq_w<0x20>(int state);
template void sonora_device::slot_irq_w<0x10>(int state);
template void sonora_device::slot_irq_w<0x08>(int state);
template void sonora_device::slot_irq_w<0x04>(int state);
template void sonora_device::slot_irq_w<0x02>(int state);
template void sonora_device::slot_irq_w<0x01>(int state);
void sonora_device::asc_irq(int state)
void sonora_device::slot1_irq_w(int state)
{
if (state == ASSERT_LINE)
{
m_pseudovia_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt
pseudovia_recalc_irqs();
}
else
{
m_pseudovia_regs[3] &= ~0x10;
pseudovia_recalc_irqs();
}
m_pseudovia->slot_irq_w<0x10>(state);
}
void sonora_device::pseudovia_recalc_irqs()
void sonora_device::slot2_irq_w(int state)
{
// 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 sonora_device::pseudovia_r(offs_t offset)
{
int data = 0;
if (offset < 0x100)
{
data = m_pseudovia_regs[offset];
if (offset == 0x10)
{
data &= ~0x38;
}
// 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 sonora_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;
}
}
m_pseudovia->slot_irq_w<0x20>(state);
}
void sonora_device::cb1_w(int state)

View File

@ -6,6 +6,8 @@
#pragma once
#include "pseudovia.h"
#include "machine/6522via.h"
#include "machine/applefdintf.h"
#include "machine/mv_sonora.h"
@ -40,8 +42,10 @@ public:
void cb1_w(int state);
void cb2_w(int state);
template <u8 mask> void slot_irq_w(int state);
void scc_irq_w(int state);
void slot0_irq_w(int state);
void slot1_irq_w(int state);
void slot2_irq_w(int state);
void pixel_clock_w(u32 pclk) { m_video->set_pixel_clock(pclk); }
@ -60,6 +64,7 @@ private:
required_device<cpu_device> m_maincpu;
required_device<mac_video_sonora_device> m_video;
required_device<via6522_device> m_via1;
required_device<pseudovia_device> m_pseudovia;
required_device<asc_device> m_asc;
required_device<applefdintf_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
@ -69,7 +74,6 @@ private:
sound_stream *m_stream;
emu_timer *m_6015_timer;
int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt;
uint8_t m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr;
floppy_image_device *m_cur_floppy = nullptr;
int m_hdsel;
bool m_overlay;
@ -78,10 +82,6 @@ private:
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);
@ -94,7 +94,6 @@ private:
void via_out_cb2(int state);
void via1_irq(int state);
void via2_irq(int state);
void asc_irq(int state);
TIMER_CALLBACK_MEMBER(mac_6015_tick);
void phases_w(uint8_t phases);

View File

@ -87,7 +87,7 @@ void v8_device::map(address_map &map)
map(0x500000, 0x501fff).rw(FUNC(v8_device::mac_via_r), FUNC(v8_device::mac_via_w));
map(0x514000, 0x515fff).rw(m_asc, FUNC(asc_device::read), FUNC(asc_device::write));
map(0x524000, 0x525fff).rw(FUNC(v8_device::dac_r), FUNC(v8_device::dac_w));
map(0x526000, 0x527fff).rw(FUNC(v8_device::pseudovia_r), FUNC(v8_device::pseudovia_w));
map(0x526000, 0x527fff).rw(m_pseudovia, FUNC(pseudovia_device::read), FUNC(pseudovia_device::write));
map(0x540000, 0x5bffff).rw(FUNC(v8_device::vram_r), FUNC(v8_device::vram_w));
}
@ -101,7 +101,7 @@ void v8_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_screen_update(FUNC(v8_device::screen_update));
m_screen->screen_vblank().set(FUNC(v8_device::slot_irq_w<0x40>));
m_screen->screen_vblank().set(m_pseudovia, FUNC(pseudovia_device::slot_irq_w<0x40>));
config.set_default_layout(layout_monitors);
PALETTE(config, m_palette).set_entries(256);
@ -115,9 +115,17 @@ void v8_device::device_add_mconfig(machine_config &config)
m_via1->irq_handler().set(FUNC(v8_device::via1_irq));
ASC(config, m_asc, C15M, asc_device::asc_type::V8);
m_asc->irqf_callback().set(FUNC(v8_device::asc_irq));
m_asc->irqf_callback().set(m_pseudovia, FUNC(pseudovia_device::asc_irq_w));
m_asc->add_route(0, tag(), 1.0);
m_asc->add_route(1, tag(), 1.0);
APPLE_PSEUDOVIA(config, m_pseudovia, C15M);
m_pseudovia->writepb_handler().set(FUNC(v8_device::via2_pb_w));
m_pseudovia->readconfig_handler().set(FUNC(v8_device::via2_config_r));
m_pseudovia->writeconfig_handler().set(FUNC(v8_device::via2_config_w));
m_pseudovia->readvideo_handler().set(FUNC(v8_device::via2_video_config_r));
m_pseudovia->writevideo_handler().set(FUNC(v8_device::via2_video_config_w));
m_pseudovia->irq_callback().set(FUNC(v8_device::via2_irq));
}
//-------------------------------------------------
@ -136,7 +144,9 @@ v8_device::v8_device(const machine_config &mconfig, device_type type, const char
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_asc(*this, "asc"),
m_pseudovia(*this, "pseudovia"),
m_overlay(false),
m_video_config(0),
write_pb4(*this),
write_pb5(*this),
write_cb2(*this),
@ -146,6 +156,7 @@ v8_device::v8_device(const machine_config &mconfig, device_type type, const char
m_montype(*this, "MONTYPE"),
m_via1(*this, "via1"),
m_rom(*this, finder_base::DUMMY_TAG),
m_config(0),
m_baseIs4M(false)
{
}
@ -168,16 +179,14 @@ void v8_device::device_start()
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_config));
save_item(NAME(m_video_config));
save_item(NAME(m_overlay));
m_pseudovia_ier = m_pseudovia_ifr = 0;
m_pal_address = m_pal_idx = m_pal_control = m_pal_colkey = 0;
}
@ -190,13 +199,6 @@ void v8_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_pseudovia_ier = 0;
m_pseudovia_ifr = 0;
m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
m_last_taken_interrupt = -1;
@ -322,230 +324,35 @@ void v8_device::scc_irq_w(int state)
field_interrupts();
}
template <u8 mask>
void v8_device::slot_irq_w(int state)
void v8_device::slot2_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~mask;
}
else
{
m_pseudovia_regs[2] |= mask;
}
pseudovia_recalc_irqs();
m_pseudovia->slot_irq_w<0x20>(state);
}
template void v8_device::slot_irq_w<0x40>(int state);
template void v8_device::slot_irq_w<0x20>(int state);
template void v8_device::slot_irq_w<0x10>(int state);
template void v8_device::slot_irq_w<0x08>(int state);
template void v8_device::slot_irq_w<0x04>(int state);
template void v8_device::slot_irq_w<0x02>(int state);
template void v8_device::slot_irq_w<0x01>(int state);
void v8_device::asc_irq(int state)
u8 v8_device::via2_config_r()
{
if (state == ASSERT_LINE)
{
m_pseudovia_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt
pseudovia_recalc_irqs();
}
else
{
m_pseudovia_regs[3] &= ~0x10;
pseudovia_recalc_irqs();
}
return m_config | 0x04;
}
void v8_device::pseudovia_recalc_irqs()
void v8_device::via2_config_w(u8 data)
{
// check slot interrupts and bubble them down to IFR
u8 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
}
u8 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);
}
m_config = data;
ram_size(data);
}
u8 v8_device::pseudovia_r(offs_t offset)
u8 v8_device::via2_video_config_r()
{
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;
return m_montype->read() << 3;
}
void v8_device::pseudovia_w(offs_t offset, u8 data)
void v8_device::via2_video_config_w(u8 data)
{
if (offset < 0x100)
{
switch (offset)
{
case 0x00: // 24/32 bit switch in bit 3 (&8)
write_hmmu_enable(BIT(data, 3));
break;
m_video_config = data;
}
/* V8 config:
bit 0 = Apple II mode (4bpp 560x384) (TODO)
bit 1 = 512Row
bit 2 = VRAM present
bits 3-4 = always read 0, can't write
bit 5 = bank B (motherboard soldered) size, 0 = 4MB, 1 = 2MB
bits 6-7 = bank A (SIMM) size,
0 = 0MB
1 = 2MB
2 = 4MB
3 = 8MB
*/
case 0x01:
if (m_pseudovia_regs[offset] != data)
{
ram_size(data);
}
m_pseudovia_regs[offset] = data | 0x04; // we always have VRAM
break;
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;
}
}
void v8_device::via2_pb_w(u8 data)
{
write_hmmu_enable(BIT(data, 3));
}
void v8_device::ram_size(u8 config)
@ -765,7 +572,7 @@ u32 v8_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const
const pen_t *pens = m_palette->pens();
switch (m_pseudovia_regs[0x10] & 7)
switch (m_video_config & 7)
{
case 0: // 1bpp
{
@ -889,7 +696,9 @@ void eagle_device::device_add_mconfig(machine_config &config)
ASC(config.replace(), m_asc, C15M, asc_device::asc_type::EAGLE);
m_asc->add_route(0, tag(), 1.0);
m_asc->add_route(1, tag(), 1.0);
m_asc->irqf_callback().set(FUNC(eagle_device::asc_irq));
m_asc->irqf_callback().set(m_pseudovia, FUNC(pseudovia_device::asc_irq_w));
m_pseudovia->readvideo_handler().set(FUNC(eagle_device::via2_video_config_r));
}
eagle_device::eagle_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@ -902,17 +711,9 @@ u8 eagle_device::via_in_a()
return 0x93;
}
u8 eagle_device::pseudovia_r(offs_t offset)
u8 eagle_device::via2_video_config_r()
{
if (offset < 0x100)
{
if (offset == 0x10)
{
return 0;
}
}
return v8_device::pseudovia_r(offset);
return 0;
}
u32 eagle_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -970,7 +771,7 @@ void spice_device::device_add_mconfig(machine_config &config)
ASC(config.replace(), m_asc, C15M, asc_device::asc_type::SONORA);
m_asc->add_route(0, tag(), 1.0);
m_asc->add_route(1, tag(), 1.0);
m_asc->irqf_callback().set(FUNC(spice_device::asc_irq));
m_asc->irqf_callback().set(m_pseudovia, FUNC(pseudovia_device::asc_irq_w));
SWIM2(config, m_fdc, C15M);
m_fdc->devsel_cb().set(FUNC(spice_device::devsel_w));
@ -978,6 +779,8 @@ void spice_device::device_add_mconfig(machine_config &config)
applefdintf_device::add_35_hd(config, m_floppy[0]);
applefdintf_device::add_35_nc(config, m_floppy[1]);
m_pseudovia->readvideo_handler().set(FUNC(spice_device::via2_video_config_r));
}
spice_device::spice_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
@ -1006,17 +809,9 @@ u8 spice_device::via_in_a()
return 0x83;
}
u8 spice_device::pseudovia_r(offs_t offset)
u8 spice_device::via2_video_config_r()
{
if (offset < 0x100)
{
if (offset == 0x10)
{
return 0x02<<3;
}
}
return v8_device::pseudovia_r(offset);
return 0x02 << 3;
}
u32 spice_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -1026,7 +821,7 @@ u32 spice_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, con
vres = 384;
const pen_t *pens = m_palette->pens();
switch (m_pseudovia_regs[0x10] & 7)
switch (m_video_config & 7)
{
case 0: // 1bpp
{
@ -1191,6 +986,8 @@ void tinkerbell_device::device_add_mconfig(machine_config &config)
{
spice_device::device_add_mconfig(config);
m_screen->set_raw(25175000, 800, 0, 640, 525, 0, 480);
m_pseudovia->readvideo_handler().set(FUNC(tinkerbell_device::via2_video_config_r));
}
tinkerbell_device::tinkerbell_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@ -1203,17 +1000,9 @@ u8 tinkerbell_device::via_in_a()
return 0x84;
}
u8 tinkerbell_device::pseudovia_r(offs_t offset)
u8 tinkerbell_device::via2_video_config_r()
{
if (offset < 0x100)
{
if (offset == 0x10)
{
return 0x06 << 3; // ID as an Apple 13" 640x480 monitor
}
}
return v8_device::pseudovia_r(offset);
return 0x06 << 3; // ID as an Apple 13" 640x480 monitor
}
u32 tinkerbell_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -1223,7 +1012,7 @@ u32 tinkerbell_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap
vres = 480;
const pen_t *pens = m_palette->pens();
switch (m_pseudovia_regs[0x10] & 7)
switch (m_video_config & 7)
{
case 0: // 1bpp
{

View File

@ -6,6 +6,8 @@
#pragma once
#include "pseudovia.h"
#include "machine/6522via.h"
#include "machine/applefdintf.h"
#include "machine/swim2.h"
@ -40,19 +42,21 @@ public:
void cb2_w(int state);
template <u8 mask> void slot_irq_w(int state);
void scc_irq_w(int state);
void slot2_irq_w(int state);
protected:
required_device<cpu_device> m_maincpu;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<asc_device> m_asc;
required_device<pseudovia_device> m_pseudovia;
std::unique_ptr<u32 []> m_vram;
u8 m_pseudovia_regs[256];
u32 *m_ram_ptr;
u32 m_ram_size;
bool m_overlay;
u8 m_video_config;
v8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
@ -64,10 +68,6 @@ protected:
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
virtual u8 pseudovia_r(offs_t offset);
void asc_irq(int state);
virtual void ram_size(u8 config);
private:
@ -81,15 +81,17 @@ private:
sound_stream *m_stream;
emu_timer *m_6015_timer;
int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt;
u8 m_pseudovia_ier, m_pseudovia_ifr;
u8 m_pal_address, m_pal_idx, m_pal_control, m_pal_colkey;
u8 m_pal_address, m_pal_idx, m_pal_control, m_pal_colkey, m_config;
bool m_baseIs4M;
u32 rom_switch_r(offs_t offset);
void pseudovia_w(offs_t offset, u8 data);
void pseudovia_recalc_irqs();
void via2_pb_w(u8 data);
u8 via2_config_r();
void via2_config_w(u8 data);
u8 via2_video_config_r();
void via2_video_config_w(u8 data);
u16 mac_via_r(offs_t offset);
void mac_via_w(offs_t offset, u16 data, u16 mem_mask);
@ -126,7 +128,7 @@ protected:
private:
u8 via_in_a() override;
u8 pseudovia_r(offs_t offset) override;
u8 via2_video_config_r();
virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
};
@ -158,7 +160,7 @@ private:
virtual u8 via_in_a() override;
virtual void via_out_a(u8 data) override;
virtual u8 pseudovia_r(offs_t offset) override;
u8 via2_video_config_r();
virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
u16 swim_r(offs_t offset, u16 mem_mask);
@ -181,7 +183,7 @@ protected:
private:
virtual u8 via_in_a() override;
virtual u8 pseudovia_r(offs_t offset) override;
u8 via2_video_config_r();
virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
};

View File

@ -56,7 +56,7 @@ void vasp_device::map(address_map &map)
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(0x10026000, 0x10027fff).rw(m_pseudovia, FUNC(pseudovia_device::read), FUNC(pseudovia_device::write)).mirror(0x00f00000);
map(0x20000000, 0x200fffff).ram().mirror(0x0ff00000).rw(FUNC(vasp_device::vram_r), FUNC(vasp_device::vram_w));
}
@ -72,7 +72,7 @@ void vasp_device::device_add_mconfig(machine_config &config)
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));
m_screen->screen_vblank().set(m_pseudovia, FUNC(pseudovia_device::vbl_irq_w));
config.set_default_layout(layout_monitors);
PALETTE(config, m_palette).set_entries(256);
@ -85,10 +85,15 @@ void vasp_device::device_add_mconfig(machine_config &config)
m_via1->cb2_handler().set(FUNC(vasp_device::via_out_cb2));
m_via1->irq_handler().set(FUNC(vasp_device::via1_irq));
APPLE_PSEUDOVIA(config, m_pseudovia, C15M);
m_pseudovia->readvideo_handler().set(FUNC(vasp_device::via2_video_config_r));
m_pseudovia->writevideo_handler().set(FUNC(vasp_device::via2_video_config_w));
m_pseudovia->irq_callback().set(FUNC(vasp_device::via2_irq));
ASC(config, m_asc, C15M, asc_device::asc_type::VASP);
m_asc->add_route(0, tag(), 1.0);
m_asc->add_route(1, tag(), 1.0);
m_asc->irqf_callback().set(FUNC(vasp_device::asc_irq));
m_asc->irqf_callback().set(m_pseudovia, FUNC(pseudovia_device::asc_irq_w));
}
//-------------------------------------------------
@ -108,9 +113,11 @@ vasp_device::vasp_device(const machine_config &mconfig, const char *tag, device_
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_via1(*this, "via1"),
m_pseudovia(*this, "pseudovia"),
m_asc(*this, "asc"),
m_rom(*this, finder_base::DUMMY_TAG),
m_overlay(false)
m_overlay(false),
m_video_config(0)
{
}
@ -132,19 +139,16 @@ void vasp_device::device_start()
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));
save_item(NAME(m_video_config));
m_rom_ptr = &m_rom[0];
m_rom_size = m_rom.length() << 2;
m_pseudovia_ier = m_pseudovia_ifr = 0;
m_pal_address = m_pal_idx = m_pal_control = m_pal_colkey = 0;
}
@ -157,13 +161,6 @@ 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_pseudovia_ier = 0;
m_pseudovia_ifr = 0;
m_via_interrupt = m_via2_interrupt = m_scc_interrupt = 0;
m_last_taken_interrupt = -1;
@ -294,240 +291,29 @@ void vasp_device::scc_irq_w(int state)
field_interrupts();
}
void vasp_device::vbl_w(int state)
{
if (!state)
{
return;
}
m_pseudovia_regs[2] &= ~0x40; // set vblank signal
if (m_pseudovia_regs[0x12] & 0x40)
{
pseudovia_recalc_irqs();
}
}
void vasp_device::slot0_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~0x08;
}
else
{
m_pseudovia_regs[2] |= 0x08;
}
pseudovia_recalc_irqs();
m_pseudovia->slot_irq_w<0x08>(state);
}
void vasp_device::slot1_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~0x10;
}
else
{
m_pseudovia_regs[2] |= 0x10;
}
pseudovia_recalc_irqs();
m_pseudovia->slot_irq_w<0x10>(state);
}
void vasp_device::slot2_irq_w(int state)
{
if (state)
{
m_pseudovia_regs[2] &= ~0x20;
}
else
{
m_pseudovia_regs[2] |= 0x20;
}
pseudovia_recalc_irqs();
m_pseudovia->slot_irq_w<0x20>(state);
}
void vasp_device::asc_irq(int state)
u8 vasp_device::via2_video_config_r()
{
if (state == ASSERT_LINE)
{
m_pseudovia_regs[3] |= 0x10; // any VIA 2 interrupt | sound interrupt
pseudovia_recalc_irqs();
}
else
{
m_pseudovia_regs[3] &= ~0x10;
pseudovia_recalc_irqs();
}
return m_montype->read() << 3;
}
void vasp_device::pseudovia_recalc_irqs()
void vasp_device::via2_video_config_w(u8 data)
{
// 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;
}
}
m_video_config = data;
}
void vasp_device::cb1_w(int state)
@ -677,7 +463,7 @@ u32 vasp_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, cons
const pen_t *pens = m_palette->pens();
switch (m_pseudovia_regs[0x10] & 7)
switch (m_video_config & 7)
{
case 0: // 1bpp
{

View File

@ -6,6 +6,8 @@
#pragma once
#include "pseudovia.h"
#include "machine/6522via.h"
#include "sound/asc.h"
#include "emupal.h"
@ -40,7 +42,6 @@ public:
void cb1_w(int state);
void cb2_w(int state);
void vbl_w(int state);
void scc_irq_w(int state);
void slot0_irq_w(int state);
void slot1_irq_w(int state);
@ -64,6 +65,7 @@ private:
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<via6522_device> m_via1;
required_device<pseudovia_device> m_pseudovia;
required_device<asc_device> m_asc;
required_region_ptr<u32> m_rom;
@ -71,17 +73,16 @@ private:
sound_stream *m_stream;
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;
u8 m_video_config;
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();
u8 via2_video_config_r();
void via2_video_config_w(u8 data);
uint16_t mac_via_r(offs_t offset);
void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask);