machine/applepic.cpp: Cleaned up IRQ handling, finished and tested DMA. [R. Belmont]

machine/swim1.cpp: Cleaned up DAT1BYTE output handling, added timer so the disk spins when you aren't polling it. [R. Belmont]

machine/swim2.cpp: Cleaned up DAT1BYTE output handling. [R. Belmont]

apple/dafb.cpp: Added support for the Quadra 950's standalone DAFB II with 16-bit color. [R. Belmont]

apple/macadb.cpp: Major cleanup, removed ADB modem HLE, now echoes ADB line state changes so everyone stays in sync. [R. Belmont]

apple/maciifx.cpp: Cleanup/modernization and corrected SWIM hookup for IOP control. Now can boot floppies. [R. Belmont]

apple/macquadra700.cpp: Cleanup/modernization and added the Quadra 900 and 950. [R. Belmont]

New WORKING machines
--------------------
Macintosh Quadra 900 [R. Belmont]
Macintosh Quadra 950 [R. Belmont]
This commit is contained in:
arbee 2024-07-03 16:57:54 -04:00
parent ab2451cb8d
commit a97c06e24c
13 changed files with 1260 additions and 951 deletions

View File

@ -19,6 +19,18 @@ DEFINE_DEVICE_TYPE(APPLEPIC, applepic_device, "applepic", "Apple 343S1021 PIC")
const std::string_view applepic_device::s_interrupt_names[8] = { "0", "DMA 1", "DMA 2", "peripheral", "host", "timer", "6", "7" };
static constexpr int IRQ_DMA1 = 1;
static constexpr int IRQ_DMA2 = 2;
static constexpr int IRQ_PERIPHERAL = 3;
static constexpr int IRQ_HOST = 4;
static constexpr int IRQ_TIMER = 5;
static constexpr u8 DMAEN = 0x01; // 1 = channel enabled
static constexpr u8 DREQ = 0x02; // 1 = DREQ line for this channel is active
static constexpr u8 DMADIR = 0x04; // 1 = I/O to RAM, 0 = RAM to I/O
static constexpr u8 DENxONx = 0x08; // 1 = enable this channel when the other channel completes a transfer
static constexpr int DIOASHIFT = 0x04; // right shift amount for I/O offset bits
applepic_device::applepic_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, APPLEPIC, tag, owner, clock)
, m_iopcpu(*this, "iopcpu")
@ -28,6 +40,7 @@ applepic_device::applepic_device(const machine_config &mconfig, const char *tag,
, m_gpin_callback(*this, 0)
, m_gpout_callback(*this)
, m_timer1(nullptr)
, m_dma_timer(nullptr)
, m_timer_last_expired(attotime::zero)
, m_ram_address(0)
, m_status_reg(0x80)
@ -43,6 +56,7 @@ applepic_device::applepic_device(const machine_config &mconfig, const char *tag,
channel.control = 0;
channel.map = 0;
channel.tc = 0;
channel.req = false;
}
}
@ -73,6 +87,9 @@ void applepic_device::device_start()
// Initialize timer
m_timer1 = timer_alloc(FUNC(applepic_device::timer1_callback), this);
// get a timer for the DMA
m_dma_timer = timer_alloc(FUNC(applepic_device::dma_timer_callback), this);
// Save internal state
save_item(NAME(m_timer_last_expired));
save_item(NAME(m_ram_address));
@ -96,6 +113,13 @@ void applepic_device::device_reset()
m_iopcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_iopcpu->set_input_line(r65c02_device::IRQ_LINE, CLEAR_LINE);
m_hint_callback(CLEAR_LINE);
for (dma_channel &channel : m_dma_channel)
{
channel.control = 0;
}
m_dma_timer->adjust(attotime::zero, 0, clocks_to_attotime(8));
}
u8 applepic_device::host_r(offs_t offset)
@ -154,7 +178,7 @@ void applepic_device::host_w(offs_t offset, u8 data)
m_iopcpu->set_input_line(INPUT_LINE_RESET, BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE);
}
if (BIT(data, 3))
set_interrupt(4);
set_interrupt(IRQ_HOST);
if ((m_status_reg & data & 0x30) != 0)
{
m_status_reg &= ~(data & 0x30);
@ -178,30 +202,40 @@ void applepic_device::pint_w(int state)
{
m_status_reg |= 0x40;
if (!BIT(m_scc_control, 0))
set_interrupt(3);
set_interrupt(IRQ_PERIPHERAL);
}
else
{
m_status_reg &= 0xbf;
if (!BIT(m_scc_control, 0))
reset_interrupt(3);
reset_interrupt(IRQ_PERIPHERAL);
}
}
void applepic_device::reqa_w(int state)
{
if (state == ASSERT_LINE)
m_dma_channel[0].control |= 0x02;
m_dma_channel[0].req = state;
if (state)
{
m_dma_channel[0].control |= DREQ;
}
else
m_dma_channel[0].control &= 0xfd;
{
m_dma_channel[0].control &= ~DREQ;
}
}
void applepic_device::reqb_w(int state)
{
if (state == ASSERT_LINE)
m_dma_channel[1].control |= 0x02;
m_dma_channel[1].req = state;
if (state)
{
m_dma_channel[1].control |= DREQ;
}
else
m_dma_channel[1].control &= 0xfd;
{
m_dma_channel[1].control &= ~DREQ;
}
}
u8 applepic_device::timer_r(offs_t offset)
@ -212,7 +246,7 @@ u8 applepic_device::timer_r(offs_t offset)
else
{
if (offset == 0 && !machine().side_effects_disabled())
reset_interrupt(5);
reset_interrupt(IRQ_TIMER);
return reg & 0x00ff;
}
}
@ -224,7 +258,7 @@ void applepic_device::timer_w(offs_t offset, u8 data)
m_timer_latch = u16(data) << 8 | (m_timer_latch & 0x00ff);
if (offset == 1)
{
reset_interrupt(5);
reset_interrupt(IRQ_TIMER);
m_timer1->adjust(clocks_to_attotime(m_timer_latch * 8 + 12));
}
}
@ -242,7 +276,7 @@ u16 applepic_device::get_timer_count() const
TIMER_CALLBACK_MEMBER(applepic_device::timer1_callback)
{
set_interrupt(5);
set_interrupt(IRQ_TIMER);
if (BIT(m_timer_dpll_control, 0))
m_timer1->adjust(clocks_to_attotime((m_timer_latch + 2) * 8));
else
@ -284,7 +318,7 @@ void applepic_device::dma_channel_w(offs_t offset, u8 data)
switch (offset & 7)
{
case 0:
channel.control = (data & 0xfd) | (channel.control & 0x02);
channel.control = ((data & ~DREQ) | (channel.control & DREQ));
break;
case 1:
@ -300,7 +334,7 @@ void applepic_device::dma_channel_w(offs_t offset, u8 data)
break;
case 4:
channel.tc = (data & 0x07) | (channel.tc & 0x0ff);
channel.tc = ((data & 0x07) << 8) | (channel.tc & 0x0ff);
break;
default:
@ -309,6 +343,44 @@ void applepic_device::dma_channel_w(offs_t offset, u8 data)
}
}
TIMER_CALLBACK_MEMBER(applepic_device::dma_timer_callback)
{
for (int ch = 0; ch < 2; ch++)
{
auto &channel = m_dma_channel[ch];
auto other_channel = m_dma_channel[ch ^ 1];
if ((channel.control & DMAEN) && (channel.req) && (channel.tc > 0))
{
if (channel.control & DMADIR)
{
const u8 xfer = m_prd_callback(channel.control >> DIOASHIFT);
m_iopcpu->space(AS_PROGRAM).write_byte(channel.map, xfer);
}
else
{
const u8 xfer = m_iopcpu->space(AS_PROGRAM).read_byte(channel.map);
m_pwr_callback(channel.control >> DIOASHIFT, xfer);
}
channel.map++;
channel.tc--;
// if this channel completed, handle the DEN1ON2/DEN2ON1 alternating transfer bits and IRQ
if (channel.tc == 0)
{
channel.control &= ~DMAEN;
if (other_channel.control & DENxONx)
{
other_channel.control |= DMAEN;
}
set_interrupt(IRQ_DMA1 + ch);
}
}
}
}
u8 applepic_device::scc_control_r()
{
return m_scc_control;
@ -318,9 +390,9 @@ void applepic_device::scc_control_w(u8 data)
{
m_scc_control = data;
if (!BIT(data, 0) && BIT(m_status_reg, 6))
set_interrupt(3);
set_interrupt(IRQ_PERIPHERAL);
else
reset_interrupt(3);
reset_interrupt(IRQ_PERIPHERAL);
m_gpout_callback[1](BIT(data, 7));
}

View File

@ -51,12 +51,14 @@ private:
u8 control;
u16 map;
u16 tc;
bool req;
};
u8 timer_r(offs_t offset);
void timer_w(offs_t offset, u8 data);
u16 get_timer_count() const;
TIMER_CALLBACK_MEMBER(timer1_callback);
TIMER_CALLBACK_MEMBER(dma_timer_callback);
u8 dma_channel_r(offs_t offset);
void dma_channel_w(offs_t offset, u8 data);
u8 scc_control_r();
@ -89,7 +91,7 @@ private:
devcb_write_line::array<2> m_gpout_callback;
// internal state
emu_timer *m_timer1;
emu_timer *m_timer1, *m_dma_timer;
attotime m_timer_last_expired;
u16 m_ram_address;
u8 m_status_reg;

View File

@ -9,7 +9,7 @@
#include "emu.h"
#include "swim1.h"
#define VERBOSE 0
#define VERBOSE (0)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(SWIM1, swim1_device, "swim1", "Apple SWIM1 (Sander/Wozniak Integrated Machine) version 1 floppy controller")
@ -26,6 +26,8 @@ void swim1_device::device_start()
applefdintf_device::device_start();
m_timer = timer_alloc(FUNC(swim1_device::update), this);
m_sync_timer = timer_alloc(FUNC(swim1_device::ism_periodic_sync), this);
save_item(NAME(m_last_sync));
save_item(NAME(m_flux_write_start));
save_item(NAME(m_flux_write));
@ -104,7 +106,7 @@ void swim1_device::device_reset()
m_devsel_cb(0);
m_sel35_cb(true);
m_hdsel_cb(false);
m_dat1byte_cb(0);
m_dat1byte_cb(CLEAR_LINE);
}
void swim1_device::set_floppy(floppy_image_device *floppy)
@ -174,11 +176,11 @@ u8 swim1_device::ism_read(offs_t offset)
{
ism_sync();
// static const char *const names[] = {
// "data", "mark", "crc", "param", "phases", "setup", "status", "handshake"
// };
static const char *const names[] = {
"data", "mark", "crc", "param", "phases", "setup", "status", "handshake"
};
// LOG("read ism %s\n", names[offset & 7]);
LOG("read ism %s\n", names[offset & 7]);
switch(offset & 7) {
case 0x0: { // data
u16 r = ism_fifo_pop();
@ -227,9 +229,9 @@ u8 swim1_device::ism_read(offs_t offset)
if(!(m_ism_fifo[m_ism_fifo_pos - 1] & M_CRC0))
h |= 0x02;
}
// rddata on 4
// rddata on 3
if(!m_floppy || m_floppy->wpt_r())
h |= 0x08;
h |= 0x0c;
if(m_ism_error)
h |= 0x20;
if(m_ism_mode & 0x10) {
@ -249,7 +251,7 @@ u8 swim1_device::ism_read(offs_t offset)
}
default:
// logerror("read %s\n", names[offset & 7]);
logerror("read %s\n", names[offset & 7]);
break;
}
return 0xff;
@ -315,8 +317,7 @@ void swim1_device::ism_write(offs_t offset, u8 data)
m_ism_mode &= ~data;
m_ism_param_idx = 0;
ism_show_mode();
if(data & 0x10)
m_dat1byte_cb((m_ism_fifo_pos != 0) ? 1 : 0);
ism_update_dat1byte();
if(!(m_ism_mode & 0x40)) {
LOG("switch to iwm\n");
u8 ism_devsel = m_ism_mode & 0x80 ? (m_ism_mode >> 1) & 3 : 0;
@ -328,8 +329,7 @@ void swim1_device::ism_write(offs_t offset, u8 data)
case 0x7:
m_ism_mode |= data;
ism_show_mode();
if(data & 0x10)
m_dat1byte_cb((m_ism_fifo_pos != 2) ? 1 : 0);
ism_update_dat1byte();
break;
default:
@ -345,6 +345,13 @@ void swim1_device::ism_write(offs_t offset, u8 data)
if((m_ism_mode ^ prev_mode) & 0x20)
m_hdsel_cb((m_ism_mode >> 5) & 1);
if ((m_ism_mode ^ prev_mode) & 0x40) {
if (m_ism_mode & 0x40)
m_sync_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()/16));
else
m_sync_timer->adjust(attotime::never);
}
if((m_ism_mode & 0x18) == 0x18 && ((prev_mode & 0x18) != 0x18)) {
// Entering write mode
m_ism_current_bit = 0;
@ -558,9 +565,12 @@ void swim1_device::iwm_control(int offset, u8 data)
if(data & 0x40) {
m_ism_mode |= 0x40;
LOG("switch to ism\n");
u8 ism_devsel = m_ism_mode & 0x80 ? (m_ism_mode >> 1) & 3 : 0;
if(ism_devsel != m_iwm_devsel)
m_devsel_cb(ism_devsel);
m_sync_timer->adjust(attotime::zero, 0, attotime::from_hz(clock()/16));
}
break;
}
@ -607,24 +617,18 @@ attotime swim1_device::cycles_to_time(u64 cycles) const
void swim1_device::ism_fifo_clear()
{
m_ism_fifo_pos = 0;
m_dat1byte_cb((m_ism_mode & 0x10) ? 1 : 0);
ism_update_dat1byte();
ism_crc_clear();
}
bool swim1_device::ism_fifo_push(u16 data)
{
if(m_ism_fifo_pos == 2)
{
return true;
m_ism_fifo[m_ism_fifo_pos ++] = data;
if(m_ism_mode & 0x10) {
// write
if(m_ism_fifo_pos == 2)
m_dat1byte_cb(0);
} else {
// read
if(m_ism_fifo_pos == 1)
m_dat1byte_cb(1);
}
m_ism_fifo[m_ism_fifo_pos ++] = data;
ism_update_dat1byte();
return false;
}
@ -635,15 +639,7 @@ u16 swim1_device::ism_fifo_pop()
u16 r = m_ism_fifo[0];
m_ism_fifo[0] = m_ism_fifo[1];
m_ism_fifo_pos --;
if(m_ism_mode & 0x10) {
// write
if(m_ism_fifo_pos == 1)
m_dat1byte_cb(1);
} else {
// read
if(m_ism_fifo_pos == 0)
m_dat1byte_cb(0);
}
ism_update_dat1byte();
return r;
}
@ -861,6 +857,14 @@ void swim1_device::iwm_sync()
}
}
TIMER_CALLBACK_MEMBER(swim1_device::ism_periodic_sync)
{
if (m_ism_mode & 0x40)
{
ism_sync();
}
}
void swim1_device::ism_sync()
{
u64 next_sync = time_to_cycles(machine().time());
@ -1210,3 +1214,17 @@ void swim1_device::sync()
else
return iwm_sync();
}
void swim1_device::ism_update_dat1byte()
{
if (m_ism_mode & 0x10)
{
// write: Does FIFO have room?
m_dat1byte_cb((m_ism_fifo_pos < 2) ? ASSERT_LINE : CLEAR_LINE);
}
else
{
// read: is FIFO not empty?
m_dat1byte_cb((m_ism_fifo_pos > 0) ? ASSERT_LINE : CLEAR_LINE);
}
}

View File

@ -112,6 +112,9 @@ private:
u8 m_iwm_to_ism_counter;
u8 m_iwm_devsel;
emu_timer *m_sync_timer;
TIMER_CALLBACK_MEMBER(ism_periodic_sync);
u64 time_to_cycles(const attotime &tm) const;
attotime cycles_to_time(u64 cycles) const;
void flush_write(u64 when = 0);
@ -134,6 +137,7 @@ private:
u8 ism_read(offs_t offset);
void ism_write(offs_t offset, u8 data);
void ism_sync();
void ism_update_dat1byte();
};
DECLARE_DEVICE_TYPE(SWIM1, swim1_device)

View File

@ -71,7 +71,7 @@ void swim2_device::device_reset()
m_devsel_cb(0);
m_sel35_cb(true);
m_hdsel_cb(false);
m_dat1byte_cb(0);
m_dat1byte_cb(CLEAR_LINE);
m_flux_write_start = 0;
m_flux_write_count = 0;
std::fill(m_flux_write.begin(), m_flux_write.end(), 0);
@ -280,15 +280,13 @@ void swim2_device::write(offs_t offset, u8 data)
m_mode |= 0x40;
m_param_idx = 0;
show_mode();
if(data & 0x10)
m_dat1byte_cb((m_fifo_pos != 0) ? 1 : 0);
update_dat1byte();
break;
case 7: // mode set
m_mode |= data;
show_mode();
if(data & 0x10)
m_dat1byte_cb((m_fifo_pos != 2) ? 1 : 0);
update_dat1byte();
break;
default:
@ -369,7 +367,7 @@ attotime swim2_device::cycles_to_time(u64 cycles) const
void swim2_device::fifo_clear()
{
m_fifo_pos = 0;
m_dat1byte_cb((m_mode & 0x10) ? 1 : 0);
update_dat1byte();
crc_clear();
}
@ -378,15 +376,7 @@ bool swim2_device::fifo_push(u16 data)
if(m_fifo_pos == 2)
return true;
m_fifo[m_fifo_pos ++] = data;
if(m_mode & 0x10) {
// write
if(m_fifo_pos == 2)
m_dat1byte_cb(0);
} else {
// read
if(m_fifo_pos == 1)
m_dat1byte_cb(1);
}
update_dat1byte();
return false;
}
@ -397,15 +387,7 @@ u16 swim2_device::fifo_pop()
u16 r = m_fifo[0];
m_fifo[0] = m_fifo[1];
m_fifo_pos --;
if(m_mode & 0x10) {
// write
if(m_fifo_pos == 1)
m_dat1byte_cb(1);
} else {
// read
if(m_fifo_pos == 0)
m_dat1byte_cb(0);
}
update_dat1byte();
return r;
}
@ -567,3 +549,17 @@ void swim2_device::sync()
m_last_sync = next_sync;
}
void swim2_device::update_dat1byte()
{
if (m_mode & 0x10)
{
// write: Does FIFO have room?
m_dat1byte_cb((m_fifo_pos < 2) ? ASSERT_LINE : CLEAR_LINE);
}
else
{
// read: is FIFO not empty?
m_dat1byte_cb((m_fifo_pos > 0) ? ASSERT_LINE : CLEAR_LINE);
}
}

View File

@ -69,6 +69,8 @@ private:
void crc_update(int bit);
void crc_clear();
void update_dat1byte();
};
DECLARE_DEVICE_TYPE(SWIM2, swim2_device)

View File

@ -11,16 +11,20 @@
off /DTACK on pseudo-DMA reads and writes.
Shipping configurations:
DAFB - original standalone chip, Quadra 700 and 900 (returns versions 0 and 1)
DAFB II - revised standalone chip with 15 bpp support added (uses AC842a CODEC instead of AC842) (returns version 2)
DAFB - original standalone chip, Quadra 700 and 900 (returns versions 0, 1, and 2)
DAFB II - revised standalone chip with 15 bpp support added (uses AC842a CODEC instead of AC842) (returns version 3)
Used in Quadra 950.
MEMC - DAFB II without the Turbo SCSI logic, in the djMEMC and MEMCjr memory controllers. (returns version 3)
Used in LC 475, LC 575, Quadra 605, Quadra 610, Quadra 650, and Quadra 800.
This version uses a DP8534 timing generator instead of the DP8531 and an AC842a DAC instead of AC842.
Valkyrie - This video used in the LC/Performa/Quadra 630 and LC580 is stated by the developer note to be very similar to DAFB.
DaMFB - DAFB II with a PowerPC bus interface instead of 68040. Used in the HPV card for the PowerMac 6100/7100/8100.
Platinum - DAFB II with 4 MB VRAM support and a blitter bolted on.
The "Valkyrie" chip used in the LC/Performa/Quadra 630 and 580 and the Power Macintosh 5200/6200 is stated by
Apple's developer note to be "very similar" to DAFB but its register interface is entirely different.
Valkyrie implements a small set of fixed video modes that are selected by number rather than a fully programmable
CRTC as is found in DAFB.
The Turbo SCSI block moved into the IOSB and PrimeTime I/O ASICs for the machines where DAFB moved into the
memory controller. It was enhanced slightly to allow longword pseudo-DMA transfers.
@ -52,9 +56,11 @@
#define LOG_TURBOSCSI (1U << 5)
#define VERBOSE (0)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(DAFB, dafb_device, "macdafb", "Apple DAFB video")
DEFINE_DEVICE_TYPE(DAFB_Q950, dafb_q950_device, "macdafb_q950", "Apple DAFB II video")
DEFINE_DEVICE_TYPE(DAFB_MEMC, dafb_memc_device, "macdafb_djmemc", "Apple DAFB II video (djMEMC integrated)")
DEFINE_DEVICE_TYPE(DAFB_MEMCJR, dafb_memcjr_device, "macdafb_memcjr", "Apple DAFB II video (MEMCjr integrated)")
@ -94,13 +100,25 @@ dafb_base::dafb_base(const machine_config &mconfig, device_type type, const char
}
dafb_device::dafb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
dafb_base(mconfig, DAFB, tag, owner, clock),
dafb_device(mconfig, DAFB, tag, owner, clock)
{
}
dafb_device::dafb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
dafb_base(mconfig, type, tag, owner, clock),
m_maincpu(*this, finder_base::DUMMY_TAG)
{
m_drq[0] = m_drq[1] = 0;
m_ncr[0] = m_ncr[1] = nullptr;
}
dafb_q950_device::dafb_q950_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
dafb_device(mconfig, DAFB_Q950, tag, owner, clock),
m_pcbr1(0)
{
}
dafb_memc_device::dafb_memc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
dafb_base(mconfig, DAFB_MEMC, tag, owner, clock),
m_pcbr1(0),
@ -216,6 +234,11 @@ ioport_constructor dafb_base::device_input_ports() const
return INPUT_PORTS_NAME(monitor_config);
}
ioport_constructor dafb_q950_device::device_input_ports() const
{
return INPUT_PORTS_NAME(monitor_config_noconv);
}
ioport_constructor dafb_memc_device::device_input_ports() const
{
return INPUT_PORTS_NAME(monitor_config_noconv);
@ -1064,6 +1087,88 @@ void dafb_device::turboscsi_drq_w(int state)
template void dafb_device::turboscsi_drq_w<0>(int state);
template void dafb_device::turboscsi_drq_w<1>(int state);
// ************************************************************************
// dafb_q950_device overrides/additions
// ************************************************************************
void dafb_q950_device::device_start()
{
m_dafb_version = 3;
dafb_base::device_start();
}
u32 dafb_q950_device::ramdac_r(offs_t offset)
{
switch (offset << 2)
{
case 0x20:
if ((m_pal_address == 1) && ((m_ac842_pbctrl & 0x06) == 0x06))
{
LOGMASKED(LOG_RAMDAC, "Read %02x from PCBR1\n", m_pcbr1);
return m_pcbr1;
}
else
{
return dafb_base::ramdac_r(offset);
}
default:
return dafb_base::ramdac_r(offset);
}
}
void dafb_q950_device::ramdac_w(offs_t offset, u32 data)
{
switch (offset << 2)
{
case 0x20:
if ((m_pal_address == 1) && ((m_ac842_pbctrl & 0x06) == 0x06))
{
LOGMASKED(LOG_RAMDAC, "%02x to AC842a PCBR1\n", data);
m_pcbr1 = (data & 0xf0) | 0x01; // AC842a version ID
}
else
{
LOGMASKED(LOG_RAMDAC, "%02x to AC842a PCBR0, & 0x1c = %02x\n", data, data & 0x1c);
m_ac842_pbctrl = data;
if (((m_pcbr1 & 0xc0) == 0xc0) && ((data & 0x06) == 0x06))
{
m_mode = 5; // 16 bpp (x555)
}
else
{
switch (data & 0x1c)
{
case 0x00:
m_mode = 0; // 1bpp
break;
case 0x08:
m_mode = 1; // 2bpp
break;
case 0x10:
m_mode = 2; // 4bpp
break;
case 0x18:
m_mode = 3; // 8bpp
break;
case 0x1c:
m_mode = 4; // 24bpp
break;
}
}
recalc_mode();
}
break;
default:
dafb_base::ramdac_w(offset, data);
break;
}
}
// ************************************************************************
// dafb_memc_device overrides/additions
// ************************************************************************

View File

@ -101,7 +101,7 @@ private:
TIMER_CALLBACK_MEMBER(cursor_tick);
};
// Discrete DAFB: Quadra 700 & 900, includes "TurboSCSI"
// Discrete DAFB II: Quadra 950, includes "TurboSCSI"
class dafb_device: public dafb_base
{
public:
@ -120,6 +120,8 @@ public:
template <int bus> void turboscsi_dma_w(offs_t offset, u16 data, u16 mem_mask);
protected:
dafb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void device_start() override;
private:
@ -127,6 +129,22 @@ private:
ncr53c94_device *m_ncr[2];
};
class dafb_q950_device : public dafb_device
{
public:
dafb_q950_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
protected:
virtual void device_start() override;
virtual ioport_constructor device_input_ports() const override;
virtual u32 ramdac_r(offs_t offset) override;
virtual void ramdac_w(offs_t offset, u32 data) override;
private:
u8 m_pcbr1;
};
class dafb_memc_device: public dafb_base
{
public:
@ -171,6 +189,7 @@ private:
};
DECLARE_DEVICE_TYPE(DAFB, dafb_device)
DECLARE_DEVICE_TYPE(DAFB_Q950, dafb_q950_device)
DECLARE_DEVICE_TYPE(DAFB_MEMC, dafb_memc_device)
DECLARE_DEVICE_TYPE(DAFB_MEMCJR, dafb_memcjr_device)

File diff suppressed because it is too large Load Diff

View File

@ -17,25 +17,18 @@ class macadb_device : public device_t
{
public:
// construction/destruction
macadb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
macadb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
void set_mcu_mode(bool bMCUMode) { m_bIsMCUMode = bMCUMode; }
auto via_clock_callback() { return write_via_clock.bind(); }
auto via_data_callback() { return write_via_data.bind(); }
auto adb_data_callback() { return write_adb_data.bind(); }
auto adb_irq_callback() { return write_adb_irq.bind(); }
required_ioport m_mouse0, m_mouse1, m_mouse2;
required_ioport_array<8> m_keys;
devcb_write_line write_via_clock, write_via_data, write_adb_data, write_adb_irq;
devcb_write_line write_adb_data, write_adb_irq;
void adb_data_w(int state);
void adb_linechange_w(int state);
void adb_vblank();
void mac_adb_newaction(int state);
int32_t get_adb_state(void) { return m_adb_state; }
void adb_vblank() {}
protected:
// device-level overrides
@ -44,46 +37,42 @@ protected:
virtual void device_reset() override;
private:
bool m_bIsMCUMode;
uint64_t m_last_adb_time;
emu_timer *m_adb_timer;
u64 m_last_adb_time;
emu_timer *m_timer;
/* keyboard matrix to detect transition */
u16 m_key_matrix[9];
// ADB HLE state
int32_t m_adb_state, m_adb_waiting_cmd, m_adb_datasize;
int32_t m_adb_command, m_adb_send, m_adb_timer_ticks, m_adb_extclock, m_adb_direction;
int32_t m_adb_listenreg, m_adb_listenaddr, m_adb_last_talk, m_adb_srq_switch;
int32_t m_adb_stream_ptr;
int32_t m_adb_linestate;
u8 m_adb_buffer[257], m_last_kbd[2], m_last_mouse[2], m_keyboard_handler, m_mouse_handler;
bool m_adb_srqflag;
int m_adb_linein;
bool m_waiting_cmd;
s32 m_datasize;
s32 m_command, m_direction;
u8 m_listenreg, m_listenaddr;
s32 m_srq_switch, m_stream_ptr, m_linestate;
u8 m_buffer[16], m_last_kbd[2], m_last_mouse[2];
u8 m_keyboard_handler, m_mouse_handler;
bool m_srqflag;
s32 m_linein;
#define kADBKeyBufSize 32
uint8_t m_adb_keybuf[kADBKeyBufSize];
uint8_t m_adb_keybuf_start;
uint8_t m_adb_keybuf_end;
static constexpr int kADBKeyBufSize = 32;
u8 m_keybuf[kADBKeyBufSize];
u8 m_keybuf_start;
u8 m_keybuf_end;
// ADB mouse state
int m_adb_mouseaddr;
int m_adb_lastmousex, m_adb_lastmousey, m_adb_lastbutton, m_adb_mouse_initialized;
u8 m_mouseaddr;
s32 m_lastmousex, m_lastmousey, m_lastbutton;
// ADB keyboard state
int m_adb_keybaddr;
int m_adb_keybinitialized, m_adb_currentkeys[2], m_adb_modifiers;
u8 m_keybaddr;
s32 m_currentkeys[2], m_modifiers;
int adb_pollkbd(int update);
int adb_pollmouse();
void adb_accummouse( uint8_t *MouseX, uint8_t *MouseY );
bool adb_pollkbd(int update);
bool adb_pollmouse();
void adb_accummouse(u8 *MouseX, u8 *MouseY );
void adb_talk();
inline void set_adb_line(int linestate) { write_adb_data(linestate); }
TIMER_CALLBACK_MEMBER(mac_adb_tick);
TIMER_CALLBACK_MEMBER(timer_tick);
};
// device type definition

View File

@ -67,7 +67,12 @@ public:
m_scc(*this, "scc"),
m_asc(*this, "asc"),
m_cur_floppy(nullptr),
m_hdsel(0)
m_hdsel(0),
m_last_taken_interrupt(-1),
m_overlay(true),
m_rom_ptr(nullptr),
m_rom_size(0),
m_adb_in(0)
{
}
@ -100,8 +105,8 @@ private:
emu_timer *m_6015_timer;
bool m_overlay;
u32 *m_rom_ptr = nullptr;
u32 m_rom_size = 0;
u32 *m_rom_ptr;
u32 m_rom_size;
int m_adb_in;
@ -117,6 +122,7 @@ private:
void phases_w(uint8_t phases);
void devsel_w(uint8_t devsel);
void fdc_hdsel(int state);
uint32_t biu_r(offs_t offset, uint32_t mem_mask = ~0);
void biu_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
@ -129,13 +135,13 @@ private:
uint8_t maciifx_8010_r();
uint8_t maciifx_8040_r();
uint16_t mac_via_r(offs_t offset);
void mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask);
uint8_t mac_via_in_a();
uint8_t mac_via_in_b();
void mac_via_out_a(uint8_t data);
void mac_via_out_b(uint8_t data);
void mac_via_sync();
uint16_t via_r(offs_t offset);
void via_w(offs_t offset, uint16_t data, uint16_t mem_mask);
uint8_t via_in_a();
uint8_t via_in_b();
void via_out_a(uint8_t data);
void via_out_b(uint8_t data);
void via_sync();
uint32_t rom_switch_r(offs_t offset);
@ -200,7 +206,7 @@ void maciifx_state::maciifx_map(address_map &map)
{
map(0x40000000, 0x4007ffff).r(FUNC(maciifx_state::rom_switch_r)).mirror(0x0ff80000);
map(0x50000000, 0x50001fff).rw(FUNC(maciifx_state::mac_via_r), FUNC(maciifx_state::mac_via_w)).mirror(0x00f00000);
map(0x50000000, 0x50001fff).rw(FUNC(maciifx_state::via_r), FUNC(maciifx_state::via_w)).mirror(0x00f00000);
map(0x50004000, 0x50005fff).rw("sccpic", FUNC(applepic_device::host_r), FUNC(applepic_device::host_w)).mirror(0x00f00000).umask32(0xff00ff00);
map(0x50004000, 0x50005fff).rw("sccpic", FUNC(applepic_device::host_r), FUNC(applepic_device::host_w)).mirror(0x00f00000).umask32(0x00ff00ff);
map(0x50008010, 0x50008010).r(FUNC(maciifx_state::maciifx_8010_r)).mirror(0x00f00000);
@ -215,10 +221,10 @@ void maciifx_state::maciifx_map(address_map &map)
map(0x50018000, 0x50019fff).rw(FUNC(maciifx_state::biu_r), FUNC(maciifx_state::biu_w)).mirror(0x00f00000);
map(0x5001a000, 0x5001bfff).rw(FUNC(maciifx_state::oss_r), FUNC(maciifx_state::oss_w)).mirror(0x00f00000);
map(0x50024000, 0x50027fff).r(FUNC(maciifx_state::buserror_r)).mirror(0x00f00000); // must bus error on access here so ROM can determine we're an FMC
map(0x50040000, 0x50041fff).rw(FUNC(maciifx_state::mac_via_r), FUNC(maciifx_state::mac_via_w)).mirror(0x00f00000);
map(0x50040000, 0x50041fff).rw(FUNC(maciifx_state::via_r), FUNC(maciifx_state::via_w)).mirror(0x00f00000);
}
void maciifx_state::mac_via_sync()
void maciifx_state::via_sync()
{
// The via runs at 783.36KHz while the main cpu runs at 15MHz or
// more, so we need to sync the access with the via clock. Plus
@ -241,7 +247,7 @@ void maciifx_state::mac_via_sync()
m_maincpu->adjust_icount(-int(main_cycle - cycle));
}
uint16_t maciifx_state::mac_via_r(offs_t offset)
uint16_t maciifx_state::via_r(offs_t offset)
{
uint16_t data;
@ -249,19 +255,19 @@ uint16_t maciifx_state::mac_via_r(offs_t offset)
offset &= 0x0f;
if (!machine().side_effects_disabled())
mac_via_sync();
via_sync();
data = m_via1->read(offset);
return (data & 0xff) | (data << 8);
}
void maciifx_state::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask)
void maciifx_state::via_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
offset >>= 8;
offset &= 0x0f;
mac_via_sync();
via_sync();
if (ACCESSING_BITS_0_7)
m_via1->write(offset, data & 0xff);
@ -269,37 +275,22 @@ void maciifx_state::mac_via_w(offs_t offset, uint16_t data, uint16_t mem_mask)
m_via1->write(offset, (data >> 8) & 0xff);
}
uint8_t maciifx_state::mac_via_in_a()
uint8_t maciifx_state::via_in_a()
{
return 0xd3; // PA6 | PA4 | PA1
}
uint8_t maciifx_state::mac_via_in_b()
uint8_t maciifx_state::via_in_b()
{
int val = m_rtc->data_r();
// printf("%s VIA1 IN_B = %02x\n", machine().describe_context().c_str(), val);
return val;
return m_rtc->data_r();
}
void maciifx_state::mac_via_out_a(uint8_t data)
void maciifx_state::via_out_a(uint8_t data)
{
int hdsel = BIT(data, 5);
if (hdsel != m_hdsel)
{
if (m_cur_floppy)
{
m_cur_floppy->ss_w(hdsel);
}
}
m_hdsel = hdsel;
}
void maciifx_state::mac_via_out_b(uint8_t data)
void maciifx_state::via_out_b(uint8_t data)
{
// printf("%s VIA1 OUT B: %02x\n", machine().describe_context().c_str(), data);
m_rtc->ce_w((data & 0x04) >> 2);
m_rtc->data_w(data & 0x01);
m_rtc->clk_w((data >> 1) & 0x01);
@ -376,43 +367,69 @@ void maciifx_state::phases_w(uint8_t phases)
void maciifx_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);
}
}
void maciifx_state::fdc_hdsel(int state)
{
if (state != m_hdsel)
{
if (m_cur_floppy)
{
m_cur_floppy->ss_w(state);
}
}
m_hdsel = state;
}
uint32_t maciifx_state::biu_r(offs_t offset, uint32_t mem_mask)
{
// printf("biu_r @ %x, mask %08x\n", offset, mem_mask);
return 0;
}
void maciifx_state::biu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
// printf("biu_w %x @ %x, mask %08x\n", data, offset, mem_mask);
}
template <int N>
void maciifx_state::oss_interrupt(int state)
{
if (state == ASSERT_LINE)
{
m_oss_regs[N >= 8 ? 0x202 : 0x203] |= 1 << (N & 7);
}
else
{
m_oss_regs[N >= 8 ? 0x202 : 0x203] &= ~(1 << (N & 7));
}
int take_interrupt = 0;
for (int n = 0; n < 8; n++)
{
if (BIT(m_oss_regs[0x203], n) && take_interrupt < m_oss_regs[n])
{
take_interrupt = m_oss_regs[n];
}
if (BIT(m_oss_regs[0x202], n) && take_interrupt < m_oss_regs[8 + n])
{
take_interrupt = m_oss_regs[8 + n];
}
}
if (m_last_taken_interrupt > -1)
@ -439,25 +456,26 @@ TIMER_CALLBACK_MEMBER(maciifx_state::oss_6015_tick)
uint8_t maciifx_state::oss_r(offs_t offset)
{
// printf("oss_r @ %x\n", offset);
// if (offset <= 0xe) // for interrupt mask registers, we're intended to return something different than is written in the low 3 bits (?)
// {
// return m_oss_regs[offset]<<4;
// }
if (offset < std::size(m_oss_regs))
{
return m_oss_regs[offset];
}
else
{
return 0;
}
}
void maciifx_state::oss_w(offs_t offset, uint8_t data)
{
// printf("oss_w %x @ %x\n", data, offset);
if (offset == 0x207)
{
oss_interrupt<10>(CLEAR_LINE);
}
else if (offset < std::size(m_oss_regs))
{
m_oss_regs[offset] = data;
}
}
uint32_t maciifx_state::buserror_r()
@ -500,6 +518,7 @@ void maciifx_state::maciifx(machine_config &config)
SWIM1(config, m_fdc, C15M);
m_fdc->devsel_cb().set(FUNC(maciifx_state::devsel_w));
m_fdc->phases_cb().set(FUNC(maciifx_state::phases_w));
m_fdc->hdsel_cb().set(FUNC(maciifx_state::fdc_hdsel));
applefdintf_device::add_35_hd(config, m_floppy[0]);
applefdintf_device::add_35_nc(config, m_floppy[1]);
@ -560,10 +579,10 @@ void maciifx_state::maciifx(machine_config &config)
m_asc->irqf_callback().set(FUNC(maciifx_state::oss_interrupt<8>));
R65NC22(config, m_via1, C7M / 10);
m_via1->readpa_handler().set(FUNC(maciifx_state::mac_via_in_a));
m_via1->readpb_handler().set(FUNC(maciifx_state::mac_via_in_b));
m_via1->writepa_handler().set(FUNC(maciifx_state::mac_via_out_a));
m_via1->writepb_handler().set(FUNC(maciifx_state::mac_via_out_b));
m_via1->readpa_handler().set(FUNC(maciifx_state::via_in_a));
m_via1->readpb_handler().set(FUNC(maciifx_state::via_in_b));
m_via1->writepa_handler().set(FUNC(maciifx_state::via_out_a));
m_via1->writepb_handler().set(FUNC(maciifx_state::via_out_b));
m_via1->irq_handler().set(FUNC(maciifx_state::oss_interrupt<11>));
MACADB(config, m_macadb, C15M);

File diff suppressed because it is too large Load Diff

View File

@ -936,6 +936,8 @@ maclc580 // April 3, 1995 Apple Macintosh LC/Performa 580
@source:apple/macquadra700.cpp
macqd700 // 1991 Apple Macintosh Quadra 700
macqd900 // 1991 Apple Macintosh Quadra 900
macqd950 // 1992 Apple Macintosh Quadra 950
@source:apple/macquadra800.cpp
macqd800 // 1993 Apple Macintosh Quadra 800