--- xmil/io/ctc.c 2004/08/15 07:52:16 1.13 +++ xmil/io/ctc.c 2008/06/02 20:07:31 1.18 @@ -1,3 +1,7 @@ + +/* #define CTCCOUNTER */ +#define CTCFAST + #include "compiler.h" #include "z80core.h" #include "pccore.h" @@ -6,6 +10,10 @@ #include "ievent.h" +#if defined(TRACE) && defined(CTCCOUNTER) +extern UINT ctccnt; +#endif + static SINT32 minclock(const CTCCH *ch) { UINT32 event; @@ -14,16 +22,16 @@ static SINT32 minclock(const CTCCH *ch) event = 0x01000000; for (i=0; i<3; i++) { - if ((ch->cmd[i] & 0x82) == 0x80) { - clock = ch->count[i]; + if ((ch->s.cmd[i] & 0x82) == 0x80) { + clock = ch->s.count[i]; event = min(event, clock); } } - if ((ch->cmd[3] & 0x82) == 0x80) { - clock = ch->count[3]; - if (ch->cmd[3] & 0x40) { - clock = (clock - 1) * ch->countmax[0]; - clock += ch->count[0]; + if ((ch->s.cmd[3] & 0x82) == 0x80) { + clock = ch->s.count[3]; + if (ch->s.cmd[3] & 0x40) { + clock = (clock - 1) * ch->s.countmax[0]; + clock += ch->s.count[0]; } event = min(event, clock); } @@ -42,64 +50,95 @@ static REG8 ctcwork(CTCCH *ch) { SINT32 pulse; SINT32 count; +#if defined(TRACE) && defined(CTCCOUNTER) + ctccnt++; +#endif + baseclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - stepclock = baseclock - ch->baseclock; + stepclock = baseclock - ch->s.baseclock; +#if defined(FIX_Z80A) /* 2x2MHz */ + ch->s.baseclock += stepclock & (~1); + stepclock = stepclock >> 1; +#else stepclock /= pccore.multiple; - ch->baseclock += stepclock * pccore.multiple; + ch->s.baseclock += stepclock * pccore.multiple; +#endif intr = 0; pulse3 = 0; - // 0 - if (!(ch->cmd[0] & 0x02)) { + /* 0 */ + if (!(ch->s.cmd[0] & 0x02)) { pulse = stepclock; - count = ch->count[0]; + count = ch->s.count[0]; count -= pulse; if (count <= 0) { - pulse3 = (0 - count) / ch->countmax[0]; +#if defined(CTCFAST) + count += ch->s.countmax[0]; + if (count <= 0) { + pulse3 = (0 - count) / ch->s.countmax[0]; + pulse3 += 1; + count += pulse3 * ch->s.countmax[0]; + } pulse3 += 1; - count += pulse3 * ch->countmax[0]; - intr |= (ch->cmd[0] & 0x80) >> (7 - 0); +#else + pulse3 = (0 - count) / ch->s.countmax[0]; + pulse3 += 1; + count += pulse3 * ch->s.countmax[0]; +#endif + intr |= (ch->s.cmd[0] & 0x80) >> (7 - 0); } - ch->count[0] = count; + ch->s.count[0] = count; } - // 3 - if (!(ch->cmd[3] & 0x02)) { - if (!(ch->cmd[3] & 0x40)) { + /* 3 */ + if (!(ch->s.cmd[3] & 0x02)) { + if (!(ch->s.cmd[3] & 0x40)) { pulse3 = stepclock; } - count = ch->count[3]; + count = ch->s.count[3]; count -= pulse3; if (count <= 0) { - count = ch->countmax[3] - ((0 - count) % ch->countmax[3]); - intr |= (ch->cmd[3] & 0x80) >> (7 - 3); +#if defined(CTCFAST) + count += ch->s.countmax[3]; + if (count <= 0) { + count = ch->s.countmax[3] - ((0 - count) % ch->s.countmax[3]); + } +#else + count = ch->s.countmax[3] - ((0 - count) % ch->s.countmax[3]); +#endif + intr |= (ch->s.cmd[3] & 0x80) >> (7 - 3); +#if 0 + TRACEOUT(("<- ch.3 %.8x [%.2x:%.2x %.2x:%.2x]", baseclock, + ch->s.basecnt[0], ch->s.cmd[0], + ch->s.basecnt[3], ch->s.cmd[3])); +#endif } - ch->count[3] = count; + ch->s.count[3] = count; } - // 1 - if (!(ch->cmd[1] & 0x02)) { + /* 1 */ + if (!(ch->s.cmd[1] & 0x02)) { pulse = stepclock; - count = ch->count[1]; + count = ch->s.count[1]; count -= pulse; if (count <= 0) { - count = ch->countmax[1] - ((0 - count) % ch->countmax[1]); - intr |= (ch->cmd[1] & 0x80) >> (7 - 1); + count = ch->s.countmax[1] - ((0 - count) % ch->s.countmax[1]); + intr |= (ch->s.cmd[1] & 0x80) >> (7 - 1); } - ch->count[1] = count; + ch->s.count[1] = count; } - // 2 - if (!(ch->cmd[2] & 0x02)) { + /* 2 */ + if (!(ch->s.cmd[2] & 0x02)) { pulse = stepclock; - count = ch->count[2]; + count = ch->s.count[2]; count -= pulse; if (count <= 0) { - count = ch->countmax[2] - ((0 - count) % ch->countmax[2]); - intr |= (ch->cmd[2] & 0x80) >> (7 - 2); + count = ch->s.countmax[2] - ((0 - count) % ch->s.countmax[2]); + intr |= (ch->s.cmd[2] & 0x80) >> (7 - 2); } - ch->count[2] = count; + ch->s.count[2] = count; } return(intr); } @@ -110,8 +149,8 @@ static void ctcstep(CTCCH *ch) { intr = ctcwork(ch); if (intr) { - ch->intr |= intr; - ievent_set(IEVENT_CTC0 + ch->num); + ch->s.intr |= intr; + ievent_set(IEVENT_CTC0 + ch->s.num); } } @@ -119,11 +158,15 @@ static void ctcnextevent(CTCCH *ch) { UINT32 event; - if (ch->intr) { + if (ch->s.intr) { return; } +#if defined(FIX_Z80A) + event = minclock(ch) * 2; +#else event = minclock(ch) * pccore.multiple; - nevent_set(NEVENT_CTC0 + ch->num, event, neitem_ctc, NEVENT_ABSOLUTE); +#endif + nevent_set(NEVENT_CTC0 + ch->s.num, event, neitem_ctc, NEVENT_ABSOLUTE); } void neitem_ctc(UINT id) { @@ -134,8 +177,8 @@ void neitem_ctc(UINT id) { ch = ctc.ch + (id - NEVENT_CTC0); intr = ctcwork(ch); if (intr) { - ch->intr |= intr; - ievent_set(IEVENT_CTC0 + ch->num); + ch->s.intr |= intr; + ievent_set(IEVENT_CTC0 + ch->s.num); } else { ctcnextevent(ch); @@ -152,41 +195,32 @@ BRESULT ieitem_ctc(UINT id) { ch = ctc.ch + (id - IEVENT_CTC0); intr = ctcwork(ch); - intr |= ch->intr; + intr |= ch->s.intr; r = FALSE; if (intr) { -// for (i=0, bit=1; i<4; i++, bit<<=1) +#if 1 + for (i=0, bit=1; i<4; i++, bit<<=1) +#else /* 1 */ for (i=4, bit=8; i--; bit>>=1) +#endif /* 1 */ { if (intr & bit) { - if (!(ch->cmd[i] & 0x80)) { - intr ^= bit; - } -#if 0 // アークスのタイミング→あとで修正 - else if (0) -#elif 1 - if ((ch->countmax[i] - ch->count[i]) >= ch->range[i]) -#elif 0 - else if (((ch->cmd[i] & 0x10) == 0) && - ((ch->countmax[i] - ch->count[i]) >= (256 >> 1))) -#else - else if (ch->count[i] != ch->countmax[i]) -#endif - { + if (!(ch->s.cmd[i] & 0x80)) { intr ^= bit; } else if (!r) { r = TRUE; intr ^= bit; -// TRACEOUT(("ctc int %d %d", ch->num, i)); - Z80_INTERRUPT((REG8)(ch->vector + (i << 1))); + ch->s.irq = (UINT8)i; + /* TRACEOUT(("ctc int %d %d [%.2x]", ch->s.num, i, ch->s.cmd[i])); */ + Z80_INTERRUPT((REG8)(ch->s.vector + (i << 1))); } } } } - ch->intr = intr; + ch->s.intr = intr; if (intr) { - ievent_set(IEVENT_CTC0 + ch->num); + ievent_set(IEVENT_CTC0 + ch->s.num); } else { ctcnextevent(ch); @@ -194,8 +228,33 @@ BRESULT ieitem_ctc(UINT id) { return(r); } +void ieeoi_ctc(UINT id) { + + CTCCH *ch; + REG8 intr; + UINT curirq; + + ch = ctc.ch + (id - IEVENT_CTC0); + intr = ctcwork(ch) | ch->s.intr; + curirq = ch->s.irq; + if (intr & (1 << curirq)) { /* 割り込み中に割り込んだ… */ + /* カウンタが0でなければ割り込みを消す */ + if ((ch->s.countmax[curirq] - ch->s.count[curirq]) + >= ch->s.range[curirq]) { + intr ^= (1 << curirq); + } + } + ch->s.intr = intr; + if (intr) { + ievent_set(id); + } + else { + ctcnextevent(ch); + } +} + -// ---- +/* ---- */ static void ctcch_o(CTCCH *ch, UINT port, REG8 value) { @@ -203,34 +262,33 @@ static void ctcch_o(CTCCH *ch, UINT port REG8 scale; port &= 3; - if (ch->cmd[port] & 0x04) { + if (ch->s.cmd[port] & 0x04) { ctcstep(ch); - ch->basecnt[port] = value; + ch->s.basecnt[port] = value; count = ((value - 1) & 0xff) + 1; scale = 0; - if (!(ch->cmd[port] & 0x40)) { - if (ch->cmd[port] & 0x20) { + if (!(ch->s.cmd[port] & 0x40)) { + if (ch->s.cmd[port] & 0x20) { scale = 8 - 1; } else { scale = 4 - 1; } } - ch->scale[port] = scale; - ch->countmax[port] = count << scale; - ch->count[port] = count << scale; -// ch->range[port] = ((count + 3) >> 2) << scale; - ch->range[port] = 4 << scale; - ch->cmd[port] &= ~6; + ch->s.scale[port] = scale; + ch->s.countmax[port] = count << scale; + ch->s.count[port] = count << scale; + ch->s.range[port] = 1 << scale; + ch->s.cmd[port] &= ~6; ctcnextevent(ch); } else if (value & 1) { ctcstep(ch); - ch->cmd[port] = value; + ch->s.cmd[port] = value; ctcnextevent(ch); } - else if (!port) { // ver0.25 - ch->vector = (UINT8)(value & 0xf8); + else if (!port) { /* ver0.25 */ + ch->s.vector = (UINT8)(value & 0xf8); } } @@ -238,28 +296,28 @@ static REG8 ctcch_i(CTCCH *ch, UINT port port &= 3; if (port != 3) { - return(ch->basecnt[port]); + return(ch->s.basecnt[port]); } else { ctcstep(ch); - return((REG8)(ch->count[3] >> ch->scale[3])); + return((REG8)(ch->s.count[3] >> ch->s.scale[3])); } } -// ---- +/* ---- */ static CTCCH *getctcch(UINT port) { port &= ~3; if (port == 0x1fa0) { - return(ctc.ch + 0); + return(ctc.ch + CTC_TURBO1); } if (port == 0x1fa8) { - return(ctc.ch + 1); + return(ctc.ch + CTC_TURBO2); } if (port == 0x0704) { - return(ctc.ch + 2); + return(ctc.ch + CTC_OPM); } return(NULL); } @@ -268,7 +326,7 @@ void IOOUTCALL ctc_o(UINT port, REG8 val CTCCH *ch; - TRACEOUT(("ctc - %.4x %.2x [%.4x]", port, value, Z80_PC)); + /* TRACEOUT(("ctc - %.4x %.2x [%.4x]", port, value, Z80_PC)); */ ch = getctcch(port); if (ch != NULL) { ctcch_o(ch, port, value); @@ -289,7 +347,7 @@ REG8 IOINPCALL ctc_i(UINT port) { } -// ---- +/* ---- */ void ctc_reset(void) { @@ -298,12 +356,12 @@ void ctc_reset(void) { ZeroMemory(&ctc, sizeof(ctc)); for (i=0; i<3; i++) { - ctc.ch[i].num = (UINT8)i; + ctc.ch[i].s.num = (UINT8)i; for (j=0; j<4; j++) { - ctc.ch[i].cmd[j] = 0x23; - ctc.ch[i].scale[j] = 7; - ctc.ch[i].count[j] = 256 << 7; - ctc.ch[i].countmax[j] = 256 << 7; + ctc.ch[i].s.cmd[j] = 0x23; + ctc.ch[i].s.scale[j] = 7; + ctc.ch[i].s.count[j] = 256 << 7; + ctc.ch[i].s.countmax[j] = 256 << 7; } } }