--- xmil/io/fdc.c 2004/08/11 17:45:06 1.10 +++ xmil/io/fdc.c 2004/08/18 08:08:13 1.19 @@ -12,22 +12,116 @@ static const UINT8 fdctype[] = {1,1,1,1,1,1,1,1,2,2,2,2,3,4,3,3}; +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 +}; -void nvitem_fdcbusy(UINT id) { + +// ---- + +void neitem_fdcbusy(UINT id) { fdc.s.busy = FALSE; if (fdc.s.bufdir) { - TRACEOUT(("dma ready!")); +// TRACEOUT(("dma ready!")); dmac_sendready(TRUE); } + (void)id; +} + +static void setbusy(SINT32 clock) { + + if (clock > 0) { + fdc.s.busy = TRUE; + nevent_set(NEVENT_FDC, clock, neitem_fdcbusy, NEVENT_ABSOLUTE); + } + else { + fdc.s.busy = FALSE; + nevent_reset(NEVENT_FDC); + } +} + +#if defined(SUPPORT_MOTORRISEUP) +static void setmotor(REG8 drvcmd) { + + UINT drv; + SINT32 clock; + + drv = drvcmd & 3; + clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + if (drvcmd & 0x80) { + if (fdc.s.motorevent[drv] == FDCMOTOR_STOP) { + fdc.s.motorevent[drv] = FDCMOTOR_STARTING; + fdc.s.motorclock[drv] = clock; + } + else if (fdc.s.motorevent[drv] == FDCMOTOR_STOPING) { + fdc.s.motorevent[drv] = FDCMOTOR_READY; + } + } + else { + if ((fdc.s.motorevent[drv] == FDCMOTOR_STARTING) || + (fdc.s.motorevent[drv] == FDCMOTOR_READY)) { + fdc.s.motorevent[drv] = FDCMOTOR_STOPING; + fdc.s.motorclock[drv] = clock; + } + } } -static void setbusy(UINT clock) { +void fdc_callback(void) { + + SINT32 clock; + UINT i; - fdc.s.busy = TRUE; - nevent_set(NEVENT_FDC, clock, nvitem_fdcbusy, NEVENT_ABSOLUTE); + 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; + } + } + else if (fdc.s.motorevent[i] == FDCMOTOR_STOPING) { + if ((clock - fdc.s.motorclock[i]) >= (SINT32)pccore.realclock) { + fdc.s.motorevent[i] = FDCMOTOR_STOP; + } + } + } } +static SINT32 motorwait(REG8 drv) { + + SINT32 curclock; + SINT32 nextclock; + + if (fdc.s.motorevent[drv] == FDCMOTOR_STARTING) { + curclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + curclock -= fdc.s.motorclock[drv]; + if (curclock < (SINT32)pccore.realclock) { + nextclock = pccore.realclock - curclock; +// TRACEOUT(("motor starting busy %d", nextclock)); + return(nextclock); + } + } + return(0); +} +#endif + + static REG8 getstat(void) { FDDFILE fdd; @@ -97,6 +191,12 @@ static REG8 type2cmd(REG8 sc) { FDDFILE fdd; UINT size; REG8 stat; + SINT32 clock; +#if defined(SUPPORT_DISKEXT) + SINT32 curclock; + SINT32 nextclock; + UINT32 secinfo; +#endif track = (fdc.s.c << 1) + fdc.s.h; if (!(fdc.s.cmd & 0x20)) { @@ -109,7 +209,7 @@ static REG8 type2cmd(REG8 sc) { } size = sizeof(fdc.s.buffer); fdd = fddfile + fdc.s.drv; - TRACEOUT(("read %.2x %d %d", fdc.s.drv, track, sc)); +// TRACEOUT(("read %.2x %d %d", fdc.s.drv, track, sc)); stat = fdd->read(fdd, fdc.s.media, track, sc, p, &size); if (stat & FDDSTAT_RECNFND) { size = 0; @@ -131,6 +231,28 @@ static REG8 type2cmd(REG8 sc) { fdc.s.bufpos = 0; fdc.s.bufsize = size; fdc.s.curtime = 0; + + clock = 0; +#if defined(SUPPORT_MOTORRISEUP) + clock += motorwait(fdc.s.drv); +#endif +#if defined(SUPPORT_DISKEXT) + secinfo = fdd->sec(fdd, fdc.s.media, track, sc); + if (secinfo) { + nextclock = LOW16(secinfo); + nextclock *= fdc.s.loopclock; + nextclock /= LOW16(secinfo >> 16); + curclock = nevent_getwork(NEVENT_RTC); + nextclock -= curclock; + if (nextclock < 0) { + nextclock += fdc.s.loopclock; + } +// TRACEOUT(("wait clock -> %d [%d/%d]", nextclock, +// LOW16(secinfo), LOW16(secinfo >> 16))); + clock += nextclock; + } +#endif + setbusy(max(clock, 500)); return(stat); } @@ -155,6 +277,7 @@ static REG8 crccmd(void) { track = (fdc.s.c << 1) + fdc.s.h; fdd = fddfile + fdc.s.drv; +// TRACEOUT(("fdd->crc %d %d %d", fdc.s.drv, track, fdc.s.crcnum)); stat = fdd->crc(fdd, fdc.s.media, track, fdc.s.crcnum, fdc.s.buffer); if (stat & FDDSTAT_RECNFND) { fdc.s.crcnum = 0; @@ -164,6 +287,7 @@ static REG8 crccmd(void) { fdc.s.bufdir = FDCDIR_IN; fdc.s.bufsize = 6; fdc.s.rreg = fdc.s.buffer[0]; + fdc.s.crcnum++; } else { fdc.s.bufdir = FDCDIR_NONE; @@ -198,21 +322,16 @@ static void bufposinc(void) { } fdc.s.stat = stat; } - if (r) { - fdc.s.rreg = fdc.s.r + 1; - stat = type2cmd(fdc.s.rreg); - if (!(stat & FDDSTAT_RECNFND)) { - fdc.s.r = fdc.s.r + 1; - fdc.s.stat = stat; - } - else { - r = FALSE; - } - } } - if (!r) { - fdc.s.bufdir = FDCDIR_NONE; - dmac_sendready(FALSE); + fdc.s.bufdir = FDCDIR_NONE; + dmac_sendready(FALSE); + if (r) { + fdc.s.rreg = fdc.s.r + 1; + stat = type2cmd(fdc.s.rreg); + if (!(stat & FDDSTAT_RECNFND)) { + fdc.s.r = fdc.s.r + 1; + fdc.s.stat = stat; + } } } } @@ -224,26 +343,24 @@ void IOOUTCALL fdc_o(UINT port, REG8 val if ((port & (~7)) != 0x0ff8) { return; } -// TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC)); + TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC)); switch(port & 7) { case 0: // コマンド fdc.s.cmd = value; cmd = (REG8)(value >> 4); fdc.s.type = fdctype[cmd]; - TRACEOUT(("fdc cmd: %.2x", value)); +// TRACEOUT(("fdc cmd: %.2x", value)); if (fdc.s.bufwrite) { fdc.s.stat = type2flash(); } fdc.s.bufdir = FDCDIR_NONE; - // マリオは コマンド発行後にbusyを見張る - // 逆にソーサリアンとかは busyだとエラーになる… + // リストアコマンドにおいて + //  マリオは コマンド発行後にbusyを見張る + //  逆にソーサリアンとかは busyだとエラーになる… // 条件は何? setbusy(20); switch(cmd) { case 0x00: // リストア - // if (value & 8) { // LAYDOCK - // setbusy(0); - // } fdc.s.motor = 0x80; // モーターOn? fdc.s.c = 0; fdc.s.step = 1; @@ -295,7 +412,6 @@ void IOOUTCALL fdc_o(UINT port, REG8 val case 0x09: case 0x0a: // ライトデータ case 0x0b: - setbusy(500); fdc.s.stat = type2cmd(fdc.s.r); break; @@ -307,6 +423,7 @@ void IOOUTCALL fdc_o(UINT port, REG8 val case 0x0d: // フォースインタラプト setbusy(0); // 必要ない? // fdc.s.skip = 0; // 000330 + fdc.s.stat = 0; dmac_sendready(FALSE); break; @@ -356,27 +473,22 @@ void IOOUTCALL fdc_o(UINT port, REG8 val fdc.s.r = 0; // SACOM TELENET fdc.s.rreg = 0; } +#if defined(SUPPORT_MOTORRISEUP) + setmotor(value); +#endif break; } } REG8 IOINPCALL fdc_i(UINT port) { -// static BYTE timeoutwait; -// static BYTE last_r; -// static short last_off; REG8 ret; +// TRACEOUT(("fdc inp %.4x", port)); + if ((port & (~7)) != 0x0ff8) { return(0xff); } -#if 0 - if ((port &= 0xf) != 8) { - last_r = -1; - last_off = -1; - timeoutwait = 4; - } -#endif switch(port & 7) { case 0: // ステータス ret = fdc.s.busy; @@ -396,6 +508,7 @@ REG8 IOINPCALL fdc_i(UINT port) { if (!(ret & 0x02)) { dmac_sendready(FALSE); } +// TRACEOUT(("ret->%.2x", ret)); return(ret); case 1: // トラック @@ -408,7 +521,7 @@ REG8 IOINPCALL fdc_i(UINT port) { if (fdc.s.motor) { if (fdc.s.bufdir == FDCDIR_IN) { fdc.s.data = fdc.s.buffer[fdc.s.bufpos]; -TRACEOUT(("read %.2x %.2x [%.4x]", fdc.s.data, fdc.s.bufpos, Z80_PC)); +// TRACEOUT(("read %.2x - %.2x [%.4x]", fdc.s.bufpos, fdc.s.data, Z80_PC)); bufposinc(); } } @@ -437,5 +550,7 @@ void fdc_reset(void) { FDDMTR_INIT; ZeroMemory(&fdc, sizeof(fdc)); fdc.s.step = 1; + fdc.s.equip = xmilcfg.fddequip; + fdc.s.loopclock = pccore.realclock / 5; }