|
|
| version 1.1, 2004/08/02 13:38:46 | version 1.17, 2004/08/15 11:14:42 |
|---|---|
| Line 3 | Line 3 |
| #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_2d.h" |
| #include "fdd_d88.h" | #include "fdd_d88.h" |
| #include "fdd_mtr.h" | #include "fdd_mtr.h" |
| 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 const UINT8 fdctype[] = {1,1,1,1,1,1,1,1,2,2,2,2,3,4,3,3}; |
| static BYTE fdd_stat(void) { | void neitem_fdcbusy(UINT id) { |
| fdc.s.busy = FALSE; | |
| if (fdc.s.bufdir) { | |
| // TRACEOUT(("dma ready!")); | |
| dmac_sendready(TRUE); | |
| } | |
| (void)id; | |
| } | |
| static void setbusy(SINT32 clock) { | |
| FDDFILE fdd; | 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); | |
| } | |
| } | |
| fdd = fddfile + fdc.drv; | #if defined(SUPPORT_MOTORRISEUP) |
| switch(fdd->type) { | static void setmotor(REG8 drvcmd) { |
| case DISKTYPE_NOTREADY: | |
| return(0); | |
| case DISKTYPE_BETA: | UINT drv; |
| return(fdd_stat_2d()); | SINT32 clock; |
| case DISKTYPE_D88: | drv = drvcmd & 3; |
| default: | clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; |
| return(fdd_stat_d88()); | 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; | |
| } | |
| } | |
| } | |
| void fdc_callback(void) { | |
| SINT32 clock; | |
| UINT i; | |
| 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; | |
| } | |
| } | |
| } | } |
| return(0); | |
| } | } |
| static SINT32 motorwait(REG8 drv) { | |
| /*********************************************************************** | SINT32 curclock; |
| FDC (X1から見るI/Oに相当する関数) | 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 int inc_off(void) { | |
| BYTE ret; | static REG8 getstat(void) { |
| FDDFILE fdd; | |
| FDDFILE fdd; | |
| REG8 cmd; | |
| REG8 type; | |
| REG8 ret; | |
| if (!fdc.motor) { | fdd = fddfile + fdc.s.drv; |
| return(0); | cmd = (REG8)(fdc.s.cmd >> 4); |
| type = fdc.s.type; | |
| if (fdd->type == DISKTYPE_NOTREADY) { | |
| ret = FDDSTAT_NOTREADY; | |
| } | } |
| if (fdcdummyread) { | else if (type != 0) { |
| fdcdummyread--; | ret = fdc.s.stat; |
| return(0); | |
| } | } |
| else { | else { |
| fdd = fddfile + fdc.drv; | ret = 0; |
| switch(fdd->type) { | } |
| case DISKTYPE_NOTREADY: | if ((type == 1) && (fdc.s.c == 0)) { |
| return(0); | ret |= FDDSTAT_TRACK00; |
| } | |
| case DISKTYPE_BETA: | if ((type == 0) || (type == 1) || (type == 4) || |
| ret = fdd_incoff_2d(); | (cmd == 0x0a) || (cmd == 0x0b) || (cmd == 0x0f)) { |
| break; | if (fdd->protect) { |
| ret |= FDDSTAT_WRITEP; | |
| case DISKTYPE_D88: | } |
| default: | } |
| ret = fdd_incoff_d88(); | if ((type == 1) || (type == 4)) { |
| break; | fdc.s.hole++; |
| if (fdc.s.hole < 8) { | |
| ret |= FDDSTAT_INDEX; | |
| } | } |
| if (ret) { | } |
| dma.DMA_REDY = 8; // <- DMA ノ レディシンゴウ ヲ クリア | else if (!(ret & 0xf0)) { |
| if (FDDMTR_BUSY) { | |
| ret |= FDDSTAT_BUSY; | |
| } | |
| if (fdc.s.bufdir) { | |
| ret |= FDDSTAT_DRQ | FDDSTAT_BUSY; | |
| } | |
| else if (cmd == 0x0f) { | |
| ret |= FDDSTAT_LOSTDATA; | |
| } | } |
| } | } |
| return(ret); | return(ret); |
| } | } |
| void IOOUTCALL fdc_o(UINT port, REG8 value) { | static void seekcmd(void) { |
| REG8 cmd; | FDDFILE fdd; |
| UINT track; | |
| port &= 0xf; | fdc.s.crcnum = 0; |
| if (port == 8) { // コマンド | fdc.s.creg = fdc.s.c; |
| driveset = 0; | fdd = fddfile + fdc.s.drv; |
| fdc.cmd = value; | track = (fdc.s.c << 1) + fdc.s.h; |
| cmd = (REG8)(value >> 4); | fdc.s.stat = fdd->seek(fdd, fdc.s.media, track) | FDDSTAT_HEADENG; |
| fdc.type = fdctype[cmd]; | FDDMTR_MOVE; |
| fdc.skip = 2; | } |
| switch(cmd) { | |
| case 0x00: // リストア | static REG8 type2cmd(REG8 sc) { |
| if (value & 8) { // LAYDOCK | |
| fdc.skip = 0; | REG8 dir; |
| fdc.busyclock = 20; // ver0.25 (now testing) | UINT track; |
| fdc.busystart = h_cntbase + h_cnt; | UINT8 *p; |
| } | FDDFILE fdd; |
| fdc.motor = 0x80; // モーターOn? | UINT size; |
| fdc.c = 0; | REG8 stat; |
| fdc.treg = 0; | SINT32 clock; |
| FDDMTR_MOVE; | #if defined(SUPPORT_DISKEXT) |
| fdc.step = 1; | SINT32 curclock; |
| #if 1 // ver0.25 | SINT32 nextclock; |
| fdc.r = 0; // デゼニワールド | UINT32 secinfo; |
| fdc.rreg = 0; | |
| #endif | #endif |
| break; | |
| case 0x01: // シーク | track = (fdc.s.c << 1) + fdc.s.h; |
| fdc.motor = 0x80; // モーターOn | if (!(fdc.s.cmd & 0x20)) { |
| fdc.step = (char)((fdc.c<=fdc.data)?1:-1); | p = fdc.s.buffer; |
| #if 0 // スタクル // ver0.50 | dir = FDCDIR_IN; |
| fdc.rreg = fdc.r = 0; | } |
| else { | |
| p = NULL; | |
| dir = FDCDIR_OUT; | |
| } | |
| size = sizeof(fdc.s.buffer); | |
| fdd = fddfile + fdc.s.drv; | |
| // 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; | |
| dir = FDCDIR_NONE; | |
| } | |
| else if (dir == FDCDIR_OUT) { | |
| if (size) { | |
| ZeroMemory(fdc.s.buffer, size); | |
| } | |
| stat = stat & (~FDDSTAT_RECTYPE); | |
| } | |
| fdc.s.bufmedia = fdc.s.media; | |
| fdc.s.bufunit = fdc.s.drv; | |
| fdc.s.buftrack = track; | |
| fdc.s.bufsc = sc; | |
| fdc.s.bufwrite = FALSE; | |
| fdc.s.bufdir = dir; | |
| fdc.s.bufmark = fdc.s.cmd & 1; | |
| fdc.s.bufpos = 0; | |
| fdc.s.bufsize = size; | |
| fdc.s.curtime = 0; | |
| clock = 0; | |
| #if defined(SUPPORT_MOTORRISEUP) | |
| clock += motorwait(fdc.s.drv); | |
| #endif | #endif |
| fdc.c = fdc.data; | #if defined(SUPPORT_DISKEXT) |
| fdc.treg = fdc.data; | secinfo = fdd->sec(fdd, fdc.s.media, track, sc); |
| FDDMTR_MOVE; | if (secinfo) { |
| break; | nextclock = LOW16(secinfo); |
| nextclock *= fdc.s.loopclock; | |
| case 0x02: // ステップ | nextclock /= LOW16(secinfo >> 16); |
| case 0x03: | curclock = nevent_getwork(NEVENT_RTC); |
| if (fdc.motor) { | nextclock -= curclock; |
| fdc.c += fdc.step; | if (nextclock < 0) { |
| if (cmd & 1) { | nextclock += fdc.s.loopclock; |
| FDDMTR_MOVE; | } |
| fdc.treg = fdc.c; | // TRACEOUT(("wait clock -> %d [%d/%d]", nextclock, |
| } | // LOW16(secinfo), LOW16(secinfo >> 16))); |
| } | clock += nextclock; |
| break; | } |
| #endif | |
| setbusy(max(clock, 500)); | |
| return(stat); | |
| } | |
| case 0x04: // ステップイン | static REG8 type2flash(void) { |
| case 0x05: | |
| if (fdc.motor) { | |
| fdc.step = 1; | |
| fdc.c++; | |
| if (cmd & 1) { | |
| FDDMTR_MOVE; | |
| fdc.treg = fdc.c; | |
| } | |
| } | |
| break; | |
| case 0x06: // ステップアウト | FDDFILE fdd; |
| case 0x07: | |
| if (fdc.motor) { | |
| fdc.step = -1; | |
| fdc.c--; | |
| if (cmd & 1) { | |
| FDDMTR_MOVE; | |
| fdc.treg = fdc.c; | |
| } | |
| } | |
| break; | |
| case 0x08: // リードデータ | fdc.s.bufwrite = FALSE; |
| case 0x09: | fdd = fddfile + fdc.s.bufunit; |
| case 0x0a: // ライトデータ | if (fdd->protect) { |
| case 0x0b: | return(FDDSTAT_WRITEFAULT); |
| fdc.off = 0; | } |
| fdcdummyread = 2; | return(fdd->write(fdd, fdc.s.bufmedia, fdc.s.buftrack, |
| if (fdc.motor) { | fdc.s.bufsc, fdc.s.buffer, fdc.s.bufpos)); |
| if (dma.DMA_ENBL) { | } |
| dma.DMA_REDY = 0; | |
| // fdc.skip = 0; // DMAで割り込みを監視する事! | |
| } | |
| } | |
| break; | |
| case 0xc: // リードアドレス | static REG8 crccmd(void) { |
| fdc.crc_off = 0; | |
| fdcdummyread = 2; | |
| if (fdc.motor) { // ver0.25 | |
| if (dma.DMA_ENBL) { | |
| dma.DMA_REDY = 0; | |
| } | |
| } | |
| { | |
| 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: // フォースインタラプト | UINT track; |
| fdcdummyread = 0; // 必要ない? | FDDFILE fdd; |
| fdc.skip = 0; // 000330 | REG8 stat; |
| dma.DMA_REDY = 8; // ver0.25 | |
| break; | track = (fdc.s.c << 1) + fdc.s.h; |
| fdd = fddfile + fdc.s.drv; | |
| case 0x0e: // リードトラック | // TRACEOUT(("fdd->crc %d %d %d", fdc.s.drv, track, fdc.s.crcnum)); |
| readdiag = 0; | stat = fdd->crc(fdd, fdc.s.media, track, fdc.s.crcnum, fdc.s.buffer); |
| break; | if (stat & FDDSTAT_RECNFND) { |
| fdc.s.crcnum = 0; | |
| case 0x0f: // ライトトラック | stat = fdd->crc(fdd, fdc.s.media, track, 0, fdc.s.buffer); |
| { | } |
| FDDFILE fdd = fddfile + fdc.drv; | if (!(stat & FDDSTAT_RECNFND)) { |
| switch(fdd->type) { | fdc.s.bufdir = FDCDIR_IN; |
| case DISKTYPE_NOTREADY: | fdc.s.bufsize = 6; |
| case DISKTYPE_BETA: | fdc.s.rreg = fdc.s.buffer[0]; |
| break; | fdc.s.crcnum++; |
| case DISKTYPE_D88: | |
| default: | |
| if (fdc.motor) { // ver0.25 | |
| init_tao_d88(); | |
| if (dma.DMA_ENBL) { | |
| dma.DMA_REDY = 0; | |
| } | |
| } | |
| break; | |
| } | |
| } | |
| break; | |
| } | |
| } | } |
| else { | else { |
| cmd = (REG8)(fdc.cmd >> 4); | fdc.s.bufdir = FDCDIR_NONE; |
| switch(port) { | fdc.s.bufsize = 0; |
| case 0x09: // トラック | |
| fdc.treg = value; | |
| break; | |
| case 0x0a: // セクタ | |
| FDDMTR_WAITSEC(value); | |
| fdc.r = value; | |
| fdc.rreg = value; | |
| break; | |
| case 0x0b: // データ | |
| fdc.data = value; | |
| 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: // ドライブ・サイド | |
| driveset = 1; | |
| FDC_c[fdc.drv] = fdc.c; | |
| fdc.c = FDC_c[value & 0x03]; // XTAL !!! | |
| fdc.motor = (UINT8)(value & 0x80); | |
| fdc.drv = (UINT8)(value & 0x03); | |
| fdc.h = (UINT8)((value >> 4) & 1); | |
| fdc.cmd = 0; // T&E SORCERIAN | |
| // fdc.data = 0; // 影の伝説 | |
| 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 | |
| } | |
| break; | |
| } | |
| } | } |
| fdc.s.bufwrite = FALSE; | |
| fdc.s.curtime = 0; | |
| return(stat); | |
| } | } |
| REG8 IOINPCALL fdc_i(UINT port) { | static void bufposinc(void) { |
| static BYTE timeoutwait; | BRESULT r; |
| static BYTE last_r; | REG8 stat; |
| static short last_off; | |
| BYTE ans; | if (fdc.s.busy) { |
| REG8 cmd; | return; |
| } | |
| cmd = (REG8)(fdc.cmd >> 4); | fdc.s.bufpos++; |
| fdc.s.curtime = 0; | |
| if ((port &= 0xf) != 8) { | if (fdc.s.bufpos >= fdc.s.bufsize) { |
| last_r = -1; | r = FALSE; |
| last_off = -1; | if (fdc.s.type == 2) { |
| timeoutwait = 4; | stat = 0; |
| } | if (fdc.s.cmd & 0x10) { |
| switch(port) { | r = TRUE; |
| 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.cmd & 0x20) && (fdc.s.bufwrite)) { |
| FDDFILE fdd = fddfile + fdc.drv; | stat = type2flash(); |
| if (fdd->type == DISKTYPE_NOTREADY) { | if (stat & (FDDSTAT_RECNFND | FDDSTAT_WRITEFAULT)) { |
| if (fdc.type == 1 && fdc.c == 0) { // ドライブチェック !!! | r = FALSE; |
| return(0x84); // ←接続されてる時だけ | |
| } | } |
| return(0x80); | fdc.s.stat = stat; |
| } | } |
| } | } |
| if (fdc.type == 2) { | fdc.s.bufdir = FDCDIR_NONE; |
| if (last_r == fdc.r && last_off == fdc.off && | dmac_sendready(FALSE); |
| !(--timeoutwait)) { | if (r) { |
| inc_off(); | fdc.s.rreg = fdc.s.r + 1; |
| timeoutwait = 4; | stat = type2cmd(fdc.s.rreg); |
| } | if (!(stat & FDDSTAT_RECNFND)) { |
| last_r = fdc.r; | fdc.s.r = fdc.s.r + 1; |
| last_off = fdc.off; | fdc.s.stat = stat; |
| } // Read Write時のみの変化でいい筈 | |
| if (!((ans = fdd_stat()) & 2)) { | |
| dma.DMA_REDY = 8; // <- DMA ノ レディシンゴウ ヲ クリア | |
| } | |
| #if 1 | |
| if (driveset) { // 0xffcを叩いた直後だったら | |
| ans &= 0xc4; | |
| } | } |
| #endif | } |
| return(ans); | } |
| } | |
| case 0x9: // トラック | void IOOUTCALL fdc_o(UINT port, REG8 value) { |
| return(fdc.treg); | |
| case 0xa: // セクタ | REG8 cmd; |
| return(fdc.rreg); // ver0.25 | |
| case 0xb: // データ | if ((port & (~7)) != 0x0ff8) { |
| if (fdc.motor) { | return; |
| if ((cmd == 0x08) || (cmd == 0x09)) { // リード・データ | } |
| FDDFILE fdd; | // TRACEOUT(("fdc %.4x,%.2x [%.4x]", port, value, Z80_PC)); |
| fdd = fddfile + fdc.drv; | switch(port & 7) { |
| switch(fdd->type) { | case 0: // コマンド |
| case DISKTYPE_NOTREADY: | fdc.s.cmd = value; |
| break; | cmd = (REG8)(value >> 4); |
| fdc.s.type = fdctype[cmd]; | |
| case DISKTYPE_BETA: | // TRACEOUT(("fdc cmd: %.2x", value)); |
| fdd_read_2d(); | if (fdc.s.bufwrite) { |
| break; | fdc.s.stat = type2flash(); |
| } | |
| case DISKTYPE_D88: | fdc.s.bufdir = FDCDIR_NONE; |
| default: | // リストアコマンドにおいて |
| fdd_read_d88(); // WOODY POCO !!! | // マリオは コマンド発行後にbusyを見張る |
| break; | // 逆にソーサリアンとかは busyだとエラーになる… |
| // 条件は何? | |
| setbusy(20); | |
| switch(cmd) { | |
| case 0x00: // リストア | |
| fdc.s.motor = 0x80; // モーターOn? | |
| fdc.s.c = 0; | |
| fdc.s.step = 1; | |
| fdc.s.r = 0; // デゼニワールド | |
| seekcmd(); | |
| 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(); | |
| break; | |
| case 0x02: // ステップ | |
| case 0x03: | |
| if (fdc.s.motor) { | |
| fdc.s.c += fdc.s.step; | |
| if (cmd & 1) { | |
| seekcmd(); | |
| } | |
| } | } |
| inc_off(); | break; |
| } | |
| else if (cmd == 0x0c) { // リード・アドレス | case 0x04: // ステップイン |
| if (fdc.crc_off < 6) { // ver0.25 | case 0x05: |
| fdc.data = fdc.crc_dat[fdc.crc_off]; | if (fdc.s.motor) { |
| if (fdcdummyread) { // ver0.25 | fdc.s.step = 1; |
| fdcdummyread--; | fdc.s.c++; |
| if (cmd & 1) { | |
| seekcmd(); | |
| } | } |
| else { | } |
| fdc.crc_off++; | break; |
| case 0x06: // ステップアウト | |
| case 0x07: | |
| if (fdc.s.motor) { | |
| fdc.s.step = -1; | |
| fdc.s.c--; | |
| if (cmd & 1) { | |
| seekcmd(); | |
| } | } |
| } | } |
| break; | |
| case 0x08: // リードデータ | |
| case 0x09: | |
| case 0x0a: // ライトデータ | |
| case 0x0b: | |
| fdc.s.stat = type2cmd(fdc.s.r); | |
| break; | |
| case 0xc: // リードアドレス | |
| setbusy(200); | |
| fdc.s.stat = crccmd(); | |
| break; | |
| case 0x0d: // フォースインタラプト | |
| setbusy(0); // 必要ない? | |
| // fdc.s.skip = 0; // 000330 | |
| fdc.s.stat = 0; | |
| dmac_sendready(FALSE); | |
| break; | |
| case 0x0e: // リードトラック | |
| setbusy(200); | |
| ZeroMemory(fdc.s.buffer, 0x1a00); | |
| fdc.s.bufpos = 0; | |
| fdc.s.bufsize = 0x1a00; | |
| fdc.s.bufdir = FDCDIR_IN; | |
| break; | |
| case 0x0f: // ライトトラック | |
| break; | |
| } | |
| break; | |
| case 1: // トラック | |
| fdc.s.c = value; | |
| break; | |
| case 2: // セクタ | |
| FDDMTR_WAITSEC(value); | |
| fdc.s.r = value; | |
| fdc.s.rreg = value; | |
| break; | |
| case 3: // データ | |
| fdc.s.data = value; | |
| if ((fdc.s.motor) && (fdc.s.bufdir == FDCDIR_OUT)) { | |
| fdc.s.buffer[fdc.s.bufpos] = value; | |
| fdc.s.bufwrite = TRUE; | |
| bufposinc(); | |
| } | |
| break; | |
| 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.type = 0; | |
| FDDMTR_DRVSET; | |
| if (!fdc.s.motor) { | |
| fdc.s.r = 0; // SACOM TELENET | |
| fdc.s.rreg = 0; | |
| } | |
| #if defined(SUPPORT_MOTORRISEUP) | |
| setmotor(value); | |
| #endif | |
| break; | |
| } | |
| } | |
| REG8 IOINPCALL fdc_i(UINT port) { | |
| REG8 ret; | |
| // TRACEOUT(("fdc inp %.4x", port)); | |
| if ((port & (~7)) != 0x0ff8) { | |
| return(0xff); | |
| } | |
| switch(port & 7) { | |
| case 0: // ステータス | |
| ret = fdc.s.busy; | |
| if (ret) { | |
| return(ret); | |
| } | |
| #if 1 | |
| if (fdc.s.bufdir) { // YsII | |
| fdc.s.curtime++; | |
| if (fdc.s.curtime >= 8) { | |
| fdc.s.stat |= 0x04; | |
| bufposinc(); | |
| } | } |
| else if (cmd == 0x0e) { // ver0.25 | } |
| fdc.data = 0; | #endif |
| readdiag++; | ret = getstat(); |
| if (!(ret & 0x02)) { | |
| dmac_sendready(FALSE); | |
| } | |
| // TRACEOUT(("ret->%.2x", ret)); | |
| return(ret); | |
| case 1: // トラック | |
| return(fdc.s.creg); | |
| case 2: // セクタ | |
| return(fdc.s.rreg); | |
| case 3: // データ | |
| 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.bufpos, fdc.s.data, Z80_PC)); | |
| bufposinc(); | |
| } | } |
| } | } |
| 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); |
| } | } |
| Line 418 void fdc_reset(void) { | Line 527 void fdc_reset(void) { |
| FDDMTR_INIT; | FDDMTR_INIT; |
| ZeroMemory(&fdc, sizeof(fdc)); | ZeroMemory(&fdc, sizeof(fdc)); |
| fdc.step = 1; | fdc.s.step = 1; |
| ZeroMemory(FDC_c, 4); | fdc.s.equip = xmilcfg.fddequip; |
| fdc.s.loopclock = pccore.realclock / 5; | |
| } | } |