wicat: Reduce video glitchiness with more sensible interrupt handling

This commit is contained in:
AJR 2018-06-08 10:21:02 -04:00
parent 1b8d0decb5
commit a279ee3773
2 changed files with 75 additions and 97 deletions

View File

@ -313,7 +313,7 @@ void i8275_device::device_timer(emu_timer &timer, device_timer_id id, int param,
}
}
if ((m_status & ST_IE) && m_scanline == m_irq_scanline)
if ((m_status & ST_IE) && !(m_status & ST_IR) && m_scanline == m_irq_scanline)
{
//LOG("I8275 y %u x %u IRQ 1\n", y, x);
m_status |= ST_IR;
@ -557,7 +557,7 @@ WRITE8_MEMBER( i8275_device::write )
case CMD_RESET:
LOG("I8275 Reset\n");
m_status &= ~(ST_IE | ST_VE);
m_status &= ~(ST_IE | ST_IR | ST_VE);
LOG("I8275 IRQ 0\n");
m_write_irq(CLEAR_LINE);
m_write_drq(0);

View File

@ -26,6 +26,7 @@ Wicat - various systems.
#include "machine/6522via.h"
#include "machine/am9517a.h"
#include "machine/im6402.h"
#include "machine/input_merger.h"
#include "machine/mc2661.h"
#include "machine/mm58274c.h"
#include "machine/wd_fdc.h"
@ -52,7 +53,9 @@ public:
m_uart5(*this, "uart5"),
m_uart6(*this, "uart6"),
m_videocpu(*this, "videocpu"),
m_videoctrl(*this,"video"),
m_videoctrl(*this, "videoctrl"),
m_videoirq(*this, "videoirq"),
m_crtc(*this, "video"),
m_videodma(*this, "videodma"),
m_videouart0(*this, "videouart0"),
m_videouart1(*this, "videouart1"),
@ -88,19 +91,16 @@ public:
DECLARE_WRITE8_MEMBER(video_timer_w);
DECLARE_READ8_MEMBER(vram_r);
DECLARE_WRITE8_MEMBER(vram_w);
DECLARE_READ8_MEMBER(video_ctrl_r);
DECLARE_WRITE8_MEMBER(video_ctrl_w);
DECLARE_READ8_MEMBER(video_status_r);
DECLARE_WRITE_LINE_MEMBER(dma_hrq_w);
DECLARE_WRITE_LINE_MEMBER(dma_nmi_cb);
DECLARE_WRITE_LINE_MEMBER(crtc_cb);
DECLARE_WRITE_LINE_MEMBER(crtc_irq_w);
DECLARE_WRITE_LINE_MEMBER(crtc_irq_clear_w);
DECLARE_READ8_MEMBER(hdc_r);
DECLARE_WRITE8_MEMBER(hdc_w);
DECLARE_READ8_MEMBER(fdc_r);
DECLARE_WRITE8_MEMBER(fdc_w);
DECLARE_READ16_MEMBER(via_r);
DECLARE_WRITE16_MEMBER(via_w);
DECLARE_WRITE_LINE_MEMBER(kb_data_ready);
I8275_DRAW_CHARACTER_MEMBER(wicat_display_pixels);
required_shared_ptr<uint8_t> m_vram;
@ -115,7 +115,9 @@ public:
required_device<mc2661_device> m_uart5;
required_device<mc2661_device> m_uart6;
required_device<cpu_device> m_videocpu;
required_device<i8275_device> m_videoctrl;
required_device<ls259_device> m_videoctrl;
required_device<input_merger_device> m_videoirq;
required_device<i8275_device> m_crtc;
required_device<am9517a_device> m_videodma;
required_device<mc2661_device> m_videouart0;
required_device<mc2661_device> m_videouart1;
@ -143,19 +145,14 @@ private:
void poll_kb();
void send_key(uint8_t val);
emu_timer* m_video_timer;
emu_timer* m_kb_timer;
emu_timer* m_kb_serial_timer;
static const device_timer_id VIDEO_TIMER = 0;
static const device_timer_id KB_TIMER = 1;
static const device_timer_id KB_SERIAL_TIMER = 2;
uint8_t m_portA;
uint8_t m_portB;
bool m_video_timer_irq;
bool m_video_kb_irq;
uint8_t m_nmi_enable;
uint8_t m_crtc_irq;
bool m_crtc_irq;
uint16_t m_kb_data;
uint8_t m_kb_bit;
uint32_t m_kb_keys[8];
@ -203,7 +200,7 @@ void wicat_state::wicat_video_io(address_map &map)
map(0x0400, 0x047f).rw(FUNC(wicat_state::videosram_r), FUNC(wicat_state::videosram_w)); // XD2210 4-bit NOVRAM
map(0x0500, 0x0500).w(FUNC(wicat_state::videosram_recall_w));
map(0x0600, 0x0600).w(FUNC(wicat_state::videosram_store_w));
map(0x0800, 0x080f).rw(FUNC(wicat_state::video_ctrl_r), FUNC(wicat_state::video_ctrl_w));
map(0x0800, 0x0807).w("videoctrl", FUNC(ls259_device::write_d0)).umask16(0xffff);
map(0x0a00, 0x0a1f).rw(FUNC(wicat_state::video_dma_r), FUNC(wicat_state::video_dma_w)); // AM9517A DMA
map(0x0b00, 0x0b03).rw(FUNC(wicat_state::video_r), FUNC(wicat_state::video_w)); // i8275 CRTC
map(0x0e00, 0x0eff).ram();
@ -297,7 +294,6 @@ static void wicat_floppies(device_slot_interface &device)
void wicat_state::driver_start()
{
m_video_timer = timer_alloc(VIDEO_TIMER);
m_kb_timer = timer_alloc(KB_TIMER);
m_kb_serial_timer = timer_alloc(KB_SERIAL_TIMER);
}
@ -325,12 +321,8 @@ void wicat_state::machine_reset()
m_videouart->sbs_w(0);
m_videouart->crl_w(1);
m_video_timer_irq = false;
m_video_kb_irq = false;
m_video_timer->adjust(attotime::zero,0,attotime::from_hz(60));
m_kb_timer->adjust(attotime::zero,0,attotime::from_msec(50));
m_nmi_enable = 0;
m_crtc_irq = CLEAR_LINE;
m_crtc_irq = false;
for(auto & elem : m_kb_keys)
elem = 0;
}
@ -339,10 +331,6 @@ void wicat_state::device_timer(emu_timer &timer, device_timer_id id, int param,
{
switch (id)
{
case VIDEO_TIMER:
m_video_timer_irq = true;
m_videocpu->set_input_line(INPUT_LINE_IRQ0,ASSERT_LINE);
break;
case KB_TIMER:
poll_kb();
break;
@ -576,9 +564,9 @@ READ8_MEMBER(wicat_state::video_r)
switch(offset)
{
case 0x00:
return m_videoctrl->read(space,0);
return m_crtc->read(space,0);
case 0x02:
return m_videoctrl->read(space,1);
return m_crtc->read(space,1);
default:
return 0xff;
}
@ -589,10 +577,10 @@ WRITE8_MEMBER(wicat_state::video_w)
switch(offset)
{
case 0x00:
m_videoctrl->write(space,0,data);
m_crtc->write(space,0,data);
break;
case 0x02:
m_videoctrl->write(space,1,data);
m_crtc->write(space,1,data);
break;
}
}
@ -682,22 +670,16 @@ READ8_MEMBER(wicat_state::video_timer_r)
uint8_t ret = 0x00;
if(offset == 0x00)
{
if(m_video_timer_irq)
{
ret |= 0x08;
m_video_timer_irq = false;
m_videocpu->set_input_line(INPUT_LINE_IRQ0,CLEAR_LINE);
}
if(m_video_kb_irq)
{
ret |= 0x10;
m_video_kb_irq = false;
m_videocpu->set_input_line(INPUT_LINE_IRQ0,CLEAR_LINE);
}
}
return (m_videouart->dr_r() << 4) | (m_videouart->tbre_r() && m_videoctrl->q6_r() ? 0x08 : 0x00);
if(offset == 0x02)
{
if (!machine().side_effects_disabled())
{
m_videouart->drr_w(1);
m_videouart->drr_w(0);
}
return m_videouart->read(space,0);
}
return ret;
}
@ -708,28 +690,10 @@ WRITE8_MEMBER(wicat_state::video_timer_w)
m_videouart->write(space,0,data);
}
READ8_MEMBER(wicat_state::video_ctrl_r)
{
return 0x00; // TODO
}
WRITE8_MEMBER(wicat_state::video_ctrl_w)
{
if(offset == 0x07)
m_nmi_enable = data;
}
READ8_MEMBER(wicat_state::video_status_r)
{
// this port is read in the NVI IRQ routine, which if bit 2 is set, will unmask DMA channel 0. But no idea what triggers it...
if(m_crtc_irq == ASSERT_LINE)
{
m_crtc_irq = CLEAR_LINE;
m_videocpu->set_input_line(INPUT_LINE_IRQ0,CLEAR_LINE);
return 0x04;
}
else
return 0x00;
return m_crtc_irq ? 0x04 : 0x00;
}
WRITE_LINE_MEMBER(wicat_state::dma_hrq_w)
@ -738,25 +702,22 @@ WRITE_LINE_MEMBER(wicat_state::dma_hrq_w)
m_videodma->hack_w(state);
}
WRITE_LINE_MEMBER(wicat_state::dma_nmi_cb)
WRITE_LINE_MEMBER(wicat_state::crtc_irq_w)
{
if(state)
if (state && m_videoctrl->q0_r())
{
if(m_nmi_enable != 0)
m_videocpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
m_crtc_irq = true;
m_videoirq->in_w<1>(1);
}
}
WRITE_LINE_MEMBER(wicat_state::kb_data_ready)
WRITE_LINE_MEMBER(wicat_state::crtc_irq_clear_w)
{
m_video_kb_irq = state ? ASSERT_LINE : CLEAR_LINE;
m_videocpu->set_input_line(INPUT_LINE_IRQ0,m_video_kb_irq);
if (!state)
{
m_crtc_irq = false;
m_videoirq->in_w<1>(0);
}
WRITE_LINE_MEMBER(wicat_state::crtc_cb)
{
m_crtc_irq = state ? ASSERT_LINE : CLEAR_LINE;
m_videocpu->set_input_line(INPUT_LINE_IRQ0,m_crtc_irq);
}
I8275_DRAW_CHARACTER_MEMBER(wicat_state::wicat_display_pixels)
@ -879,26 +840,43 @@ MACHINE_CONFIG_START(wicat_state::wicat)
MCFG_DEVICE_PROGRAM_MAP(wicat_video_mem)
MCFG_DEVICE_IO_MAP(wicat_video_io)
MCFG_INPUT_MERGER_ANY_HIGH("videoirq")
MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("videocpu", INPUT_LINE_IRQ0))
MCFG_DEVICE_ADD("videoctrl", LS259, 0)
MCFG_ADDRESSABLE_LATCH_Q0_OUT_CB(WRITELINE(*this, wicat_state, crtc_irq_clear_w))
MCFG_ADDRESSABLE_LATCH_Q6_OUT_CB(WRITELINE("tbreirq", input_merger_device, in_w<1>))
MCFG_ADDRESSABLE_LATCH_Q7_OUT_CB(WRITELINE("dmairq", input_merger_device, in_w<1>))
// Q1-Q5 are all used but unknown
MCFG_DEVICE_ADD("videodma", AM9517A, 8_MHz_XTAL) // clock is a bit of guess
MCFG_AM9517A_OUT_HREQ_CB(WRITELINE(*this, wicat_state, dma_hrq_w))
MCFG_AM9517A_OUT_EOP_CB(WRITELINE(*this, wicat_state, dma_nmi_cb))
MCFG_AM9517A_OUT_EOP_CB(WRITELINE("dmairq", input_merger_device, in_w<0>))
MCFG_AM9517A_IN_MEMR_CB(READ8(*this, wicat_state, vram_r))
MCFG_AM9517A_OUT_MEMW_CB(WRITE8(*this, wicat_state, vram_w))
MCFG_AM9517A_OUT_IOW_0_CB(WRITE8("video", i8275_device, dack_w))
MCFG_IM6402_ADD("videouart", 0, 0)
MCFG_IM6402_DR_CALLBACK(WRITELINE(*this, wicat_state, kb_data_ready))
MCFG_INPUT_MERGER_ALL_HIGH("dmairq")
MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("videocpu", INPUT_LINE_NMI))
MCFG_IM6402_ADD("videouart", 0, 1200)
MCFG_IM6402_DR_CALLBACK(WRITELINE("videoirq", input_merger_device, in_w<2>))
MCFG_IM6402_TBRE_CALLBACK(WRITELINE("tbreirq", input_merger_device, in_w<0>))
MCFG_INPUT_MERGER_ALL_HIGH("tbreirq")
MCFG_INPUT_MERGER_OUTPUT_HANDLER(WRITELINE("videoirq", input_merger_device, in_w<3>))
// terminal (2x INS2651, 1x IM6042 - one of these is for the keyboard, another communicates with the main board, the third is unknown)
MCFG_DEVICE_ADD("videouart0", MC2661, 5.0688_MHz_XTAL) // the INS2651 looks similar enough to the MC2661...
MCFG_MC2661_TXD_HANDLER(WRITELINE("uart0", mc2661_device, rx_w))
MCFG_MC2661_RXRDY_HANDLER(INPUTLINE("videocpu", INPUT_LINE_IRQ0))
MCFG_MC2661_RXRDY_HANDLER(WRITELINE("videoirq", input_merger_device, in_w<0>))
MCFG_MC2661_RTS_HANDLER(WRITELINE("uart0", mc2661_device, cts_w))
MCFG_MC2661_DTR_HANDLER(WRITELINE("uart0", mc2661_device, dsr_w))
MCFG_DEVICE_ADD("videouart1", MC2661, 5.0688_MHz_XTAL)
MCFG_MC2661_RXC(19200)
MCFG_MC2661_TXC(19200)
MCFG_MC2661_RXRDY_HANDLER(INPUTLINE("videocpu", INPUT_LINE_IRQ0))
MCFG_MC2661_RXRDY_HANDLER(WRITELINE("videoirq", input_merger_device, in_w<4>))
MCFG_X2210_ADD("vsram") // XD2210
@ -912,7 +890,7 @@ MACHINE_CONFIG_START(wicat_state::wicat)
MCFG_I8275_CHARACTER_WIDTH(10)
MCFG_I8275_DRAW_CHARACTER_CALLBACK_OWNER(wicat_state, wicat_display_pixels)
MCFG_I8275_DRQ_CALLBACK(WRITELINE("videodma", am9517a_device, dreq0_w))
MCFG_I8275_IRQ_CALLBACK(WRITELINE(*this, wicat_state,crtc_cb))
MCFG_I8275_VRTC_CALLBACK(WRITELINE(*this, wicat_state, crtc_irq_w))
MCFG_VIDEO_SET_SCREEN("screen")
MCFG_DEFAULT_LAYOUT(layout_wicat)