|
|
| version 1.22, 2005/02/13 22:27:53 | version 1.24, 2009/03/23 15:02:25 |
|---|---|
| Line 36 static const UINT8 fdctype[] = { | Line 36 static const UINT8 fdctype[] = { |
| FDCCTYPE_CMD3}; | FDCCTYPE_CMD3}; |
| // write track | /* write track */ |
| #if !defined(CONST_DISKIMAGE) | #if !defined(CONST_DISKIMAGE) |
| enum { | enum { |
| Line 183 static void wrtrkdata(FDC *f, REG8 data) | Line 183 static void wrtrkdata(FDC *f, REG8 data) |
| } | } |
| break; | break; |
| case TAO_MODE_DATA: // DATA WRITE | case TAO_MODE_DATA: /* DATA WRITE */ |
| if ((f->s.wt_ptr == 0) && | if ((f->s.wt_ptr == 0) && |
| ((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM))) { | ((data == TAO_CMD_DAM) || (data == TAO_CMD_DDAM))) { |
| break; | break; |
| Line 217 wtd_err: | Line 217 wtd_err: |
| #endif | #endif |
| // ---- | /* ---- */ |
| void neitem_fdcbusy(UINT id) { | void neitem_fdcbusy(UINT id) { |
| fdc.s.busy = 0; | fdc.s.busy = 0; |
| if (fdc.s.bufdir) { | if (fdc.s.bufdir) { |
| // TRACEOUT(("dma ready!")); | /* TRACEOUT(("dma ready!")); */ |
| dmac_sendready(TRUE); | dmac_sendready(TRUE); |
| } | } |
| (void)id; | (void)id; |
| Line 297 static SINT32 motorwait(const FDC *f) { | Line 297 static SINT32 motorwait(const FDC *f) { |
| curclock -= f->s.motorclock[f->s.drv]; | curclock -= f->s.motorclock[f->s.drv]; |
| if (curclock < (SINT32)pccore.realclock) { | if (curclock < (SINT32)pccore.realclock) { |
| nextclock = pccore.realclock - curclock; | nextclock = pccore.realclock - curclock; |
| // TRACEOUT(("motor starting busy %d", nextclock)); | /* TRACEOUT(("motor starting busy %d", nextclock)); */ |
| return(nextclock); | return(nextclock); |
| } | } |
| } | } |
| Line 436 static REG8 type2cmd(FDC *f, REG8 sc) { | Line 436 static REG8 type2cmd(FDC *f, REG8 sc) { |
| if (nextclock < 0) { | if (nextclock < 0) { |
| nextclock += f->s.loopclock; | nextclock += f->s.loopclock; |
| } | } |
| // TRACEOUT(("wait clock -> %d [%d/%d]", nextclock, | /* TRACEOUT(("wait clock -> %d [%d/%d]", nextclock, |
| // LOW16(secinfo), LOW16(secinfo >> 16))); | LOW16(secinfo), LOW16(secinfo >> 16))); */ |
| clock += nextclock; | clock += nextclock; |
| } | } |
| #endif | #endif |
| Line 479 static REG8 crccmd(FDC *f) { | Line 479 static REG8 crccmd(FDC *f) { |
| track = (f->s.c << 1) + f->s.h; | track = (f->s.c << 1) + f->s.h; |
| fdd = fddfile + f->s.drv; | fdd = fddfile + f->s.drv; |
| // TRACEOUT(("fdd->crc %d %d %d", f->s.drv, track, f->s.crcnum)); | /* 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); | stat = fdd->crc(fdd, f->s.media, track, f->s.crcnum, crcbuf); |
| if (stat & FDDSTAT_RECNFND) { | if (stat & FDDSTAT_RECNFND) { |
| f->s.crcnum = 0; | f->s.crcnum = 0; |
| Line 512 static void fdcenddata(FDC *f) { | Line 512 static void fdcenddata(FDC *f) { |
| r = TRUE; | r = TRUE; |
| } | } |
| if ((f->s.cmd & 0x20) && (f->s.bufwrite)) { | if ((f->s.cmd & 0x20) && (f->s.bufwrite)) { |
| stat = type2flash(&fdc); | stat = type2flash(f); |
| if (stat & (FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT)) { | if (stat & (FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT)) { |
| r = FALSE; | r = FALSE; |
| } | } |
| Line 531 static void fdcenddata(FDC *f) { | Line 531 static void fdcenddata(FDC *f) { |
| } | } |
| } | } |
| void IOOUTCALL fdc_o(UINT port, REG8 value) { | |
| /* IO-Sub */ | |
| static void IOOUTCALL fdc_o0ff8(FDC *f, REG8 value) { | |
| REG8 cmd; | REG8 cmd; |
| if ((port & (~7)) != 0x0ff8) { | /* コマンド */ |
| return; | if (f->s.bufwrite) { |
| f->s.stat = type2flash(f); | |
| } | |
| if (f->s.bufdir != FDCDIR_NONE) { | |
| f->s.bufdir = FDCDIR_NONE; | |
| dmac_sendready(FALSE); | |
| } | } |
| TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC)); | |
| switch(port & 7) { | |
| case 0: // コマンド | |
| if (fdc.s.bufwrite) { | |
| fdc.s.stat = type2flash(&fdc); | |
| } | |
| if (fdc.s.bufdir != FDCDIR_NONE) { | |
| fdc.s.bufdir = FDCDIR_NONE; | |
| dmac_sendready(FALSE); | |
| } | |
| fdc.s.cmd = value; | |
| cmd = (REG8)(value >> 4); | |
| fdc.s.ctype = fdctype[cmd]; | |
| // TRACEOUT(("fdc cmd: %.2x", value)); | |
| // リストアコマンドにおいて | |
| // マリオは コマンド発行後に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: // リードトラック | f->s.cmd = value; |
| cmd = (REG8)(value >> 4); | |
| f->s.ctype = fdctype[cmd]; | |
| /* TRACEOUT(("fdc cmd: %.2x", value)); */ | |
| /* リストアコマンドにおいて | |
| * マリオは コマンド発行後にbusyを見張る | |
| * 逆にソーサリアンとかは busyだとエラーになる… | |
| * 条件は何? | |
| */ | |
| setbusy(f, 20); | |
| switch(cmd) { | |
| case 0x00: /* リストア */ | |
| f->s.motor = 0x80; /* モーターOn? */ | |
| f->s.c = 0; | |
| f->s.step = 1; | |
| f->s.r = 0; /* デゼニワールド */ | |
| seekcmd(f); | |
| f->s.rreg = 0; | |
| break; | |
| case 0x01: /* シーク */ | |
| f->s.motor = 0x80; /* モーターOn */ | |
| f->s.step = (SINT8)((f->s.c<=f->s.data)?1:-1); | |
| f->s.c = f->s.data; | |
| seekcmd(f); | |
| break; | |
| case 0x02: /* ステップ */ | |
| case 0x03: | |
| case 0x04: /* ステップイン */ | |
| case 0x05: | |
| case 0x06: /* ステップアウト */ | |
| case 0x07: | |
| f->s.stat = FDDSTAT_HEADENG; | |
| if (f->s.motor) { | |
| if (cmd & 0x04) { | |
| f->s.step = (cmd & 0x02)?-1:1; | |
| } | |
| f->s.c += f->s.step; | |
| if (cmd & 1) { | |
| seekcmd(f); | |
| } | |
| } | |
| break; | |
| case 0x08: /* リードデータ */ | |
| case 0x09: | |
| case 0x0a: /* ライトデータ */ | |
| case 0x0b: | |
| f->s.stat = type2cmd(f, f->s.r); | |
| break; | |
| case 0xc: /* リードアドレス */ | |
| setbusy(f, 200); | |
| f->s.stat = crccmd(f); | |
| break; | |
| case 0x0d: /* フォースインタラプト */ | |
| setbusy(f, 0); /* 必要ない? */ | |
| /* f->s.skip = 0; */ /* 000330 */ | |
| f->s.stat = 0; | |
| dmac_sendready(FALSE); | |
| break; | |
| case 0x0e: /* リードトラック */ | |
| #if !defined(CONST_DISKIMAGE) | #if !defined(CONST_DISKIMAGE) |
| setbusy(&fdc, 200); | setbusy(f, 200); |
| ZeroMemory(fdc.s.buffer, 0x1a00); | ZeroMemory(f->s.buffer, 0x1a00); |
| fdc.s.bufpos = 0; | f->s.bufpos = 0; |
| fdc.s.bufsize = 0x1a00; | f->s.bufsize = 0x1a00; |
| fdc.s.bufdir = FDCDIR_IN; | f->s.bufdir = FDCDIR_IN; |
| fdc.s.stat = 0; | f->s.stat = 0; |
| #else | #else |
| fdc.s.stat = FDDSTAT_SEEKERR; | f->s.stat = FDDSTAT_SEEKERR; |
| #endif | #endif |
| break; | break; |
| case 0x0f: // ライトトラック | case 0x0f: /* ライトトラック */ |
| #if !defined(CONST_DISKIMAGE) | #if !defined(CONST_DISKIMAGE) |
| setbusy(&fdc, 200); | setbusy(f, 200); |
| fdc.s.stat = wrtrkstart(&fdc); | f->s.stat = wrtrkstart(f); |
| #else | #else |
| fdc.s.stat = FDDSTAT_LOSTDATA; | f->s.stat = FDDSTAT_LOSTDATA; |
| #endif | #endif |
| break; | |
| } | |
| break; | break; |
| } | |
| } | |
| case 1: // トラック | static void IOOUTCALL fdc_o0ff9(FDC *f, REG8 value) { |
| fdc.s.creg = value; | |
| break; | |
| case 2: // セクタ | /* トラック */ |
| fddmtr_waitsec(value); | f->s.creg = value; |
| fdc.s.r = value; | } |
| fdc.s.rreg = value; | |
| break; | static void IOOUTCALL fdc_o0ffa(FDC *f, REG8 value) { |
| /* セクタ */ | |
| fddmtr_waitsec(value); | |
| f->s.r = value; | |
| f->s.rreg = value; | |
| } | |
| static void IOOUTCALL fdc_o0ffb(FDC *f, REG8 value) { | |
| case 3: // データ | /* データ */ |
| fdc.s.data = value; | f->s.data = value; |
| #if !defined(CONST_DISKIMAGE) | #if !defined(CONST_DISKIMAGE) |
| if (fdc.s.motor) { | if (f->s.motor) { |
| if (fdc.s.bufdir == FDCDIR_OUT) { | if (f->s.bufdir == FDCDIR_OUT) { |
| fdc.s.bufwrite = TRUE; | f->s.bufwrite = TRUE; |
| fdc.s.curtime = 0; | f->s.curtime = 0; |
| fdc.s.buffer[fdc.s.bufpos] = value; | f->s.buffer[f->s.bufpos] = value; |
| if (!fdc.s.busy) { | if (!f->s.busy) { |
| fdc.s.bufpos++; | f->s.bufpos++; |
| if (fdc.s.bufpos >= fdc.s.bufsize) { | if (f->s.bufpos >= f->s.bufsize) { |
| fdcenddata(&fdc); | fdcenddata(f); |
| } | |
| } | |
| } | |
| else if (fdc.s.bufdir == FDCDIR_TAO) { | |
| wrtrkdata(&fdc, value); | |
| } | } |
| } | } |
| } | |
| else if (f->s.bufdir == FDCDIR_TAO) { | |
| wrtrkdata(f, value); | |
| } | |
| } | |
| #endif | #endif |
| break; | } |
| case 4: // ドライブ・サイド | static void IOOUTCALL fdc_o0ffc(FDC *f, REG8 value) { |
| fdc.s.ctbl[fdc.s.drv] = fdc.s.c; | |
| fdc.s.c = fdc.s.ctbl[value & 0x03]; | /* ドライブ・サイド */ |
| fdc.s.motor = (UINT8)(value & 0x80); | f->s.ctbl[f->s.drv] = f->s.c; |
| fdc.s.drv = (UINT8)(value & 0x03); | f->s.c = f->s.ctbl[value & 0x03]; |
| fdc.s.h = (UINT8)((value >> 4) & 1); | f->s.motor = (UINT8)(value & 0x80); |
| fdc.s.cmd = 0; // T&E SORCERIAN | f->s.drv = (UINT8)(value & 0x03); |
| fdc.s.ctype = 0; | f->s.h = (UINT8)((value >> 4) & 1); |
| fdc.s.stat = 0; | f->s.cmd = 0; /* T&E SORCERIAN */ |
| f->s.ctype = 0; | |
| fddmtr_drvset(); | f->s.stat = 0; |
| if (!fdc.s.motor) { | |
| fdc.s.r = 0; // SACOM TELENET | fddmtr_drvset(); |
| fdc.s.rreg = 0; | if (!f->s.motor) { |
| } | f->s.r = 0; /* SACOM TELENET */ |
| f->s.rreg = 0; | |
| } | |
| #if defined(SUPPORT_MOTORRISEUP) | #if defined(SUPPORT_MOTORRISEUP) |
| setmotor(&fdc, value); | setmotor(f, value); |
| #endif | #endif |
| break; | |
| } | |
| } | } |
| REG8 IOINPCALL fdc_i(UINT port) { | static void IOOUTCALL fdc_o0(FDC *f, REG8 value) { |
| } | |
| REG8 ret; | static REG8 IOINPCALL fdc_i0ff8(FDC *f) { |
| // TRACEOUT(("fdc inp %.4x", port)); | REG8 ret; |
| if ((port & (~7)) != 0x0ff8) { | /* ステータス */ |
| return(0xff); | ret = f->s.busy; |
| if (ret) { | |
| return(ret); | |
| } | } |
| switch(port & 7) { | |
| case 0: // ステータス | |
| ret = fdc.s.busy; | |
| if (ret) { | |
| return(ret); | |
| } | |
| #if 1 | #if 1 |
| if (fdc.s.bufdir >= FDCDIR_IN) { // YsII | if (f->s.bufdir >= FDCDIR_IN) { /* YsII */ |
| fdc.s.curtime++; | f->s.curtime++; |
| if (fdc.s.curtime >= 8) { | if (f->s.curtime >= 8) { |
| fdc.s.curtime = 0; | f->s.curtime = 0; |
| fdc.s.stat |= FDDSTAT_LOSTDATA; | f->s.stat |= FDDSTAT_LOSTDATA; |
| fdc.s.bufpos++; | f->s.bufpos++; |
| if (fdc.s.bufpos >= fdc.s.bufsize) { | if (f->s.bufpos >= f->s.bufsize) { |
| fdcenddata(&fdc); | fdcenddata(f); |
| } | |
| } | |
| } | } |
| } | |
| } | |
| #endif | #endif |
| ret = getstat(&fdc); | ret = getstat(f); |
| #if 1 | #if 1 |
| if (!(ret & 0x02)) { | if (!(ret & 0x02)) { |
| dmac_sendready(FALSE); | dmac_sendready(FALSE); |
| } | } |
| #endif | #endif |
| // TRACEOUT(("ret->%.2x", ret)); | /* TRACEOUT(("ret->%.2x", ret)); */ |
| return(ret); | return(ret); |
| } | |
| static REG8 IOINPCALL fdc_i0ff9(FDC *f) { | |
| /* トラック */ | |
| TRACEOUT(("fdc inp %.4x,%.2x", 0x0ff9, f->s.creg)); | |
| return(f->s.creg); | |
| } | |
| case 1: // トラック | static REG8 IOINPCALL fdc_i0ffa(FDC *f) { |
| TRACEOUT(("fdc inp %.4x,%.2x", port, fdc.s.creg)); | |
| return(fdc.s.creg); | |
| case 2: // セクタ | /* セクタ */ |
| TRACEOUT(("fdc inp %.4x,%.2x", port, fdc.s.rreg)); | TRACEOUT(("fdc inp %.4x,%.2x", 0x0ffa, f->s.rreg)); |
| return(fdc.s.rreg); | return(f->s.rreg); |
| } | |
| static REG8 IOINPCALL fdc_i0ffb(FDC *f) { | |
| case 3: // データ | /* データ */ |
| if (fdc.s.motor) { | if (f->s.motor) { |
| if (fdc.s.bufdir == FDCDIR_IN) { | if (f->s.bufdir == FDCDIR_IN) { |
| fdc.s.curtime = 0; | f->s.curtime = 0; |
| #if !defined(CONST_DISKIMAGE) | #if !defined(CONST_DISKIMAGE) |
| fdc.s.data = fdc.s.buffer[fdc.s.bufpos]; | f->s.data = f->s.buffer[f->s.bufpos]; |
| #else | #else |
| fdc.s.data = fdc.e.buffer[fdc.s.bufpos]; | f->s.data = f->e.buffer[f->s.bufpos]; |
| #endif | #endif |
| // TRACEOUT(("read %.2x - %.2x [%.4x]", fdc.s.bufpos, fdc.s.data, Z80_PC)); | if (!f->s.busy) { |
| if (!fdc.s.busy) { | f->s.bufpos++; |
| fdc.s.bufpos++; | if (f->s.bufpos >= f->s.bufsize) { |
| if (fdc.s.bufpos >= fdc.s.bufsize) { | fdcenddata(f); |
| fdcenddata(&fdc); | |
| } | |
| } | |
| } | } |
| } | } |
| return(fdc.s.data); | /* TRACEOUT(("read %.2x - %.2x [%.4x]", f->s.bufpos, f->s.data, Z80_PC)); */ |
| } | |
| } | |
| return(f->s.data); | |
| } | |
| case 4: // FM | static REG8 IOINPCALL fdc_i0ffc(FDC *f) { |
| case 5: // MFM | |
| return(0x00); | |
| case 6: // 1.6M | /* FM */ |
| fdc.s.media = DISKTYPE_2HD; | return(0x00); |
| break; | } |
| case 7: // 500K/1M | static REG8 IOINPCALL fdc_i0ffd(FDC *f) { |
| fdc.s.media = DISKTYPE_2D; | |
| break; | /* MFM */ |
| } | return(0x00); |
| } | |
| static REG8 IOINPCALL fdc_i0ffe(FDC *f) { | |
| /* 1.6M */ | |
| f->s.media = DISKTYPE_2HD; | |
| return(0xff); | |
| } | |
| static REG8 IOINPCALL fdc_i0fff(FDC *f) { | |
| /* 500K/1M */ | |
| f->s.media = DISKTYPE_2D; | |
| return(0xff); | return(0xff); |
| } | } |
| // ---- | /* IO */ |
| typedef void (IOINPCALL * FNFDCOUT)(FDC *f, REG8 value); | |
| static const FNFDCOUT s_fnOut[] = | |
| { | |
| fdc_o0ff8, fdc_o0ff9, fdc_o0ffa, fdc_o0ffb, | |
| fdc_o0ffc, fdc_o0, fdc_o0, fdc_o0, | |
| }; | |
| typedef REG8 (IOINPCALL * FNFDCINP)(FDC *f); | |
| static const FNFDCINP s_fnInp[] = | |
| { | |
| fdc_i0ff8, fdc_i0ff9, fdc_i0ffa, fdc_i0ffb, | |
| fdc_i0ffc, fdc_i0ffd, fdc_i0ffe, fdc_i0fff, | |
| }; | |
| void IOINPCALL fdc_o(UINT port, REG8 value) | |
| { | |
| if ((port & (~7)) != 0x0ff8) | |
| { | |
| return; | |
| } | |
| /* TRACEOUT(("fdc out %.4x,%.2x", port, value)); */ | |
| (s_fnOut[port & 7])(&fdc, value); | |
| } | |
| REG8 IOINPCALL fdc_i(UINT uPort) | |
| { | |
| if ((uPort & (~7)) != 0x0ff8) | |
| { | |
| return 0xff; | |
| } | |
| /* TRACEOUT(("fdc inp %.4x", port)); */ | |
| return (s_fnInp[uPort & 7])(&fdc); | |
| } | |
| /* reset */ | |
| void fdc_reset(void) { | void fdc_reset(void) { |