public static byte[] MarshalSector(RawSector sector) { if (sector == null) { return(null); } MemoryStream raw = new MemoryStream(); raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length); raw.WriteByte(sector.addressField.track); raw.WriteByte(sector.addressField.sector); raw.WriteByte(sector.addressField.side); raw.WriteByte((byte)sector.addressField.format); raw.WriteByte(sector.addressField.checksum); raw.Write(sector.innerGap, 0, sector.innerGap.Length); raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); raw.WriteByte(sector.dataField.spare); raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); raw.Write(sector.dataField.checksum, 0, sector.dataField.checksum.Length); raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length); raw.Write(sector.gap, 0, sector.gap.Length); return(raw.ToArray()); }
public static byte[] DecodeSector(RawSector sector) { if (sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA) { return(null); } // Pre DOS 3.3 if (sector.addressField.prologue[2] == 0xB5) { return(Decode5and3(sector.dataField.data)); } // DOS 3.3 return(sector.addressField.prologue[2] == 0x96 ? Decode6and2(sector.dataField.data) : null); // Unknown // Not Apple ][ GCR? }
public static byte[] MarshalSector(RawSector sector) { if (sector == null) { return(null); } var raw = new MemoryStream(); raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length); raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length); raw.Write(sector.addressField.track, 0, sector.addressField.track.Length); raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length); raw.Write(sector.addressField.checksum, 0, sector.addressField.checksum.Length); raw.Write(sector.addressField.epilogue, 0, sector.addressField.epilogue.Length); raw.Write(sector.innerGap, 0, sector.innerGap.Length); raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); raw.WriteByte(sector.dataField.checksum); raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length); raw.Write(sector.gap, 0, sector.gap.Length); return(raw.ToArray()); }
public static bool IsAppleSonyGCR(byte[] data) { RawSector sector = MarshalSector(data, out int position); return(sector != null && position != 0); }
public static RawTrack MarshalTrack(byte[] data, out int endOffset, int offset = 0) { int position = offset; bool firstSector = true; bool onSync = false; MemoryStream gaps = new MemoryStream(); int count = 0; List <RawSector> sectors = new List <RawSector>(); byte trackNumber = 0; byte sideNumber = 0; endOffset = offset; while (position < data.Length && data[position] == 0xFF) { gaps.WriteByte(data[position]); count++; position++; onSync = count >= 5; } if (position >= data.Length) { return(null); } if (!onSync) { return(null); } while (position < data.Length) { int oldPosition = position; RawSector sector = MarshalSector(data, out position, position); if (sector == null) { break; } if (firstSector) { trackNumber = sector.addressField.track; sideNumber = sector.addressField.side; firstSector = false; } if (sector.addressField.track != trackNumber || sector.addressField.side != sideNumber) { position = oldPosition; break; } sectors.Add(sector); } if (sectors.Count == 0) { return(null); } RawTrack track = new RawTrack { gap = gaps.ToArray(), sectors = sectors.ToArray() }; endOffset = position; return(track); }
public static RawSector MarshalSector(byte[] data, out int endOffset, int offset = 0) { endOffset = offset; // Not an Apple ][ GCR sector if (data == null || data.Length < 363) { return(null); } int position = offset; try { while (position < data.Length) { // Prologue found if (data[position] == 0xD5 && data[position + 1] == 0xAA && data[position + 2] == 0x96) { // Epilogue not in correct position if (data[position + 8] != 0xDE || data[position + 9] != 0xAA) { return(null); } RawSector sector = new RawSector { addressField = new RawAddressField { prologue = new[] { data[position], data[position + 1], data[position + 2] }, track = data[position + 3], sector = data[position + 4], side = data[position + 5], format = (AppleEncodedFormat)data[position + 6], checksum = data[position + 7], epilogue = new[] { data[position + 8], data[position + 9] } } }; position += 10; int syncCount = 0; bool onSync = false; MemoryStream gaps = new MemoryStream(); while (data[position] == 0xFF) { gaps.WriteByte(data[position]); syncCount++; onSync = syncCount >= 5; position++; } // Lost sync if (!onSync) { return(null); } // Prologue not found if (data[position] != 0xDE || data[position + 1] != 0xAA || data[position + 2] != 0xAD) { return(null); } sector.innerGap = gaps.ToArray(); sector.dataField = new RawDataField { prologue = new[] { data[position], data[position + 1], data[position + 2] }, spare = data[position + 3] }; position += 4; gaps = new MemoryStream(); // Read data until epilogue is found while (data[position + 4] != 0xD5 || data[position + 5] != 0xAA) { gaps.WriteByte(data[position]); position++; // No space left for epilogue if (position + 7 > data.Length) { return(null); } } sector.dataField.data = gaps.ToArray(); sector.dataField.checksum = new byte[4]; sector.dataField.checksum[0] = data[position]; sector.dataField.checksum[1] = data[position + 2]; sector.dataField.checksum[2] = data[position + 3]; sector.dataField.checksum[3] = data[position + 4]; sector.dataField.epilogue = new byte[2]; sector.dataField.epilogue[0] = data[position + 5]; sector.dataField.epilogue[1] = data[position + 6]; position += 7; gaps = new MemoryStream(); // Read gap, if any while (position < data.Length && data[position] == 0xFF) { gaps.WriteByte(data[position]); position++; } // Reduces last sector gap so doesn't eat next tracks's gap if (gaps.Length > 5) { gaps.SetLength(gaps.Length / 2); position -= (int)gaps.Length; } sector.gap = gaps.ToArray(); // Return current position to be able to read separate sectors endOffset = position; return(sector); } if (data[position] == 0xFF) { position++; } // Found data that is not sync or a prologue else { return(null); } } } catch (IndexOutOfRangeException) { return(null); } return(null); }
public static byte[] DecodeSector(RawSector sector) { if (sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA || sector.addressField.prologue[2] != 0x96) { return(null); } byte[] bf1 = new byte[175]; byte[] bf2 = new byte[175]; byte[] bf3 = new byte[175]; byte[] nib_data = sector.dataField.data; MemoryStream ms = new MemoryStream(); int j = 0; byte w3 = 0; for (int i = 0; i <= 174; i++) { byte w4 = nib_data[j++]; byte w1 = nib_data[j++]; byte w2 = nib_data[j++]; if (i != 174) { w3 = nib_data[j++]; } bf1[i] = (byte)(((w1 & 0x3F) | ((w4 << 2) & 0xC0)) & 0x0F); bf2[i] = (byte)(((w2 & 0x3F) | ((w4 << 4) & 0xC0)) & 0x0F); bf3[i] = (byte)(((w3 & 0x3F) | ((w4 << 6) & 0xC0)) & 0x0F); } j = 0; uint ck1 = 0; uint ck2 = 0; uint ck3 = 0; while (true) { ck1 = (ck1 & 0xFF) << 1; if ((ck1 & 0x0100) > 0) { ck1++; } byte carry = (byte)((bf1[j] ^ ck1) & 0xFF); ck3 += carry; if ((ck1 & 0x0100) > 0) { ck3++; ck1 &= 0xFF; } ms.WriteByte(carry); carry = (byte)((bf2[j] ^ ck3) & 0xFF); ck2 += carry; if (ck3 > 0xFF) { ck2++; ck3 &= 0xFF; } ms.WriteByte(carry); if (ms.Length == 524) { break; } carry = (byte)((bf3[j] ^ ck2) & 0xFF); ck1 += carry; if (ck2 > 0xFF) { ck1++; ck2 &= 0xFF; } ms.WriteByte(carry); j++; } return(ms.ToArray()); // Not Apple Sony GCR? }
public static RawTrack MarshalTrack(byte[] data, out int endOffset, int offset = 0) { int position = offset; bool firstSector = true; bool onSync = false; MemoryStream gaps = new MemoryStream(); int count = 0; List <RawSector> sectors = new List <RawSector>(); byte[] trackNumber = new byte[2]; endOffset = offset; while (position < data.Length && data[position] == 0xFF) { gaps.WriteByte(data[position]); count++; position++; onSync = count >= 5; } if (position >= data.Length) { return(null); } if (!onSync) { return(null); } while (position < data.Length) { int oldPosition = position; RawSector sector = MarshalSector(data, out position, position); if (sector == null) { break; } if (firstSector) { trackNumber[0] = sector.addressField.track[0]; trackNumber[1] = sector.addressField.track[1]; firstSector = false; } if (sector.addressField.track[0] != trackNumber[0] || sector.addressField.track[1] != trackNumber[1]) { position = oldPosition; break; } DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Adding sector {0} of track {1}", (((sector.addressField.sector[0] & 0x55) << 1) | (sector.addressField.sector[1] & 0x55)) & 0xFF, (((sector.addressField.track[0] & 0x55) << 1) | (sector.addressField.track[1] & 0x55)) & 0xFF); sectors.Add(sector); } if (sectors.Count == 0) { return(null); } RawTrack track = new RawTrack { gap = gaps.ToArray(), sectors = sectors.ToArray() }; endOffset = position; return(track); }
public static RawSector MarshalSector(byte[] data, out int endOffset, int offset = 0) { endOffset = offset; // Not an Apple ][ GCR sector if (data == null || data.Length < 363) { return(null); } int position = offset; try { while (position < data.Length) { // Prologue found if (data[position] == 0xD5 && data[position + 1] == 0xAA) { DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position); // Epilogue not in correct position if (data[position + 11] != 0xDE || data[position + 12] != 0xAA) { return(null); } RawSector sector = new RawSector { addressField = new RawAddressField { prologue = new[] { data[position], data[position + 1], data[position + 2] }, volume = new[] { data[position + 3], data[position + 4] }, track = new[] { data[position + 5], data[position + 6] }, sector = new[] { data[position + 7], data[position + 8] }, checksum = new[] { data[position + 9], data[position + 10] }, epilogue = new[] { data[position + 11], data[position + 12], data[position + 13] } } }; DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Volume {0}", (((sector.addressField.volume[0] & 0x55) << 1) | (sector.addressField.volume[1] & 0x55)) & 0xFF); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Track {0}", (((sector.addressField.track[0] & 0x55) << 1) | (sector.addressField.track[1] & 0x55)) & 0xFF); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Sector {0}", (((sector.addressField.sector[0] & 0x55) << 1) | (sector.addressField.sector[1] & 0x55)) & 0xFF); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Checksum {0}", (((sector.addressField.checksum[0] & 0x55) << 1) | (sector.addressField.checksum[1] & 0x55)) & 0xFF); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Epilogue {0:X2}{1:X2}{2:X2}", sector.addressField.epilogue[0], sector.addressField.epilogue[1], sector.addressField.epilogue[2]); position += 14; int syncCount = 0; bool onSync = false; MemoryStream gaps = new MemoryStream(); while (data[position] == 0xFF) { gaps.WriteByte(data[position]); syncCount++; onSync = syncCount >= 5; position++; } // Lost sync if (!onSync) { return(null); } // Prologue not found if (data[position] != 0xD5 || data[position + 1] != 0xAA) { return(null); } sector.innerGap = gaps.ToArray(); sector.dataField = new RawDataField(); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Inner gap has {0} bytes", sector.innerGap.Length); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position); sector.dataField.prologue = new byte[3]; sector.dataField.prologue[0] = data[position]; sector.dataField.prologue[1] = data[position + 1]; sector.dataField.prologue[2] = data[position + 2]; position += 3; gaps = new MemoryStream(); // Read data until epilogue is found while (data[position + 1] != 0xDE || data[position + 2] != 0xAA) { gaps.WriteByte(data[position]); position++; // No space left for epilogue if (position + 4 > data.Length) { return(null); } } sector.dataField.data = gaps.ToArray(); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Data has {0} bytes", sector.dataField.data.Length); sector.dataField.checksum = data[position]; sector.dataField.epilogue = new byte[3]; sector.dataField.epilogue[0] = data[position + 1]; sector.dataField.epilogue[1] = data[position + 2]; sector.dataField.epilogue[2] = data[position + 3]; position += 4; gaps = new MemoryStream(); // Read gap, if any while (position < data.Length && data[position] == 0xFF) { gaps.WriteByte(data[position]); position++; } // Reduces last sector gap so doesn't eat next tracks's gap if (gaps.Length > 5) { gaps.SetLength(gaps.Length / 2); position -= (int)gaps.Length; } sector.gap = gaps.ToArray(); // Return current position to be able to read separate sectors endOffset = position; DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length); DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Finished sector at {0}", position); return(sector); } if (data[position] == 0xFF) { position++; } // Found data that is not sync or a prologue else { return(null); } } } catch (IndexOutOfRangeException) { return(null); } return(null); }