Example #1
0
        private void Write(byte head, byte cyl, byte sec, int count)
        {
            head = (head == 0) ? (byte)0 : (byte)1;
            bool error = false;

            if (!_loaded ||
                cyl > _disk.CylinderCount ||
                head > (_disk.IsSingleSided ? 1 : 2) ||
                sec > _disk.GetTrack(cyl, head).SectorCount ||
                _setFormat != _disk.GetSector(cyl, head, sec - 1).Format)
            {
                error = true;

#if TRACING_ENABLED
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.Warnings, "Invalid Floppy write to Cylinder {0} Head {1} Sector {2}.",
                              _cylinder, _head, sec);
                }
#endif
            }
            else
            {
#if TRACING_ENABLED
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.FloppyDisk, "Floppy write to Cylinder {0} Head {1} Sector {2}.",
                              _cylinder, _head, sec);
                }
#endif
            }

            // Busy based on byte count...
            _busyClocks = (error ? 5 : count);

            // Read the sector in.
            Sector sector = _disk.GetSector(cyl, head, sec - 1);

            // The starting offset for the data is at index 5 of the message data
            for (int b = 0; b < count; b++)
            {
                sector.Data[b] = _messageData[5 + b];
            }

            // Message out format:
            //  SOM
            //  0x11 (floppy done)
            //  0 for success, 1 for failure.
            Z80System.Instance.FIFO.Enqueue(Z80System.SOM);
            Z80System.Instance.FIFO.Enqueue((byte)Z80toPERQMessage.FloppyDone);
            Z80System.Instance.FIFO.Enqueue(error ? (byte)1 : (byte)0);

            // Set up the NEC status registers.
            // 7 registers for a write operation
            _necStatusLength = 7;

            StatusRegister0 reg0 =
                StatusRegister0.FlpUnit0 |
                (head == 0 ? 0 : StatusRegister0.FlpHead) |
                (_loaded ? 0 : StatusRegister0.FlpNotReady) |
                (0) |                                           // Equipment check
                (0) |                                           // Seek end
                (error ? StatusRegister0.FlpIntrCode0 : 0) |    // Interrupt code (0 = ok, 1 = unsuccessful command)
                (0);                                            // Same (high bit not set for our purposes)

            StatusRegister1 reg1 =
                (_setFormat != sector.Format ? StatusRegister1.FlpMissAddr : 0) |                                    // Missing address mark
                (0) |                                                                                                // Not writeable
                (0) |                                                                                                // No data
                (0) |                                                                                                // Overrun
                (0) |                                                                                                // Data error
                (_disk != null && sec > _disk.GetTrack(cyl, head).SectorCount ? StatusRegister1.FlpEndCylinder : 0); // End of cyl

            StatusRegister2 reg2 =
                (_setFormat != sector.Format ? StatusRegister2.FlpDataMissAddr : 0) | // Missing address mark
                (0) |                                                                 // Bad cylinder
                (0) |                                                                 // Wrong cylinder
                (0);                                                                  // Data error in data

            _necStatus[0] = (byte)reg0;
            _necStatus[1] = (byte)reg1;
            _necStatus[2] = (byte)reg2;
            _necStatus[3] = (byte)cyl;
            _necStatus[4] = (byte)head;
            _necStatus[5] = (byte)sec;
            _necStatus[6] = _disk != null ? (byte)sector.Data.Length : (byte)0;
        }
Example #2
0
        private void Format(byte head, byte cyl, byte sec)
        {
            head = (head == 0) ? (byte)0 : (byte)1;
            bool error = false;

            if (!_loaded ||
                cyl > _disk.CylinderCount ||
                head > (_disk.IsSingleSided ? 0 : 1) ||
                sec > _disk.GetTrack(cyl, head).SectorCount)
            {
                error = true;

#if TRACING_ENABLED
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.Warnings, "Invalid Floppy format Cylinder {0} Head {1} Sector {2}.",
                              _cylinder, _head, sec);
                }
#endif
            }
            else
            {
#if TRACING_ENABLED
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.FloppyDisk, "Floppy format Cylinder {0} Head {1} Sector {2}.",
                              _cylinder, _head, sec);
                }
#endif
            }

            // Formatting should take way longer...
            int sectorSize = _setFormat == PhysicalDisk.Format.FM500 ? 128 : 256;
            _busyClocks = error ? 5 : sectorSize;

            //
            // Note:
            // Even though the message includes a sector number, we're really formatting an entire track.
            // (the controller can only format an entire track at a time).
            //
            _disk.FormatTrack(_setFormat, cyl, head, 26, sectorSize);

            // Message out format:
            //  SOM
            //  0x11 (floppy done)
            //  0 for success, 1 for failure.
            Z80System.Instance.FIFO.Enqueue(Z80System.SOM);
            Z80System.Instance.FIFO.Enqueue((byte)Z80toPERQMessage.FloppyDone);
            Z80System.Instance.FIFO.Enqueue(error ? (byte)1 : (byte)0);

            // Set up the NEC status registers.
            // 7 registers for a format operation
            _necStatusLength = 7;

            StatusRegister0 reg0 =
                StatusRegister0.FlpUnit0 |
                (head == 0 ? 0 : StatusRegister0.FlpHead) |
                (_loaded ? 0 : StatusRegister0.FlpNotReady) |
                (0) |                                           // Equipment check
                (0) |                                           // Seek end
                (error ? StatusRegister0.FlpIntrCode0 : 0) |    // Interrupt code (0 = ok, 1 = unsuccessful command)
                (0);                                            // Same (high bit not set for our purposes)

            StatusRegister1 reg1 =
                (0) |                                           // Missing address mark
                (0) |                                           // Not writeable
                (0) |                                           // No data
                (0) |                                           // Overrun
                (0) |                                           // Data error
                (0);                                            // end of cyl

            StatusRegister2 reg2 =
                (0) |                                           // Missing address mark
                (0) |                                           // Bad cylinder
                (0) |                                           // Wrong cylinder
                (0);                                            // Data error in data

            _necStatus[0] = (byte)reg0;
            _necStatus[1] = (byte)reg1;
            _necStatus[2] = (byte)reg2;
            _necStatus[3] = (byte)cyl;
            _necStatus[4] = (byte)head;
            _necStatus[5] = sec;
            _necStatus[6] = 0;
        }
Example #3
0
        private void Read(byte head, byte cyl, byte sec)
        {
            head = (head == 0) ? (byte)0 : (byte)1;
            bool error = false;

            if (!_loaded ||
                cyl > _disk.CylinderCount ||
                head > (_disk.IsSingleSided ? 0 : 1) ||
                sec > _disk.GetTrack(cyl, head).SectorCount ||
                _setFormat != _disk.GetSector(cyl, head, sec - 1).Format)
            {
#if TRACING_ENABLED
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.Warnings, "Invalid Floppy read from Cylinder {0} Head {1} Sector {2}.",
                              _cylinder, _head, sec);
                }
#endif

                error = true;
            }
            else
            {
#if TRACING_ENABLED
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.FloppyDisk, "Floppy read from Cylinder {0} Head {1} Sector {2}.",
                              _cylinder, _head, sec);
                }
#endif
            }

            // Message format is:
            //  SOM
            //  5 (Floppy Data)
            //  0 for success, 1 for error
            //  byte count
            //  data
            Z80System.Instance.FIFO.Enqueue(Z80System.SOM);
            Z80System.Instance.FIFO.Enqueue((byte)Z80toPERQMessage.FloppyData);

            Sector sector = null;

            if (error)
            {
                Z80System.Instance.FIFO.Enqueue(1);     // Indicate an error
                Z80System.Instance.FIFO.Enqueue(1);     // Length (can't use 0 as the PERQ interprets that as 256)
                Z80System.Instance.FIFO.Enqueue(0);     // Bogus data
                _busyClocks = 5;
            }
            else
            {
                // Read the sector in
                sector = _disk.GetSector(cyl, head, sec - 1);

                Z80System.Instance.FIFO.Enqueue(0);                        // No error
                Z80System.Instance.FIFO.Enqueue((byte)sector.Data.Length); // A full sector

                // Set our busy time based on byte count... should be way longer...
                _busyClocks = (int)sector.Data.Length;

                for (int b = 0; b < sector.Data.Length; b++)
                {
                    byte data = sector.Data[b];
                    Z80System.Instance.FIFO.Enqueue(data);
                }
            }

            // Set up the NEC status registers.
            // 7 registers for a read operation
            _necStatusLength = 7;

            StatusRegister0 reg0 =
                StatusRegister0.FlpUnit0 |
                (head == 0 ? 0 : StatusRegister0.FlpHead) |
                (_loaded ? 0 : StatusRegister0.FlpNotReady) |
                (0) |                                           // Equipment check
                (0) |                                           // Seek end
                (error ? StatusRegister0.FlpIntrCode0 : 0) |    // Interrupt code (0 = ok, 1 = unsuccessful command)
                (0);                                            // Same (high bit not set for our purposes)

            // TODO: if cyl,head,sec are out of range, bad things will happen.

            StatusRegister1 reg1 =
                (_setFormat != sector.Format ? StatusRegister1.FlpMissAddr : 0) |                                    // Missing address mark
                (0) |                                                                                                // Not writeable
                (0) |                                                                                                // No data
                (0) |                                                                                                // Overrun
                (0) |                                                                                                // Data error
                (_disk != null && sec > _disk.GetTrack(cyl, head).SectorCount ? StatusRegister1.FlpEndCylinder : 0); // end of cyl

            StatusRegister2 reg2 =
                (_setFormat != sector.Format ? StatusRegister2.FlpDataMissAddr : 0) |  // Missing address mark
                (0) |                                                                  // Bad cylinder
                (0) |                                                                  // Wrong cylinder
                (0);                                                                   // Data error in data

            _necStatus[0] = (byte)reg0;
            _necStatus[1] = (byte)reg1;
            _necStatus[2] = (byte)reg2;
            _necStatus[3] = (byte)cyl;
            _necStatus[4] = (byte)head;
            _necStatus[5] = (byte)sec;
            _necStatus[6] = _disk != null ? (byte)sector.Data.Length : (byte)0;
        }