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; }
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; }
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; }