Diff for /xmil/io/ctc.c between versions 1.12 and 1.18

version 1.12, 2004/08/14 12:16:17 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];
                         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];
                 }                  }
                 event = min(event, clock);                  event = min(event, clock);
         }          }
Line 42  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;                  pulse = stepclock;
                 count = ch->count[0];                  count = ch->s.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;                          pulse3 += 1;
                         count += pulse3 * ch->countmax[0];  #else
                         intr |= (ch->cmd[0] & 0x80) >> (7 - 0);                          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          /* 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;                          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];
 TRACEOUT(("ctc3 !"));                          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;                  pulse = stepclock;
                 count = ch->count[1];                  count = ch->s.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;                  pulse = stepclock;
                 count = ch->count[2];                  count = ch->s.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 111  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 120  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 135  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 153  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 (!(ch->cmd[i] & 0x80)) {                                  if (!(ch->s.cmd[i] & 0x80)) {
                                         intr ^= bit;  
                                 }  
 #if 0                   // アークスのタイミング→あとで修正  
                                 else if (0)  
 #elif 1  
                                 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  
                                 {  
                                         intr ^= bit;                                          intr ^= bit;
                                 }                                  }
                                 else if (!r) {                                  else if (!r) {
                                         r = TRUE;                                          r = TRUE;
                                         intr ^= bit;                                          intr ^= bit;
                                         TRACEOUT(("ctc int %d %d", ch->num, 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 191  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 200  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 = ((value - 1) & 0xff) + 1;                  count = ((value - 1) & 0xff) + 1;
                 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 - 1;                                  scale = 8 - 1;
                         }                          }
                         else {                          else {
                                 scale = 4 - 1;                                  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 234  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 264  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 285  REG8 IOINPCALL ctc_i(UINT port) { Line 347  REG8 IOINPCALL ctc_i(UINT port) {
 }  }
   
   
 // ----  /* ---- */
   
 void ctc_reset(void) {  void ctc_reset(void) {
   
Line 294  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] = 0x23;                          ctc.ch[i].s.cmd[j] = 0x23;
                         ctc.ch[i].scale[j] = 7;                          ctc.ch[i].s.scale[j] = 7;
                         ctc.ch[i].count[j] = 256 << 7;                          ctc.ch[i].s.count[j] = 256 << 7;
                         ctc.ch[i].countmax[j] = 256 << 7;                          ctc.ch[i].s.countmax[j] = 256 << 7;
                 }                  }
         }          }
 }  }

Removed from v.1.12  
changed lines
  Added in v.1.18


RetroPC.NET-CVS <cvs@retropc.net>