| version 1.2, 2004/08/04 10:49:21 | version 1.5, 2004/08/11 12:08:16 | 
| Line 2 | Line 2 | 
 | #include        "z80core.h" | #include        "z80core.h" | 
 | #include        "pccore.h" | #include        "pccore.h" | 
 | #include        "iocore.h" | #include        "iocore.h" | 
 |  | #include        "nevent.h" | 
 |  | #include        "ievent.h" | 
 |  |  | 
 |  |  | 
 |  | static REG8 ctcwork(CTCCH *ch) { | 
 |  |  | 
 |  | UINT32  baseclock; | 
 |  | SINT32  stepclock; | 
 |  | REG8    intr; | 
 |  | SINT32  pulse3; | 
 |  | SINT32  pulse; | 
 |  | SINT32  count; | 
 |  |  | 
 |  | baseclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; | 
 |  | stepclock = baseclock - ch->baseclock; | 
 |  | stepclock /= pccore.multiple; | 
 |  | ch->baseclock += stepclock * pccore.multiple; | 
 |  |  | 
 |  | intr = 0; | 
 |  | pulse3 = 0; | 
 |  |  | 
 |  | // 0 | 
 |  | if (!(ch->cmd[0] & 0x02)) { | 
 |  | pulse = stepclock;                                      // 2MHz | 
 |  | if (!(ch->cmd[0] & 0x40)) { | 
 |  | pulse = pulse * 2;                              // 4MHz | 
 |  | } | 
 |  | count = ch->count[0]; | 
 |  | count -= pulse; | 
 |  | if (count <= 0) { | 
 |  | pulse3 = (0 - count) / ch->countmax[0]; | 
 |  | pulse3 += 1; | 
 |  | count += pulse3 * ch->countmax[0]; | 
 |  | intr |= (ch->cmd[0] & 0x80) >> (7 - 0); | 
 |  | } | 
 |  | ch->count[0] = count; | 
 |  | } | 
 |  |  | 
 |  | // 3 | 
 |  | if (!(ch->cmd[3] & 0x02)) { | 
 |  | if (!(ch->cmd[3] & 0x40)) { | 
 |  | pulse3 = stepclock * 2;                         // 4MHz | 
 |  | } | 
 |  | count = ch->count[3]; | 
 |  | count -= pulse3; | 
 |  | if (count <= 0) { | 
 |  | count = ch->countmax[3] - ((0 - count) % ch->countmax[3]); | 
 |  | intr |= (ch->cmd[3] & 0x80) >> (7 - 3); | 
 |  | } | 
 |  | ch->count[3] = count; | 
 |  | } | 
 |  |  | 
 |  | // 1 | 
 |  | if (!(ch->cmd[1] & 0x02)) { | 
 |  | pulse = stepclock;                                      // 2MHz | 
 |  | if (!(ch->cmd[1] & 0x40)) { | 
 |  | pulse = pulse * 2;                              // 4MHz | 
 |  | } | 
 |  | count = ch->count[1]; | 
 |  | count -= pulse; | 
 |  | if (count <= 0) { | 
 |  | count = ch->countmax[1] - ((0 - count) % ch->countmax[1]); | 
 |  | intr |= (ch->cmd[1] & 0x80) >> (7 - 1); | 
 |  | } | 
 |  | ch->count[1] = count; | 
 |  | } | 
 |  |  | 
 |  | // 2 | 
 |  | if (!(ch->cmd[2] & 0x02)) { | 
 |  | pulse = stepclock;                                      // 2MHz | 
 |  | if (!(ch->cmd[2] & 0x40)) { | 
 |  | pulse = pulse * 2;                              // 4MHz | 
 |  | } | 
 |  | count = ch->count[2]; | 
 |  | count -= pulse; | 
 |  | if (count <= 0) { | 
 |  | count = ch->countmax[2] - ((0 - count) % ch->countmax[2]); | 
 |  | intr |= (ch->cmd[2] & 0x80) >> (7 - 2); | 
 |  | } | 
 |  | ch->count[2] = count; | 
 |  | } | 
 |  | return(intr); | 
 |  | } | 
 |  |  | 
 |  | static void ctcstep(CTCCH *ch) { | 
 |  |  | 
 |  | REG8    intr; | 
 |  |  | 
 |  | intr = ctcwork(ch); | 
 |  | if (intr) { | 
 |  | ch->intr |= intr; | 
 |  | TRACEOUT(("-> ievent_set")); | 
 |  | ievent_set(IEVENT_CTC0 + ch->num); | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | static void ctcnextevent(CTCCH *ch) { | 
 |  |  | 
 |  | UINT32  event; | 
 |  | UINT    i; | 
 |  | UINT32  clock; | 
 |  |  | 
 |  | if (ch->intr) { | 
 |  | return; | 
 |  | } | 
 |  | event = 0x04000000; | 
 |  | for (i=0; i<3; i++) { | 
 |  | if ((ch->cmd[i] & 0x82) == 0x80) { | 
 |  | clock = ch->count[i]; | 
 |  | if (ch->cmd[i] & 0x40) { | 
 |  | clock = clock * 2; | 
 |  | } | 
 |  | TRACEOUT(("ch %d -> %d :%.2x:%.8x", i, clock, ch->cmd[i], ch->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->cmd[0] & 0x40) { | 
 |  | clock = clock * 2; | 
 |  | } | 
 |  | } | 
 |  | TRACEOUT(("ch %d -> %d", 3, clock)); | 
 |  | event = min(event, clock); | 
 |  | } | 
 |  | event /= 2; | 
 |  | event *= pccore.multiple; | 
 |  | nevent_set(NEVENT_CTC0 + ch->num, event, neitem_ctc, NEVENT_ABSOLUTE); | 
 |  | TRACEOUT(("ctc -> %d (%x)", event, event)); | 
 |  | } | 
 |  |  | 
 |  | void neitem_ctc(UINT id) { | 
 |  |  | 
 |  | CTCCH   *ch; | 
 |  | REG8    intr; | 
 |  |  | 
 |  | ch = ctc.ch + (id - NEVENT_CTC0); | 
 |  | intr = ctcwork(ch); | 
 |  | if (intr) { | 
 |  | ch->intr |= intr; | 
 |  | TRACEOUT(("-> ievent_set")); | 
 |  | ievent_set(IEVENT_CTC0 + ch->num); | 
 |  | } | 
 |  | else { | 
 |  | ctcnextevent(ch); | 
 |  | } | 
 |  | } | 
 |  |  | 
 |  | BRESULT ieitem_ctc(UINT id) { | 
 |  |  | 
 |  | CTCCH   *ch; | 
 |  | REG8    intr; | 
 |  | BRESULT r; | 
 |  | UINT    i; | 
 |  | REG8    bit; | 
 |  |  | 
 |  | ch = ctc.ch + (id - IEVENT_CTC0); | 
 |  | intr = ctcwork(ch); | 
 |  | intr |= ch->intr; | 
 |  | TRACEOUT(("ieitem_ctc %d - %.2x", id - IEVENT_CTC0, intr)); | 
 |  | r = FALSE; | 
 |  | if (intr) { | 
 |  | for (i=0, bit=1; i<4; i++, bit<<=1) { | 
 |  | if (intr & bit) { | 
 |  | #if 1                   // アークスのタイミング→あとで修正 | 
 |  | if (0) | 
 |  | #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; | 
 |  | } | 
 |  | else if (!r) { | 
 |  | r = TRUE; | 
 |  | intr ^= bit; | 
 |  | TRACEOUT(("z80int %d", i)); | 
 |  | Z80_INT((REG8)(ch->vector + (i << 1))); | 
 |  | } | 
 |  | } | 
 |  | } | 
 |  | } | 
 |  | TRACEOUT(("--> %.2x", intr)); | 
 |  | ch->intr = intr; | 
 |  | if (intr) { | 
 |  | TRACEOUT(("-> ievent_set")); | 
 |  | ievent_set(IEVENT_CTC0 + ch->num); | 
 |  | } | 
 |  | else { | 
 |  | ctcnextevent(ch); | 
 |  | } | 
 |  | return(r); | 
 |  | } | 
 |  |  | 
 |  |  | 
 |  |  | 
 |  |  | 
 |  | #if 0 | 
 | void x1_ctc_int(void) { | void x1_ctc_int(void) { | 
 |  |  | 
 | CTCCH   *ch; | CTCCH   *ch; | 
| Line 67  void x1_ctc_int(void) { | Line 270  void x1_ctc_int(void) { | 
 | else if (ctcint_flg) { | else if (ctcint_flg) { | 
 | ctcint_flg = 0; | ctcint_flg = 0; | 
 | ch->int_flag ^= bit; | ch->int_flag ^= bit; | 
| TRACEOUT(("ctc%u int -- %d", 3 - r, i)); | //                                      TRACEOUT(("ctc%u int -- %d", 3 - r, i)); | 
 | Z80_INT((REG8)(ch->vector + (i << 1))); | Z80_INT((REG8)(ch->vector + (i << 1))); | 
 | } | } | 
 | } | } | 
| Line 76  void x1_ctc_int(void) { | Line 279  void x1_ctc_int(void) { | 
 | ch++; | ch++; | 
 | } while(--r); | } while(--r); | 
 | } | } | 
 |  | #endif | 
 |  |  | 
 |  |  | 
 | // ---- | // ---- | 
 |  |  | 
 | static void ctcch_o(CTCCH *ch, UINT port, REG8 value) { | static void ctcch_o(CTCCH *ch, UINT port, REG8 value) { | 
 |  |  | 
 | REG8    scale; |  | 
 | SINT32  count; | SINT32  count; | 
 |  | REG8    scale; | 
 |  |  | 
 | port &= 3; | port &= 3; | 
 | if (ch->cmd[port] & 0x04) { | if (ch->cmd[port] & 0x04) { | 
| scale = 0; | ctcstep(ch); | 
| count = 256; |  | 
 | ch->basecnt[port] = value; | ch->basecnt[port] = value; | 
 |  | count = 256; | 
 | if (value) { | if (value) { | 
 | count = (SINT32)value; | count = (SINT32)value; | 
 | } | } | 
 |  | scale = 0; | 
 | if (!(ch->cmd[port] & 0x40)) { | if (!(ch->cmd[port] & 0x40)) { | 
 | if (ch->cmd[port] & 0x20) { | if (ch->cmd[port] & 0x20) { | 
 | scale = 8; | scale = 8; | 
| Line 105  static void ctcch_o(CTCCH *ch, UINT port | Line 310  static void ctcch_o(CTCCH *ch, UINT port | 
 | ch->countmax[port] = count; | ch->countmax[port] = count; | 
 | ch->count[port] = count; | ch->count[port] = count; | 
 | ch->cmd[port] &= ~6; | ch->cmd[port] &= ~6; | 
 |  | ctcnextevent(ch); | 
 | } | } | 
 | else if (value & 1) { | else if (value & 1) { | 
 |  | ctcstep(ch); | 
 | ch->cmd[port] = value; | ch->cmd[port] = value; | 
 |  | ctcnextevent(ch); | 
 | } | } | 
 | else if (!port) {                                                                                               // ver0.25 | else if (!port) {                                                                                               // ver0.25 | 
 | ch->vector = (UINT8)(value & 0xf8); | ch->vector = (UINT8)(value & 0xf8); | 
| Line 116  static void ctcch_o(CTCCH *ch, UINT port | Line 324  static void ctcch_o(CTCCH *ch, UINT port | 
 |  |  | 
 | static REG8 ctcch_i(CTCCH *ch, UINT port) { | static REG8 ctcch_i(CTCCH *ch, UINT port) { | 
 |  |  | 
| UINT    scale; | REG8    scale; | 
 |  |  | 
 | port &= 3; | port &= 3; | 
 | if (port != 3) { | if (port != 3) { | 
 | return(ch->basecnt[port]); | return(ch->basecnt[port]); | 
 | } | } | 
 | else { | else { | 
 |  | ctcstep(ch); | 
 | scale = 0; | scale = 0; | 
 | if (!(ch->cmd[3] & 0x40)) { | if (!(ch->cmd[3] & 0x40)) { | 
 | if (ch->cmd[3] & 0x20) { | if (ch->cmd[3] & 0x20) { | 
| Line 148  static CTCCH *getctcch(UINT port) { | Line 357  static CTCCH *getctcch(UINT port) { | 
 | if (port == 0x1fa8) { | if (port == 0x1fa8) { | 
 | return(ctc.ch + 1); | return(ctc.ch + 1); | 
 | } | } | 
| if ((pccore.SOUND_SW) && (port == 0x0704)) { | if (port == 0x0704) { | 
 | return(ctc.ch + 2); | return(ctc.ch + 2); | 
 | } | } | 
 | return(NULL); | return(NULL); | 
| Line 174  REG8 IOINPCALL ctc_i(UINT port) { | Line 383  REG8 IOINPCALL ctc_i(UINT port) { | 
 | return(ctcch_i(ch, port)); | return(ctcch_i(ch, port)); | 
 | } | } | 
 | else { | else { | 
| return((REG8)0xff); | return(0xff); | 
 | } | } | 
 | } | } | 
 |  |  | 
| Line 183  REG8 IOINPCALL ctc_i(UINT port) { | Line 392  REG8 IOINPCALL ctc_i(UINT port) { | 
 |  |  | 
 | void ctc_reset(void) { | void ctc_reset(void) { | 
 |  |  | 
| UINT    i, j; | UINT    i; | 
|  | UINT    j; | 
 |  |  | 
 | 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; | 
 | for (j=0; j<4; j++) { | for (j=0; j<4; j++) { | 
| ctc.ch[i].cmd[j] = 0x83; | ctc.ch[i].cmd[j] = 0x03; | 
|  | ctc.ch[i].count[j] = 256 << 8; | 
|  | ctc.ch[i].countmax[j] = 256 << 8; | 
 | } | } | 
 | } | } | 
 | } | } |