|
|
| version 1.8, 2004/08/13 01:35:59 | version 1.18, 2008/06/02 20:07:31 |
|---|---|
| Line 1 | Line 1 |
| /* #define CTCCOUNTER */ | |
| #define CTCFAST | |
| #include "compiler.h" | #include "compiler.h" |
| #include "z80core.h" | #include "z80core.h" |
| #include "pccore.h" | #include "pccore.h" |
| Line 6 | Line 10 |
| #include "ievent.h" | #include "ievent.h" |
| #if defined(TRACE) && defined(CTCCOUNTER) | |
| extern UINT ctccnt; | |
| #endif | |
| static SINT32 minclock(const CTCCH *ch) { | static SINT32 minclock(const CTCCH *ch) { |
| UINT32 event; | UINT32 event; |
| Line 14 static SINT32 minclock(const CTCCH *ch) | Line 22 static SINT32 minclock(const CTCCH *ch) |
| event = 0x01000000; | event = 0x01000000; |
| for (i=0; i<3; i++) { | for (i=0; i<3; i++) { |
| if ((ch->cmd[i] & 0x82) == 0x80) { | if ((ch->s.cmd[i] & 0x82) == 0x80) { |
| clock = ch->count[i]; | clock = ch->s.count[i]; |
| if (ch->cmd[i] & 0x40) { | |
| clock = clock * 2; | |
| } | |
| event = min(event, clock); | event = min(event, clock); |
| } | } |
| } | } |
| if ((ch->cmd[3] & 0x82) == 0x80) { | if ((ch->s.cmd[3] & 0x82) == 0x80) { |
| clock = ch->count[3]; | clock = ch->s.count[3]; |
| if (ch->cmd[3] & 0x40) { | if (ch->s.cmd[3] & 0x40) { |
| clock = (clock - 1) * ch->countmax[0]; | clock = (clock - 1) * ch->s.countmax[0]; |
| clock += ch->count[0]; | clock += ch->s.count[0]; |
| if (ch->cmd[0] & 0x40) { | |
| clock = clock * 2; | |
| } | |
| } | } |
| event = min(event, clock); | event = min(event, clock); |
| } | } |
| event = event / 2; | |
| if (event == 0) { | if (event == 0) { |
| event = 1; | event = 1; |
| } | } |
| Line 49 static REG8 ctcwork(CTCCH *ch) { | Line 50 static REG8 ctcwork(CTCCH *ch) { |
| SINT32 pulse; | SINT32 pulse; |
| SINT32 count; | SINT32 count; |
| #if defined(TRACE) && defined(CTCCOUNTER) | |
| ctccnt++; | |
| #endif | |
| baseclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; | 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; | stepclock /= pccore.multiple; |
| ch->baseclock += stepclock * pccore.multiple; | ch->s.baseclock += stepclock * pccore.multiple; |
| #endif | |
| intr = 0; | intr = 0; |
| pulse3 = 0; | pulse3 = 0; |
| // 0 | /* 0 */ |
| if (!(ch->cmd[0] & 0x02)) { | if (!(ch->s.cmd[0] & 0x02)) { |
| pulse = stepclock; // 2MHz | pulse = stepclock; |
| if (!(ch->cmd[0] & 0x40)) { | count = ch->s.count[0]; |
| pulse = pulse * 2; // 4MHz | |
| } | |
| count = ch->count[0]; | |
| count -= pulse; | count -= pulse; |
| if (count <= 0) { | 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; | |
| #else | |
| pulse3 = (0 - count) / ch->s.countmax[0]; | |
| pulse3 += 1; | pulse3 += 1; |
| count += pulse3 * ch->countmax[0]; | count += pulse3 * ch->s.countmax[0]; |
| intr |= (ch->cmd[0] & 0x80) >> (7 - 0); | #endif |
| intr |= (ch->s.cmd[0] & 0x80) >> (7 - 0); | |
| } | } |
| ch->count[0] = count; | ch->s.count[0] = count; |
| } | } |
| // 3 | /* 3 */ |
| if (!(ch->cmd[3] & 0x02)) { | if (!(ch->s.cmd[3] & 0x02)) { |
| if (!(ch->cmd[3] & 0x40)) { | if (!(ch->s.cmd[3] & 0x40)) { |
| pulse3 = stepclock * 2; // 4MHz | pulse3 = stepclock; |
| } | } |
| count = ch->count[3]; | count = ch->s.count[3]; |
| count -= pulse3; | count -= pulse3; |
| if (count <= 0) { | if (count <= 0) { |
| count = ch->countmax[3] - ((0 - count) % ch->countmax[3]); | #if defined(CTCFAST) |
| intr |= (ch->cmd[3] & 0x80) >> (7 - 3); | 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 | /* 1 */ |
| if (!(ch->cmd[1] & 0x02)) { | if (!(ch->s.cmd[1] & 0x02)) { |
| pulse = stepclock; // 2MHz | pulse = stepclock; |
| if (!(ch->cmd[1] & 0x40)) { | count = ch->s.count[1]; |
| pulse = pulse * 2; // 4MHz | |
| } | |
| count = ch->count[1]; | |
| count -= pulse; | count -= pulse; |
| if (count <= 0) { | if (count <= 0) { |
| count = ch->countmax[1] - ((0 - count) % ch->countmax[1]); | count = ch->s.countmax[1] - ((0 - count) % ch->s.countmax[1]); |
| intr |= (ch->cmd[1] & 0x80) >> (7 - 1); | intr |= (ch->s.cmd[1] & 0x80) >> (7 - 1); |
| } | } |
| ch->count[1] = count; | ch->s.count[1] = count; |
| } | } |
| // 2 | /* 2 */ |
| if (!(ch->cmd[2] & 0x02)) { | if (!(ch->s.cmd[2] & 0x02)) { |
| pulse = stepclock; // 2MHz | pulse = stepclock; |
| if (!(ch->cmd[2] & 0x40)) { | count = ch->s.count[2]; |
| pulse = pulse * 2; // 4MHz | |
| } | |
| count = ch->count[2]; | |
| count -= pulse; | count -= pulse; |
| if (count <= 0) { | if (count <= 0) { |
| count = ch->countmax[2] - ((0 - count) % ch->countmax[2]); | count = ch->s.countmax[2] - ((0 - count) % ch->s.countmax[2]); |
| intr |= (ch->cmd[2] & 0x80) >> (7 - 2); | intr |= (ch->s.cmd[2] & 0x80) >> (7 - 2); |
| } | } |
| ch->count[2] = count; | ch->s.count[2] = count; |
| } | } |
| return(intr); | return(intr); |
| } | } |
| Line 126 static void ctcstep(CTCCH *ch) { | Line 149 static void ctcstep(CTCCH *ch) { |
| intr = ctcwork(ch); | intr = ctcwork(ch); |
| if (intr) { | if (intr) { |
| ch->intr |= intr; | ch->s.intr |= intr; |
| ievent_set(IEVENT_CTC0 + ch->num); | ievent_set(IEVENT_CTC0 + ch->s.num); |
| } | } |
| } | } |
| Line 135 static void ctcnextevent(CTCCH *ch) { | Line 158 static void ctcnextevent(CTCCH *ch) { |
| UINT32 event; | UINT32 event; |
| if (ch->intr) { | if (ch->s.intr) { |
| return; | return; |
| } | } |
| #if defined(FIX_Z80A) | |
| event = minclock(ch) * 2; | |
| #else | |
| event = minclock(ch) * pccore.multiple; | 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) { | void neitem_ctc(UINT id) { |
| Line 150 void neitem_ctc(UINT id) { | Line 177 void neitem_ctc(UINT id) { |
| ch = ctc.ch + (id - NEVENT_CTC0); | ch = ctc.ch + (id - NEVENT_CTC0); |
| intr = ctcwork(ch); | intr = ctcwork(ch); |
| if (intr) { | if (intr) { |
| ch->intr |= intr; | ch->s.intr |= intr; |
| ievent_set(IEVENT_CTC0 + ch->num); | ievent_set(IEVENT_CTC0 + ch->s.num); |
| } | } |
| else { | else { |
| ctcnextevent(ch); | ctcnextevent(ch); |
| Line 168 BRESULT ieitem_ctc(UINT id) { | Line 195 BRESULT ieitem_ctc(UINT id) { |
| ch = ctc.ch + (id - IEVENT_CTC0); | ch = ctc.ch + (id - IEVENT_CTC0); |
| intr = ctcwork(ch); | intr = ctcwork(ch); |
| intr |= ch->intr; | intr |= ch->s.intr; |
| r = FALSE; | r = FALSE; |
| if (intr) { | 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 (intr & bit) { |
| #if 0 // アークスのタイミング→あとで修正 | if (!(ch->s.cmd[i] & 0x80)) { |
| if (0) | |
| #elif 1 | |
| if ((ch->countmax[i] - ch->count[i]) >= 256) | |
| #elif 0 | |
| if (((ch->count[i] * 17) >> 4) < ch->countmax[i]) | |
| #else | |
| if (ch->count[i] != ch->countmax[i]) | |
| #endif | |
| { | |
| intr ^= bit; | |
| } | |
| else if (!(ch->cmd[i] & 0x80)) { | |
| intr ^= bit; | intr ^= bit; |
| } | } |
| else if (!r) { | else if (!r) { |
| r = TRUE; | r = TRUE; |
| intr ^= bit; | intr ^= bit; |
| // TRACEOUT(("ctc int %d", i)); | ch->s.irq = (UINT8)i; |
| Z80_INTERRUPT((REG8)(ch->vector + (i << 1))); | /* 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) { | if (intr) { |
| ievent_set(IEVENT_CTC0 + ch->num); | ievent_set(IEVENT_CTC0 + ch->s.num); |
| } | } |
| else { | else { |
| ctcnextevent(ch); | ctcnextevent(ch); |
| Line 207 BRESULT ieitem_ctc(UINT id) { | Line 228 BRESULT ieitem_ctc(UINT id) { |
| return(r); | 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) { | static void ctcch_o(CTCCH *ch, UINT port, REG8 value) { |
| Line 216 static void ctcch_o(CTCCH *ch, UINT port | Line 262 static void ctcch_o(CTCCH *ch, UINT port |
| REG8 scale; | REG8 scale; |
| port &= 3; | port &= 3; |
| if (ch->cmd[port] & 0x04) { | if (ch->s.cmd[port] & 0x04) { |
| ctcstep(ch); | ctcstep(ch); |
| ch->basecnt[port] = value; | ch->s.basecnt[port] = value; |
| count = 256; | count = ((value - 1) & 0xff) + 1; |
| if (value) { | |
| count = (SINT32)value; | |
| } | |
| scale = 0; | scale = 0; |
| if (!(ch->cmd[port] & 0x40)) { | if (!(ch->s.cmd[port] & 0x40)) { |
| if (ch->cmd[port] & 0x20) { | if (ch->s.cmd[port] & 0x20) { |
| scale = 8; | scale = 8 - 1; |
| } | } |
| else { | else { |
| scale = 4; | scale = 4 - 1; |
| } | } |
| } | } |
| count <<= scale; | ch->s.scale[port] = scale; |
| ch->scale[port] = scale; | ch->s.countmax[port] = count << scale; |
| ch->countmax[port] = count; | ch->s.count[port] = count << scale; |
| ch->count[port] = count; | ch->s.range[port] = 1 << scale; |
| ch->cmd[port] &= ~6; | ch->s.cmd[port] &= ~6; |
| ctcnextevent(ch); | ctcnextevent(ch); |
| } | } |
| else if (value & 1) { | else if (value & 1) { |
| ctcstep(ch); | ctcstep(ch); |
| ch->cmd[port] = value; | ch->s.cmd[port] = value; |
| ctcnextevent(ch); | ctcnextevent(ch); |
| } | } |
| else if (!port) { // ver0.25 | else if (!port) { /* ver0.25 */ |
| ch->vector = (UINT8)(value & 0xf8); | ch->s.vector = (UINT8)(value & 0xf8); |
| } | } |
| } | } |
| Line 253 static REG8 ctcch_i(CTCCH *ch, UINT port | Line 296 static REG8 ctcch_i(CTCCH *ch, UINT port |
| port &= 3; | port &= 3; |
| if (port != 3) { | if (port != 3) { |
| return(ch->basecnt[port]); | return(ch->s.basecnt[port]); |
| } | } |
| else { | else { |
| ctcstep(ch); | 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) { | static CTCCH *getctcch(UINT port) { |
| port &= ~3; | port &= ~3; |
| if (port == 0x1fa0) { | if (port == 0x1fa0) { |
| return(ctc.ch + 0); | return(ctc.ch + CTC_TURBO1); |
| } | } |
| if (port == 0x1fa8) { | if (port == 0x1fa8) { |
| return(ctc.ch + 1); | return(ctc.ch + CTC_TURBO2); |
| } | } |
| if (port == 0x0704) { | if (port == 0x0704) { |
| return(ctc.ch + 2); | return(ctc.ch + CTC_OPM); |
| } | } |
| return(NULL); | return(NULL); |
| } | } |
| Line 283 void IOOUTCALL ctc_o(UINT port, REG8 val | Line 326 void IOOUTCALL ctc_o(UINT port, REG8 val |
| CTCCH *ch; | CTCCH *ch; |
| // TRACEOUT(("ctc - %.4x %.2x [%.4x]", port, value, Z80_PC)); | /* TRACEOUT(("ctc - %.4x %.2x [%.4x]", port, value, Z80_PC)); */ |
| ch = getctcch(port); | ch = getctcch(port); |
| if (ch != NULL) { | if (ch != NULL) { |
| ctcch_o(ch, port, value); | ctcch_o(ch, port, value); |
| Line 304 REG8 IOINPCALL ctc_i(UINT port) { | Line 347 REG8 IOINPCALL ctc_i(UINT port) { |
| } | } |
| // ---- | /* ---- */ |
| void ctc_reset(void) { | void ctc_reset(void) { |
| Line 313 void ctc_reset(void) { | Line 356 void ctc_reset(void) { |
| ZeroMemory(&ctc, sizeof(ctc)); | ZeroMemory(&ctc, sizeof(ctc)); |
| for (i=0; i<3; i++) { | 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++) { | for (j=0; j<4; j++) { |
| ctc.ch[i].cmd[j] = 0x03; | ctc.ch[i].s.cmd[j] = 0x23; |
| ctc.ch[i].scale[j] = 8; | ctc.ch[i].s.scale[j] = 7; |
| ctc.ch[i].count[j] = 256 << 8; | ctc.ch[i].s.count[j] = 256 << 7; |
| ctc.ch[i].countmax[j] = 256 << 8; | ctc.ch[i].s.countmax[j] = 256 << 7; |
| } | } |
| } | } |
| } | } |