mirror of
https://github.com/holub/mame
synced 2025-07-05 01:48:29 +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,6 +111,30 @@ static void check_interrupts(running_device *device)
|
|||||||
{
|
{
|
||||||
pio_port *port = &z80pio->port[index];
|
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)
|
if (port->ie && port->ip && !port->ius)
|
||||||
{
|
{
|
||||||
state = ASSERT_LINE;
|
state = ASSERT_LINE;
|
||||||
@ -254,6 +278,14 @@ WRITE8_DEVICE_HANDLER( z80pio_c_w )
|
|||||||
case 0x07: /* set interrupt control word */
|
case 0x07: /* set interrupt control word */
|
||||||
port->icw = data;
|
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)
|
if (port->icw & ICW_MASK_FOLLOWS)
|
||||||
{
|
{
|
||||||
/* disable interrupts until mask is written */
|
/* disable interrupts until mask is written */
|
||||||
@ -269,6 +301,11 @@ WRITE8_DEVICE_HANDLER( z80pio_c_w )
|
|||||||
/* next word is mask control */
|
/* next word is mask control */
|
||||||
port->next_control_word = MASK;
|
port->next_control_word = MASK;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* monitor all bits */
|
||||||
|
port->mask = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03: /* set interrupt enable flip-flop */
|
case 0x03: /* set interrupt enable flip-flop */
|
||||||
@ -394,7 +431,8 @@ WRITE8_DEVICE_HANDLER( z80pio_d_w )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_INPUT:
|
case MODE_INPUT:
|
||||||
/* do nothing */
|
/* latch output data */
|
||||||
|
port->output = data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_BIDIRECTIONAL:
|
case MODE_BIDIRECTIONAL:
|
||||||
@ -497,60 +535,6 @@ READ8_DEVICE_HANDLER( z80pio_pa_r )
|
|||||||
return data;
|
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
|
z80pio_pa_w - port A write
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
@ -562,7 +546,9 @@ WRITE8_DEVICE_HANDLER( z80pio_pa_w )
|
|||||||
|
|
||||||
if (port->mode == MODE_BIT_CONTROL)
|
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)
|
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 */
|
/* clear interrupt pending flag */
|
||||||
port->ip = 0;
|
port->ip = 0;
|
||||||
check_interrupts(device);
|
|
||||||
|
|
||||||
/* set interrupt under service flag */
|
/* set interrupt under service flag */
|
||||||
port->ius = 1;
|
port->ius = 1;
|
||||||
|
|
||||||
|
check_interrupts(device);
|
||||||
|
|
||||||
return port->vector;
|
return port->vector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -854,9 +843,6 @@ static DEVICE_RESET( z80pio )
|
|||||||
/* set mode 1 */
|
/* set mode 1 */
|
||||||
set_mode(device, index, MODE_INPUT);
|
set_mode(device, index, MODE_INPUT);
|
||||||
|
|
||||||
/* reset port mask registers */
|
|
||||||
port->mask = 0;
|
|
||||||
|
|
||||||
/* reset interrupt enable flip-flops */
|
/* reset interrupt enable flip-flops */
|
||||||
port->icw &= ~ICW_ENABLE_INT;
|
port->icw &= ~ICW_ENABLE_INT;
|
||||||
port->ie = 0;
|
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_vdp0_state = 0;
|
||||||
static int meritm_interrupt_vdp1_state = 0;
|
static int meritm_interrupt_vdp1_state = 0;
|
||||||
static bitmap_t *vdp0_bitmap, *vdp1_bitmap;
|
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)
|
static void meritm_vdp0_interrupt(running_machine *machine, int i)
|
||||||
{
|
{
|
||||||
if ( meritm_interrupt_vdp0_state != i )
|
/* this is not used as the v9938 interrupt callbacks are broken
|
||||||
{
|
interrupts seem to be fired quite randomly */
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void meritm_vdp1_interrupt(running_machine *machine, int i)
|
static void meritm_vdp1_interrupt(running_machine *machine, int i)
|
||||||
{
|
{
|
||||||
if ( meritm_interrupt_vdp1_state != i )
|
/* this is not used as the v9938 interrupt callbacks are broken
|
||||||
{
|
interrupts seem to be fired quite randomly */
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int layer0_enabled, layer1_enabled;
|
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_XBORDER_PIXELS 8 * 2
|
||||||
#define MSX2_VISIBLE_YBORDER_PIXELS 14 * 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)
|
static MACHINE_DRIVER_START(meritm_crt250)
|
||||||
MDRV_CPU_ADD("maincpu", Z80, SYSTEM_CLK/6)
|
MDRV_CPU_ADD("maincpu", Z80, SYSTEM_CLK/6)
|
||||||
MDRV_CPU_PROGRAM_MAP(meritm_crt250_map)
|
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_0", SYSTEM_CLK/6, meritm_audio_pio_intf )
|
||||||
MDRV_Z80PIO_ADD( "z80pio_1", SYSTEM_CLK/6, meritm_io_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_NVRAM_HANDLER(generic_0fill)
|
||||||
|
|
||||||
MDRV_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
|
MDRV_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK)
|
||||||
|
Loading…
Reference in New Issue
Block a user