Diff for /xmil/io/fdc.c between versions 1.1 and 1.23

version 1.1, 2004/08/02 13:38:46 version 1.23, 2008/06/02 20:07:31
Line 1 Line 1
 #include        "compiler.h"  #include        "compiler.h"
 #include        "dosio.h"  
 #include        "z80core.h"  #include        "z80core.h"
 #include        "pccore.h"  #include        "pccore.h"
 #include        "iocore.h"  #include        "iocore.h"
   #include        "nevent.h"
 #include        "fddfile.h"  #include        "fddfile.h"
 #include        "fdd_2d.h"  
 #include        "fdd_d88.h"  
 #include        "fdd_mtr.h"  #include        "fdd_mtr.h"
   
   enum {
           FDCCTYPE_CMD1           = 0x01,
           FDCCTYPE_CMD2           = 0x02,
           FDCCTYPE_CMD3           = 0x04,
           FDCCTYPE_CMD4           = 0x08,
   
           FDCCTYPE_RO                     = 0x10,
           FDCCTYPE_DATA           = 0x80
   };
   
   
   static const UINT8 fdctype[] = {
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD1,
                                           FDCCTYPE_CMD2 + FDCCTYPE_RO,
                                           FDCCTYPE_CMD2 + FDCCTYPE_RO,
                                           FDCCTYPE_CMD2,
                                           FDCCTYPE_CMD2,
                                           FDCCTYPE_CMD3 + FDCCTYPE_RO,
                                           FDCCTYPE_CMD4,
                                           FDCCTYPE_CMD3 + FDCCTYPE_RO,
                                           FDCCTYPE_CMD3};
   
   
   /* write track */
   
   #if !defined(CONST_DISKIMAGE)
   enum {
           TAO_MODE_GAP    = 0x4e,
           TAO_MODE_SYNC   = 0x00,
           TAO_MODE_AM             = 0xf5,
           TAO_MODE_IM             = 0xf6,
           TAO_MODE_ID             = 0xfe,
           TAO_MODE_DATA   = 0xfb,
           TAO_ENDOFDATA   = 0xf7,
   
           TAO_CMD_GAP             = 0x4e,
           TAO_CMD_SYNC    = 0x00,
           TAO_CMD_IM_IN   = 0xf6,
           TAO_CMD_IM              = 0xfc,
           TAO_CMD_AM_IN   = 0xf5,
           TAO_CMD_IAM             = 0xfe,
           TAO_CMD_DAM             = 0xfb,
           TAO_CMD_DDAM    = 0xf8,
           TAO_CMD_CRC             = 0xf7
   };
   
                 BYTE            FDC_c[4];  
                 BYTE            driveset = 0;  
                 BYTE            fdcdummyread = 0;  
                 WORD            readdiag = 0;  
   
 static const UINT8 fdctype[] = {1,1,1,1,1,1,1,1,2,2,2,2,3,4,3,3};  static REG8 wrtrkstart(FDC *f) {
   
           FDDFILE fdd;
   
 static BYTE fdd_stat(void) {          fdd = fddfile + f->s.drv;
           if ((fdd->type == DISKTYPE_NOTREADY) || (fdd->protect)) {
                   return(0);
           }
           f->s.bufdir = FDCDIR_TAO;
           f->s.bufpos = 0;
           f->s.bufmedia = f->s.media;
           f->s.bufunit = f->s.drv;
           f->s.buftrack = (f->s.c << 1) + f->s.h;
   
           f->s.wt_mode = TAO_ENDOFDATA;
           f->s.wt_sectors = 0;
           f->s.wt_ptr = 0;
           f->s.wt_datpos = 0;
           f->s.wt_datsize = 0;
           ZeroMemory(f->s.buffer, sizeof(f->s.buffer));
   
           return(0);
   }
   
   static void wrtrkdata(FDC *f, REG8 data) {
   
           TAOSEC  *t;
           REG8    n;
           UINT    datsize;
           FDDFILE fdd;
   
           switch(f->s.wt_mode) {
                   case TAO_ENDOFDATA:
                           if (data == TAO_MODE_GAP) {
                                   f->s.wt_mode = TAO_MODE_GAP;
                                   f->s.wt_ptr = 0;
                           }
                           break;
   
                   case TAO_MODE_GAP:
                           if (data == TAO_MODE_GAP) {
                                   f->s.wt_ptr++;
                                   if (f->s.wt_ptr >= 256) {
                                           goto wtd_done;
                                   }
                           }
                           else if (data == TAO_CMD_SYNC) {
                                   f->s.wt_mode = TAO_MODE_SYNC;
                           }
                           else if (data == 0xf4) {
                                   goto wtd_done;
                           }
                           else {
                                   goto wtd_err;
                           }
                           break;
   
         FDDFILE fdd;                  case TAO_MODE_SYNC:
                           if (data == TAO_CMD_AM_IN) {
                                   f->s.wt_mode = TAO_MODE_AM;
                           }
                           else if (data == TAO_CMD_IM_IN) {
                                   f->s.wt_mode = TAO_MODE_IM;
                           }
                           else if (data) {
                                   goto wtd_err;
                           }
                           break;
   
         fdd = fddfile + fdc.drv;                  case TAO_MODE_IM:
         switch(fdd->type) {                          if (data == TAO_CMD_IM) {
                 case DISKTYPE_NOTREADY:                                  f->s.wt_mode = TAO_ENDOFDATA;
                         return(0);                          }
                           else if (data != TAO_CMD_IM_IN) {
                                   goto wtd_err;
                           }
                           break;
   
                 case DISKTYPE_BETA:                  case TAO_MODE_AM:
                         return(fdd_stat_2d());                          if (data == TAO_CMD_IAM) {
                                   f->s.wt_mode = TAO_MODE_ID;
                                   f->s.wt_ptr = 0;
                           }
                           else if ((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM)) {
                                   f->s.wt_mode = TAO_MODE_DATA;
                                   f->s.wt_ptr = 0;
                                   if (f->s.wt_datsize) {
                                           t = (TAOSEC *)(f->s.buffer + f->s.wt_datpos);
                                           t[-1].flag = (UINT8)(data == TAO_CMD_DDAM);
                                   }
                           }
                           break;
   
                 case DISKTYPE_D88:                  case TAO_MODE_ID:
                 default:                          if ((f->s.wt_ptr == 0) && (data == TAO_CMD_IAM)) {
                         return(fdd_stat_d88());                                  break;
                           }
                           else if (f->s.wt_ptr < 4) {
                                   f->s.buffer[f->s.bufpos + f->s.wt_ptr] = data;
                                   f->s.wt_ptr++;
                           }
                           else if (data == TAO_CMD_CRC) {
                                   f->s.wt_mode = TAO_ENDOFDATA;
                                   n = f->s.buffer[f->s.bufpos + 3];
                                   if (n > 3) {
                                           n = 3;
                                   }
                                   datsize = 128 << n;
                                   if ((f->s.bufpos + (sizeof(TAOSEC) * 2) + datsize)
                                                                                                           <= sizeof(f->s.buffer)) {
                                           t = (TAOSEC *)(f->s.buffer + f->s.bufpos);
                                           STOREINTELWORD(t->size, datsize);
                                           f->s.wt_datpos = f->s.bufpos + sizeof(TAOSEC);
                                           f->s.wt_datsize = datsize;
                                           f->s.bufpos = f->s.wt_datpos + datsize;
                                           f->s.wt_sectors += 1;
                                   }
                                   else {
                                           goto wtd_err;
                                   }
                           }
                           break;
   
                   case TAO_MODE_DATA:                                             /* DATA WRITE */
                           if ((f->s.wt_ptr == 0) &&
                                   ((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM))) {
                                   break;
                           }
                           else if (f->s.wt_ptr < f->s.wt_datsize) {
                                   f->s.buffer[f->s.wt_datpos + f->s.wt_ptr] = data;
                                   f->s.wt_ptr++;
                           }
                           else if (data == TAO_CMD_CRC) {
                                   f->s.wt_mode = TAO_ENDOFDATA;
                                   f->s.wt_datsize = 0;
                           }
                           break;
         }          }
         return(0);          return;
   
   wtd_done:
           fdd = fddfile + f->s.bufunit;
           TRACEOUT(("write! %d %dbytes", f->s.wt_sectors, f->s.bufpos));
           f->s.stat = (*fdd->wrtrk)(fdd, f->s.bufmedia, f->s.buftrack,
                                                                   f->s.wt_sectors, f->s.buffer, f->s.bufpos);
           f->s.bufdir = FDCDIR_NONE;
           dmac_sendready(FALSE);
           return;
   
   wtd_err:
           f->s.stat = FDDSTAT_LOSTDATA;
           f->s.bufdir = FDCDIR_NONE;
           dmac_sendready(FALSE);
 }  }
   #endif
   
   
 /***********************************************************************  /* ---- */
         FDC (X1から見るI/Oに相当する関数)  
 ***********************************************************************/  
   
 static int inc_off(void) {  void neitem_fdcbusy(UINT id) {
   
         BYTE    ret;          fdc.s.busy = 0;
         FDDFILE fdd;          if (fdc.s.bufdir) {
                   /* TRACEOUT(("dma ready!")); */
                   dmac_sendready(TRUE);
           }
           (void)id;
   }
   
         if (!fdc.motor) {  static void setbusy(FDC *f, SINT32 clock) {
                 return(0);  
           if (clock > 0) {
                   f->s.busy = FDDSTAT_BUSY;
                   nevent_set(NEVENT_FDC, clock, neitem_fdcbusy, NEVENT_ABSOLUTE);
         }          }
         if (fdcdummyread) {          else {
                 fdcdummyread--;                  f->s.busy = 0;
                 return(0);                  nevent_reset(NEVENT_FDC);
           }
   }
   
   #if defined(SUPPORT_MOTORRISEUP)
   static void setmotor(FDC *f, REG8 drvcmd) {
   
           UINT    drv;
           SINT32  clock;
   
           drv = drvcmd & 3;
           clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
           if (drvcmd & 0x80) {
                   if (f->s.motorevent[drv] == FDCMOTOR_STOP) {
                           f->s.motorevent[drv] = FDCMOTOR_STARTING;
                           f->s.motorclock[drv] = clock;
                   }
                   else if (f->s.motorevent[drv] == FDCMOTOR_STOPING) {
                           f->s.motorevent[drv] = FDCMOTOR_READY;
                   }
         }          }
         else {          else {
                 fdd = fddfile + fdc.drv;                  if ((f->s.motorevent[drv] == FDCMOTOR_STARTING) ||
                 switch(fdd->type) {                          (f->s.motorevent[drv] == FDCMOTOR_READY)) {
                         case DISKTYPE_NOTREADY:                          f->s.motorevent[drv] = FDCMOTOR_STOPING;
                                 return(0);                          f->s.motorclock[drv] = clock;
                   }
           }
   }
   
                         case DISKTYPE_BETA:  void fdc_callback(void) {
                                 ret = fdd_incoff_2d();  
                                 break;  
   
                         case DISKTYPE_D88:          SINT32  clock;
                         default:          UINT    i;
                                 ret = fdd_incoff_d88();  
                                 break;          clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
           for (i=0; i<4; i++) {
                   if (fdc.s.motorevent[i] == FDCMOTOR_STARTING) {
                           if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) {
                                   fdc.s.motorevent[i] = FDCMOTOR_READY;
                           }
                 }                  }
                 if (ret) {                  else if (fdc.s.motorevent[i] == FDCMOTOR_STOPING) {
                         dma.DMA_REDY = 8;       // <- DMA ノ レディシンゴウ ヲ クリア                          if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) {
                                   fdc.s.motorevent[i] = FDCMOTOR_STOP;
                           }
                 }                  }
         }          }
         return(ret);  
 }  }
   
 void IOOUTCALL fdc_o(UINT port, REG8 value) {  static SINT32 motorwait(const FDC *f) {
   
         REG8    cmd;          SINT32  curclock;
           SINT32  nextclock;
   
         port &= 0xf;          if (f->s.motorevent[f->s.drv] == FDCMOTOR_STARTING) {
         if (port == 8) {                                                // コマンド                  curclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK;
                 driveset = 0;                  curclock -= f->s.motorclock[f->s.drv];
                 fdc.cmd = value;                  if (curclock < (SINT32)pccore.realclock) {
                 cmd = (REG8)(value >> 4);                          nextclock = pccore.realclock - curclock;
                 fdc.type = fdctype[cmd];                          /* TRACEOUT(("motor starting busy %d", nextclock)); */
                 fdc.skip = 2;                          return(nextclock);
                 switch(cmd) {                  }
                         case 0x00:                                                              // リストア          }
                                 if (value & 8) {                                        // LAYDOCK          return(0);
                                         fdc.skip = 0;  }
                                         fdc.busyclock = 20;                             // ver0.25 (now testing)  
                                         fdc.busystart = h_cntbase + h_cnt;  
                                 }  
                                 fdc.motor = 0x80;                                       // モーターOn?  
                                 fdc.c = 0;  
                                 fdc.treg = 0;  
                                 FDDMTR_MOVE;  
                                 fdc.step = 1;  
 #if 1                                                                                           // ver0.25  
                                 fdc.r = 0;                                                      // デゼニワールド  
                                 fdc.rreg = 0;  
 #endif  #endif
                                 break;  
   
                         case 0x01:                                                              // シーク  
                                 fdc.motor = 0x80;                                       // モーターOn  
                                 fdc.step = (char)((fdc.c<=fdc.data)?1:-1);  
 #if 0                                                                                           // スタクル             // ver0.50  
                                 fdc.rreg = fdc.r = 0;  
 #endif  
                                 fdc.c = fdc.data;  
                                 fdc.treg = fdc.data;  
                                 FDDMTR_MOVE;  
                                 break;  
   
                         case 0x02:                                                              // ステップ  static REG8 getstat(FDC *f) {
                         case 0x03:  
                                 if (fdc.motor) {  
                                         fdc.c += fdc.step;  
                                         if (cmd & 1) {  
                                                 FDDMTR_MOVE;  
                                                 fdc.treg = fdc.c;  
                                         }  
                                 }  
                                 break;  
   
                         case 0x04:                                                              // ステップイン          FDDFILE fdd;
                         case 0x05:          REG8    ctype;
                                 if (fdc.motor) {          REG8    ret;
                                         fdc.step = 1;  
                                         fdc.c++;          fdd = fddfile + f->s.drv;
                                         if (cmd & 1) {          ctype = f->s.ctype;
                                                 FDDMTR_MOVE;          if (fdd->type == DISKTYPE_NOTREADY) {
                                                 fdc.treg = fdc.c;                  ret = FDDSTAT_NOTREADY;
                                         }          }
                                 }          else {
                                 break;                  ret = f->s.stat;
           }
           if ((ctype & FDCCTYPE_CMD1) && (f->s.c == 0)) {
                   ret |= FDDSTAT_TRACK00;
           }
           if (!(ctype & FDCCTYPE_RO)) {
                   if (fdd->protect) {
                           ret |= FDDSTAT_WRITEP;
                   }
           }
           if (ctype & (FDCCTYPE_CMD1 | FDCCTYPE_CMD4)) {
                   f->s.hole++;
                   if (f->s.hole < 8) {
                           ret |= FDDSTAT_INDEX;
                   }
           }
           else if (!(ret & 0xf0)) {
                   if (fddmtr_isbusy()) {
                           ret |= FDDSTAT_BUSY;
                   }
                   if (f->s.bufdir) {
                           ret |= FDDSTAT_DRQ | FDDSTAT_BUSY;
                   }
           }
           return(ret);
   }
   
                         case 0x06:                                                              // ステップアウト  static void seekcmd(FDC *f) {
                         case 0x07:  
                                 if (fdc.motor) {  
                                         fdc.step = -1;  
                                         fdc.c--;  
                                         if (cmd & 1) {  
                                                 FDDMTR_MOVE;  
                                                 fdc.treg = fdc.c;  
                                         }  
                                 }  
                                 break;  
   
                         case 0x08:                                                              // リードデータ          FDDFILE fdd;
                         case 0x09:          UINT    track;
                         case 0x0a:                                                              // ライトデータ  
                         case 0x0b:  
                                 fdc.off = 0;  
                                 fdcdummyread = 2;  
                                 if (fdc.motor) {  
                                         if (dma.DMA_ENBL) {  
                                                 dma.DMA_REDY = 0;  
 //                                              fdc.skip = 0;                   // DMAで割り込みを監視する事!  
                                         }  
                                 }  
                                 break;  
   
                         case 0xc:                                                               // リードアドレス          f->s.crcnum = 0;
                                 fdc.crc_off = 0;          f->s.creg = f->s.c;
                                 fdcdummyread = 2;          fdd = fddfile + f->s.drv;
                                 if (fdc.motor) {                                                                        // ver0.25          track = (f->s.c << 1) + f->s.h;
                                         if (dma.DMA_ENBL) {          f->s.stat = fdd->seek(fdd, f->s.media, track) | FDDSTAT_HEADENG;
                                                 dma.DMA_REDY = 0;          fddmtr_motormove();
                                         }  }
                                 }  
                                 {  
                                         FDDFILE fdd = fddfile + fdc.drv;  
                                         switch(fdd->type) {  
                                                 case DISKTYPE_NOTREADY:  
                                                         break;  
   
                                                 case DISKTYPE_BETA:  
                                                         fdd_crc_2d();  
                                                         break;  
   
                                                 case DISKTYPE_D88:  
                                                 default:  
                                                         fdd_crc_d88();  
                                                         break;  
                                         }  
                                 }  
                                 break;  
   
                         case 0x0d:                                                              // フォースインタラプト  static REG8 type2cmd(FDC *f, REG8 sc) {
                                 fdcdummyread = 0;                                       // 必要ない?  
                                 fdc.skip = 0;                                           // 000330  
                                 dma.DMA_REDY = 8;                                       // ver0.25  
                                 break;  
   
                         case 0x0e:                                                              // リードトラック          REG8    dir;
                                 readdiag = 0;          UINT    track;
                                 break;          UINT8   *p;
           FDDFILE fdd;
           UINT    size;
           REG8    stat;
           SINT32  clock;
   #if defined(SUPPORT_DISKEXT)
           SINT32  curclock;
           SINT32  nextclock;
           UINT32  secinfo;
   #endif
   
                         case 0x0f:                                                              // ライトトラック          track = (f->s.c << 1) + f->s.h;
                                 {          fdd = fddfile + f->s.drv;
                                         FDDFILE fdd = fddfile + fdc.drv;  #if !defined(CONST_DISKIMAGE)
                                         switch(fdd->type) {          if (!(f->s.cmd & 0x20)) {
                                                 case DISKTYPE_NOTREADY:                  p = f->s.buffer;
                                                 case DISKTYPE_BETA:                  dir = FDCDIR_IN;
                                                         break;          }
           else {
                                                 case DISKTYPE_D88:                  p = NULL;
                                                 default:                  dir = FDCDIR_OUT;
                                                         if (fdc.motor) {                                                // ver0.25          }
                                                                 init_tao_d88();          size = sizeof(f->s.buffer);
                                                                 if (dma.DMA_ENBL) {          stat = fdd->read(fdd, f->s.media, track, sc, p, &size);
                                                                         dma.DMA_REDY = 0;          if (stat & FDDSTAT_RECNFND) {
                                                                 }                  size = 0;
                                                         }                  dir = FDCDIR_NONE;
                                                         break;          }
                                         }          else if (dir == FDCDIR_OUT) {
                                 }                  if (size) {
                                 break;                          ZeroMemory(f->s.buffer, size);
                   }
                   stat = stat & (~FDDSTAT_RECTYPE);
           }
   #else
           size = 0;
           dir = FDCDIR_NONE;
           if (!(f->s.cmd & 0x20)) {
                   stat = fdd->readp(fdd, f->s.media, track, sc, (void **)&p, &size);
                   if (!(stat & FDDSTAT_RECNFND)) {
                           f->e.buffer = p;
                           dir = FDCDIR_IN;
                 }                  }
         }          }
         else {          else {
                 cmd = (REG8)(fdc.cmd >> 4);                  stat = FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT;
                 switch(port) {          }
                         case 0x09:                                                              // トラック  #endif
                                 fdc.treg = value;          f->s.bufmedia = f->s.media;
                                 break;          f->s.bufunit = f->s.drv;
           f->s.buftrack = track;
           f->s.bufsc = sc;
           f->s.bufwrite = FALSE;
           f->s.bufdir = dir;
           f->s.bufmark = f->s.cmd & 1;
           f->s.bufpos = 0;
           f->s.bufsize = size;
           f->s.curtime = 0;
   
           clock = 0;
   #if defined(SUPPORT_MOTORRISEUP)
           clock += motorwait(f);
   #endif
   #if defined(SUPPORT_DISKEXT)
           secinfo = fdd->sec(fdd, f->s.media, track, sc);
           if (secinfo) {
                   nextclock = LOW16(secinfo);
                   nextclock *= f->s.loopclock;
                   nextclock /= LOW16(secinfo >> 16);
                   curclock = nevent_getwork(NEVENT_RTC);
                   nextclock -= curclock;
                   if (nextclock < 0) {
                           nextclock += f->s.loopclock;
                   }
                   /* TRACEOUT(("wait clock -> %d [%d/%d]", nextclock,
                                                                           LOW16(secinfo), LOW16(secinfo >> 16))); */
                   clock += nextclock;
           }
   #endif
           setbusy(f, max(clock, 500));
           return(stat);
   }
   
                         case 0x0a:                                                              // セクタ  static REG8 type2flash(FDC *f) {
                                 FDDMTR_WAITSEC(value);  
                                 fdc.r = value;  
                                 fdc.rreg = value;  
                                 break;  
   
                         case 0x0b:                                                              // データ  #if !defined(CONST_DISKIMAGE)
                                 fdc.data = value;          FDDFILE fdd;
                                 if ((cmd == 0x0a) || (cmd == 0x0b)) {  
                                         FDDFILE fdd = fddfile + fdc.drv;  
                                         switch(fdd->type) {  
                                                 case DISKTYPE_NOTREADY:  
                                                         break;  
   
                                                 case DISKTYPE_BETA:  
                                                         fdd_write_2d();  
                                                         break;  
   
                                                 case DISKTYPE_D88:  
                                                 default:  
                                                         fdd_write_d88();  
                                                         break;  
                                         }  
                                         inc_off();  
                                 }  
                                 else if (cmd == 0x0f) {                         // TRACK WRITE  
                                         FDDFILE fdd = fddfile + fdc.drv;  
                                         switch(fdd->type) {  
                                                 case DISKTYPE_NOTREADY:  
                                                 case DISKTYPE_BETA:  
                                                         break;  
   
                                                 case DISKTYPE_D88:  
                                                 default:  
                                                         fdd_wtao_d88(value);  
                                                         break;  
                                         }  
                                 }  
                                 break;  
   
                         case 0x0c:                                                              // ドライブ・サイド          f->s.bufwrite = FALSE;
                                 driveset = 1;          fdd = fddfile + f->s.bufunit;
                                 FDC_c[fdc.drv] = fdc.c;          if (fdd->protect) {
                                 fdc.c = FDC_c[value & 0x03];                    // XTAL !!!                  return(FDDSTAT_WRITEFAULT);
                                 fdc.motor = (UINT8)(value & 0x80);          }
                                 fdc.drv = (UINT8)(value & 0x03);          return(fdd->write(fdd, f->s.bufmedia, f->s.buftrack,
                                 fdc.h = (UINT8)((value >> 4) & 1);                                                                          f->s.bufsc, f->s.buffer, f->s.bufpos));
   #else
                                 fdc.cmd = 0;                                                    // T&E SORCERIAN          (void)f;
 //                              fdc.data = 0;                                                   // 影の伝説          return(FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT);
                                 fdc.type = 0;  
   
                                 FDDMTR_DRVSET;  
                                 if (!fdc.motor) {  
                                         fdc.r = 0;                                                      // SACOM TELENET  
                                         fdc.rreg = 0;  
 #if 0                                                                                                   // XTAL  
                                         fdc.c = 0;  
                                         fdc.step = 1;  
 #endif  #endif
                                 }  }
                                 break;  
   static REG8 crccmd(FDC *f) {
   
           UINT8   *crcbuf;
           UINT    track;
           FDDFILE fdd;
           REG8    stat;
   
   #if !defined(CONST_DISKIMAGE)
           crcbuf = f->s.buffer;
   #else
           crcbuf = f->s.crcbuf;
           f->e.buffer = crcbuf;
   #endif
   
           track = (f->s.c << 1) + f->s.h;
           fdd = fddfile + f->s.drv;
           /* TRACEOUT(("fdd->crc %d %d %d", f->s.drv, track, f->s.crcnum)); */
           stat = fdd->crc(fdd, f->s.media, track, f->s.crcnum, crcbuf);
           if (stat & FDDSTAT_RECNFND) {
                   f->s.crcnum = 0;
                   stat = fdd->crc(fdd, f->s.media, track, 0, crcbuf);
           }
           if (!(stat & FDDSTAT_RECNFND)) {
                   f->s.bufdir = FDCDIR_IN;
                   f->s.bufsize = 6;
                   f->s.rreg = crcbuf[0];
                   f->s.crcnum++;
           }
           else {
                   f->s.bufdir = FDCDIR_NONE;
                   f->s.bufsize = 0;
           }
           f->s.bufwrite = FALSE;
           f->s.curtime = 0;
           return(stat);
   }
   
   static void fdcenddata(FDC *f) {
   
           BRESULT r;
           REG8    stat;
   
           r = FALSE;
           if (f->s.ctype & FDCCTYPE_CMD2) {
                   stat = 0;
                   if (f->s.cmd & 0x10) {
                           r = TRUE;
                   }
                   if ((f->s.cmd & 0x20) && (f->s.bufwrite)) {
                           stat = type2flash(&fdc);
                           if (stat & (FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT)) {
                                   r = FALSE;
                           }
                           f->s.stat = stat;
                   }
           }
           f->s.bufdir = FDCDIR_NONE;
           dmac_sendready(FALSE);
           if (r) {
                   f->s.rreg = f->s.r + 1;
                   stat = type2cmd(f, f->s.rreg);
                   if (!(stat & FDDSTAT_RECNFND)) {
                           f->s.r = f->s.r + 1;
                           f->s.stat = stat;
                 }                  }
         }          }
 }  }
   
 REG8 IOINPCALL fdc_i(UINT port) {  void IOOUTCALL fdc_o(UINT port, REG8 value) {
   
 static  BYTE    timeoutwait;          REG8    cmd;
 static  BYTE    last_r;  
 static  short   last_off;          if ((port & (~7)) != 0x0ff8) {
                 BYTE    ans;                  return;
                 REG8    cmd;          }
           TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC));
         cmd = (REG8)(fdc.cmd >> 4);          switch(port & 7) {
                   case 0:                                                                 /* コマンド */
         if ((port &= 0xf) != 8) {                          if (fdc.s.bufwrite) {
                 last_r = -1;                                  fdc.s.stat = type2flash(&fdc);
                 last_off = -1;  
                 timeoutwait = 4;  
         }  
         switch(port) {  
                 case 0x8:       // ステータス  
                         ans = 0;  
                         fdcdummyread = 0;  
                         if (fdc.skip) {  
                                 fdc.skip--;  
                                 return(0x01);  
                         }  
                         if (fdc.busyclock) {                                    // ver0.25  
                                 if (((h_cntbase + h_cnt) - fdc.busystart) < fdc.busyclock) {  
                                         return(0x01);  
                                 }  
                                 fdc.busyclock = 0;  
                         }                          }
                 {                          if (fdc.s.bufdir != FDCDIR_NONE) {
                         FDDFILE fdd = fddfile + fdc.drv;                                  fdc.s.bufdir = FDCDIR_NONE;
                         if (fdd->type == DISKTYPE_NOTREADY) {                                  dmac_sendready(FALSE);
                                 if (fdc.type == 1 && fdc.c == 0) {      // ドライブチェック !!!  
                                         return(0x84);                                   // ←接続されてる時だけ  
                                 }  
                                 return(0x80);  
                         }                          }
                 }  
                         if (fdc.type == 2) {                          fdc.s.cmd = value;
                                 if (last_r == fdc.r && last_off == fdc.off &&                          cmd = (REG8)(value >> 4);
                                                 !(--timeoutwait)) {                          fdc.s.ctype = fdctype[cmd];
                                         inc_off();                          /* TRACEOUT(("fdc cmd: %.2x", value)); */
                                         timeoutwait = 4;                          /* リストアコマンドにおいて
                            *  マリオは コマンド発行後にbusyを見張る
                            *  逆にソーサリアンとかは busyだとエラーになる…
                            * 条件は何?
                            */
                           setbusy(&fdc, 20);
                           switch(cmd) {
                                   case 0x00:                                                              /* リストア */
                                           fdc.s.motor = 0x80;                                     /* モーターOn? */
                                           fdc.s.c = 0;
                                           fdc.s.step = 1;
                                           fdc.s.r = 0;                                            /* デゼニワールド */
                                           seekcmd(&fdc);
                                           fdc.s.rreg = 0;
                                           break;
   
                                   case 0x01:                                                              /* シーク */
                                           fdc.s.motor = 0x80;                                     /* モーターOn */
                                           fdc.s.step = (SINT8)((fdc.s.c<=fdc.s.data)?1:-1);
                                           fdc.s.c = fdc.s.data;
                                           seekcmd(&fdc);
                                           break;
   
                                   case 0x02:                                                              /* ステップ */
                                   case 0x03:
                                   case 0x04:                                                              /* ステップイン */
                                   case 0x05:
                                   case 0x06:                                                              /* ステップアウト */
                                   case 0x07:
                                           fdc.s.stat = FDDSTAT_HEADENG;
                                           if (fdc.s.motor) {
                                                   if (cmd & 0x04) {
                                                           fdc.s.step = (cmd & 0x02)?-1:1;
                                                   }
                                                   fdc.s.c += fdc.s.step;
                                                   if (cmd & 1) {
                                                           seekcmd(&fdc);
                                                   }
                                           }
                                           break;
   
                                   case 0x08:                                                              /* リードデータ */
                                   case 0x09:
                                   case 0x0a:                                                              /* ライトデータ */
                                   case 0x0b:
                                           fdc.s.stat = type2cmd(&fdc, fdc.s.r);
                                           break;
   
                                   case 0xc:                                                               /* リードアドレス */
                                           setbusy(&fdc, 200);
                                           fdc.s.stat = crccmd(&fdc);
                                           break;
   
                                   case 0x0d:                                                              /* フォースインタラプト */
                                           setbusy(&fdc, 0);                                       /* 必要ない? */
                                           /* fdc.s.skip = 0; */                           /* 000330 */
                                           fdc.s.stat = 0;
                                           dmac_sendready(FALSE);
                                           break;
   
                                   case 0x0e:                                                              /* リードトラック */
   #if !defined(CONST_DISKIMAGE)
                                           setbusy(&fdc, 200);
                                           ZeroMemory(fdc.s.buffer, 0x1a00);
                                           fdc.s.bufpos = 0;
                                           fdc.s.bufsize = 0x1a00;
                                           fdc.s.bufdir = FDCDIR_IN;
                                           fdc.s.stat = 0;
   #else
                                           fdc.s.stat = FDDSTAT_SEEKERR;
   #endif
                                           break;
   
                                   case 0x0f:                                                              /* ライトトラック */
   #if !defined(CONST_DISKIMAGE)
                                           setbusy(&fdc, 200);
                                           fdc.s.stat = wrtrkstart(&fdc);
   #else
                                           fdc.s.stat = FDDSTAT_LOSTDATA;
   #endif
                                           break;
                           }
                           break;
   
                   case 1:                                                                 /* トラック */
                           fdc.s.creg = value;
                           break;
   
                   case 2:                                                                 /* セクタ */
                           fddmtr_waitsec(value);
                           fdc.s.r = value;
                           fdc.s.rreg = value;
                           break;
   
                   case 3:                                                                 /* データ */
                           fdc.s.data = value;
   #if !defined(CONST_DISKIMAGE)
                           if (fdc.s.motor) {
                                   if (fdc.s.bufdir == FDCDIR_OUT) {
                                           fdc.s.bufwrite = TRUE;
                                           fdc.s.curtime = 0;
                                           fdc.s.buffer[fdc.s.bufpos] = value;
                                           if (!fdc.s.busy) {
                                                   fdc.s.bufpos++;
                                                   if (fdc.s.bufpos >= fdc.s.bufsize) {
                                                           fdcenddata(&fdc);
                                                   }
                                           }
                                   }
                                   else if (fdc.s.bufdir == FDCDIR_TAO) {
                                           wrtrkdata(&fdc, value);
                                 }                                  }
                                 last_r = fdc.r;  
                                 last_off = fdc.off;  
                         }                                                       // Read Write時のみの変化でいい筈  
                         if (!((ans = fdd_stat()) & 2)) {  
                                 dma.DMA_REDY = 8;                               // <- DMA ノ レディシンゴウ ヲ クリア  
                         }                          }
 #if 1  #endif
                         if (driveset) {                                 // 0xffcを叩いた直後だったら                          break;
                                 ans &= 0xc4;  
                   case 4:                                                                 /* ドライブ・サイド */
                           fdc.s.ctbl[fdc.s.drv] = fdc.s.c;
                           fdc.s.c = fdc.s.ctbl[value & 0x03];
                           fdc.s.motor = (UINT8)(value & 0x80);
                           fdc.s.drv = (UINT8)(value & 0x03);
                           fdc.s.h = (UINT8)((value >> 4) & 1);
                           fdc.s.cmd = 0;                                                  /* T&E SORCERIAN */
                           fdc.s.ctype = 0;
                           fdc.s.stat = 0;
   
                           fddmtr_drvset();
                           if (!fdc.s.motor) {
                                   fdc.s.r = 0;                                            /* SACOM TELENET */
                                   fdc.s.rreg = 0;
                         }                          }
   #if defined(SUPPORT_MOTORRISEUP)
                           setmotor(&fdc, value);
 #endif  #endif
                         return(ans);                          break;
           }
   }
   
                 case 0x9:                                                       // トラック  REG8 IOINPCALL fdc_i(UINT port) {
                         return(fdc.treg);  
           REG8    ret;
   
           /* TRACEOUT(("fdc inp %.4x", port)); */
   
                 case 0xa:                                                       // セクタ          if ((port & (~7)) != 0x0ff8) {
                         return(fdc.rreg);                               // ver0.25                  return(0xff);
           }
                 case 0xb:                                                       // データ          switch(port & 7) {
                         if (fdc.motor) {                  case 0:                                                                         /* ステータス */
                                 if ((cmd == 0x08) || (cmd == 0x09)) {   // リード・データ                          ret = fdc.s.busy;
                                         FDDFILE fdd;                          if (ret) {
                                         fdd = fddfile + fdc.drv;                                  return(ret);
                                         switch(fdd->type) {                          }
                                                 case DISKTYPE_NOTREADY:  #if 1
                                                         break;                          if (fdc.s.bufdir >= FDCDIR_IN) {                /* YsII */
                                   fdc.s.curtime++;
                                                 case DISKTYPE_BETA:                                  if (fdc.s.curtime >= 8) {
                                                         fdd_read_2d();                                          fdc.s.curtime = 0;
                                                         break;                                          fdc.s.stat |= FDDSTAT_LOSTDATA;
                                           fdc.s.bufpos++;
                                                 case DISKTYPE_D88:                                          if (fdc.s.bufpos >= fdc.s.bufsize) {
                                                 default:                                                  fdcenddata(&fdc);
                                                         fdd_read_d88();         // WOODY POCO !!!  
                                                         break;  
                                         }                                          }
                                         inc_off();  
                                 }                                  }
                                 else if (cmd == 0x0c) {                 // リード・アドレス                          }
                                         if (fdc.crc_off < 6) {          // ver0.25  #endif
                                                 fdc.data = fdc.crc_dat[fdc.crc_off];                          ret = getstat(&fdc);
                                                 if (fdcdummyread) {             // ver0.25  #if 1
                                                         fdcdummyread--;                          if (!(ret & 0x02)) {
                                                 }                                  dmac_sendready(FALSE);
                                                 else {                          }
                                                         fdc.crc_off++;  #endif
                           /* TRACEOUT(("ret->%.2x", ret)); */
                           return(ret);
   
                   case 1:                                                                 /* トラック */
   TRACEOUT(("fdc inp %.4x,%.2x", port, fdc.s.creg));
                           return(fdc.s.creg);
   
                   case 2:                                                                 /* セクタ */
   TRACEOUT(("fdc inp %.4x,%.2x", port, fdc.s.rreg));
                           return(fdc.s.rreg);
   
                   case 3:                                                                 /* データ */
                           if (fdc.s.motor) {
                                   if (fdc.s.bufdir == FDCDIR_IN) {
                                           fdc.s.curtime = 0;
   #if !defined(CONST_DISKIMAGE)
                                           fdc.s.data = fdc.s.buffer[fdc.s.bufpos];
   #else
                                           fdc.s.data = fdc.e.buffer[fdc.s.bufpos];
   #endif
                                           if (!fdc.s.busy) {
                                                   fdc.s.bufpos++;
                                                   if (fdc.s.bufpos >= fdc.s.bufsize) {
                                                           fdcenddata(&fdc);
                                                 }                                                  }
                                         }                                          }
                                 }                                          /* TRACEOUT(("read %.2x - %.2x [%.4x]", fdc.s.bufpos, fdc.s.data, Z80_PC)); */
                                 else if (cmd == 0x0e) {                                                         // ver0.25  
                                         fdc.data = 0;  
                                         readdiag++;  
                                 }                                  }
                         }                          }
                         return(fdc.data);                                       // WOODY POCO !!!                          return(fdc.s.data);
   
 //              case 0xc:                                                               // FM                  case 4:                                                                 /* FM */
 //              case 0xd:                                                               // MFM                  case 5:                                                                 /* MFM */
 //                      break;                          return(0x00);
   
                 case 0xe:                                                               // 1.6M                  case 6:                                                                 /* 1.6M */
                         fdc.media = 1;                          fdc.s.media = DISKTYPE_2HD;
                         return(0xff);                          break;
   
                 case 0xf:                                                               // 500K/1M                  case 7:                                                                 /* 500K/1M */
                         fdc.media = 0;                          fdc.s.media = DISKTYPE_2D;
                         return(0xff);                          break;
         }          }
         return(0);          return(0xff);
 }  }
   
   
 // ----  /* reset */
   
 void fdc_reset(void) {  void fdc_reset(void) {
   
         FDDMTR_INIT;          fddmtr_initialize();
         ZeroMemory(&fdc, sizeof(fdc));          ZeroMemory(&fdc, sizeof(fdc));
         fdc.step = 1;          fdc.s.step = 1;
         ZeroMemory(FDC_c, 4);          fdc.s.equip = xmilcfg.fddequip;
   #if defined(FIX_Z80A)
           fdc.s.loopclock = 2000000 * 2 / 5;
   #else
           fdc.s.loopclock = pccore.realclock / 5;
   #endif
 }  }
   

Removed from v.1.1  
changed lines
  Added in v.1.23


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