예제 #1
0
 private void NoIOPort(int port)
 {
     X8086.Notify("No IO port response from {0} called at {1}:{2}", NotificationReasons.Warn,
                  port.ToString("X4"),
                  mRegisters.CS.ToString("X4"),
                  mRegisters.IP.ToString("X4"));
 }
예제 #2
0
        public void HandleInput(ExternalInputEvent e)
        {
            if (ReferenceEquals(e.Handler, null))
            {
                return;
            }

            if (e.TheEvent is KeyEventArgs)
            {
                var theEvent = (KeyEventArgs)e.TheEvent;

                if (cadCounter > 0)
                {
                    cadCounter--;
                    return;
                }

                if (((int)(theEvent.Modifiers) & (int)Keys.Control) == (int)Keys.Control)
                {
                    isCtrlDown = !System.Convert.ToBoolean(e.Extra);
                }
                else
                {
                    isCtrlDown = false;
                }
                if (((int)(theEvent.Modifiers) & (int)Keys.Alt) == (int)Keys.Alt)
                {
                    isAltDown = !System.Convert.ToBoolean(e.Extra);
                }
                else
                {
                    isAltDown = false;
                }

                if (isCtrlDown && isAltDown && ((int)(theEvent.KeyCode) & (int)Keys.Insert) == (int)Keys.Insert)
                {
                    cadCounter = 3; // Ignore the next three events, which will be the release of CTRL, ALT and DEL
                    e.TheEvent = new KeyEventArgs(Keys.Delete);
                    X8086.Notify("Sending CTRL+ALT+DEL", X8086.NotificationReasons.Info);
                }
            }

            if (pendingInput.Count == 0)
            {
                // Wake up the scheduler in case it is sleeping
                Notify();
                // Kick the CPU simulation to make it yield
                mCPU.DoReschedule = true;
            }

            pendingInput.Add(e);
        }
예제 #3
0
        private void PrintStack()
        {
            int f = Math.Min(mRegisters.SP + (0xFFFF - mRegisters.SP) - 1, mRegisters.SP + 10);
            int t = Math.Max(0, mRegisters.SP - 10);

            for (int i = f; i >= t; i -= 2)
            {
                X8086.Notify("{0}:{1}  {2}{3}", NotificationReasons.Info,
                             mRegisters.SS.ToString("X4"),
                             i.ToString("X4"),
                             get_RAM16(mRegisters.SS, (ushort)i, (byte)0, true).ToString("X4"), i == mRegisters.SP ? "<<" : "");
            }
        }
예제 #4
0
 private void PrintFlags()
 {
     X8086.Notify("{0}{1}{2}{3}{4}{5}{6}{7}", NotificationReasons.Info,
                  mFlags.CF,
                  mFlags.ZF,
                  mFlags.SF,
                  mFlags.OF,
                  mFlags.PF,
                  mFlags.AF,
                  mFlags.IF,
                  mFlags.DF);
     X8086.Notify("CZSOPAID", NotificationReasons.Info);
 }
예제 #5
0
        public void LoadBIN(string fileName, ushort segment, ushort offset)
        {
            //X8086.Notify("Loading: {fileName} @ {segment:X4}:{offset:X4}", NotificationReasons.Info, null);
            X8086.Notify($"Loading: {fileName} @ {segment:X4}:{offset:X4}", NotificationReasons.Info);
            fileName = X8086.FixPath(fileName);

            if (System.IO.File.Exists(fileName))
            {
                CopyToMemory(System.IO.File.ReadAllBytes(fileName), segment, offset);
            }
            else
            {
                ThrowException(System.Convert.ToString("File Not Found: " + "\r\n" + fileName));
            }
        }
예제 #6
0
 private void ThrowException(string message)
 {
     if (mEnableExceptions)
     {
         throw (new Exception(message));
     }
     else
     {
         X8086.Notify(message, NotificationReasons.Err);
         if (ErrorEvent != null)
         {
             ErrorEvent(this, new EmulatorErrorEventArgs(message));
         }
     }
 }
예제 #7
0
        public DiskImage(string fileName, bool mountInReadOnlyMode = false, bool isHardDisk = false)
        {
            mFileName = X8086.FixPath(fileName);

            mCylinders  = (ushort)(0);
            mHeads      = (ushort)(0);
            mSectors    = (ushort)(0);
            mFileLength = 0;

            if (!System.IO.File.Exists(mFileName))
            {
                mStatus = ImageStatus.DiskImageNotFound;
            }
            else
            {
                OpenImage(mountInReadOnlyMode, isHardDisk);
            }

            X8086.Notify("DiskImage '{0}': {1}", X8086.NotificationReasons.Info, mFileName, mStatus.ToString());
        }
예제 #8
0
        public HostFolderAsDisk(string fileName, bool mountInReadOnlyMode = false)
        {
            throw (new NotImplementedException());

            mFileName = fileName;

            s     = new System.IO.FileStream(mFileName, System.IO.FileMode.Open);
            image = new StandardDiskFormat(s);

            //mSectorSize = image.BootSectors(0).BIOSParameterBlock.BytesPerSector
            //mCylinders = image.Partitions(0).Cylinders + 1
            //mHeads = image.Partitions(0).Heads * 2
            //mSectors = image.Partitions(0).Sectors + 1
            //mFileLength = s.Length

            //mReadOnly = mountInReadOnlyMode
            //mIsHardDisk = CType(image.Partitions(0).FileSystem, FAT12_16.BootSector).BIOSParameterBlock.MediaDescriptor = &HF8
            //mStatus = ImageStatus.DiskLoaded

            X8086.Notify("DiskImage '{0}': {1}", X8086.NotificationReasons.Info, mFileName, mStatus.ToString());
        }
예제 #9
0
 private void PrintRegisters()
 {
     X8086.Notify("AX: {0}   SP: {1} ", NotificationReasons.Info, mRegisters.AX.ToString("X4"), mRegisters.SP.ToString("X4"));
     X8086.Notify("BX: {0}   DI: {1} ", NotificationReasons.Info, mRegisters.BX.ToString("X4"), mRegisters.DI.ToString("X4"));
     X8086.Notify("CX: {0}   BP: {1} ", NotificationReasons.Info, mRegisters.CX.ToString("X4"), mRegisters.BP.ToString("X4"));
     X8086.Notify("DX: {0}   SI: {1} ", NotificationReasons.Info, mRegisters.DX.ToString("X4"), mRegisters.SI.ToString("X4"));
     X8086.Notify("ES: {0}   CS: {1} ", NotificationReasons.Info, mRegisters.ES.ToString("X4"), mRegisters.CS.ToString("X4"));
     X8086.Notify("SS: {0}   DS: {1} ", NotificationReasons.Info, mRegisters.SS.ToString("X4"), mRegisters.DS.ToString("X4"));
     X8086.Notify("IP: {0} FLGS: {1}{2}{3}{4}{5}{6}{7}{8}", NotificationReasons.Info,
                  mRegisters.IP.ToString("X4"),
                  mFlags.CF,
                  mFlags.ZF,
                  mFlags.SF,
                  mFlags.OF,
                  mFlags.PF,
                  mFlags.AF,
                  mFlags.IF,
                  mFlags.DF);
     X8086.Notify("                CZSOPAID", NotificationReasons.Info);
     for (int i = 0; i <= 3; i++)
     {
         Debug.Write(get_RAM8(mRegisters.CS, (ushort)(mRegisters.IP + i), (byte)0, false).ToString("X2") + " ");
     }
 }
예제 #10
0
 public override void Run()
 {
     X8086.Notify("{Name} Running", X8086.NotificationReasons.Info);
 }
예제 #11
0
 public override void Run()
 {
     X8086.Notify("Speaker Running", X8086.NotificationReasons.Info);
 }
예제 #12
0
        private bool HandleINT13()
        {
            if (mFloppyController == null)
            {
                ThrowException("Disk Adapter Not Found");
                return(true);
            }

            int  ret    = 0;
            int  AL     = 0;
            long offset = 0;

            DiskImage dskImg  = mFloppyController.get_DiskImage((int)mRegisters.DL);
            int       bufSize = 0;

            if (mRegisters.AH == ((byte)(0x0))) // Reset drive
            {
                X8086.Notify("Drive {0:000} Reset", NotificationReasons.Info, mRegisters.DL);
                ret = (int)(ReferenceEquals(dskImg, null) ? 0xAA : 0);
            } // Get last operation status
            else if (mRegisters.AH == ((byte)(0x1)))
            {
                X8086.Notify("Drive {0:000} Get Last Operation Status", NotificationReasons.Info, mRegisters.DL);
                mRegisters.AH = (byte)lastAH[mRegisters.DL];
                mFlags.CF     = lastCF[mRegisters.DL];
                ret           = 0;
            } // Read sectors
            else if (mRegisters.AH == ((byte)(0x2)))
            {
                if (dskImg == null)
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    offset  = dskImg.LBA((uint)(mRegisters.CH), (uint)(mRegisters.DH), (uint)(mRegisters.CL));
                    bufSize = mRegisters.AL * dskImg.SectorSize;

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Read Sectors: Drive {0:000} Seek Fail", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Read  H{1:00} T{2:000} S{3:000} x {4:000} {5:X6} -> {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL,
                                 offset,
                                 mRegisters.ES,
                                 mRegisters.BX);

                    byte[] buf = new byte[bufSize];
                    ret = dskImg.Read((ulong)offset, buf);
                    if (ret == DiskImage.EIO)
                    {
                        X8086.Notify("Read Sectors: Drive {0:000} CRC Error", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x10; // CRC error
                    }
                    else if (ret == DiskImage.EOF)
                    {
                        X8086.Notify("Read Sectors: Drive {0:000} Sector Not Found", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x4; // sector not found
                    }
                    CopyToMemory(buf, X8086.SegmentOffetToAbsolute(mRegisters.ES, mRegisters.BX));
                    AL = bufSize / dskImg.SectorSize;
                }
            } // Write sectors
            else if (mRegisters.AH == ((byte)(0x3)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    if (dskImg.IsReadOnly)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} Failed / Read Only", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x3; // write protected
                    }

                    offset  = dskImg.LBA((uint)(mRegisters.CH), (uint)(mRegisters.DH), (uint)(mRegisters.CL));
                    bufSize = mRegisters.AL * dskImg.SectorSize;

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} Seek Failed", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Write H{1:00} T{2:000} S{3:000} x {4:000} {5:X6} <- {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL,
                                 offset,
                                 mRegisters.ES,
                                 mRegisters.BX);

                    byte[] buf = new byte[bufSize];
                    CopyFromMemory(buf, X8086.SegmentOffetToAbsolute(mRegisters.ES, mRegisters.BX));
                    ret = dskImg.Write((ulong)offset, buf);
                    if (ret == DiskImage.EIO)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} CRC Error", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x10; // CRC error
                    }
                    else if (ret == DiskImage.EOF)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} Sector Not Found", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x4; // sector not found
                    }
                    AL = bufSize / dskImg.SectorSize;
                }
            } // Verify Sectors
            else if (mRegisters.AH == ((byte)(0x4)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    offset  = dskImg.LBA((uint)(mRegisters.CH), (uint)(mRegisters.DH), (uint)(mRegisters.CL));
                    bufSize = mRegisters.AL * dskImg.SectorSize;

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Verify Sector: Drive {0} Seek Failed", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Verify Sectors H{1:00} T{2:000} S{3:000} ? {4:000} {5:X6} ? {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL,
                                 offset,
                                 mRegisters.ES,
                                 mRegisters.BX);

                    AL  = bufSize / dskImg.SectorSize;
                    ret = 0;
                }
            } // Format Track
            else if (mRegisters.AH == ((byte)(0x5)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    offset  = dskImg.LBA((uint)(mRegisters.CH), (uint)(mRegisters.DH), (uint)(mRegisters.CL));
                    bufSize = mRegisters.AL * dskImg.SectorSize;

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Format Track: Drive {0:000} Seek Failed", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Format Track H{1:00} T{2:000} S{3:000} ? {4:000} {5:X6} = {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL,
                                 offset,
                                 mRegisters.ES,
                                 mRegisters.BX);
                    ret = 0;
                }
            } // Format Track - Set Bad Sector Flag
            else if (mRegisters.AH == ((byte)(0x6)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    X8086.Notify("Drive {0:000} Format Track (SBSF) H{1:00} T{2:000} S{3:000} ? {4:000}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL);
                    ret = 0;
                }
            } // Format Drive Starting at Track
            else if (mRegisters.AH == ((byte)(0x7)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    X8086.Notify("Drive {0:000} Format Drive H{1:00} T{2:000} S{3:000}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL);
                    ret = 0;
                }
            } // Get Drive Parameters
            else if (mRegisters.AH == ((byte)(0x8)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    if (dskImg.Tracks <= 0)
                    {
                        X8086.Notify("Get Drive Parameters: Drive {0:000} Unknown Geometry", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0xAA;
                    }
                    else
                    {
                        mRegisters.CH  = (byte)((dskImg.Cylinders - 1) & 0xFF);
                        mRegisters.CL  = (byte)(dskImg.Sectors & 63);
                        mRegisters.CL += (byte)(((dskImg.Cylinders - 1) / 256) * 64);
                        mRegisters.DH  = (byte)(dskImg.Heads - 1);

                        if (mRegisters.DL < 0x80)
                        {
                            mRegisters.BL = (byte)4;
                            mRegisters.DL = (byte)2;
                        }
                        else
                        {
                            mRegisters.DL = (byte)DiskImage.HardDiskCount;
                        }

                        X8086.Notify("Drive {0:000} Get Parameters", NotificationReasons.Info, mRegisters.DL);
                        ret = 0;
                    }
                }
            } // Initialize Drive Pair Characteristic
            else if (mRegisters.AH == ((byte)(0x9)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                X8086.Notify("Drive {0:000} Init Drive Pair Characteristic", NotificationReasons.Info, mRegisters.DL);
                ret = 0;

                // The following are meant to keep diagnostic tools happy ;)
            } // Read Long Sectors
            else if (mRegisters.AH == ((byte)(0xA)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    offset  = dskImg.LBA((uint)(mRegisters.CH), (uint)(mRegisters.DH), (uint)(mRegisters.CL));
                    bufSize = mRegisters.AL * dskImg.SectorSize;

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Read Sectors Long: Drive {0:000} Seek Fail", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Read Long H{1:00} T{2:000} S{3:000} x {4:000} {5:X6} -> {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 mRegisters.DH,
                                 mRegisters.CH,
                                 mRegisters.CL,
                                 mRegisters.AL,
                                 offset,
                                 mRegisters.ES,
                                 mRegisters.BX);

                    byte[] buf = new byte[bufSize];
                    ret = dskImg.Read((ulong)offset, buf);
                    if (ret == DiskImage.EIO)
                    {
                        X8086.Notify("Read Sectors Long: Drive {0:000} CRC Error", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x10; // CRC error
                    }
                    else if (ret == DiskImage.EOF)
                    {
                        X8086.Notify("Read Sectors Long: Drive {0:000} Sector Not Found", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x4; // sector not found
                    }
                    byte[] ecc = BitConverter.GetBytes(buf.Sum(b => b));
                    Array.Resize(ref buf, buf.Length + 4 + 1);
                    buf[buf.Length - 4] = ecc[1];
                    buf[buf.Length - 3] = ecc[0];
                    buf[buf.Length - 2] = ecc[3];
                    buf[buf.Length - 1] = ecc[2];
                    CopyToMemory(buf, X8086.SegmentOffetToAbsolute(mRegisters.ES, mRegisters.BX));
                    AL = bufSize / dskImg.SectorSize;
                }
            } // Seek to Cylinder
            else if (mRegisters.AH == ((byte)(0xC)))
            {
                X8086.Notify("Drive {0:000} Seek to Cylinder ", NotificationReasons.Info, mRegisters.DL);
                ret = 0;
            } // Alternate Disk Reset
            else if (mRegisters.AH == ((byte)(0xD)))
            {
                X8086.Notify("Drive {0:000} Alternate Disk Reset", NotificationReasons.Info, mRegisters.DL);
                ret = 0;
            } // Controller Internal Diagnostic
            else if (mRegisters.AH == ((byte)(0x14)))
            {
                X8086.Notify("Drive {0:000} Controller Internal Diagnostic", NotificationReasons.Info, mRegisters.DL);
                ret = 0;
            } // Recalibrate
            else if (mRegisters.AH == ((byte)(0x11)))
            {
                X8086.Notify("Drive {0:000} Recalibrate", NotificationReasons.Info, mRegisters.DL);
                ret = 0;
            } // Read DASD Type
            else if (mRegisters.AH == ((byte)(0x15)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    if (mRegisters.DL < 0x80)
                    {
                        ret = 0x64;
                    }
                    else
                    {
                        mRegisters.CX = (ushort)(dskImg.Sectors / 256);
                        mRegisters.DX = (ushort)(dskImg.Sectors & 0xFF);
                        ret           = 0x12C;
                    }
                    X8086.Notify("Drive {0:000} Read DASD Type", NotificationReasons.Info, mRegisters.DL);
                }
            } // Controller RAM Diagnostic
            else if (mRegisters.AH == ((byte)(0x12)))
            {
                X8086.Notify("Drive {0:000} Controller RAM Diagnostic", NotificationReasons.Info, mRegisters.DL);
                ret = 0;
            } // Drive Diagnostic
            else if (mRegisters.AH == ((byte)(0x13)))
            {
                X8086.Notify("Drive {0:000} Drive Diagnostic", NotificationReasons.Info, mRegisters.DL);
                ret = 0;
            } // Check Extensions Support
            else if (mRegisters.AH == ((byte)(0x41)))
            {
                X8086.Notify("Drive {0:000} Extensions Check", NotificationReasons.Info, mRegisters.DL);
                if (mRegisters.BX == 0x55AA)
                {
                    mFlags.CF     = (byte)0;
                    mRegisters.AH = (byte)(0x1);
                    mRegisters.CX = (ushort)(0x4);
                }
                else
                {
                    mFlags.CF     = (byte)1;
                    mRegisters.AH = (byte)(0xFF);
                }
                return(true);
            } // Extended Sectors Read
            else if (mRegisters.AH == ((byte)(0x42)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    uint dap = X8086.SegmentOffetToAbsolute(mRegisters.DS, mRegisters.SI);
                    bufSize = (int)(get_RAM(dap + 3) << 8 | get_RAM(dap + 2));
                    int seg = (int)(get_RAM(dap + 7) << 8 | get_RAM(dap + 6));
                    int Off = (int)(get_RAM(dap + 5) << 8 | get_RAM(dap + 4));
                    offset = (long)(get_RAM(dap + 0xF) << 56 | get_RAM(dap + 0xE) << 48 |
                                    get_RAM(dap + 0xD) << 40 | get_RAM(dap + 0xC) << 32 |
                                    get_RAM(dap + 0xB) << 24 | get_RAM(dap + 0xA) << 16 |
                                    get_RAM(dap + 0x9) << 8 | get_RAM(dap + 0x8));

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Read Sectors: Drive {0:000} Seek Fail", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Read {4:000} {5:X6} -> {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 bufSize,
                                 offset,
                                 seg,
                                 Off);

                    byte[] buf = new byte[bufSize];
                    ret = dskImg.Read((ulong)offset, buf);
                    if (ret == DiskImage.EIO)
                    {
                        X8086.Notify("Read Sectors: Drive {0:000} CRC Error", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x10; // CRC error
                    }
                    else if (ret == DiskImage.EOF)
                    {
                        X8086.Notify("Read Sectors: Drive {0:000} Sector Not Found", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x4; // sector not found
                    }
                    CopyToMemory(buf, X8086.SegmentOffetToAbsolute((ushort)seg, (ushort)(Off)));
                    AL = bufSize / dskImg.SectorSize;
                }
            } // Extended Sectors Write
            else if (mRegisters.AH == ((byte)(0x43)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    uint dap = X8086.SegmentOffetToAbsolute(mRegisters.DS, mRegisters.SI);
                    bufSize = (int)(get_RAM(dap + 3) << 8 | get_RAM(dap + 2));
                    int seg = (int)(get_RAM(dap + 7) << 8 | get_RAM(dap + 6));
                    int Off = (int)(get_RAM(dap + 5) << 8 | get_RAM(dap + 4));
                    offset = (long)(get_RAM(dap + 0xF) << 56 | get_RAM(dap + 0xE) << 48 |
                                    get_RAM(dap + 0xD) << 40 | get_RAM(dap + 0xC) << 32 |
                                    get_RAM(dap + 0xB) << 24 | get_RAM(dap + 0xA) << 16 |
                                    get_RAM(dap + 0x9) << 8 | get_RAM(dap + 0x8));

                    if (offset < 0 || (int)(offset + bufSize) > (int)dskImg.FileLength)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} Seek Fail", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x40; // seek failed
                    }

                    X8086.Notify("Drive {0:000} Write {4:000} {5:X6} <- {6:X4}:{7:X4}", NotificationReasons.Info,
                                 mRegisters.DL,
                                 bufSize,
                                 offset,
                                 seg,
                                 Off);

                    byte[] buf = new byte[bufSize];
                    CopyFromMemory(buf, X8086.SegmentOffetToAbsolute((ushort)seg, (ushort)(Off)));
                    ret = dskImg.Write((ulong)offset, buf);
                    if (ret == DiskImage.EIO)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} CRC Error", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x10; // CRC error
                    }
                    else if (ret == DiskImage.EOF)
                    {
                        X8086.Notify("Write Sectors: Drive {0:000} Sector Not Found", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0x4; // sector not found
                    }
                    AL = bufSize / dskImg.SectorSize;
                }
            } // Extended get Drive Parameters
            else if (mRegisters.AH == ((byte)(0x48)))
            {
                if (ReferenceEquals(dskImg, null))
                {
                    X8086.Notify("Invalid Drive Number: Drive {0:000} Not Ready", NotificationReasons.Info, mRegisters.DL);
                    ret = 0xAA; // fixed disk drive not ready
                }
                else
                {
                    if (dskImg.Tracks <= 0)
                    {
                        X8086.Notify("Get Drive Parameters: Drive {0:000} Unknown Geometry", NotificationReasons.Warn, mRegisters.DL);
                        ret = 0xAA;
                    }
                    else
                    {
                        throw (new NotImplementedException("Extended get Drive Parameters is not Implemented"));
                        X8086.Notify("Drive {0:000} Get Parameters", NotificationReasons.Info, mRegisters.DL);
                        ret = 0;
                    }
                }
            }
            else
            {
                X8086.Notify("Drive {0:000} Unknown Request {1}", NotificationReasons.Err,
                             mRegisters.DL,
                             ((mRegisters.AX & 0xFF00) >> 8).ToString("X2"));
                ret = 0x1;
            }

            if (mRegisters.AH != 0)
            {
                set_RAM8((ushort)(0x40), (ushort)(0x41), 0, false, (byte)ret);
                mRegisters.AX = (ushort)((ret << 8) | AL);
            }
            mFlags.CF = (byte)(ret != 0 ? 1 : 0);

            lastAH[mRegisters.DL] = (ushort)(mRegisters.AH);
            lastCF[mRegisters.DL] = mFlags.CF;

            if ((mRegisters.DL & 0x80) != 0)
            {
                Memory[0x474] = mRegisters.AH;
            }

            return(true);
        }
예제 #13
0
        private void Run()
        {
            ArrayList          cleanInputBuf = new ArrayList();
            ArrayList          inputBuf      = new ArrayList();
            Task               tsk           = null;
            ExternalInputEvent evt           = default(ExternalInputEvent);

            while (true)
            {
                // Detect the end of the simulation run
                if (nextTime == STOPPING)
                {
                    nextTime = pq.MinPriority();
                    break;
                }

                if (pendingInput.Count > 0)
                {
                    // Fetch pending input events
                    inputBuf     = pendingInput;
                    pendingInput = cleanInputBuf;
                }
                else if (nextTime <= mCurrentTime)
                {
                    // Fetch the next pending task
                    tsk = NextTask();
                    if (ReferenceEquals(tsk, null))
                    {
                        continue; // This task was canceled, go round again
                    }
                    inputBuf.Clear();
                }
                else
                {
                    tsk = null;
                }

                if (inputBuf.Count > 0)
                {
                    // Process pending input events
                    for (int i = 0; i <= inputBuf.Count - 1; i++)
                    {
                        evt           = (ExternalInputEvent)(inputBuf[i]);
                        evt.TimeStamp = mCurrentTime;
                        evt.Handler.HandleInput(evt);
                    }
                    inputBuf.Clear();
                    cleanInputBuf = inputBuf;
                }
                else if (tsk != null)
                {
                    // Run the first pending task
                    tsk.Start();
                }
                else
                {
                    // Run the CPU simulation for a bit (maxRunCycl)
                    try
                    {
                        mCPU.RunEmulation();
                    }
                    catch (Exception ex)
                    {
                        X8086.Notify("Shit happens at {0}:{1}: {2}", X8086.NotificationReasons.Fck, mCPU.Registers.CS.ToString("X4"), mCPU.Registers.IP.ToString("X4"), ex.Message);
                        mCPU.RaiseException($"Scheduler Main Loop Error: {ex.Message}");
                    }

                    if (mCPU.IsHalted)
                    {
                        SkipToNextEvent(); // The CPU is halted, skip immediately to the next event
                    }
                }
            }
        }