mirror of
https://github.com/holub/mame
synced 2025-06-02 10:59:52 +03:00
Fixed Z80-PIO mode 3 interrupts, and mode 1 data writes.
meritm.c: Added scanline timer-based vblank interrupt to work around the broken V9938 interrupts. Megatouch games are now working again. [Curt Coder]
This commit is contained in:
parent
a3da167012
commit
651caf7f1b
@ -111,12 +111,36 @@ static void check_interrupts(running_device *device)
|
||||
{
|
||||
pio_port *port = &z80pio->port[index];
|
||||
|
||||
if (port->mode == MODE_BIT_CONTROL)
|
||||
{
|
||||
/* fetch input data (ignore output lines) */
|
||||
UINT8 data = (port->input & port->ior) | (port->output & ~port->ior);
|
||||
UINT8 mask = ~port->mask;
|
||||
int match = 0;
|
||||
|
||||
data &= mask;
|
||||
|
||||
if ((port->icw & 0x60) == 0 && data != mask) match = 1;
|
||||
else if ((port->icw & 0x60) == 0x20 && data != 0) match = 1;
|
||||
else if ((port->icw & 0x60) == 0x40 && data == 0) match = 1;
|
||||
else if ((port->icw & 0x60) == 0x60 && data == mask) match = 1;
|
||||
|
||||
if (!port->match && match)
|
||||
{
|
||||
/* trigger interrupt */
|
||||
port->ip = 1;
|
||||
if (LOG) logerror("Z80PIO '%s' Port %c Interrupt Pending\n", device->tag.cstr(), 'A' + index);
|
||||
}
|
||||
|
||||
port->match = match;
|
||||
}
|
||||
|
||||
if (port->ie && port->ip && !port->ius)
|
||||
{
|
||||
state = ASSERT_LINE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
devcb_call_write_line(&z80pio->out_int_func, state);
|
||||
}
|
||||
|
||||
@ -254,6 +278,14 @@ WRITE8_DEVICE_HANDLER( z80pio_c_w )
|
||||
case 0x07: /* set interrupt control word */
|
||||
port->icw = data;
|
||||
|
||||
if (LOG)
|
||||
{
|
||||
logerror("Z80PIO '%s' Port %c Interrupt Enable: %u\n", device->tag.cstr(), 'A' + index, BIT(data, 7));
|
||||
logerror("Z80PIO '%s' Port %c Logic: %s\n", device->tag.cstr(), 'A' + index, BIT(data, 6) ? "AND" : "OR");
|
||||
logerror("Z80PIO '%s' Port %c Active %s\n", device->tag.cstr(), 'A' + index, BIT(data, 5) ? "High" : "Low");
|
||||
logerror("Z80PIO '%s' Port %c Mask Follows: %u\n", device->tag.cstr(), 'A' + index, BIT(data, 4));
|
||||
}
|
||||
|
||||
if (port->icw & ICW_MASK_FOLLOWS)
|
||||
{
|
||||
/* disable interrupts until mask is written */
|
||||
@ -269,6 +301,11 @@ WRITE8_DEVICE_HANDLER( z80pio_c_w )
|
||||
/* next word is mask control */
|
||||
port->next_control_word = MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* monitor all bits */
|
||||
port->mask = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: /* set interrupt enable flip-flop */
|
||||
@ -394,7 +431,8 @@ WRITE8_DEVICE_HANDLER( z80pio_d_w )
|
||||
break;
|
||||
|
||||
case MODE_INPUT:
|
||||
/* do nothing */
|
||||
/* latch output data */
|
||||
port->output = data;
|
||||
break;
|
||||
|
||||
case MODE_BIDIRECTIONAL:
|
||||
@ -497,60 +535,6 @@ READ8_DEVICE_HANDLER( z80pio_pa_r )
|
||||
return data;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
check_equation - check bit logic equation
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void check_equation(running_device *device, int index, UINT8 data)
|
||||
{
|
||||
z80pio_t *z80pio = get_safe_token(device);
|
||||
pio_port *port = &z80pio->port[index];
|
||||
|
||||
if (port->mask == 0xff) return;
|
||||
|
||||
int bit;
|
||||
int match = 0;
|
||||
|
||||
int edge = (port->icw & ICW_HIGH) ? 1 : 0;
|
||||
|
||||
UINT8 mask = port->mask;
|
||||
UINT8 ior = port->ior;
|
||||
UINT8 old_data = port->input;
|
||||
|
||||
if (old_data == data) return;
|
||||
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
{
|
||||
if (BIT(mask, bit)) continue; /* masked out */
|
||||
if (!BIT(ior, bit)) continue; /* output bit */
|
||||
|
||||
if ((BIT(old_data, bit) ^ edge) && !(BIT(data, bit) ^ edge)) /* falling edge */
|
||||
{
|
||||
/* logic equation is true, until proven otherwise */
|
||||
match = 1;
|
||||
|
||||
if (LOG) logerror("Z80PIO '%s' Port %c Edge Transition detected on bit %u, data %02x %02x\n", device->tag.cstr(), 'A' + index, bit, old_data, data);
|
||||
}
|
||||
else if (port->icw & ICW_AND)
|
||||
{
|
||||
/* all bits must match in AND mode, so logic equation is false */
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!port->match && match) /* rising edge */
|
||||
{
|
||||
/* latch data */
|
||||
port->input = data;
|
||||
|
||||
/* trigger interrupt only once */
|
||||
trigger_interrupt(device, index);
|
||||
}
|
||||
|
||||
port->match = match;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
z80pio_pa_w - port A write
|
||||
-------------------------------------------------*/
|
||||
@ -562,7 +546,9 @@ WRITE8_DEVICE_HANDLER( z80pio_pa_w )
|
||||
|
||||
if (port->mode == MODE_BIT_CONTROL)
|
||||
{
|
||||
check_equation(device, PORT_A, data);
|
||||
/* latch data */
|
||||
port->input = data;
|
||||
check_interrupts(device);
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,7 +588,9 @@ WRITE8_DEVICE_HANDLER( z80pio_pb_w )
|
||||
|
||||
if (port->mode == MODE_BIT_CONTROL)
|
||||
{
|
||||
check_equation(device, PORT_B, data);
|
||||
/* latch data */
|
||||
port->input = data;
|
||||
check_interrupts(device);
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,11 +748,12 @@ static int z80pio_irq_ack(running_device *device)
|
||||
|
||||
/* clear interrupt pending flag */
|
||||
port->ip = 0;
|
||||
check_interrupts(device);
|
||||
|
||||
/* set interrupt under service flag */
|
||||
port->ius = 1;
|
||||
|
||||
check_interrupts(device);
|
||||
|
||||
return port->vector;
|
||||
}
|
||||
}
|
||||
@ -854,9 +843,6 @@ static DEVICE_RESET( z80pio )
|
||||
/* set mode 1 */
|
||||
set_mode(device, index, MODE_INPUT);
|
||||
|
||||
/* reset port mask registers */
|
||||
port->mask = 0;
|
||||
|
||||
/* reset interrupt enable flip-flops */
|
||||
port->icw &= ~ICW_ENABLE_INT;
|
||||
port->ie = 0;
|
||||
|
@ -299,7 +299,7 @@ static int meritm_touch_coord_transform(running_machine *machine, int *touch_x,
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static int meritm_vint = 0x00;
|
||||
static int meritm_vint = 0x18;
|
||||
static int meritm_interrupt_vdp0_state = 0;
|
||||
static int meritm_interrupt_vdp1_state = 0;
|
||||
static bitmap_t *vdp0_bitmap, *vdp1_bitmap;
|
||||
@ -317,32 +317,14 @@ static INTERRUPT_GEN( meritm_interrupt )
|
||||
|
||||
static void meritm_vdp0_interrupt(running_machine *machine, int i)
|
||||
{
|
||||
if ( meritm_interrupt_vdp0_state != i )
|
||||
{
|
||||
meritm_interrupt_vdp0_state = i;
|
||||
if (i)
|
||||
meritm_vint &= ~0x08;
|
||||
else
|
||||
meritm_vint |= 0x08;
|
||||
|
||||
if(i)
|
||||
z80pio_pa_w(meritm_z80pio[0], 0, meritm_vint);
|
||||
}
|
||||
/* this is not used as the v9938 interrupt callbacks are broken
|
||||
interrupts seem to be fired quite randomly */
|
||||
}
|
||||
|
||||
static void meritm_vdp1_interrupt(running_machine *machine, int i)
|
||||
{
|
||||
if ( meritm_interrupt_vdp1_state != i )
|
||||
{
|
||||
meritm_interrupt_vdp1_state = i;
|
||||
if (i)
|
||||
meritm_vint &= ~0x10;
|
||||
else
|
||||
meritm_vint |= 0x10;
|
||||
|
||||
if(i)
|
||||
z80pio_pa_w(meritm_z80pio[0], 0, meritm_vint);
|
||||
}
|
||||
/* this is not used as the v9938 interrupt callbacks are broken
|
||||
interrupts seem to be fired quite randomly */
|
||||
}
|
||||
|
||||
static int layer0_enabled, layer1_enabled;
|
||||
@ -1051,6 +1033,20 @@ static NVRAM_HANDLER(meritm_crt260)
|
||||
#define MSX2_VISIBLE_XBORDER_PIXELS 8 * 2
|
||||
#define MSX2_VISIBLE_YBORDER_PIXELS 14 * 2
|
||||
|
||||
static TIMER_DEVICE_CALLBACK( vblank_start_tick )
|
||||
{
|
||||
/* this is a workaround to signal the v9938 vblank interrupt correctly */
|
||||
meritm_vint = 0x08;
|
||||
z80pio_pa_w(meritm_z80pio[0], 0, meritm_vint);
|
||||
}
|
||||
|
||||
static TIMER_DEVICE_CALLBACK( vblank_end_tick )
|
||||
{
|
||||
/* this is a workaround to signal the v9938 vblank interrupt correctly */
|
||||
meritm_vint = 0x18;
|
||||
z80pio_pa_w(meritm_z80pio[0], 0, meritm_vint);
|
||||
}
|
||||
|
||||
static MACHINE_DRIVER_START(meritm_crt250)
|
||||
MDRV_CPU_ADD("maincpu", Z80, SYSTEM_CLK/6)
|
||||
MDRV_CPU_PROGRAM_MAP(meritm_crt250_map)
|
||||
@ -1065,6 +1061,9 @@ static MACHINE_DRIVER_START(meritm_crt250)
|
||||
MDRV_Z80PIO_ADD( "z80pio_0", SYSTEM_CLK/6, meritm_audio_pio_intf )
|
||||
MDRV_Z80PIO_ADD( "z80pio_1", SYSTEM_CLK/6, meritm_io_pio_intf )
|
||||
|
||||
MDRV_TIMER_ADD_SCANLINE("vblank_start", vblank_start_tick, "screen", 259, 262)
|
||||
MDRV_TIMER_ADD_SCANLINE("vblank_end", vblank_end_tick, "screen", 262, 262)
|
||||
|
||||
MDRV_NVRAM_HANDLER(generic_0fill)
|
||||
|
||||
MDRV_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
|
||||
|
Loading…
Reference in New Issue
Block a user