| version 1.2, 2004/08/02 11:48:13 | version 1.15, 2005/02/04 06:42:11 | 
| Line 1 | Line 1 | 
 | #include        "compiler.h" | #include        "compiler.h" | 
 | #include        "dosio.h" | #include        "dosio.h" | 
 | #include        "pccore.h" | #include        "pccore.h" | 
 | #include        "x1_io.h" |  | 
 | #include        "x1_fdc.h" |  | 
 | #include        "fdd_mtr.h" |  | 
 | #include        "fdd_d88.h" |  | 
 | #include        "fddfile.h" | #include        "fddfile.h" | 
 |  | #include        "fdd_d88.h" | 
 |  | #include        "fdd_mtr.h" | 
 |  |  | 
 |  |  | 
| static  D88_HEADER      d88head[4]; | enum { | 
| static  D88_SECTOR      cursec; | D88BUFSIZE              = 0x4000 | 
| static  short           curdrv = -1; | }; | 
| static  WORD            curtrk = -1; |  | 
| static  BYTE            curtype = 0; |  | 
| static  WORD            cursct = -1; |  | 
| static  long            curfp = 0; |  | 
| static  DWORD           cursize = 0; |  | 
| static  BYTE            curwrite = 0; |  | 
| static  BYTE            curtrkerr = 0; |  | 
| static  BYTE            hole = 0; |  | 
| static  BYTE            *curdata; |  | 
| static  WORD            crcnum = 0; |  | 
| static  BYTE            crcerror = FALSE; |  | 
|  |  | 
| extern  BYTE            WRITEPT[]; |  | 
| extern  BYTE            DISKNUM[]; |  | 
|  |  | 
| extern  WORD            readdiag; |  | 
|  |  | 
| #define         TAO_MODE_GAP    0x4e |  | 
| #define         TAO_MODE_SYNC   0x00 |  | 
| #define         TAO_MODE_AM             0xf5 |  | 
| #define         TAO_MODE_IM             0xf6 |  | 
| #define         TAO_MODE_ID             0xfe |  | 
| #define         TAO_MODE_DATA   0xfb |  | 
| #define         TAO_ENDOFDATA   0xf7 |  | 
|  |  | 
| #define         TAO_CMD_GAP             0x4e |  | 
| #define         TAO_CMD_SYNC    0x00 |  | 
| #define         TAO_CMD_IM_IN   0xf6 |  | 
| #define         TAO_CMD_IM              0xfc |  | 
| #define         TAO_CMD_AM_IN   0xf5 |  | 
| #define         TAO_CMD_IAM             0xfe |  | 
| #define         TAO_CMD_DAM             0xfb |  | 
| #define         TAO_CMD_DDAM    0xf8 |  | 
| #define         TAO_CMD_CRC             0xf7 |  | 
 |  |  | 
 | typedef struct { | typedef struct { | 
| BYTE    mode; | FDDFILE fdd; | 
| BYTE    flag; | UINT8   media; | 
| WORD    cnt; | UINT8   write; | 
| WORD    size; | UINT8   padding[2]; | 
| WORD    ptr; | UINT    track; | 
| WORD    top; | long    fptr; | 
| WORD    gap; | UINT    size; | 
| BYTE    sector; | UINT    sectors; | 
| WORD    lostdatacnt; | UINT8   buf[D88BUFSIZE]; | 
| BYTE    maxsector; | } _D88TRK, *D88TRK; | 
| WORD    maxsize; |  | 
| } WID_PARA; |  | 
|  |  | 
| #define LOSTDATA_COUNT  256 |  | 
|  |  | 
| static  WID_PARA WID_2D = {TAO_ENDOFDATA, 3, 0, 0, 0, 0, 0, 0, 0, 33, 0x1f80}; |  | 
| static  WID_PARA WID_2HD= {TAO_ENDOFDATA, 3, 0, 0, 0, 0, 0, 0, 0, 55, 0x2f80}; |  | 
| static  WID_PARA WID_ERR= {TAO_ENDOFDATA, 4, 0, 0, 0, 0, 0, 0, 0,  0, 0x0000}; |  | 
| static  WID_PARA tao    = {TAO_ENDOFDATA, 4, 0, 0, 0, 0, 0, 0, 0,  0, 0x0000}; |  | 
|  |  | 
| static  BYTE            D88_BUF[0x4000]; |  | 
| static  BYTE            TAO_BUF[0x3000]; |  | 
 |  |  | 
 |  | static  _D88TRK         d88trk; | 
 |  |  | 
 | //---------------------------------------------------------------------- |  | 
 |  |  | 
| static UINT32 nexttrackp(D88_HEADER *head, UINT32 fptr, UINT32 last) { | static UINT32 nexttrackptr(FDDFILE fdd, UINT32 fptr, UINT32 last) { | 
 |  |  | 
 | UINT    t; | UINT    t; | 
 | const DWORD     *trkp; |  | 
 | UINT32  cur; | UINT32  cur; | 
 |  |  | 
 | trkp = (DWORD *)head->trackp; |  | 
 | for (t=0; t<164; t++) { | for (t=0; t<164; t++) { | 
| cur = trkp[t]; | cur = fdd->inf.d88.ptr[t]; | 
 | if ((cur > fptr) && (cur < last)) { | if ((cur > fptr) && (cur < last)) { | 
 | last = cur; | last = cur; | 
 | } | } | 
| Line 89  const DWORD *trkp; | Line 39  const DWORD *trkp; | 
 | return(last); | return(last); | 
 | } | } | 
 |  |  | 
|  | static BRESULT trackflush(D88TRK trk) { | 
| int curdataflush(void) { |  | 
 |  |  | 
 | FDDFILE fdd; | FDDFILE fdd; | 
 | FILEH   fh; | FILEH   fh; | 
 | int             ret = 0; |  | 
 |  |  | 
| if ((!curfp) || (!cursize)) { | fdd = trk->fdd; | 
| return(-1); | trk->fdd = NULL; | 
|  | if ((fdd == NULL) || (trk->size == 0) || (!trk->write)) { | 
|  | goto dtfd_exit; | 
 | } | } | 
 | if (!curwrite) { |  | 
 | return(0); |  | 
 | } |  | 
 | curwrite = 0; |  | 
 | fdd = fddfile + curdrv; |  | 
 | fh = file_open(fdd->fname); | fh = file_open(fdd->fname); | 
 | if (fh == FILEH_INVALID) { | if (fh == FILEH_INVALID) { | 
| return(-1); | goto dtfd_err1; | 
| } |  | 
| if ((file_seek(fh, curfp, FSEEK_SET) != curfp) || |  | 
| (file_write(fh, D88_BUF, cursize) != cursize)) { |  | 
| ret = -1; |  | 
 | } | } | 
| if (file_close(fh)) { | if ((file_seek(fh, trk->fptr, FSEEK_SET) != trk->fptr) || | 
| ret = -1; | (file_write(fh, trk->buf, trk->size) != trk->size)) { | 
|  | goto dtfd_err2; | 
 | } | } | 
| return(ret); | file_close(fh); | 
| } | trk->write = FALSE; | 
|  |  | 
 |  |  | 
| DWORD read_d88track(short drv, WORD track, BYTE type) { | dtfd_exit: | 
|  | return(SUCCESS); | 
 |  |  | 
| FDDFILE fdd; | dtfd_err2: | 
| FILEH   hdr; | file_close(fh); | 
 |  |  | 
| curdataflush(); | dtfd_err1: | 
| curdrv = drv; | return(FAILURE); | 
| curtrk = track; | } | 
| curtype = type; |  | 
| cursct = -1; |  | 
| curwrite = 0; |  | 
| curtrkerr = 0; |  | 
| crcnum = 0; |  | 
| crcerror = 0; |  | 
 |  |  | 
| if ((drv < 0) || (drv > 3) || (track > 163) || | static D88TRK trackread(D88TRK trk, FDDFILE fdd, REG8 media, UINT track) { | 
| ((type == 0) && (d88head[drv].fd_type == 0x20)) || |  | 
| ((type == 1) && (d88head[drv].fd_type != 0x20)) || |  | 
| ((curfp = d88head[drv].trackp[track]) == 0) || |  | 
| ((cursize = nexttrackp(&d88head[drv], curfp, |  | 
| d88head[drv].fd_size) - curfp) > 0x4000)) { |  | 
| goto readd88_err; |  | 
| } |  | 
 |  |  | 
| fdd = fddfile + drv; | FILEH           fh; | 
| if ((hdr = file_open(fdd->fname)) == FILEH_INVALID) { | UINT32          fptr; | 
| goto readd88_err; | UINT            size; | 
|  | const _D88SEC   *sec; | 
|  | UINT            rem; | 
|  | UINT            maxsectors; | 
|  | UINT            sectors; | 
|  | UINT            secsize; | 
|  |  | 
|  | trackflush(trk); | 
|  | if (media != (REG8)((fdd->inf.d88.head.fd_type >> 4))) { | 
|  | goto dtrd_err1; | 
|  | } | 
|  | if (track >= 164) { | 
|  | goto dtrd_err1; | 
|  | } | 
|  | fptr = fdd->inf.d88.ptr[track]; | 
|  | if (fptr == 0) { | 
|  | goto dtrd_err1; | 
|  | } | 
|  | size = nexttrackptr(fdd, fptr, fdd->inf.d88.fd_size) - fptr; | 
|  | if (size > D88BUFSIZE) { | 
|  | size = D88BUFSIZE; | 
 | } | } | 
| if (file_seek(hdr, curfp, FSEEK_SET) != curfp) { | fh = file_open_rb(fdd->fname); | 
| file_close(hdr); | if (fh == FILEH_INVALID) { | 
| goto readd88_err; | goto dtrd_err1; | 
| } |  | 
| if (file_read(hdr, D88_BUF, (WORD)cursize) != (WORD)cursize) { |  | 
| file_close(hdr); |  | 
| goto readd88_err; |  | 
 | } | } | 
| if (file_close(hdr)) { | if ((file_seek(fh, (long)fptr, FSEEK_SET) != (long)fptr) || | 
| goto readd88_err; | (file_read(fh, trk->buf, size) != size)) { | 
|  | goto dtrd_err2; | 
 | } | } | 
| return(TRUE); | file_close(fh); | 
|  |  | 
| readd88_err: |  | 
| curfp = 0; |  | 
| cursize = 0; |  | 
| curtrkerr = 1; |  | 
| return(FALSE); |  | 
| } |  | 
|  |  | 
 |  |  | 
 |  | trk->fdd = fdd; | 
 |  | trk->media = media; | 
 |  | trk->write = FALSE; | 
 |  | trk->track = track; | 
 |  | trk->fptr = fptr; | 
 |  | trk->size = size; | 
 |  |  | 
 |  | // セクタ数チェック | 
 |  | sec = (D88SEC)trk->buf; | 
 |  | rem = size; | 
 |  | maxsectors = 0; | 
 |  | if (rem >= sizeof(_D88SEC)) { | 
 |  | maxsectors = LOADINTELWORD(sec->sectors); | 
 |  | } | 
 |  | sectors = 0; | 
 |  | while(sectors < maxsectors) { | 
 |  | secsize = LOADINTELWORD(sec->size); | 
 |  | secsize += sizeof(_D88SEC); | 
 |  | if (rem < secsize) { | 
 |  | break; | 
 |  | } | 
 |  | rem -= secsize; | 
 |  | maxsectors = LOADINTELWORD(sec->sectors); | 
 |  | sec = (D88SEC)(((UINT8 *)sec) + secsize); | 
 |  | sectors++; | 
 |  | } | 
 |  | trk->sectors = sectors; | 
 |  | return(trk); | 
 |  |  | 
 |  | dtrd_err2: | 
 |  | file_close(fh); | 
 |  |  | 
| static int seeksector(short drv, WORD track, WORD sector) { | dtrd_err1: | 
|  | return(NULL); | 
|  | } | 
 |  |  | 
| static  int             lastflag = FALSE; | static void drvflush(FDDFILE fdd) { | 
 |  |  | 
| BYTE            *p; | D88TRK  trk; | 
| WORD            sec; |  | 
 |  |  | 
| if ((curdrv != drv) || (curtrk != track) || (curtype != fdc.media)) { | trk = &d88trk; | 
| read_d88track(drv, track, fdc.media); | if (trk->fdd == fdd) { | 
| } | trackflush(trk); | 
| if (curtrkerr) { |  | 
| cursct = sector; |  | 
| goto seekerror; |  | 
 | } | } | 
 | if (cursct != sector) { |  | 
 | cursct = sector; |  | 
 | p = D88_BUF; |  | 
 | for (sec=0; sec<40;) { |  | 
 | if ((WORD)((D88_SECTOR *)p)->r == sector) { |  | 
 | memcpy(&cursec, p, sizeof(D88_SECTOR)); |  | 
 | curdata = p + sizeof(D88_SECTOR); |  | 
 | lastflag = TRUE; |  | 
 | break; |  | 
 | } |  | 
 | if (++sec >= ((D88_SECTOR *)p)->sectors) { |  | 
 | goto seekerror; |  | 
 | } |  | 
 | p += ((D88_SECTOR *)p)->size; |  | 
 | p += sizeof(D88_SECTOR); |  | 
 | } |  | 
 | if (sec >= 40) { |  | 
 | goto seekerror; |  | 
 | } |  | 
 | } |  | 
 | return(lastflag); |  | 
 |  |  | 
 | seekerror:; |  | 
 | ZeroMemory(&cursec, sizeof(D88_SECTOR)); |  | 
 | curdata = &D88_BUF[16]; |  | 
 | lastflag = FALSE; |  | 
 | return(FALSE); |  | 
 | } | } | 
 |  |  | 
 |  | static D88TRK trackseek(FDDFILE fdd, REG8 media, UINT track) { | 
 |  |  | 
| void drvflush(short drv) { | D88TRK  trk; | 
 |  |  | 
| if (curdrv == drv) { | trk = &d88trk; | 
| curdataflush(); | if ((trk->fdd != fdd) || (trk->media != media) || (trk->track != track)) { | 
| curdrv = -1; | trk = trackread(trk, fdd, media, track); | 
| curtrk = -1; |  | 
| cursct = -1; |  | 
 | } | } | 
 |  | return(trk); | 
 | } | } | 
 |  |  | 
 |  | static D88SEC sectorseek(const _D88TRK *trk, REG8 r) { | 
 |  |  | 
 |  | const _D88SEC   *sec; | 
 |  | UINT            sectors; | 
 |  | UINT            size; | 
 |  |  | 
 |  | sec = (D88SEC)trk->buf; | 
 |  | sectors = trk->sectors; | 
 |  | while(sectors) { | 
 |  | sectors--; | 
 |  | if (sec->r == r) { | 
 |  | return((D88SEC)sec); | 
 |  | } | 
 |  | size = LOADINTELWORD(sec->size); | 
 |  | size += sizeof(_D88SEC); | 
 |  | sec = (D88SEC)(((UINT8 *)sec) + size); | 
 |  | } | 
 |  | return(NULL); | 
 |  | } | 
 |  |  | 
 | //********************************************************************** |  | 
 |  |  | 
| short fdd_crc_d88(void) { | // ---- | 
 |  |  | 
| WORD            track; | static BRESULT fileappend(FILEH fh, UINT32 ptr, UINT size) { | 
| BYTE            *p; |  | 
| WORD            sec; |  | 
 |  |  | 
| ZeroMemory(fdc.crc_dat, 6); | UINT    filesize; | 
| if ((track = (WORD)(fdc.c << 1) + (WORD)fdc.h) > 163) { | UINT    r; | 
| goto crcerror_d88; | UINT8   work[0x400]; | 
| } |  | 
| seeksector(fdc.drv, track, fdc.r); | filesize = file_getsize(fh); | 
| if (curtrkerr) { | if (filesize < ptr) { | 
| goto crcerror_d88; | return(FAILURE); | 
| } | } | 
| p = D88_BUF; | filesize -= ptr; | 
| for (sec=0; sec<crcnum;) { | while(filesize) { | 
| if (++sec >= ((D88_SECTOR *)p)->sectors) { | r = min(filesize, sizeof(work)); | 
| goto crcerror_d88; | filesize -= r; | 
| } | file_seek(fh, ptr + filesize, FSEEK_SET); | 
| p += ((D88_SECTOR *)p)->size; | r = file_read(fh, work, r); | 
| p += sizeof(D88_SECTOR); | file_seek(fh, ptr + filesize + size, FSEEK_SET); | 
| } | file_write(fh, work, r); | 
| *(long *)fdc.crc_dat = *(long *)p; |  | 
| fdc.rreg = ((D88_SECTOR *)p)->c;                                // ??? メルヘンヴェール |  | 
| crcnum++; |  | 
| if (((D88_SECTOR *)p)->stat) { |  | 
| crcerror = TRUE; |  | 
| } |  | 
| else { |  | 
| crcerror = FALSE; |  | 
 | } | } | 
| return(0); | return(SUCCESS); | 
|  |  | 
| crcerror_d88:; |  | 
| crcerror = TRUE; |  | 
| return(1); |  | 
 | } | } | 
 |  |  | 
 |  | static BRESULT writetrack(FDDFILE fdd, REG8 media, UINT track, | 
 |  | UINT8 *buf, UINT size) { | 
 |  |  | 
| BYTE fdd_stat_d88(void) { | FILEH   fh; | 
|  | UINT    i; | 
| BYTE            type, cmnd; | UINT32  curptr;                         // fpointer; | 
| BYTE            ans = 0; | UINT32  nextptr;                        // endpointer; | 
| int                     seekable; | UINT    cursize; | 
| WORD            trk; | UINT    addsize; | 
|  | UINT32  cur; | 
|  | UINT8   ptr[D88_TRACKMAX][4]; | 
 |  |  | 
| if (DISKNUM[fdc.drv] == DRV_EMPTY) { | if ((track >= D88_TRACKMAX) || (size == 0)) { | 
| return(0x80);                                           // NOT READY | return(FAILURE); | 
| } |  | 
| type = fdc.type; |  | 
| cmnd = (BYTE)(fdc.cmnd >> 4); |  | 
| trk = (fdc.c << 1) + (WORD)fdc.h; |  | 
| seekable = seeksector(fdc.drv, trk, fdc.r); |  | 
| if (!fdc.r) { |  | 
| seekable = TRUE; |  | 
 | } | } | 
 |  |  | 
| if (type == 0 || type == 1 || type == 4 || | fh = file_open(fdd->fname); | 
| cmnd == 0x0a || cmnd == 0x0b || cmnd == 0x0f) { | if (fh == FILEH_INVALID) { | 
| if (d88head[fdc.drv].protect & 0x10) {  // WRITE PROTECT | return(FAILURE); | 
| ans |= 0x40; |  | 
| } |  | 
| } |  | 
| if (type == 2 || cmnd == 0x0f) { |  | 
| if (fdc.r && cursec.del_flg) { |  | 
| ans |= 0x20;                                    // RECODE TYPE / WRITE FAULT |  | 
| } |  | 
 | } | } | 
| if (type == 1 || type == 2) { | curptr = fdd->inf.d88.ptr[track]; | 
| if ((trk > 163) || (!seekable)) { | if (curptr == 0) { | 
| ans |= 0x10;                                    // SEEK ERROR / RECORD NOT FOUND | for (i=track; i>0;) {                                   // 新規トラック | 
| } | curptr = fdd->inf.d88.ptr[--i]; | 
| if ((!(ans & 0xf0)) && fdc.r && (cursec.stat)) { | if (curptr) { | 
| ans |= 0x08;                                    // CRC ERROR | break; | 
|  | } | 
 | } | } | 
| } | if (curptr) {                                                           // ヒットした | 
| if (cmnd == 0x0c) { | curptr = nexttrackptr(fdd, curptr, fdd->inf.d88.fd_size); | 
| if (curtrkerr) { |  | 
| ans |= 0x10; |  | 
 | } | } | 
| if (crcerror) { | else { | 
| ans |= 0x08;                                    // CRC ERROR | curptr = D88_HEADERSIZE; | 
 | } | } | 
 |  | nextptr = curptr; | 
 | } | } | 
| if (type == 1 || type == 4) { | else {                                                                          // トラックデータは既にある | 
| if (type == 1) {                                        // ver0.25 | nextptr = nexttrackptr(fdd, curptr, fdd->inf.d88.fd_size); | 
| ans |= 0x20;                                    // HEAD ENGAGED (X1 デハ ツネニ 1) |  | 
| if (!fdc.c) {                                   // TRACK00 |  | 
| ans |= 0x04; |  | 
| } |  | 
| } |  | 
| if (++hole < 8) {                                       // ver0.25 |  | 
| ans |= 0x02;                                    // INDEX |  | 
| } |  | 
 | } | } | 
| else if (!(ans & 0xf0)) { | cursize = nextptr - curptr; | 
| if ((type != 4) && (FDDMTR_BUSY)) { | if (size > cursize) { | 
| ans |= 0x01; | addsize = size - cursize; | 
| } | fileappend(fh, curptr, addsize); | 
| if ((type == 2) && ((WORD)fdc.off < cursec.size)) { | fdd->inf.d88.fd_size += addsize; | 
| ans |= 0x03;                                    // DATA REQUEST / BUSY | for (i=0; i<D88_TRACKMAX; i++) { | 
| } | cur = fdd->inf.d88.ptr[i]; | 
| else if ((cmnd == 0x0e) && (readdiag < 0x1a00)) { | if ((cur) && (cur >= curptr)) { | 
| ans |= 0x03; | fdd->inf.d88.ptr[i] = cur + addsize; | 
| } |  | 
| else if ((cmnd == 0x0c) && (fdc.crc_off < 6)) {         // ver0.25 |  | 
| ans |= 0x03; |  | 
| } |  | 
| else if (cmnd == 0x0f) { |  | 
| if (tao.flag == 3) { |  | 
| if (++tao.lostdatacnt > LOSTDATA_COUNT) { |  | 
| tao.flag = 4; |  | 
| } |  | 
 | } | } | 
 | ans |= tao.flag; |  | 
 | } | } | 
 | } | } | 
| return(ans); | STOREINTELDWORD(fdd->inf.d88.head.fd_size, fdd->inf.d88.fd_size); | 
|  | fdd->inf.d88.ptr[track] = curptr; | 
|  | for (i=0; i<D88_TRACKMAX; i++) { | 
|  | STOREINTELDWORD(ptr[i], fdd->inf.d88.ptr[i]); | 
|  | } | 
|  | file_seek(fh, 0, FSEEK_SET); | 
|  | file_write(fh, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); | 
|  | file_write(fh, ptr, sizeof(ptr)); | 
|  | file_seek(fh, curptr, FSEEK_SET); | 
|  | file_write(fh, buf, size); | 
|  | file_close(fh); | 
|  | return(SUCCESS); | 
 | } | } | 
 |  |  | 
 |  |  | 
 |  | // ---- | 
 |  |  | 
| //********************************************************************** | static REG8 fddd88_seek(FDDFILE fdd, REG8 media, UINT track) { | 
 |  |  | 
| void fdd_read_d88(void) { | if (trackseek(fdd, media, track) != NULL) { | 
| // POCO:読めなかったらレジスタを変更させない | return(0x00); | 
| if ((fdd_stat_d88() & 0xf3) == 3) { |  | 
| fdc.data = curdata[fdc.off]; |  | 
 | } | } | 
| } | else { | 
|  | return(FDDSTAT_SEEKERR); | 
|  |  | 
| void fdd_write_d88(void) { |  | 
|  |  | 
| if ((fdd_stat_d88() & 0xf3) == 3) { |  | 
| curdata[fdc.off] = fdc.data; |  | 
| curwrite = 1; |  | 
 | } | } | 
 | } | } | 
 |  |  | 
 |  | static REG8 fddd88_read(FDDFILE fdd, REG8 media, UINT track, REG8 sc, | 
 |  | UINT8 *ptr, UINT *size) { | 
 |  |  | 
| BYTE fdd_incoff_d88(void) { | const _D88TRK   *trk; | 
|  | const _D88SEC   *sec; | 
| BYTE    cmnd; | UINT            secsize; | 
| WORD    trk; | REG8            ret; | 
 |  |  | 
| cmnd = (BYTE)(fdc.cmnd >> 4); | TRACEOUT(("d88 read %d:%.2x", track, sc)); | 
| trk = (fdc.c << 1) + (WORD)fdc.h; | trk = trackseek(fdd, media, track); | 
| seeksector(fdc.drv, trk, fdc.r); | if (trk == NULL) { | 
| if ((WORD)(++fdc.off) < cursec.size) { | goto fd8r_err; | 
| return(0); |  | 
 | } | } | 
| fdc.off = cursec.size; | sec = sectorseek(trk, sc); | 
| if (cmnd == 0x09 || cmnd == 0x0b) { | if (sec == NULL) { | 
| fdc.rreg = fdc.r + 1;                                           // ver0.25 | goto fd8r_err; | 
| if (seeksector(fdc.drv, trk, fdc.rreg)) { |  | 
| fdc.r++; |  | 
| fdc.off = 0; |  | 
| return(0); |  | 
| } |  | 
 | } | } | 
| return(1); | ret = 0x00; | 
| } | if (sec->del_flg) { | 
|  | ret |= FDDSTAT_RECTYPE; | 
| // --------------------------------------------------------------------------- |  | 
|  |  | 
| void init_tao_d88(void) { |  | 
|  |  | 
| if ((fdc.media == 0) && (d88head[fdc.drv].fd_type != 0x20)) { |  | 
| tao = WID_2D; |  | 
 | } | } | 
| else if ((fdc.media == 1) && (d88head[fdc.drv].fd_type == 0x20)) { | if (sec->stat) { | 
| tao = WID_2HD; | ret |= FDDSTAT_CRCERR; | 
 | } | } | 
| else { | secsize = LOADINTELWORD(sec->size); | 
| tao = WID_ERR; | secsize = min(secsize, *size); | 
|  | if ((ptr) && (secsize)) { | 
|  | CopyMemory(ptr, sec + 1, secsize); | 
 | } | } | 
| } | *size = secsize; | 
|  | return(ret); | 
 |  |  | 
| int fileappend(FILEH hdr, D88_HEADER *head, | fd8r_err: | 
| long ptr, long last, long apsize) { | return(FDDSTAT_RECNFND); | 
|  | } | 
 |  |  | 
| long    length; | static REG8 fddd88_write(FDDFILE fdd, REG8 media, UINT track, REG8 sc, | 
| WORD    size; | const UINT8 *ptr, UINT size) { | 
| WORD    rsize; |  | 
| int             t; |  | 
| long    *trkp; |  | 
 |  |  | 
| if ((length = last - ptr) <= 0) {                       // 書き換える必要なし | D88TRK  trk; | 
| return(0); | D88SEC  sec; | 
|  | UINT    secsize; | 
|  |  | 
|  | TRACEOUT(("d88 write %d:%.2x", track, sc)); | 
|  | trk = trackseek(fdd, media, track); | 
|  | if (trk == NULL) { | 
|  | goto fd8w_err; | 
|  | } | 
|  | sec = sectorseek(trk, sc); | 
|  | if (sec == NULL) { | 
|  | goto fd8w_err; | 
|  | } | 
|  | secsize = LOADINTELWORD(sec->size); | 
|  | size = min(size, secsize); | 
|  | if (size) { | 
|  | CopyMemory(sec + 1, ptr, size); | 
|  | trk->write = TRUE; | 
|  | } | 
|  | return(0x00); | 
|  |  | 
|  | fd8w_err: | 
|  | return(FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT); | 
|  | } | 
|  |  | 
|  | static REG8 fddd88_wrtrk(FDDFILE fdd, REG8 media, UINT track, REG8 sc, | 
|  | const UINT8 *ptr, UINT size) { | 
|  |  | 
|  | UINT    pos; | 
|  | UINT    i; | 
|  | UINT    datsize; | 
|  | D88SEC  dst; | 
|  |  | 
|  | trackflush(&d88trk); | 
|  |  | 
|  | // データ作る | 
|  | ZeroMemory(d88trk.buf, sizeof(d88trk.buf)); | 
|  | pos = 0; | 
|  | for (i=0; i<sc; i++) { | 
|  | dst = (D88SEC)(d88trk.buf + pos); | 
|  | datsize = LOADINTELWORD(((TAOSEC *)ptr)->size); | 
|  | pos += sizeof(_D88SEC) + datsize; | 
|  | if (pos > D88BUFSIZE) { | 
|  | goto fd8wt_err; | 
|  | } | 
|  | dst->c = ((TAOSEC *)ptr)->c; | 
|  | dst->h = ((TAOSEC *)ptr)->h; | 
|  | dst->r = ((TAOSEC *)ptr)->r; | 
|  | dst->n = ((TAOSEC *)ptr)->n; | 
|  | dst->sectors[0] = sc; | 
|  | STOREINTELWORD(dst->size, datsize); | 
|  | CopyMemory((dst + 1), ptr + sizeof(TAOSEC), datsize); | 
|  | ptr += sizeof(TAOSEC) + datsize; | 
 | } | } | 
| while(length) { | if (writetrack(fdd, media, track, d88trk.buf, pos) != SUCCESS) { | 
| if (length >= 0x4000) { | goto fd8wt_err; | 
| size = 0x4000; |  | 
| } |  | 
| else { |  | 
| size = (WORD)length; |  | 
| } |  | 
| length -= (long)size; |  | 
| file_seek(hdr, ptr+length, 0); |  | 
| rsize = file_read(hdr, D88_BUF, size); |  | 
| file_seek(hdr, ptr+length+apsize, 0); |  | 
| file_write(hdr, D88_BUF, rsize); |  | 
| } |  | 
|  |  | 
| trkp = head->trackp; |  | 
| for (t=0; t<164; t++, trkp++) { |  | 
| if ((*trkp) && (*trkp >= ptr)) { |  | 
| (*trkp) += apsize; |  | 
| } |  | 
 | } | } | 
 | return(0); | return(0); | 
 | } |  | 
 |  |  | 
 |  | fd8wt_err: | 
 |  | return(FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT); | 
 |  | } | 
 |  |  | 
 |  | static REG8 fddd88_crc(FDDFILE fdd, REG8 media, UINT track, UINT num, | 
 |  | UINT8 *ptr) { | 
 |  |  | 
| void endoftrack(void) { | const _D88TRK   *trk; | 
|  | const _D88SEC   *sec; | 
|  | UINT            sectors; | 
|  | UINT            size; | 
|  |  | 
|  | trk = trackseek(fdd, media, track); | 
|  | if (trk == NULL) { | 
|  | return(FDDSTAT_RECNFND); | 
|  | } | 
|  | sec = (D88SEC)trk->buf; | 
|  | sectors = trk->sectors; | 
|  | if (num >= sectors) { | 
|  | return(FDDSTAT_RECNFND); | 
|  | } | 
|  | while(num) { | 
|  | num--; | 
|  | size = LOADINTELWORD(sec->size); | 
|  | size += sizeof(_D88SEC); | 
|  | sec = (D88SEC)(((UINT8 *)sec) + size); | 
|  | } | 
|  | ptr[0] = sec->c; | 
|  | ptr[1] = sec->h; | 
|  | ptr[2] = sec->r; | 
|  | ptr[3] = sec->n; | 
|  | ptr[4] = 0; | 
|  | ptr[5] = 0; | 
|  | //      fdc.s.rreg = sec->c;                                                            // メルヘンヴェール | 
|  | if (sec->stat) { | 
|  | return(FDDSTAT_CRCERR); | 
|  | } | 
|  | return(0x00); | 
|  | } | 
|  |  | 
|  | #if defined(SUPPORT_DISKEXT) | 
|  | static UINT32 fddd88_sec(FDDFILE fdd, REG8 media, UINT track, REG8 sc) { | 
|  |  | 
|  | const _D88TRK   *trk; | 
|  | const _D88SEC   *sec; | 
|  | UINT            sectors; | 
|  | UINT            num; | 
|  | UINT            size; | 
 |  |  | 
| FDDFILE         fdd; | trk = trackseek(fdd, media, track); | 
| FILEH           hdr; | if (trk == NULL) { | 
| int                     i; | return(0); | 
| WORD            trk; |  | 
| D88_HEADER      *head; |  | 
| long            fpointer; |  | 
| long            endpointer; |  | 
| long            lastpointer; |  | 
| long            trksize; |  | 
| int                     ptr; |  | 
| long            apsize; |  | 
|  |  | 
| if (!tao.sector) { |  | 
| tao.flag = 4; |  | 
| return; |  | 
| } |  | 
| tao.flag = 0; |  | 
|  |  | 
| curdataflush();                                         // write cache flush & |  | 
| curdrv = -1;                                            // use D88_BUF[] for temp |  | 
|  |  | 
| head = &d88head[fdc.drv]; |  | 
| trk = (fdc.c << 1) + (WORD)fdc.h; |  | 
|  |  | 
| ptr = 0; |  | 
| for (i=0; i<(int)tao.sector; i++) { |  | 
| ((D88_SECTOR *)&TAO_BUF[ptr])->sectors = tao.sector; |  | 
| ptr += ((D88_SECTOR *)&TAO_BUF[ptr])->size + 16; |  | 
| } |  | 
|  |  | 
| fdd = fddfile + fdc.drv; |  | 
| if ((hdr = file_open(fdd->fname)) == FILEH_INVALID) { |  | 
| return; |  | 
| } |  | 
| lastpointer = file_seek(hdr, 0, 2); |  | 
| if ((fpointer = head->trackp[trk]) == 0) { |  | 
| fpointer = 0;                                                           // 新規トラック |  | 
| for (i=trk; i>=0; i--) { |  | 
| if (head->trackp[i]) { |  | 
| fpointer = head->trackp[i]; |  | 
| break; |  | 
| } |  | 
| } |  | 
| if (fpointer) {                                                         // ヒットした |  | 
| fpointer = nexttrackp(head, fpointer, lastpointer); |  | 
| } |  | 
| else { |  | 
| fpointer = sizeof(D88_HEADER); |  | 
| } |  | 
| endpointer = fpointer; |  | 
| } |  | 
| else {                                                                          // トラックデータは既にある |  | 
| endpointer = nexttrackp(head, fpointer, lastpointer); |  | 
 | } | } | 
| trksize = endpointer - fpointer; | sec = (D88SEC)trk->buf; | 
| if ((apsize = (long)tao.size - trksize) > 0) { | sectors = trk->sectors; | 
| // 書き込むデータのほーが大きい | num = 0; | 
| fileappend(hdr, head, endpointer, lastpointer, apsize); | while(num < sectors) { | 
| head->fd_size += apsize; | if (sec->r == sc) { | 
| } |  | 
| head->trackp[trk] = fpointer; |  | 
| file_seek(hdr, fpointer, 0); |  | 
| file_write(hdr, TAO_BUF, tao.size); |  | 
| file_seek(hdr, 0, 0); |  | 
| file_write(hdr, head, sizeof(D88_HEADER)); |  | 
| file_close(hdr); |  | 
| } |  | 
|  |  | 
|  |  | 
| void fdd_wtao_d88(BYTE data) { |  | 
|  |  | 
| if (tao.flag != 3) { |  | 
| return; |  | 
| } |  | 
| tao.lostdatacnt = 0; |  | 
| if (tao.cnt > tao.maxsize) { |  | 
| endoftrack(); |  | 
| return; |  | 
| } |  | 
| tao.cnt++; |  | 
| switch(tao.mode) { |  | 
| case TAO_ENDOFDATA: |  | 
| if (data == TAO_MODE_GAP) { |  | 
| tao.mode = TAO_MODE_GAP; |  | 
| tao.gap = 0; |  | 
| } |  | 
| break; |  | 
| case TAO_MODE_GAP: |  | 
| if (data == TAO_MODE_GAP) { |  | 
| if (tao.gap++ > 256) { |  | 
| endoftrack(); |  | 
| } |  | 
| } |  | 
| else if (data == TAO_CMD_SYNC) { |  | 
| tao.mode = TAO_MODE_SYNC; |  | 
| } |  | 
| #if 1                                                                                           // ver0.26 Zeliard |  | 
| else if (data == 0xf4) { |  | 
| endoftrack(); |  | 
| } |  | 
| #endif |  | 
| else { |  | 
| tao.flag = 4; |  | 
| } |  | 
| break; |  | 
| case TAO_MODE_SYNC: |  | 
| //                      tao.cnt--;                                                              // ver0.26 Zeliard |  | 
| if (data == TAO_CMD_AM_IN) { |  | 
| tao.mode = TAO_MODE_AM; |  | 
| } |  | 
| else if (data == TAO_CMD_IM_IN) { |  | 
| tao.mode = TAO_MODE_IM; |  | 
| } |  | 
| else if (data) { |  | 
| tao.flag = 4; |  | 
| } |  | 
| break; |  | 
| case TAO_MODE_IM: |  | 
| if (data == TAO_CMD_IM) { |  | 
| tao.mode = TAO_ENDOFDATA; |  | 
| } |  | 
| else if (data != TAO_CMD_IM_IN) { |  | 
| tao.flag = 4; |  | 
| } |  | 
| break; |  | 
| case TAO_MODE_AM: |  | 
| if (data == TAO_CMD_IAM) { |  | 
| tao.mode = TAO_MODE_ID; |  | 
| tao.ptr = 0; |  | 
| tao.top = tao.size; |  | 
| } |  | 
| else if (data == TAO_CMD_DAM) { |  | 
| tao.mode = TAO_MODE_DATA; |  | 
| tao.ptr = 0; |  | 
| } |  | 
| else if (data == TAO_CMD_DDAM) { |  | 
| tao.mode = TAO_MODE_DATA; |  | 
| tao.ptr = 0; |  | 
| ((D88_SECTOR *)&TAO_BUF[tao.top])->del_flg = 1; |  | 
| } |  | 
| break; |  | 
| case TAO_MODE_ID: |  | 
| if ((data == TAO_CMD_IAM) && (!tao.ptr)) { |  | 
| break; |  | 
| } |  | 
| else if (tao.ptr < 4) { |  | 
| TAO_BUF[tao.size++] = data; |  | 
| tao.ptr++; |  | 
| } |  | 
| else if (data == TAO_CMD_CRC) { |  | 
| tao.mode = TAO_ENDOFDATA; |  | 
| ZeroMemory(&TAO_BUF[tao.size], 12); |  | 
| tao.size += 12; |  | 
| } |  | 
| break; |  | 
| case TAO_MODE_DATA:                                             // DATA WRITE |  | 
| if ((!tao.ptr) && |  | 
| ((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM))) { |  | 
| break; |  | 
| } |  | 
| else if (data == TAO_CMD_CRC) {                 // nで判定した方が無難か? |  | 
| tao.mode = TAO_ENDOFDATA; |  | 
| ((D88_SECTOR *)&TAO_BUF[tao.top])->size = tao.ptr; |  | 
| if (tao.sector++ > tao.maxsector) { |  | 
| tao.flag = 4; |  | 
| } |  | 
| } |  | 
| else { |  | 
| TAO_BUF[tao.size++] = data; |  | 
| tao.ptr++; |  | 
| } |  | 
 | break; | break; | 
 |  | } | 
 |  | size = LOADINTELWORD(sec->size); | 
 |  | size += sizeof(_D88SEC); | 
 |  | sec = (D88SEC)(((UINT8 *)sec) + size); | 
 |  | num++; | 
 | } | } | 
 |  | return((UINT32)(sectors << 16) + num); | 
 | } | } | 
 |  | #endif | 
 |  |  | 
 |  |  | 
 | // ---- | // ---- | 
 |  |  | 
| BRESULT fddd88_eject(REG8 drv) { | BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname) { | 
 |  |  | 
 | FDDFILE fdd; |  | 
 |  |  | 
 | drvflush(drv); |  | 
 | fdd = fddfile + drv; |  | 
 | ZeroMemory(&d88head[drv], sizeof(D88_HEADER)); |  | 
 | fdd->fname[0] = '\0'; |  | 
 | DISKNUM[drv] = 0; |  | 
 | return(SUCCESS); |  | 
 | } |  | 
 |  |  | 
 | BRESULT fddd88_set(REG8 drv, const OEMCHAR *fname) { |  | 
 |  |  | 
 | FDDFILE fdd; |  | 
 | short   attr; | short   attr; | 
 | FILEH   fh; | FILEH   fh; | 
| UINT    rsize; | BRESULT r; | 
|  | UINT8   ptr[D88_TRACKMAX][4]; | 
|  | UINT    i; | 
 |  |  | 
 | fdd = fddfile + drv; |  | 
 | attr = file_attr(fname); | attr = file_attr(fname); | 
 | if (attr & 0x18) { | if (attr & 0x18) { | 
 | goto fdst_err; | goto fdst_err; | 
 | } | } | 
| fh = file_open(fname); | fh = file_open_rb(fname); | 
 | if (fh == FILEH_INVALID) { | if (fh == FILEH_INVALID) { | 
 | goto fdst_err; | goto fdst_err; | 
 | } | } | 
| rsize = file_read(fh, &d88head[drv], sizeof(D88_HEADER)); | r = (file_read(fh, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)) | 
|  | != sizeof(fdd->inf.d88.head)) || | 
|  | (file_read(fh, ptr, sizeof(ptr)) != sizeof(ptr)); | 
 | file_close(fh); | file_close(fh); | 
| if (rsize != sizeof(D88_HEADER)) { | if (r) { | 
 | goto fdst_err; | goto fdst_err; | 
 | } | } | 
| if (attr & 1) { | fdd->inf.d88.fd_size = LOADINTELDWORD(fdd->inf.d88.head.fd_size); | 
| d88head[drv].protect |= (WORD)0x10; | for (i=0; i<D88_TRACKMAX; i++) { | 
| } | fdd->inf.d88.ptr[i] = LOADINTELDWORD(ptr[i]); | 
| milstr_ncpy(fdd->fname, fname, NELEMENTS(fdd->fname)); | } | 
| DISKNUM[drv] = 1; | if (fdd->inf.d88.head.protect & 0x10) { | 
|  | attr |= 1; | 
|  | } | 
|  | fdd->type = DISKTYPE_D88; | 
|  | fdd->protect = (UINT8)(attr & 1); | 
|  | fdd->seek = fddd88_seek; | 
|  | fdd->read = fddd88_read; | 
|  | fdd->write = fddd88_write; | 
|  | fdd->wrtrk = fddd88_wrtrk; | 
|  | fdd->crc = fddd88_crc; | 
|  | #if defined(SUPPORT_DISKEXT) | 
|  | fdd->sec = fddd88_sec; | 
|  | #endif | 
 | return(SUCCESS); | return(SUCCESS); | 
 |  |  | 
 | fdst_err: | fdst_err: | 
 | return(FAILURE); | return(FAILURE); | 
 | } | } | 
 |  |  | 
 |  | void fddd88_eject(FDDFILE fdd) { | 
 |  |  | 
 |  | drvflush(fdd); | 
 |  | } | 
 |  |  |