Example #1
0
        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);
        }
Example #2
0
        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;
        }