upd7810: updates for taito c-chip

This commit is contained in:
dinkc64 2018-03-24 04:11:51 +00:00
parent c8bc050024
commit 703ab31483
3 changed files with 220 additions and 285 deletions

View File

@ -1,3 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Juergen Buchmueller
/*****************************************************************************
*
* Portable uPD7810/11, 7810H/11H, 78C10/C11/C14 emulator V0.2
@ -7,6 +9,9 @@
*
*****************************************************************************/
static void illegal(void)
{
// logerror("uPD7810 #%d: illegal opcode %02x at PC:%04x\n", cpu_getactivecpu(), OP, PC);
@ -6808,7 +6813,7 @@ static void ACI_V_xx(void)
RDOPARG( imm );
tmp = V + imm + (PSW & CY);
ZHC_SUB( tmp, V, (PSW & CY) );
ZHC_ADD( tmp, V, (PSW & CY) );
V = tmp;
}
@ -6819,7 +6824,7 @@ static void ACI_A_xx(void)
RDOPARG( imm );
tmp = A + imm + (PSW & CY);
ZHC_SUB( tmp, A, (PSW & CY) );
ZHC_ADD( tmp, A, (PSW & CY) );
A = tmp;
}
@ -6830,7 +6835,7 @@ static void ACI_B_xx(void)
RDOPARG( imm );
tmp = B + imm + (PSW & CY);
ZHC_SUB( tmp, B, (PSW & CY) );
ZHC_ADD( tmp, B, (PSW & CY) );
B = tmp;
}
@ -6841,7 +6846,7 @@ static void ACI_C_xx(void)
RDOPARG( imm );
tmp = C + imm + (PSW & CY);
ZHC_SUB( tmp, C, (PSW & CY) );
ZHC_ADD( tmp, C, (PSW & CY) );
C = tmp;
}
@ -6852,7 +6857,7 @@ static void ACI_D_xx(void)
RDOPARG( imm );
tmp = D + imm + (PSW & CY);
ZHC_SUB( tmp, D, (PSW & CY) );
ZHC_ADD( tmp, D, (PSW & CY) );
D = tmp;
}
@ -6863,7 +6868,7 @@ static void ACI_E_xx(void)
RDOPARG( imm );
tmp = E + imm + (PSW & CY);
ZHC_SUB( tmp, E, (PSW & CY) );
ZHC_ADD( tmp, E, (PSW & CY) );
E = tmp;
}
@ -6874,7 +6879,7 @@ static void ACI_H_xx(void)
RDOPARG( imm );
tmp = H + imm + (PSW & CY);
ZHC_SUB( tmp, H, (PSW & CY) );
ZHC_ADD( tmp, H, (PSW & CY) );
H = tmp;
}
@ -6885,7 +6890,7 @@ static void ACI_L_xx(void)
RDOPARG( imm );
tmp = L + imm + (PSW & CY);
ZHC_SUB( tmp, L, (PSW & CY) );
ZHC_ADD( tmp, L, (PSW & CY) );
L = tmp;
}
@ -8828,12 +8833,13 @@ static void PRE_60(void)
/* 61: 0110 0001 */
static void DAA(void)
{
UINT8 l = A & 0x0f, h = A >> 4, tmp, adj = 0x00;
UINT8 l = A & 0x0f, h = A >> 4, tmp, adj = 0x00, old_cy = PSW & CY;
if (0 == (PSW & HC))
{
if (l < 10)
{
if (!(h < 10 && 0 == (PSW & CY)))
if (!(h < 10 && 0 == (PSW & CY)))
adj = 0x60;
}
else
@ -8854,6 +8860,7 @@ static void DAA(void)
}
tmp = A + adj;
ZHC_ADD( tmp, A, PSW & CY );
PSW |= old_cy;
A = tmp;
}
@ -8917,9 +8924,9 @@ static void MVI_V_xx(void)
/* 69: 0110 1001 xxxx xxxx */
static void MVI_A_xx(void)
{
if (PSW & L1) { /* overlay active? */
if (PSW & L1) { /* overlay active? */
PC++;
return; /* NOP */
return; /* NOP */
}
RDOPARG( A );
PSW |= L1;
@ -8958,9 +8965,9 @@ static void MVI_H_xx(void)
/* 6f: 0110 1111 xxxx xxxx */
static void MVI_L_xx(void)
{
if (PSW & L0) { /* overlay active? */
if (PSW & L0) { /* overlay active? */
PC++;
return; /* NOP */
return; /* NOP */
}
RDOPARG( L );
PSW |= L0;
@ -9054,26 +9061,16 @@ static void CALT(void)
PAIR w;
w.d = 0;
switch (upd7810_config_type) {
case TYPE_7810_GAMEMASTER:
// logerror ("!!!!!!!%.4x calt %.2x game master table position not known\n",PPC, OP);
break;
default:
w.w.l = 0x80 + 2 * (OP & 0x1f);
}
if (upd7810_config_type!=TYPE_7810_GAMEMASTER) {
SP--;
WM( SPD, PCH );
SP--;
WM( SPD, PCL );
PCL=RM(w.w.l);
PCH=RM(w.w.l+1);
PCL=RM(w.w.l);
PCH=RM(w.w.l+1);
change_pc( PCD );
// logerror ("!!!!!!!%.4x calt %.2x %.4x; game master table position not known\n",PPC, OP, PCD);
}
}
/* a0: 1010 0000 */
@ -9279,7 +9276,7 @@ static void RETS(void)
SP++;
PCH = RM( SPD );
SP++;
PSW|=SK; /* skip one instruction */
PSW|=SK; /* skip one instruction */
change_pc( PCD );
}

View File

@ -569,6 +569,7 @@ static UINT8 upd7810_win_layout[] = {
#define INTFST 0x0400
#define INTER 0x0800
#define INTOV 0x1000
#define INTF0 0x2000
/* ITF flags */
#define INTAN4 0x0001
@ -657,6 +658,8 @@ static UINT8 upd7810_win_layout[] = {
#define TI upd7810.ti
#define TO upd7810.to
#define CI upd7810.ci
#define LV0 upd7810.lv0
#define LV1 upd7810.lv1
#define CO0 upd7810.co0
#define CO1 upd7810.co1
@ -874,6 +877,14 @@ static void upd7810_take_irq(void)
return;
/* check the interrupts in priority sequence */
if (IRR & INTNMI)
{
/* Nonmaskable interrupt */
irqline = CPU_IRQLINE_NMI;
vector = 0x0004;
IRR &= ~INTNMI;
}
else
if ((IRR & INTFT0) && 0 == (MKL & 0x02))
{
switch (upd7810_config_type)
@ -982,6 +993,69 @@ static void upd7810_take_irq(void)
}
}
static void upd7810_co0_output_change()
{
/* Output LV0 Content to CO0 */
CO0 = LV0;
/* LV0 Level Inversion */
if (EOM & 0x02)
LV0 ^= 1;
//m_co0_func(CO0);
}
static void upd7810_co1_output_change()
{
/* Output LV1 Content to CO1 */
CO1 = LV1;
/* LV1 Level Inversion */
if (EOM & 0x20)
LV1 ^= 1;
//m_co1_func(CO1);
}
static void upd7810_write_EOM()
{
switch (EOM & 0x0c)
{
case 0x04: /* To Reset LV0 */
LV0 = 0;
EOM &= 0xfb; /* LRE0 is reset to 0 */
break;
case 0x08: /* To Set LV0 */
LV0 = 1;
EOM &= 0xf7; /* LRE1 is reset to 0 */
break;
}
/* Output LV0 Content */
if (EOM & 0x01) {
upd7810_co0_output_change();
EOM &= 0xfe; /* LO0 is reset to 0 */
}
switch (EOM & 0xc0)
{
case 0x40: /* To Reset LV1 */
LV1 = 0;
EOM &= 0xbf; /* LRE2 is reset to 0 */
break;
case 0x80: /* To Set LV1 */
LV1 = 1;
EOM &= 0x7f; /* LRE3 is reset to 0 */
break;
}
/* Output LV1 Content */
if (EOM & 0x10) {
upd7810_co1_output_change();
EOM &= 0xef; /* LO1 is reset to 0 */
}
}
#if 0
OLD
static void upd7810_write_EOM(void)
{
if (EOM & 0x01) /* output LV0 content ? */
@ -1015,6 +1089,7 @@ static void upd7810_write_EOM(void)
}
}
}
#endif
static void upd7810_write_TXB(void)
{
@ -1308,146 +1383,105 @@ static void upd7810_sio_input(void)
}
}
static void upd7810_handle_timer0(int cycles, int clkdiv)
{
OVC0 += cycles;
while (OVC0 >= clkdiv)
{
OVC0 -= clkdiv;
CNT0++;
if (CNT0 == TM0)
{
CNT0 = 0;
IRR |= INTFT0;
/* timer F/F source is timer 0 ? */
if (0x00 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
/* timer 1 chained with timer 0 ? */
if ((TMM & 0xe0) == 0x60)
{
CNT1++;
if (CNT1 == TM1)
{
CNT1 = 0;
IRR |= INTFT1;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
}
}
}
}
}
static void upd7810_handle_timer1(int cycles, int clkdiv)
{
OVC1 += cycles;
while (OVC1 >= clkdiv)
{
OVC1 -= clkdiv;
CNT1++;
if (CNT1 == TM1)
{
CNT1 = 0;
IRR |= INTFT1;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
}
}
}
static void upd7810_timers(int cycles)
{
/**** TIMER 0 ****/
if (TMM & 0x10) /* timer 0 upcounter reset ? */
if (TMM & 0x10) /* timer 0 upcounter reset ? */
CNT0 = 0;
else
{
switch (TMM & 0x0c) /* timer 0 clock source */
{
case 0x00: /* clock divided by 12 */
OVC0 += cycles;
while (OVC0 >= 12)
{
OVC0 -= 12;
CNT0++;
if (CNT0 == TM0)
{
CNT0 = 0;
IRR |= INTFT0;
/* timer F/F source is timer 0 ? */
if (0x00 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
/* timer 1 chained with timer 0 ? */
if ((TMM & 0xe0) == 0x60)
{
CNT1++;
if (CNT1 == TM1)
{
IRR |= INTFT1;
CNT1 = 0;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
}
}
}
}
case 0x00: /* clock divided by 12 */
upd7810_handle_timer0(cycles, 12);
break;
case 0x04: /* clock divided by 384 */
OVC0 += cycles;
while (OVC0 >= 384)
{
OVC0 -= 384;
CNT0++;
if (CNT0 == TM0)
{
CNT0 = 0;
IRR |= INTFT0;
/* timer F/F source is timer 0 ? */
if (0x00 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
/* timer 1 chained with timer 0 ? */
if ((TMM & 0xe0) == 0x60)
{
CNT1++;
if (CNT1 == TM1)
{
CNT1 = 0;
IRR |= INTFT1;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
}
}
}
}
case 0x04: /* clock divided by 384 */
upd7810_handle_timer0(cycles, 384);
break;
case 0x08: /* external signal at TI */
case 0x08: /* external signal at TI */
break;
case 0x0c: /* disabled */
case 0x0c: /* disabled */
break;
}
}
/**** TIMER 1 ****/
if (TMM & 0x80) /* timer 1 upcounter reset ? */
if (TMM & 0x80) /* timer 1 upcounter reset ? */
CNT1 = 0;
else
{
switch (TMM & 0x60) /* timer 1 clock source */
{
case 0x00: /* clock divided by 12 */
OVC1 += cycles;
while (OVC1 >= 12)
{
OVC1 -= 12;
CNT1++;
if (CNT1 == TM1)
{
CNT1 = 0;
IRR |= INTFT1;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
}
}
case 0x00: /* clock divided by 12 */
upd7810_handle_timer1(cycles, 12);
break;
case 0x20: /* clock divided by 384 */
OVC1 += cycles;
while (OVC1 >= 384)
{
OVC1 -= 384;
CNT1++;
if (CNT1 == TM1)
{
CNT1 = 0;
IRR |= INTFT1;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
if (upd7810_io_callback)
(*upd7810_io_callback)(UPD7810_TO,TO);
}
}
}
case 0x20: /* clock divided by 384 */
upd7810_handle_timer1(cycles, 384);
break;
case 0x40: /* external signal at TI */
case 0x40: /* external signal at TI */
break;
case 0x60: /* clocked with timer 0 */
case 0x60: /* clocked with timer 0 */
break;
}
}
@ -1479,142 +1513,52 @@ static void upd7810_timers(int cycles)
{
OVCE -= 12;
ECNT++;
/* Interrupt Control Circuit */
if (ETM0 == ECNT)
IRR |= INTFE0;
if (ETM1 == ECNT)
IRR |= INTFE1;
/* Conditions When ECNT Causes a CO0 Output Change */
if (((0x00 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 */
/* ((0x10 == (ETMM & 0x30)) prohibited */
((0x20 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 or at falling CI input */
((0x30 == (ETMM & 0x30)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
{
upd7810_co0_output_change();
}
/* Conditions When ECNT Causes a CO1 Output Change */
if (((0x00 == (ETMM & 0xc0)) && (ETM1 == ECNT)) || /* set CO1 if ECNT == ETM1 */
/* ((0x40 == (ETMM & 0xc0)) prohibited */
((0x80 == (ETMM & 0xc0)) && (ETM1 == ECNT)) || /* set CO1 if ECNT == ETM1 or at falling CI input */
((0xc0 == (ETMM & 0xc0)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
{
upd7810_co1_output_change();
}
/* How and When ECNT is Cleared */
switch (ETMM & 0x0c)
{
case 0x00: /* clear ECNT */
case 0x00: /* clear ECNT */
break;
case 0x04: /* free running */
case 0x04: /* free running */
if (0 == ECNT)
ITF |= INTOV; /* set overflow flag if counter wrapped */
ITF |= INTOV; /* set overflow flag if counter wrapped */
break;
case 0x08: /* reset at falling edge of CI or TO */
case 0x08: /* reset at falling edge of CI or TO */
break;
case 0x0c: /* reset if ECNT == ETM1 */
case 0x0c: /* reset if ECNT == ETM1 */
if (ETM1 == ECNT)
ECNT = 0;
break;
}
switch (ETMM & 0x30)
{
case 0x00: /* set CO0 if ECNT == ETM0 */
if (ETM0 == ECNT)
{
switch (EOM & 0x0e)
{
case 0x02: /* toggle CO0 */
CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
break;
case 0x04: /* reset CO0 */
CO0 = 0;
break;
case 0x08: /* set CO0 */
CO0 = 1;
break;
}
}
break;
case 0x10: /* prohibited */
break;
case 0x20: /* set CO0 if ECNT == ETM0 or at falling CI input */
if (ETM0 == ECNT)
{
switch (EOM & 0x0e)
{
case 0x02: /* toggle CO0 */
CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
break;
case 0x04: /* reset CO0 */
CO0 = 0;
break;
case 0x08: /* set CO0 */
CO0 = 1;
break;
}
}
break;
case 0x30: /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
if (ETM0 == ECNT || ETM1 == ECNT)
{
switch (EOM & 0x0e)
{
case 0x02: /* toggle CO0 */
CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
break;
case 0x04: /* reset CO0 */
CO0 = 0;
break;
case 0x08: /* set CO0 */
CO0 = 1;
break;
}
}
break;
}
switch (ETMM & 0xc0)
{
case 0x00: /* lacth CO1 if ECNT == ETM1 */
if (ETM1 == ECNT)
{
switch (EOM & 0xe0)
{
case 0x20: /* toggle CO1 */
CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
break;
case 0x40: /* reset CO1 */
CO1 = 0;
break;
case 0x80: /* set CO1 */
CO1 = 1;
break;
}
}
break;
case 0x40: /* prohibited */
break;
case 0x80: /* latch CO1 if ECNT == ETM1 or falling edge of CI input */
if (ETM1 == ECNT)
{
switch (EOM & 0xe0)
{
case 0x20: /* toggle CO1 */
CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
break;
case 0x40: /* reset CO1 */
CO1 = 0;
break;
case 0x80: /* set CO1 */
CO1 = 1;
break;
}
}
break;
case 0xc0: /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
if (ETM0 == ECNT || ETM1 == ECNT)
{
switch (EOM & 0xe0)
{
case 0x20: /* toggle CO1 */
CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
break;
case 0x40: /* reset CO1 */
CO1 = 0;
break;
case 0x80: /* set CO1 */
CO1 = 1;
break;
}
}
break;
}
}
}
/**** SIO ****/
switch (SMH & 0x03)
{
case 0x00: /* interval timer F/F */
case 0x00: /* interval timer F/F */
break;
case 0x01: /* internal clock divided by 384 */
case 0x01: /* internal clock divided by 384 */
OVCS += cycles;
while (OVCS >= 384)
{
@ -1625,7 +1569,7 @@ static void upd7810_timers(int cycles)
upd7810_sio_output();
}
break;
case 0x02: /* internal clock divided by 24 */
case 0x02: /* internal clock divided by 24 */
OVCS += cycles;
while (OVCS >= 24)
{
@ -1740,24 +1684,25 @@ static void upd7810_timers(int cycles)
static UINT8 fake_an_func()
{
return 0;
return 0;
}
void upd7810SetAnfunc(INT32 select, UINT8 (*func)())
{
switch (select & 7)
{
case 0: an0_func = func; break;
case 1: an1_func = func; break;
case 2: an2_func = func; break;
case 3: an3_func = func; break;
case 4: an4_func = func; break;
case 5: an5_func = func; break;
case 6: an6_func = func; break;
case 7: an7_func = func; break;
}
switch (select & 7)
{
case 0: an0_func = func; break;
case 1: an1_func = func; break;
case 2: an2_func = func; break;
case 3: an3_func = func; break;
case 4: an4_func = func; break;
case 5: an5_func = func; break;
case 6: an6_func = func; break;
case 7: an7_func = func; break;
}
}
static void upd7810_init(INT32 (*io_callback)(INT32 ioline, INT32 state))
{
upd7810_io_callback = io_callback;
@ -2052,6 +1997,7 @@ static void upd7810_set_context (void *src)
}
#endif
// if probs with taito c-chip, add the edge level checks hereunder in latest upd7810 core
static void set_irq_line(int irqline, int state)
{
if (state != CLEAR_LINE)
@ -2062,16 +2008,6 @@ static void set_irq_line(int irqline, int state)
// if (0 == (IRR & INTNMI))
{
IRR |= INTNMI;
SP--;
WM( SP, PSW );
SP--;
WM( SP, PCH );
SP--;
WM( SP, PCL );
IFF = 0;
PSW &= ~(SK|L0|L1);
PC = 0x0004;
change_pc( PCD );
}
}
else

View File

@ -126,6 +126,8 @@ typedef struct {
UINT8 ci;
UINT8 co0;
UINT8 co1;
UINT8 lv0;
UINT8 lv1;
UINT16 irr; /* interrupt request register */
UINT16 itf; /* interrupt test flag register */