📄 z80fmly.c
字号:
/* see if the trigger value has changed */
if (data != ctc->extclk[ch])
{
ctc->extclk[ch] = data;
/* see if this is the active edge of the trigger */
if (((mode & EDGE) == EDGE_RISING && data) || ((mode & EDGE) == EDGE_FALLING && !data))
{
/* if we're waiting for a trigger, start the timer */
if ((mode & WAITING_FOR_TRIG) && (mode & MODE) == MODE_TIMER)
{
double clock = ((mode & PRESCALER) == PRESCALER_16) ? ctc->invclock16 : ctc->invclock256;
if (ctc->timer[ch])
timer_remove (ctc->timer[ch]);
if (!(ctc->notimer & (1<<ch)))
ctc->timer[ch] = timer_pulse (clock * (double)ctc->tconst[ch], (which << 2) + ch, z80ctc_timercallback);
}
/* we're no longer waiting */
ctc->mode[ch] &= ~WAITING_FOR_TRIG;
/* if we're clocking externally, decrement the count */
if ((mode & MODE) == MODE_COUNTER)
{
ctc->down[ch]--;
/* if we hit zero, do the same thing as for a timer interrupt */
if (!ctc->down[ch])
z80ctc_timercallback ((which << 2) + ch);
}
}
}
}
void z80ctc_0_trg0_w (int offset, int data) { z80ctc_trg_w (0, 0, offset, data); }
void z80ctc_0_trg1_w (int offset, int data) { z80ctc_trg_w (0, 1, offset, data); }
void z80ctc_0_trg2_w (int offset, int data) { z80ctc_trg_w (0, 2, offset, data); }
void z80ctc_0_trg3_w (int offset, int data) { z80ctc_trg_w (0, 3, offset, data); }
void z80ctc_1_trg0_w (int offset, int data) { z80ctc_trg_w (1, 0, offset, data); }
void z80ctc_1_trg1_w (int offset, int data) { z80ctc_trg_w (1, 1, offset, data); }
void z80ctc_1_trg2_w (int offset, int data) { z80ctc_trg_w (1, 2, offset, data); }
void z80ctc_1_trg3_w (int offset, int data) { z80ctc_trg_w (1, 3, offset, data); }
/*---------------------- Z80 PIO ---------------------------------*/
/* starforce emurate Z80PIO subset */
/* ch.A mode 1 input handshake mode from sound command */
/* ch.b not use */
#define PIO_MODE0 0x00 /* output mode */
#define PIO_MODE1 0x01 /* input mode */
#define PIO_MODE2 0x02 /* i/o mode */
#define PIO_MODE3 0x03 /* bit mode */
/* pio controll port operation (bit 0-3) */
#define PIO_OP_MODE 0x0f /* mode select */
#define PIO_OP_INTC 0x07 /* interrupt controll */
#define PIO_OP_INTE 0x03 /* interrupt enable */
#define PIO_OP_INTE 0x03 /* interrupt enable */
/* pio interrupt controll nit */
#define PIO_INT_ENABLE 0x80 /* ENABLE : 0=disable , 1=enable */
#define PIO_INT_AND 0x40 /* LOGIC : 0=OR , 1=AND */
#define PIO_INT_HIGH 0x20 /* LEVEL : 0=low , 1=high */
#define PIO_INT_MASK 0x10 /* MASK : 0=off , 1=on */
typedef struct
{
int vector[2]; /* interrupt vector */
void (*intr)(int which); /* interrupt callbacks */
void (*rdyr[2])(int data); /* RDY active callback */
int mode[2]; /* mode 00=in,01=out,02=i/o,03=bit*/
int enable[2]; /* interrupt enable */
int mask[2]; /* mask folowers */
int dir[2]; /* direction (bit mode) */
int rdy[2]; /* ready pin level */
int in[2]; /* input port data */
int out[2]; /* output port */
int int_state[2]; /* interrupt status (daisy chain) */
} z80pio;
static z80pio pios[MAX_PIO];
/* initialize pio emurator */
void z80pio_init (z80pio_interface *intf)
{
int i;
memset (pios, 0, sizeof (pios));
for (i = 0; i < intf->num; i++)
{
pios[i].intr = intf->intr[i];
pios[i].rdyr[0] = intf->rdyA[i];
pios[i].rdyr[1] = intf->rdyB[i];
z80pio_reset (i);
}
}
static void z80pio_interrupt_check( z80pio *pio )
{
int state;
if( pio->int_state[1] & Z80_INT_IEO ) state = Z80_INT_IEO;
else state = pio->int_state[1];
if( pio->int_state[0] & Z80_INT_IEO ) state = Z80_INT_IEO;
else state |= pio->int_state[0];
/* change daisy chain status */
if (pio->intr) (*pio->intr)(state);
}
static void z80pio_check_irq( z80pio *pio , int ch )
{
int irq = 0;
int data;
int old_state;
if( pio->enable[ch] & PIO_INT_ENABLE )
{
if( pio->mode[ch] == PIO_MODE3 )
{
data = pio->in[ch] & pio->dir[ch]; /* input data only */
data &= ~pio->mask[ch]; /* mask follow */
if( !(pio->enable[ch]&PIO_INT_HIGH) )/* active level */
data ^= pio->mask[ch]; /* active low */
if( pio->enable[ch]&PIO_INT_AND ) /* logic */
{ if( data == pio->mask[ch] ) irq = 1; }
else { if( data == 0 ) irq = 1; }
/* if portB , portA mode 2 check */
if( ch && (pio->mode[0]==PIO_MODE2) )
{
if( pio->rdy[ch] == 0 ) irq = 1;
}
}
else if( pio->rdy[ch] == 0 ) irq = 1;
}
old_state = pio->int_state[ch];
if( irq ) pio->int_state[ch] |= Z80_INT_REQ;
else pio->int_state[ch] &= ~Z80_INT_REQ;
if( old_state != pio->int_state[ch] )
z80pio_interrupt_check( pio );
}
void z80pio_reset (int which)
{
z80pio *pio = pios + which;
int i;
for( i = 0 ; i <= 1 ; i++){
pio->mask[i] = 0xff; /* mask all on */
pio->enable[i] = 0x00; /* disable */
pio->mode[i] = 0x01; /* mode input */
pio->dir[i] = 0x01; /* dir input */
pio->rdy[i] = 0x00; /* RDY = low */
pio->out[i] = 0x00; /* outdata = 0 */
pio->int_state[i] = 0;
}
z80pio_interrupt_check( pio );
}
/* pio data register write */
void z80pio_d_w( int which , int ch , int data )
{
z80pio *pio = pios + which;
if( ch ) ch = 1;
pio->out[ch] = data; /* latch out data */
switch( pio->mode[ch] ){
case PIO_MODE0: /* mode 0 output */
case PIO_MODE2: /* mode 2 i/o */
pio->rdy[ch] = 1; /* ready = H */
z80pio_check_irq( pio , ch );
return;
case PIO_MODE1: /* mode 1 intput */
case PIO_MODE3: /* mode 0 bit */
return;
default:
return;
}
}
/* pio controll register write */
void z80pio_c_w( int which , int ch , int data )
{
z80pio *pio = pios + which;
if( ch ) ch = 1;
/* load direction phase ? */
if( pio->mode[ch] == 0x13 ){
pio->dir[ch] = data;
pio->mode[ch] = 0x03;
return;
}
/* load mask folows phase ? */
if( pio->enable[ch] & PIO_INT_MASK ){ /* load mask folows */
pio->mask[ch] = data;
pio->enable[ch] &= ~PIO_INT_MASK;
return;
}
switch( data & 0x0f ){
case PIO_OP_MODE: /* mode select 0=out,1=in,2=i/o,3=bit */
pio->mode[ch] = (data >> 6 );
if( pio->mode[ch] == 0x03 ) pio->mode[ch] = 0x13;
break;
case PIO_OP_INTC: /* interrupt control */
pio->enable[ch] = data & 0xf0;
pio->mask[ch] = 0x00;
/* when interrupt enable , set vector request flag */
break;
case PIO_OP_INTE: /* interrupt enable controll */
pio->enable[ch] &= ~PIO_INT_ENABLE;
pio->enable[ch] |= (data & PIO_INT_ENABLE);
break;
default:
if( !(data&1) )
{
pio->vector[ch] = data;
}
}
/* interrupt check */
z80pio_check_irq( pio , ch );
}
/* pio controll register read */
int z80pio_c_r( int which , int ch )
{
if( ch ) ch = 1;
return 0;
}
/* pio data register read */
int z80pio_d_r( int which , int ch )
{
z80pio *pio = pios + which;
if( ch ) ch = 1;
switch( pio->mode[ch] ){
case PIO_MODE0: /* mode 0 output */
return pio->out[ch];
case PIO_MODE1: /* mode 1 intput */
pio->rdy[ch] = 1; /* ready = H */
z80pio_check_irq( pio , ch );
return pio->in[ch];
case PIO_MODE2: /* mode 2 i/o */
pio->rdy[1] = 1; /* brdy = H */
z80pio_check_irq( pio , ch );
return pio->in[ch];
case PIO_MODE3: /* mode 3 bit */
return (pio->in[ch]&pio->dir[ch])|(pio->out[ch]&~pio->dir[ch]);
}
return 0;
}
int z80pio_interrupt( int which )
{
z80pio *pio = pios + which;
int ch = 0;
/* port A */
if( pio->int_state[0] == Z80_INT_REQ )
{
pio->int_state[0] |= Z80_INT_IEO;
} if( pio->int_state[0] == 0 )
{
/* port B */
ch = 1;
if( pio->int_state[1] == Z80_INT_REQ )
{
pio->int_state[1] |= Z80_INT_IEO;
}
else
{
ch = 0;
}
}
z80pio_interrupt_check( pio );
return pio->vector[ch];
}
void z80pio_reti( int which )
{
z80pio *pio = pios + which;
if( pio->int_state[0] & Z80_INT_IEO )
{
pio->int_state[0] &= ~Z80_INT_IEO;
} else if( pio->int_state[1] & Z80_INT_IEO )
{
pio->int_state[1] &= ~Z80_INT_IEO;
}
/* set next interrupt stattus */
z80pio_interrupt_check( pio );
}
/* z80pio port write */
void z80pio_p_w( int which , int ch , int data )
{
z80pio *pio = pios + which;
if( ch ) ch = 1;
pio->in[ch] = data;
switch( pio->mode[ch] ){
case PIO_MODE0:
break;
case PIO_MODE2: /* only port A */
ch = 1; /* handshake and IRQ is use portB */
case PIO_MODE1:
pio->rdy[ch] = 0;
z80pio_check_irq( pio , ch );
break;
case PIO_MODE3:
/* irq check */
z80pio_check_irq( pio , ch );
break;
}
}
/* z80pio port read */
int z80pio_p_r( int which , int ch )
{
z80pio *pio = pios + which;
if( ch ) ch = 1;
switch( pio->mode[ch] ){
case PIO_MODE2: /* port A only */
case PIO_MODE0:
pio->rdy[ch] = 0;
z80pio_check_irq( pio , ch );
break;
case PIO_MODE1:
break;
case PIO_MODE3:
/* input bits , output bits */
return (pio->in[ch]&pio->dir[ch])|(pio->out[ch]&~pio->dir[ch]);
}
return pio->out[ch];
}
/* for mame interface */
void z80pio_0_reset (void) { z80pio_reset (0); }
void z80pio_0_w(int offset , int data)
{
if(offset&1) z80pio_c_w(0,(offset/2)&1,data);
else z80pio_d_w(0,(offset/2)&1,data);
}
int z80pio_0_r(int offset)
{
return (offset&1) ? z80pio_c_r(0,(offset/2)&1) : z80pio_d_r(0,(offset/2)&1);
}
void z80pioA_0_p_w(int offset , int data) { z80pio_p_w(0,0,data); }
void z80pioB_0_p_w(int offset , int data) { z80pio_p_w(0,1,data); }
int z80pioA_0_p_r(int offset ) { return z80pio_p_r(0,0); }
int z80pioB_0_p_r(int offset ) { return z80pio_p_r(0,1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -