Diff for /xmil/io/dmac.c between versions 1.4 and 1.8

version 1.4, 2004/08/11 16:09:04 version 1.8, 2009/03/23 15:02:25
Line 6 Line 6
 #include        "ievent.h"  #include        "ievent.h"
   
   
 static REG8 iswork(const DMAC *d) {  #define DMACMD(a)       (((a) >> 2) & 0x1f)
   
         REG8    r;  
   
         r = d->cmd;  static REG8 iswork(const DMAC *d) {
         if ((r & 3) == 0) return(FALSE);  
         if (d->enable == 0) return(FALSE);          if (d->enable == 0) return(0);
         if (d->ENDB_FLG != 0) return(FALSE);                    // mod          if (!(d->WR0 & 3)) return(0);
         if (r & 2) {  #if !defined(DMAS_STOIC)
                 if (d->MACH_FLG != 0) return(FALSE);            // mod          if (d->ENDB_FLG != 0) return(0);
         }          if ((d->WR0 & 2) && (d->MACH_FLG != 0)) return(0);
   #else
           if (!(d->flag & DMAF_ENDB)) return(0);
           if ((d->WR0 & 2) && (!(d->flag & DMAF_MACH))) return(0);
   #endif
         if (d->mode != 1) {          if (d->mode != 1) {
                 if ((d->WR[5] ^ d->ready) & 8) return(FALSE);                  if ((d->WR5 ^ d->ready) & 8) return(0);
         }          }
         return(TRUE);          return(1);
 }  }
   
 void dmac_sendready(BRESULT ready) {  void dmac_sendready(BRESULT ready) {
   
           DMAC    *d;
         REG8    working;          REG8    working;
   
           d = &dma;
         if (!ready) {          if (!ready) {
                 dma.working = FALSE;  #if !defined(DMAS_STOIC)
                 dma.ready = 8;                  d->working = FALSE;
   #else
                   d->flag &= ~DMAF_WORKING;
   #endif
                   d->ready = 8;
         }          }
         else {          else {
                 dma.ready = 0;                  d->ready = 0;
                 working = iswork(&dma);                  working = iswork(&dma);
                 if (dma.working != working) {  #if !defined(DMAS_STOIC)
                         dma.working = working;                  if (d->working != working) {
                           d->working = working;
                           nevent_forceexit();
                   }
   #else
                   if ((d->flag ^ working) & DMAF_WORKING) {
                           d->flag ^= DMAF_WORKING;
                         nevent_forceexit();                          nevent_forceexit();
                 }                  }
   #endif
         }          }
 }  }
   
   
 BRESULT ieitem_dmac(UINT id) {  BRESULT ieitem_dmac(UINT id) {
   
           DMAC    *d;
         REG8    vect;          REG8    vect;
   
         if (dma.INT_ENBL) {          d = &dma;
           if (d->INT_ENBL) {
                 vect = 0;                  vect = 0;
                 if ((dma.INT_FLG & 1) && (dma.MACH_FLG)) {  #if !defined(DMAS_STOIC)
                   if ((d->INT_FLG & 1) && (d->MACH_FLG)) {
                           vect = 2;
                   }
                   else if ((d->INT_FLG & 2) && (d->ENDB_FLG)) {
                           vect = 4;
                   }
   #else
                   if ((d->INT_FLG & 1) && (!(d->flag & DMAF_MACH))) {
                         vect = 2;                          vect = 2;
                 }                  }
                 else if ((dma.INT_FLG & 2) && (dma.ENDB_FLG)) {                  else if ((d->INT_FLG & 2) && (!(d->flag & DMAF_ENDB))) {
                         vect = 4;                          vect = 4;
                 }                  }
   #endif
                 if (vect) {                  if (vect) {
                         if (dma.INT_FLG & 0x20) {                          if (d->INT_FLG & 0x20) {
                                 vect += (dma.INT_VCT & 0xf9);                                  vect += (d->INT_VCT & 0xf9);
                         }                          }
                         else {                          else {
                                 vect = dma.INT_VCT;                                  vect = d->INT_VCT;
                         }                          }
                         Z80_INTERRUPT(vect);                          Z80_INTERRUPT(vect);
                         return(TRUE);                          return(TRUE);
Line 69  BRESULT ieitem_dmac(UINT id) { Line 97  BRESULT ieitem_dmac(UINT id) {
 }  }
   
   
 // ----  /* ---- */
   
 static void setdmareaddat(void) {  static void setdmareaddat(DMAC *d) {
   
         UINT    cnt;  
         REG8    rrmsk;          REG8    rrmsk;
           UINT8   *ptr;
   
         cnt = 0;          rrmsk = d->RR_MSK;
         rrmsk = dma.RR_MSK;          ptr = d->rtbl;
         if (rrmsk & 0x01) {          if (rrmsk & 0x01) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, RR);                  *ptr++ = offsetof(DMAC, RR);
         }          }
         if (rrmsk & 0x02) {          if (rrmsk & 0x02) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, BYT_N.b.l);                  *ptr++ = offsetof(DMAC, leng.b.nl);
         }          }
         if (rrmsk & 0x04) {          if (rrmsk & 0x04) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, BYT_N.b.h);                  *ptr++ = offsetof(DMAC, leng.b.nh);
         }          }
         if (rrmsk & 0x08) {          if (rrmsk & 0x08) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_A.b.l);                  *ptr++ = offsetof(DMAC, cnt_a.b.addrl);
         }          }
         if (rrmsk & 0x10) {          if (rrmsk & 0x10) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_A.b.h);                  *ptr++ = offsetof(DMAC, cnt_a.b.addrh);
         }          }
         if (rrmsk & 0x20) {          if (rrmsk & 0x20) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_B.b.l);                  *ptr++ = offsetof(DMAC, cnt_b.b.addrl);
         }          }
         if (rrmsk & 0x40) {          if (rrmsk & 0x40) {
                 dma.RR_TBL[cnt++] = offsetof(DMAC, CNT_B.b.h);                  *ptr++ = offsetof(DMAC, cnt_b.b.addrh);
         }          }
         dma.RR_CNT = (UINT8)cnt;          d->rcnt = (UINT8)(ptr - d->rtbl);
         dma.RR_OFF = 0;          d->rptr = 0;
 }  }
   
   static void enable(DMAC *d) {
   
 void IOOUTCALL dmac_o(UINT port, REG8 value) {  
   
         REG8    wr;  
         REG8    working;          REG8    working;
   
         dma.enable = 0;          d->enable = 1;
           working = iswork(d);
         if (!dma.WR_CNT) {  #if !defined(DMAS_STOIC)
                 wr = 6;          if (d->working != working) {
                 dma.WR_CNT = 0;                  d->working = working;
                 dma.WR_OFF = 0;                  if (d->mode == 1) {
                 if (!(value & 0x80)) {                          z80dmap();
                         if ((value & 3) != 0) {  
                                 wr = 0;  
                         }  
                         else if (value & 4) {  
                                 wr = 1;  
                         }  
                         else {  
                                 wr = 2;  
                         }  
                 }                  }
                 else {                  else {
                         if ((value & 3) == 0) {                          nevent_forceexit();
                                 wr = 3;                  }
                         }          }
                         else if (((value & 3) == 1) && (value >> 5) != 7) {  #else
                                 wr = 4;          if ((d->flag ^ working) & DMAF_WORKING) {
                         }                  d->flag ^= DMAF_WORKING;
                         else if (((value & 7) == 2) && (!(value & 0x40))) {                  if (d->mode == 1) {
                                 wr = 5;                          z80dmap();
                         }  
                         else if ((value & 3) == 3) {  
                                 wr = 6;  
                         }  
                 }                  }
                 dma.WR[wr] = value;                  else {
                 switch(wr) {                          nevent_forceexit();
                         case 0:                  }
                                 dma.cmd = (UINT8)(value & 3);          }
   #endif
   }
   
   static void disable(DMAC *d) {
   
           if (!d->enable)
           {
                   d->enable = 0;
   #if !defined(DMAS_STOIC)
                   d->working = 0;
   #else
                   d->flag &= ~DMAF_WORKING;
   #endif
           }
   }
   
   void IOOUTCALL dmac_o(UINT port, REG8 value) {
   
           DMAC    *d;
           REG8    cmd;
           REG8    mode;
   
           /* TRACEOUT(("out %.4x %.2x", port, value)); */
   
           d = &dma;
           if (!d->wcnt) {
                   disable(d);
                   d->wptr = 0;
                   if (!(value & 0x80)) {
                           if ((value & 3) != 0) {
                                   d->WR0 = value;
                                 if (value & 0x08) {                                  if (value & 0x08) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_A.b.l);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.al);
                                 }                                  }
                                 if (value & 0x10) {                                  if (value & 0x10) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_A.b.h);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.ah);
                                 }                                  }
                                 if (value & 0x20) {                                  if (value & 0x20) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, BYT_L.b.l);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, leng.b.ll);
                                 }                                  }
                                 if (value & 0x40) {                                  if (value & 0x40) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, BYT_L.b.h);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, leng.b.lh);
                                   }
                           }
                           else {
                                   if (value & 4) {
                                           d->cnt_a.b.flag = value;
                                   }
                                   else {
                                           d->cnt_b.b.flag = value;
                                 }                                  }
                                 break;  
   
                         case 1:  
                         case 2:  
                                 if (value & 0x40) {                                  if (value & 0x40) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, dummydat);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, dummydat);
                                 }                                  }
                                 break;                          }
                   }
                         case 3:                  else {
                           cmd = value & 3;
                           if (cmd == 0) {
                                   /* d->WR3 = value; */
                                 if (value & 0x08) {                                  if (value & 0x08) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, MASK_BYT);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, MASK_BYT);
                                 }                                  }
                                 if (value & 0x10) {                                  if (value & 0x10) {
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, MACH_BYT);                                          d->wtbl[d->wcnt++] = offsetof(DMAC, MACH_BYT);
                                 }  
                                 dma.INT_ENBL = (UINT8)((value & 0x20)?1:0);  
                                 dma.enable = (UINT8)((value & 0x40)?1:0);  
                                 break;  
   
                         case 4:  
                                 dma.mode = (UINT8)((dma.WR[4] >> 5) & 3);  
                                 if (value & 0x04) {  
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_B.b.l);  
                                 }  
                                 if (value & 0x08) {  
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, ADR_B.b.h);  
                                 }                                  }
                                 if (value & 0x10){                                  d->INT_ENBL = (UINT8)((value & 0x20)?1:0);
                                         dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, INT_FLG);                                  if (value & 0x40)
                                   {
                                           enable(d);
                                   }
                           }
                           else if (cmd == 1) {
                                   mode = (REG8)(value & (3 << 5));
                                   if (mode != (3 << 5)) {
                                           d->WR4 = value;
                                           d->mode = (UINT8)(mode >> 5);
                                           if (value & 0x04) {
                                                   d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.bl);
                                           }
                                           if (value & 0x08) {
                                                   d->wtbl[d->wcnt++] = offsetof(DMAC, addr.b.bh);
                                           }
                                           if (value & 0x10) {
                                                   d->wtbl[d->wcnt++] = offsetof(DMAC, INT_FLG);
                                           }
                                   }
                           }
   #if 1
                           else if (cmd == 2) {
                                   if (!(value & 0x44)) {
                                           d->WR5 = value;
                                 }                                  }
                                 break;                          }
   #else
                         case 6:                          else if (((value & 7) == 2) && (!(value & 0x40))) {
                                 switch(value) {                                  d->WR5 = value;
                                         case 0x83:                              // dma disable                          }
                                                 dma.enable = 0;  #endif
                           else if (cmd == 3) {
                                   switch(DMACMD(value)) {
                                           case DMACMD(0x83):              /* dma disable */
                                                 break;                                                  break;
   
                                         case 0x87:                              // dma enable                                          case DMACMD(0x87):              /* dma enable */
                                                 dma.enable = 1;  #if !defined(DMAS_STOIC)
                                                   d->increment = 0;
   #else
                                                   d->flag &= ~DMAF_INCREMENT;
   #endif
                                                   enable(d);
                                                 break;                                                  break;
   
                                         case 0x8b:                              // re-init status byte                                          case DMACMD(0x8b):              /* re-init status byte */
                                                 dma.MACH_FLG = 0;  #if !defined(DMAS_STOIC)
                                                 dma.ENDB_FLG = 0;                                                  d->MACH_FLG = 0;
                                                   d->ENDB_FLG = 0;
   #else
                                                   d->flag |= DMAF_MACH | DMAF_ENDB;
   #endif
                                                 break;                                                  break;
   
                                         case 0xa7:                              // イニシエイトリードシーケンス                                          case DMACMD(0xa7):              /* イニシエイトリードシーケンス */
                                                 setdmareaddat();                                                  setdmareaddat(d);
                                                 break;                                                  break;
   
                                         case 0xab:                              // interrupt enable                                          case DMACMD(0xab):              /* interrupt enable */
                                                 dma.INT_ENBL = 1;                                                  d->INT_ENBL = 1;
                                                 break;                                                  break;
   
                                         case 0xaf:                              // interrupt disable                                          case DMACMD(0xaf):              /* interrupt disable */
                                                 dma.INT_ENBL = 0;                                                  d->INT_ENBL = 0;
                                                 break;                                                  break;
   
                                         case 0xb3:                              // force ready                                          case DMACMD(0xb3):              /* force ready */
                                                 dma.ready = (dma.WR[5] & 0x08);                                                  d->ready = (d->WR5 & 0x08);
                                                 break;                                                  break;
   
                                         case 0xbb:                              // read mask follows                                          case DMACMD(0xbb):              /* read mask follows */
                                                 dma.WR_TBL[dma.WR_CNT++] = offsetof(DMAC, RR_MSK);                                                  d->wtbl[d->wcnt++] = offsetof(DMAC, RR_MSK);
                                                 break;                                                  break;
   
                                         case 0xbf:                              // read status byte                                          case DMACMD(0xbf):              /* read status byte */
                                                 dma.RR_MSK = 1;                                                  d->RR_MSK = 1;
                                                 setdmareaddat();                                                  setdmareaddat(d);
                                                 break;                                                  break;
   
                                         case 0xc3:                              // reset                                          case DMACMD(0xc3):              /* reset */
                                                                                         // ローグアライアンス   // ver0.25                                                                                          /* ローグアライアンス */        /* ver0.25 */
                                                 dma.cmd = 0;                                                  d->WR0 &= ~3;           /* 0でいいと思うケド… */
                                                 dma.enable = 0;  #if !defined(DMAS_STOIC)
                                                 dma.INT_ENBL = 0;                                                  d->increment = 0;
   #else
                                                   d->flag &= ~DMAF_INCREMENT;
   #endif
                                                   /* d->enable = 0; */
                                                   d->INT_ENBL = 0;
                                                 break;                                                  break;
   
                                         case 0xc7:                                              // リセットタイミングA                                          case DMACMD(0xc7):                              /* リセットタイミングA */
                                         case 0xcb:                                              // リセットタイミングB                                          case DMACMD(0xcb):                              /* リセットタイミングB */
                                                 break;                                                  break;
   
                                         case 0xcf:                                              // ロード                                          case DMACMD(0xcf):                              /* ロード */
                                                 dma.mode = (UINT8)((dma.WR[4] >> 5) & 3);                                                  /* d->mode = (UINT8)((d->WR4 >> 5) & 3); */
                                                 dma.CNT_A.w = dma.ADR_A.w;                                                  d->cnt_a.w.addr = d->addr.w.a;
                                                 dma.CNT_B.w = dma.ADR_B.w;                                                  d->cnt_b.w.addr = d->addr.w.b;
                                                 dma.BYT_N.w = 0;                                                  d->leng.w.n = 0;
                                                 dma.ENDB_FLG = 0;  #if !defined(DMAS_STOIC)
                                                 dma.MACH_FLG = 0;                       // 0619                                                  d->MACH_FLG = 0;
                                                 dma.enable = 0;                                                  d->ENDB_FLG = 0;
   #else
                                                   d->flag |= DMAF_MACH | DMAF_ENDB;
   #endif
                                                   /* d->enable = 0; */
                                                 break;                                                  break;
   
                                         case 0xd3:                                              // コンティニュー                                          case DMACMD(0xd3):                              /* コンティニュー */
                                                 if (dma.DMA_STOP) {                     // 前回途中でNOT READY  #if !defined(DMAS_STOIC)
                                                         dma.DMA_STOP = 0;                                                  if (d->increment) {
                                                         // ここでインクリメントするのはちょい無理が…                                                          d->increment = 0;
                                                         switch(dma.WR[1] & 0x30) {                                                          switch(d->cnt_a.b.flag & 0x30) {
                                                                 case 0x00:                                                                  case 0x00:
                                                                         dma.CNT_A.w--;                                                                          d->cnt_a.w.addr--;
                                                                         break;                                                                          break;
   
                                                                 case 0x10:                                                                  case 0x10:
                                                                         dma.CNT_A.w++;                                                                          d->cnt_a.w.addr++;
                                                                         break;                                                                          break;
                                                         }                                                          }
                                                         switch(dma.WR[2] & 0x30) {                                                          switch(d->cnt_b.b.flag & 0x30) {
                                                                 case 0x00:                                                                  case 0x00:
                                                                         dma.CNT_B.w--;                                                                          d->cnt_b.w.addr--;
                                                                         break;                                                                          break;
   
                                                                 case 0x10:                                                                  case 0x10:
                                                                         dma.CNT_B.w++;                                                                          d->cnt_b.w.addr++;
                                                                         break;                                                                          break;
                                                         }                                                          }
                                                 }                                                  }
                                                 dma.BYT_N.w = 0;                        // 0619  #else
                                                 dma.MACH_FLG = 0;                       // 0619                                                  if (d->flag & DMAF_INCREMENT) {
                                                 dma.ENDB_FLG = 0;                                                          d->flag &= ~DMAF_INCREMENT;
                                                 dma.enable = 1;                                                          switch(d->cnt_a.b.flag & 0x30) {
                                                                   case 0x00:
                                                                           d->cnt_a.w.addr--;
                                                                           break;
   
                                                                   case 0x10:
                                                                           d->cnt_a.w.addr++;
                                                                           break;
                                                           }
                                                           switch(d->cnt_b.b.flag & 0x30) {
                                                                   case 0x00:
                                                                           d->cnt_b.w.addr--;
                                                                           break;
   
                                                                   case 0x10:
                                                                           d->cnt_b.w.addr++;
                                                                           break;
                                                           }
                                                   }
   #endif
   #if !defined(DMAS_STOIC)
                                                   d->MACH_FLG = 0;
                                                   d->ENDB_FLG = 0;
   #else
                                                   d->flag |= DMAF_MACH | DMAF_ENDB;
   #endif
                                                   d->leng.w.n = 0;
                                                   enable(d);
                                                 break;                                                  break;
                                 }                                  }
                                 break;                          }
                 }                  }
         }          }
         else {          else {
                 *(((UINT8 *)&dma) + dma.WR_TBL[dma.WR_OFF]) = value;                  *(((UINT8 *)d) + d->wtbl[d->wptr]) = value;
                 if (dma.WR_TBL[dma.WR_OFF] == offsetof(DMAC, INT_FLG)) {                  if (d->wtbl[d->wptr] == offsetof(DMAC, INT_FLG)) {
                         if (value & 0x08) {                          if (value & 0x08) {
                                 dma.WR_TBL[dma.WR_OFF + dma.WR_CNT] = offsetof(DMAC, INT_PLS);                                  d->wtbl[d->wptr + d->wcnt] = offsetof(DMAC, INT_PLS);
                                 dma.WR_CNT++;                                  d->wcnt++;
                         }                          }
                         if (value & 0x10) {                          if (value & 0x10) {
                                 dma.WR_TBL[dma.WR_OFF + dma.WR_CNT] = offsetof(DMAC, INT_VCT);                                  d->wtbl[d->wptr + d->wcnt] = offsetof(DMAC, INT_VCT);
                                 dma.WR_CNT++;                                  d->wcnt++;
                         }                          }
                 }                  }
                 else if (dma.WR_TBL[dma.WR_OFF] == offsetof(DMAC, RR_MSK)) {                  else if (d->wtbl[d->wptr] == offsetof(DMAC, RR_MSK)) {
                         setdmareaddat();                          setdmareaddat(d);
                 }  
                 dma.WR_OFF++;  
                 dma.WR_CNT--;  
         }  
   
         working = iswork(&dma);  
         if (dma.working != working) {  
                 dma.working = working;  
                 if (working) {  
                         nevent_forceexit();  
                 }                  }
                   d->wptr++;
                   d->wcnt--;
         }          }
         (void)port;          (void)port;
 }  }
   
 REG8 IOINPCALL dmac_i(UINT port) {  REG8 IOINPCALL dmac_i(UINT port) {
   
           DMAC    *d;
         REG8    ret;          REG8    ret;
   
           d = &dma;
         ret = 0xcc;          ret = 0xcc;
         if (dma.enable) {          if (d->enable) {
                 ret |= 0x01;                  ret |= 0x01;
         }          }
         if ((dma.mode != 1) && ((dma.WR[5] ^ dma.ready) & 8)) {          if ((d->mode != 1) && ((d->WR5 ^ d->ready) & 8)) {
                 ret |= 0x02;                  ret |= 0x02;
         }          }
         if (!dma.MACH_FLG) {  #if !defined(DMAS_STOIC)
           if (!d->MACH_FLG) {
                 ret |= 0x10;                  ret |= 0x10;
         }          }
         if (!dma.ENDB_FLG) {          if (!d->ENDB_FLG) {
                 ret |= 0x20;                  ret |= 0x20;
         }          }
         dma.RR = ret;  #else
         if (dma.RR_CNT) {          ret |= (d->flag & (DMAF_MACH | DMAF_ENDB));
                 if (dma.RR_OFF >= dma.RR_CNT) {  #endif
                         dma.RR_OFF = 0;          d->RR = ret;
           if (d->rcnt) {
                   if (d->rptr >= d->rcnt) {
                           d->rptr = 0;
                 }                  }
                 ret = (*(((UINT8 *)&dma) + dma.RR_TBL[dma.RR_OFF++]));                  ret = (*(((UINT8 *)d) + d->rtbl[d->rptr++]));
         }          }
         (void)port;          (void)port;
           /* TRACEOUT(("inp %.4x %.2x", port, ret)); */
         return(ret);          return(ret);
 }  }
   
   
 // ----  /* reset */
   
 void dmac_reset(void) {  void dmac_reset(void) {
   
         ZeroMemory(&dma, sizeof(dma));          DMAC *d;
         dma.ready = 8;  
         dma.RR = 0x38;          d = &dma;
           ZeroMemory(d, sizeof(*d));
   #if defined(DMAS_STOIC)
           d->flag = DMAF_MACH | DMAF_ENDB;
   #endif
           d->ready = 8;
           d->RR = 0x38;
 }  }
   

Removed from v.1.4  
changed lines
  Added in v.1.8


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