public void SetReg(WD93REG reg, byte value) { long tact = m_cpu.Tact; if (LogIO) { LogAgent.Debug( "WD93 {0} <== #{1:X2} [PC=#{2:X4}, T={3}]", reg, value, m_cpu.regs.PC, tact); } process(tact); switch (reg) { case WD93REG.CMD: // COMMAND/STATUS LedDiskIO = true; // force interrupt if ((value & 0xF0) == 0xD0) { int cond = value & 0xF; next = tact; idx_cnt = 0; idx_tmo = next + 15 * Z80FQ / FDD_RPS; // 15 disk turns cmd = value; if (cond == 0) { state = WDSTATE.S_IDLE; rqs = BETA_STATUS.NONE; status &= ~WD_STATUS.WDS_BUSY; break; } if ((cond & 8) != 0) // Immediate Interrupt { state = WDSTATE.S_IDLE; rqs = BETA_STATUS.INTRQ; status &= ~WD_STATUS.WDS_BUSY; break; } if ((cond & 4) != 0) // Index Pulse (unimplemented yet) { state = WDSTATE.S_IDLE; rqs = BETA_STATUS.INTRQ; status &= ~WD_STATUS.WDS_BUSY; break; } if ((cond & 2) != 0) // Ready to Not-Ready Transition (unimplemented yet) { state = WDSTATE.S_IDLE; rqs = BETA_STATUS.INTRQ; status &= ~WD_STATUS.WDS_BUSY; break; } if ((cond & 1) != 0) // Not-Ready to Ready Transition (unimplemented yet) { state = WDSTATE.S_IDLE; rqs = BETA_STATUS.INTRQ; status &= ~WD_STATUS.WDS_BUSY; break; } break; } if ((status & WD_STATUS.WDS_BUSY) != 0) break; cmd = value; next = tact; status |= WD_STATUS.WDS_BUSY; rqs = BETA_STATUS.NONE; idx_cnt = 0; idx_tmo = long.MaxValue; //----------------------------------------------------------------------- if ((cmd & 0x80) != 0) // read/write command { // abort if no disk if ((status & WD_STATUS.WDS_NOTRDY) != 0) { state2 = WDSTATE.S_IDLE; state = WDSTATE.S_WAIT; next = tact + Z80FQ / FDD_RPS; rqs = BETA_STATUS.INTRQ; break; } // continue disk spinning if (fdd[drive].motor > 0 || wd93_nodelay) fdd[drive].motor = next + 2 * Z80FQ; state = WDSTATE.S_DELAY_BEFORE_CMD; break; } // else seek/step command state = WDSTATE.S_TYPE1_CMD; break; case WD93REG.TRK: track = value; break; case WD93REG.SEC: sector = value; break; case WD93REG.DAT: LedDiskIO = true; data = value; rqs &= ~BETA_STATUS.DRQ; status &= ~WD_STATUS.WDS_DRQ; break; case WD93REG.SYS: LedDiskIO = true; //system = value; drive = value & 3; side = 1 & ~(value >> 4); fdd[drive].HeadSide = side; //seldrive->t.clear(); fdd[drive].t = fdd[drive].CurrentTrack; if ((value & (int)WD_SYS.SYS_RST) == 0) // reset { status = WD_STATUS.WDS_NOTRDY; rqs = BETA_STATUS.INTRQ; fdd[drive].motor = 0; state = WDSTATE.S_IDLE; idx_cnt = 0; idx_status = 0; #if NO_COMPILE // move head to trk00 steptime = 6 * (Z80FQ / 1000); // 6ms next += 1*Z80FQ/1000; // 1ms before command state = S_RESET; //seldrive->track = 0; #endif } else if (((system ^ value) & (int)WD_SYS.SYS_HLT) != 0) // hlt 0->1 { if ((status & WD_STATUS.WDS_BUSY) == 0) { idx_cnt++; } } system = value; break; default: throw new Exception("WD1793.SetReg: Invalid register"); } process(tact); }
public byte GetReg(WD93REG reg) { long tact = m_cpu.Tact; process(tact); byte value = 0xFF; switch (reg) { case WD93REG.CMD: // COMMAND/STATUS #1F LedDiskIO = true; rqs &= ~BETA_STATUS.INTRQ; value = (byte)status; if ((system & (int)WD_SYS.SYS_HLT) == 0) value &= (byte)(value & (int)~WD_STATUS.WDS_HEADL); if (!fdd[drive].Present) value = (byte)(value & ~(byte)WD_STATUS.WDS_INDEX); // No disk emulation break; case WD93REG.TRK: // #3F value = track; break; case WD93REG.SEC: // #5F value = sector; break; case WD93REG.DAT: // #7F LedDiskIO = true; status &= ~WD_STATUS.WDS_DRQ; rqs &= ~BETA_STATUS.DRQ; value = data; break; case WD93REG.SYS: // #FF LedDiskIO = true; value = (byte)((byte)rqs | 0x3F); break; default: throw new InvalidOperationException(); } if (LogIO) { LogAgent.Debug( "WD93 {0} ==> #{1:X2} [PC=#{2:X4}, T={3}]", reg, value, m_cpu.regs.PC, tact); } return value; }