|
|
| version 1.23, 2008/06/02 20:07:31 | version 1.24, 2009/03/23 15:02:25 |
|---|---|
| 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); | |
| } | } |
| TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC)); | if (f->s.bufdir != FDCDIR_NONE) { |
| switch(port & 7) { | f->s.bufdir = FDCDIR_NONE; |
| case 0: /* コマンド */ | dmac_sendready(FALSE); |
| if (fdc.s.bufwrite) { | } |
| fdc.s.stat = type2flash(&fdc); | |
| } | f->s.cmd = value; |
| if (fdc.s.bufdir != FDCDIR_NONE) { | cmd = (REG8)(value >> 4); |
| fdc.s.bufdir = FDCDIR_NONE; | f->s.ctype = fdctype[cmd]; |
| dmac_sendready(FALSE); | /* 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; | |
| fdc.s.cmd = value; | case 0x08: /* リードデータ */ |
| cmd = (REG8)(value >> 4); | case 0x09: |
| fdc.s.ctype = fdctype[cmd]; | case 0x0a: /* ライトデータ */ |
| /* TRACEOUT(("fdc cmd: %.2x", value)); */ | case 0x0b: |
| /* リストアコマンドにおいて | f->s.stat = type2cmd(f, f->s.r); |
| * マリオは コマンド発行後にbusyを見張る | break; |
| * 逆にソーサリアンとかは busyだとエラーになる… | |
| * 条件は何? | case 0xc: /* リードアドレス */ |
| */ | setbusy(f, 200); |
| setbusy(&fdc, 20); | f->s.stat = crccmd(f); |
| switch(cmd) { | break; |
| 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: /* リードトラック */ | 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) { |
| case 3: /* データ */ | /* セクタ */ |
| fdc.s.data = value; | fddmtr_waitsec(value); |
| f->s.r = value; | |
| f->s.rreg = value; | |
| } | |
| static void IOOUTCALL fdc_o0ffb(FDC *f, REG8 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); | |
| } | |
| static REG8 IOINPCALL fdc_i0ffa(FDC *f) { | |
| /* セクタ */ | |
| TRACEOUT(("fdc inp %.4x,%.2x", 0x0ffa, f->s.rreg)); | |
| return(f->s.rreg); | |
| } | |
| static REG8 IOINPCALL fdc_i0ffb(FDC *f) { | |
| case 1: /* トラック */ | /* データ */ |
| TRACEOUT(("fdc inp %.4x,%.2x", port, fdc.s.creg)); | if (f->s.motor) { |
| return(fdc.s.creg); | if (f->s.bufdir == FDCDIR_IN) { |
| f->s.curtime = 0; | |
| 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) | #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 |
| 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); |
| } | |
| } | |
| /* TRACEOUT(("read %.2x - %.2x [%.4x]", fdc.s.bufpos, fdc.s.data, Z80_PC)); */ | |
| } | } |
| } | } |
| 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); | return(0xff); |
| } | } |
| static REG8 IOINPCALL fdc_i0fff(FDC *f) { | |
| /* 500K/1M */ | |
| f->s.media = DISKTYPE_2D; | |
| 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 */ | /* reset */ |