private void BtnOpen_Click(object sender, RoutedEventArgs e) { var open = new OpenFileDialog { Multiselect = false, Filter = "MP4 files|*.mp4", Title = "Open an MP4 file" }; if (open.ShowDialog(this) == true) { using (var stream = new BigEndianBinaryReader(open.OpenFile(), Encoding.Default)) { Atom.SeekToChild(stream, "moov"); Atom.SeekToChild(stream, "trak"); Atom.SeekToChild(stream, "tkhd"); var header = new TrackHeader(stream); BoxWidth.Text = (header.Width / 5).ToString(CultureInfo.CurrentUICulture); BoxHeight.Text = (header.Heigth / 5).ToString(CultureInfo.CurrentUICulture); Holder.Set(header.Matrix.ToMatrix()); _matrixLocation = header.Matrix.Location; _fileName = open.FileName; } if (OptPro.IsChecked == true) { Media.Stop(); Media.Close(); BlueForeground.Visibility = Visibility.Hidden; Media.Source = new Uri(_fileName); Media.Play(); } } }
private TrackHeader InstantiateHeader() { TrackHeader h = GameObject.Instantiate <TrackHeader>(headerPrefab); h.transform.SetParent(headerContainer); return(h); }
public Track(EndianBinaryReader er, int Id) { er.BaseStream.Position = TrackHeaderAddress + Id * 0x30; Header = new TrackHeader(er); er.BaseStream.Position = Header.DLOffset; DL = MIO0.Decompress(er.ReadBytes((int)(Header.DLEnd - Header.DLOffset))); er.BaseStream.Position = Header.TrackDataOffset; byte[] VtxData = MIO0.Decompress(er.ReadBytes((int)(Header.VertexDataMIO0Length & 0xFFFFFF))); VertexData = new VertexDataEntry[Header.VertexDataNrEntries]; for (int i = 0; i < Header.VertexDataNrEntries; i++) { VertexData[i] = new VertexDataEntry(VtxData, i * 0xE); } LevelScript = er.ReadBytes((int)(Header.TrackDataEnd - Header.TrackDataOffset - (Header.VertexDataMIO0Length & 0xFFFFFF))); er.BaseStream.Position = Header.TexTableOffset; List <TexTableEntry> texes = new List <TexTableEntry>(); while (true) { var v = new TexTableEntry(er); if (v.GPUTexAddress == 0) { break; } texes.Add(v); } TexTable = texes.ToArray(); }
// Note: it doesn't initialize it! public T InstantiateTrack <T>(T trackPrefab, string name) where T : AbstractTrack { T track = GameObject.Instantiate <T>(trackPrefab); tracks.Add(track); track.transform.SetParent(this.transform); track.TrackName = name; TrackHeader header = InstantiateHeader(); header.Initialize(this, track); return(track); }
public bool Open(IFilter imageFilter) { Header = new ScpHeader(); scpStream = imageFilter.GetDataForkStream(); scpStream.Seek(0, SeekOrigin.Begin); if (scpStream.Length < Marshal.SizeOf(Header)) { return(false); } byte[] hdr = new byte[Marshal.SizeOf(Header)]; scpStream.Read(hdr, 0, Marshal.SizeOf(Header)); IntPtr hdrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Header)); Marshal.Copy(hdr, 0, hdrPtr, Marshal.SizeOf(Header)); Header = (ScpHeader)Marshal.PtrToStructure(hdrPtr, typeof(ScpHeader)); Marshal.FreeHGlobal(hdrPtr); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.signature = \"{0}\"", StringHandlers.CToString(Header.signature)); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.version = {0}.{1}", (Header.version & 0xF0) >> 4, Header.version & 0xF); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.type = {0}", Header.type); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.revolutions = {0}", Header.revolutions); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.start = {0}", Header.start); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.end = {0}", Header.end); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.flags = {0}", Header.flags); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.bitCellEncoding = {0}", Header.bitCellEncoding); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.heads = {0}", Header.heads); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.reserved = {0}", Header.reserved); DicConsole.DebugWriteLine("SuperCardPro plugin", "header.checksum = 0x{0:X8}", Header.checksum); if (!scpSignature.SequenceEqual(Header.signature)) { return(false); } ScpTracks = new Dictionary <byte, TrackHeader>(); for (byte t = Header.start; t <= Header.end; t++) { if (t >= Header.offsets.Length) { break; } scpStream.Position = Header.offsets[t]; TrackHeader trk = new TrackHeader { Signature = new byte[3], Entries = new TrackEntry[Header.revolutions] }; scpStream.Read(trk.Signature, 0, trk.Signature.Length); trk.TrackNumber = (byte)scpStream.ReadByte(); if (!trk.Signature.SequenceEqual(trkSignature)) { DicConsole.DebugWriteLine("SuperCardPro plugin", "Track header at {0} contains incorrect signature.", Header.offsets[t]); continue; } if (trk.TrackNumber != t) { DicConsole.DebugWriteLine("SuperCardPro plugin", "Track number at {0} should be {1} but is {2}.", Header.offsets[t], t, trk.TrackNumber); continue; } DicConsole.DebugWriteLine("SuperCardPro plugin", "Found track {0} at {1}.", t, Header.offsets[t]); for (byte r = 0; r < Header.revolutions; r++) { byte[] rev = new byte[Marshal.SizeOf(typeof(TrackEntry))]; scpStream.Read(rev, 0, Marshal.SizeOf(typeof(TrackEntry))); IntPtr revPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TrackEntry))); Marshal.Copy(rev, 0, revPtr, Marshal.SizeOf(typeof(TrackEntry))); trk.Entries[r] = (TrackEntry)Marshal.PtrToStructure(revPtr, typeof(TrackEntry)); Marshal.FreeHGlobal(revPtr); // De-relative offsets trk.Entries[r].dataOffset += Header.offsets[t]; } ScpTracks.Add(t, trk); } if (Header.flags.HasFlag(ScpFlags.HasFooter)) { long position = scpStream.Position; scpStream.Seek(-4, SeekOrigin.End); while (scpStream.Position >= position) { byte[] footerSig = new byte[4]; scpStream.Read(footerSig, 0, 4); uint footerMagic = BitConverter.ToUInt32(footerSig, 0); if (footerMagic == FOOTER_SIGNATURE) { scpStream.Seek(-Marshal.SizeOf(typeof(ScpFooter)), SeekOrigin.Current); DicConsole.DebugWriteLine("SuperCardPro plugin", "Found footer at {0}", scpStream.Position); byte[] ftr = new byte[Marshal.SizeOf(typeof(ScpFooter))]; scpStream.Read(ftr, 0, Marshal.SizeOf(typeof(ScpFooter))); IntPtr ftrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ScpFooter))); Marshal.Copy(ftr, 0, ftrPtr, Marshal.SizeOf(typeof(ScpFooter))); ScpFooter footer = (ScpFooter)Marshal.PtrToStructure(ftrPtr, typeof(ScpFooter)); Marshal.FreeHGlobal(ftrPtr); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.manufacturerOffset = 0x{0:X8}", footer.manufacturerOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.modelOffset = 0x{0:X8}", footer.modelOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.serialOffset = 0x{0:X8}", footer.serialOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.creatorOffset = 0x{0:X8}", footer.creatorOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.applicationOffset = 0x{0:X8}", footer.applicationOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.commentsOffset = 0x{0:X8}", footer.commentsOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.creationTime = {0}", footer.creationTime); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.modificationTime = {0}", footer.modificationTime); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.applicationVersion = {0}.{1}", (footer.applicationVersion & 0xF0) >> 4, footer.applicationVersion & 0xF); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.hardwareVersion = {0}.{1}", (footer.hardwareVersion & 0xF0) >> 4, footer.hardwareVersion & 0xF); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.firmwareVersion = {0}.{1}", (footer.firmwareVersion & 0xF0) >> 4, footer.firmwareVersion & 0xF); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.imageVersion = {0}.{1}", (footer.imageVersion & 0xF0) >> 4, footer.imageVersion & 0xF); DicConsole.DebugWriteLine("SuperCardPro plugin", "footer.signature = \"{0}\"", StringHandlers.CToString(BitConverter.GetBytes(footer.signature))); imageInfo.DriveManufacturer = ReadPStringUtf8(scpStream, footer.manufacturerOffset); imageInfo.DriveModel = ReadPStringUtf8(scpStream, footer.modelOffset); imageInfo.DriveSerialNumber = ReadPStringUtf8(scpStream, footer.serialOffset); imageInfo.Creator = ReadPStringUtf8(scpStream, footer.creatorOffset); imageInfo.Application = ReadPStringUtf8(scpStream, footer.applicationOffset); imageInfo.Comments = ReadPStringUtf8(scpStream, footer.commentsOffset); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveManufacturer = \"{0}\"", imageInfo.DriveManufacturer); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveModel = \"{0}\"", imageInfo.DriveModel); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.driveSerialNumber = \"{0}\"", imageInfo.DriveSerialNumber); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreator = \"{0}\"", imageInfo.Creator); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageApplication = \"{0}\"", imageInfo.Application); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageComments = \"{0}\"", imageInfo.Comments); imageInfo.CreationTime = footer.creationTime != 0 ? DateHandlers.UnixToDateTime(footer.creationTime) : imageFilter.GetCreationTime(); imageInfo.LastModificationTime = footer.modificationTime != 0 ? DateHandlers.UnixToDateTime(footer.modificationTime) : imageFilter.GetLastWriteTime(); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageCreationTime = {0}", imageInfo.CreationTime); DicConsole.DebugWriteLine("SuperCardPro plugin", "ImageInfo.imageLastModificationTime = {0}", imageInfo.LastModificationTime); imageInfo.ApplicationVersion = $"{(footer.applicationVersion & 0xF0) >> 4}.{footer.applicationVersion & 0xF}"; imageInfo.DriveFirmwareRevision = $"{(footer.firmwareVersion & 0xF0) >> 4}.{footer.firmwareVersion & 0xF}"; imageInfo.Version = $"{(footer.imageVersion & 0xF0) >> 4}.{footer.imageVersion & 0xF}"; break; } scpStream.Seek(-8, SeekOrigin.Current); } } else { imageInfo.Application = "SuperCardPro"; imageInfo.ApplicationVersion = $"{(Header.version & 0xF0) >> 4}.{Header.version & 0xF}"; imageInfo.CreationTime = imageFilter.GetCreationTime(); imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); imageInfo.Version = "1.5"; } throw new NotImplementedException("Flux decoding is not yet implemented."); }
public void updateHeader() { if (controller == null) { return; } this.updatingHeader = true; while (this.trackHeaderList.Count > this.controller.trackCount()) { TrackHeader header = trackHeaderList.ElementAt(this.trackHeaderList.Count - 1); header.removeFromControl(this.Controls); this.trackHeaderList.Remove(header); } for (int i = 0; i < this.trackHeaderList.Count; i++) { Timbre t = controller.getTimbre(i); this.trackHeaderList[i].timbreBox.SelectedIndex = (int)t; int volume = controller.getVolume(i); this.trackHeaderList[i].volumeBar.Value = volume; } while (this.trackHeaderList.Count < this.controller.trackCount()) { ComboBox cb = new ComboBox(); cb.Location = new System.Drawing.Point(0, HEADER_SIZE + this.track_height * this.trackHeaderList.Count); cb.Width = this.track_header - 2; cb.BackColor = Color.FromArgb(255, 0, 0, 0); cb.ForeColor = Color.FromArgb(255, 255, 255, 255); cb.FlatStyle = FlatStyle.Flat; cb.DataSource = Enum.GetNames(typeof(Timbre)).Select(s => s.Replace("_", " ")).ToArray(); cb.SelectedValue = controller.getTimbre(this.trackHeaderList.Count); cb.Name = Convert.ToString(this.trackHeaderList.Count); cb.SelectedIndexChanged += combobox_indexChanged; Button b = new Button(); b.Location = new System.Drawing.Point(5, HEADER_SIZE + this.track_height * this.trackHeaderList.Count + 26); b.Size = new System.Drawing.Size(18, 18); b.BackColor = System.Drawing.Color.Black; b.BackgroundImage = global::MusicaMinimalista.Properties.Resources.remove_icon; b.FlatStyle = System.Windows.Forms.FlatStyle.Flat; b.Name = Convert.ToString(this.trackHeaderList.Count); b.Click += button_Click; TrackBar tb = new TrackBar(); tb.BackColor = System.Drawing.Color.Black; tb.Location = new System.Drawing.Point(55, HEADER_SIZE + this.track_height * this.trackHeaderList.Count + 26); System.Drawing.Size size = new System.Drawing.Size(80, 20); tb.MaximumSize = size; tb.MinimumSize = size; tb.Size = size; tb.Maximum = Track.MAX_VOLUME; tb.Value = Track.MAX_VOLUME / 2; tb.Name = Convert.ToString(this.trackHeaderList.Count); tb.TickStyle = System.Windows.Forms.TickStyle.None; tb.ValueChanged += trackBar_valueChanged; TrackHeader header = new TrackHeader(cb, b, tb); this.trackHeaderList.Add(header); header.addToControl(this.Controls); } this.updatingHeader = false; }
public bool Open(IFilter imageFilter) { _header = new Header(); byte[] headerBytes = new byte[12]; _inStream = imageFilter.GetDataForkStream(); var stream = new MemoryStream(); _inStream.Seek(0, SeekOrigin.Begin); _inStream.Read(headerBytes, 0, 12); stream.Write(headerBytes, 0, 12); _header.Signature = BitConverter.ToUInt16(headerBytes, 0); if (_header.Signature != TD_MAGIC && _header.Signature != TD_ADV_COMP_MAGIC) { return(false); } _header.Sequence = headerBytes[2]; _header.DiskSet = headerBytes[3]; _header.Version = headerBytes[4]; _header.DataRate = headerBytes[5]; _header.DriveType = headerBytes[6]; _header.Stepping = headerBytes[7]; _header.DosAllocation = headerBytes[8]; _header.Sides = headerBytes[9]; _header.Crc = BitConverter.ToUInt16(headerBytes, 10); _imageInfo.MediaTitle = Path.GetFileNameWithoutExtension(imageFilter.GetFilename()); _imageInfo.Version = $"{(_header.Version & 0xF0) >> 4}.{_header.Version & 0x0F}"; _imageInfo.Application = _imageInfo.Version; byte[] headerBytesForCrc = new byte[10]; Array.Copy(headerBytes, headerBytesForCrc, 10); ushort calculatedHeaderCrc = TeleDiskCrc(0x0000, headerBytesForCrc); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.signature = 0x{0:X4}", _header.Signature); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.sequence = 0x{0:X2}", _header.Sequence); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.diskSet = 0x{0:X2}", _header.DiskSet); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.version = 0x{0:X2}", _header.Version); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.dataRate = 0x{0:X2}", _header.DataRate); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.driveType = 0x{0:X2}", _header.DriveType); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.stepping = 0x{0:X2}", _header.Stepping); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.dosAllocation = 0x{0:X2}", _header.DosAllocation); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.sides = 0x{0:X2}", _header.Sides); AaruConsole.DebugWriteLine("TeleDisk plugin", "header.crc = 0x{0:X4}", _header.Crc); AaruConsole.DebugWriteLine("TeleDisk plugin", "calculated header crc = 0x{0:X4}", calculatedHeaderCrc); // We need more checks as the magic is too simply. // This may deny legal images // That would be much of a coincidence if (_header.Crc != calculatedHeaderCrc) { _aDiskCrcHasFailed = true; AaruConsole.DebugWriteLine("TeleDisk plugin", "Calculated CRC does not coincide with stored one."); } if (_header.Sequence != 0x00) { return(false); } if (_header.DataRate != DATA_RATE_250KBPS && _header.DataRate != DATA_RATE_300KBPS && _header.DataRate != DATA_RATE_500KBPS) { return(false); } if (_header.DriveType != DRIVE_TYPE_35_DD && _header.DriveType != DRIVE_TYPE_35_ED && _header.DriveType != DRIVE_TYPE_35_HD && _header.DriveType != DRIVE_TYPE_525_DD && _header.DriveType != DRIVE_TYPE_525_HD && _header.DriveType != DRIVE_TYPE_525_HD_DD_DISK && _header.DriveType != DRIVE_TYPE_8_INCH) { return(false); } if (_header.Signature == TD_ADV_COMP_MAGIC) { int rd; _inStream.Seek(12, SeekOrigin.Begin); stream.Seek(12, SeekOrigin.Begin); var lzh = new TeleDiskLzh(_inStream); do { if ((rd = lzh.Decode(out byte[] obuf, BUFSZ)) > 0) { stream.Write(obuf, 0, rd); } }while(rd == BUFSZ); } else { // Not using Stream.CopyTo() because it's failing with LZIP byte[] copybuf = new byte[_inStream.Length]; _inStream.Seek(0, SeekOrigin.Begin); _inStream.Read(copybuf, 0, copybuf.Length); stream.Seek(0, SeekOrigin.Begin); stream.Write(copybuf, 0, copybuf.Length); } stream.Seek(12, SeekOrigin.Begin); _imageInfo.CreationTime = DateTime.MinValue; if ((_header.Stepping & COMMENT_BLOCK_PRESENT) == COMMENT_BLOCK_PRESENT) { _commentHeader = new CommentBlockHeader(); byte[] commentHeaderBytes = new byte[10]; stream.Read(commentHeaderBytes, 0, 10); _commentHeader.Crc = BitConverter.ToUInt16(commentHeaderBytes, 0); _commentHeader.Length = BitConverter.ToUInt16(commentHeaderBytes, 2); _commentHeader.Year = commentHeaderBytes[4]; _commentHeader.Month = commentHeaderBytes[5]; _commentHeader.Day = commentHeaderBytes[6]; _commentHeader.Hour = commentHeaderBytes[7]; _commentHeader.Minute = commentHeaderBytes[8]; _commentHeader.Second = commentHeaderBytes[9]; _commentBlock = new byte[_commentHeader.Length]; stream.Read(_commentBlock, 0, _commentHeader.Length); byte[] commentBlockForCrc = new byte[_commentHeader.Length + 8]; Array.Copy(commentHeaderBytes, 2, commentBlockForCrc, 0, 8); Array.Copy(_commentBlock, 0, commentBlockForCrc, 8, _commentHeader.Length); ushort cmtcrc = TeleDiskCrc(0, commentBlockForCrc); AaruConsole.DebugWriteLine("TeleDisk plugin", "Comment header"); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.crc = 0x{0:X4}", _commentHeader.Crc); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tCalculated CRC = 0x{0:X4}", cmtcrc); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.length = {0} bytes", _commentHeader.Length); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.year = {0}", _commentHeader.Year); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.month = {0}", _commentHeader.Month); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.day = {0}", _commentHeader.Day); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.hour = {0}", _commentHeader.Hour); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.minute = {0}", _commentHeader.Minute); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tcommentheader.second = {0}", _commentHeader.Second); _aDiskCrcHasFailed |= cmtcrc != _commentHeader.Crc; for (int i = 0; i < _commentBlock.Length; i++) { // Replace NULLs, used by TeleDisk as newline markers, with UNIX newline marker if (_commentBlock[i] == 0x00) { _commentBlock[i] = 0x0A; } } _imageInfo.Comments = Encoding.ASCII.GetString(_commentBlock); AaruConsole.DebugWriteLine("TeleDisk plugin", "Comment"); AaruConsole.DebugWriteLine("TeleDisk plugin", "{0}", _imageInfo.Comments); _imageInfo.CreationTime = new DateTime(_commentHeader.Year + 1900, _commentHeader.Month + 1, _commentHeader.Day, _commentHeader.Hour, _commentHeader.Minute, _commentHeader.Second, DateTimeKind.Unspecified); } if (_imageInfo.CreationTime == DateTime.MinValue) { _imageInfo.CreationTime = imageFilter.GetCreationTime(); } _imageInfo.LastModificationTime = imageFilter.GetLastWriteTime(); AaruConsole.DebugWriteLine("TeleDisk plugin", "Image created on {0}", _imageInfo.CreationTime); AaruConsole.DebugWriteLine("TeleDisk plugin", "Image modified on {0}", _imageInfo.LastModificationTime); AaruConsole.DebugWriteLine("TeleDisk plugin", "Parsing image"); _totalDiskSize = 0; _imageInfo.ImageSize = 0; int totalCylinders = -1; int totalHeads = -1; int maxSector = -1; int totalSectors = 0; long currentPos = stream.Position; _imageInfo.SectorSize = uint.MaxValue; _imageInfo.SectorsPerTrack = uint.MaxValue; // Count cylinders while (true) { var teleDiskTrack = new TrackHeader { Sectors = (byte)stream.ReadByte(), Cylinder = (byte)stream.ReadByte(), Head = (byte)stream.ReadByte(), Crc = (byte)stream.ReadByte() }; if (teleDiskTrack.Cylinder > totalCylinders) { totalCylinders = teleDiskTrack.Cylinder; } if (teleDiskTrack.Head > totalHeads) { totalHeads = teleDiskTrack.Head; } if (teleDiskTrack.Sectors == 0xFF) // End of disk image { break; } for (byte processedSectors = 0; processedSectors < teleDiskTrack.Sectors; processedSectors++) { var teleDiskSector = new SectorHeader(); var teleDiskData = new DataHeader(); byte[] dataSizeBytes = new byte[2]; teleDiskSector.Cylinder = (byte)stream.ReadByte(); teleDiskSector.Head = (byte)stream.ReadByte(); teleDiskSector.SectorNumber = (byte)stream.ReadByte(); teleDiskSector.SectorSize = (byte)stream.ReadByte(); teleDiskSector.Flags = (byte)stream.ReadByte(); teleDiskSector.Crc = (byte)stream.ReadByte(); if (teleDiskSector.SectorNumber > maxSector) { maxSector = teleDiskSector.SectorNumber; } if ((teleDiskSector.Flags & FLAGS_SECTOR_DATALESS) != FLAGS_SECTOR_DATALESS && (teleDiskSector.Flags & FLAGS_SECTOR_SKIPPED) != FLAGS_SECTOR_SKIPPED) { stream.Read(dataSizeBytes, 0, 2); teleDiskData.DataSize = BitConverter.ToUInt16(dataSizeBytes, 0); teleDiskData.DataSize--; // Sydex decided to including dataEncoding byte as part of it teleDiskData.DataEncoding = (byte)stream.ReadByte(); byte[] data = new byte[teleDiskData.DataSize]; stream.Read(data, 0, teleDiskData.DataSize); } if (128 << teleDiskSector.SectorSize < _imageInfo.SectorSize) { _imageInfo.SectorSize = (uint)(128 << teleDiskSector.SectorSize); } totalSectors++; } } totalCylinders++; totalHeads++; if (totalCylinders <= 0 || totalHeads <= 0) { throw new ImageNotSupportedException("No cylinders or heads found"); } bool hasLeadOutOnHead0 = false; bool hasLeadOutOnHead1 = false; _imageInfo.Cylinders = (ushort)totalCylinders; _imageInfo.Heads = (byte)totalHeads; // Count sectors per track stream.Seek(currentPos, SeekOrigin.Begin); while (true) { var teleDiskTrack = new TrackHeader { Sectors = (byte)stream.ReadByte(), Cylinder = (byte)stream.ReadByte(), Head = (byte)stream.ReadByte(), Crc = (byte)stream.ReadByte() }; if (teleDiskTrack.Sectors == 0xFF) // End of disk image { break; } if (teleDiskTrack.Sectors < _imageInfo.SectorsPerTrack) { if (teleDiskTrack.Cylinder + 1 == totalCylinders) { hasLeadOutOnHead0 |= teleDiskTrack.Head == 0; hasLeadOutOnHead1 |= teleDiskTrack.Head == 1; if (_imageInfo.Cylinders == totalCylinders) { _imageInfo.Cylinders--; } } else { _imageInfo.SectorsPerTrack = teleDiskTrack.Sectors; } } for (byte processedSectors = 0; processedSectors < teleDiskTrack.Sectors; processedSectors++) { var teleDiskSector = new SectorHeader(); var teleDiskData = new DataHeader(); byte[] dataSizeBytes = new byte[2]; teleDiskSector.Cylinder = (byte)stream.ReadByte(); teleDiskSector.Head = (byte)stream.ReadByte(); teleDiskSector.SectorNumber = (byte)stream.ReadByte(); teleDiskSector.SectorSize = (byte)stream.ReadByte(); teleDiskSector.Flags = (byte)stream.ReadByte(); teleDiskSector.Crc = (byte)stream.ReadByte(); if ((teleDiskSector.Flags & FLAGS_SECTOR_DATALESS) == FLAGS_SECTOR_DATALESS || (teleDiskSector.Flags & FLAGS_SECTOR_SKIPPED) == FLAGS_SECTOR_SKIPPED) { continue; } stream.Read(dataSizeBytes, 0, 2); teleDiskData.DataSize = BitConverter.ToUInt16(dataSizeBytes, 0); teleDiskData.DataSize--; // Sydex decided to including dataEncoding byte as part of it teleDiskData.DataEncoding = (byte)stream.ReadByte(); byte[] data = new byte[teleDiskData.DataSize]; stream.Read(data, 0, teleDiskData.DataSize); } } _sectorsData = new byte[totalCylinders][][][]; // Total sectors per track uint[][] spts = new uint[totalCylinders][]; AaruConsole.DebugWriteLine("TeleDisk plugin", "Found {0} cylinders and {1} heads with a maximum sector number of {2}", totalCylinders, totalHeads, maxSector); // Create heads for (int i = 0; i < totalCylinders; i++) { _sectorsData[i] = new byte[totalHeads][][]; spts[i] = new uint[totalHeads]; for (int j = 0; j < totalHeads; j++) { _sectorsData[i][j] = new byte[maxSector + 1][]; } } // Decode the image stream.Seek(currentPos, SeekOrigin.Begin); while (true) { var teleDiskTrack = new TrackHeader(); byte[] tdTrackForCrc = new byte[3]; teleDiskTrack.Sectors = (byte)stream.ReadByte(); teleDiskTrack.Cylinder = (byte)stream.ReadByte(); teleDiskTrack.Head = (byte)stream.ReadByte(); teleDiskTrack.Crc = (byte)stream.ReadByte(); tdTrackForCrc[0] = teleDiskTrack.Sectors; tdTrackForCrc[1] = teleDiskTrack.Cylinder; tdTrackForCrc[2] = teleDiskTrack.Head; byte tdTrackCalculatedCrc = (byte)(TeleDiskCrc(0, tdTrackForCrc) & 0xFF); AaruConsole.DebugWriteLine("TeleDisk plugin", "Track follows"); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tTrack cylinder: {0}\t", teleDiskTrack.Cylinder); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tTrack head: {0}\t", teleDiskTrack.Head); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tSectors in track: {0}\t", teleDiskTrack.Sectors); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tTrack header CRC: 0x{0:X2} (calculated 0x{1:X2})\t", teleDiskTrack.Crc, tdTrackCalculatedCrc); _aDiskCrcHasFailed |= tdTrackCalculatedCrc != teleDiskTrack.Crc; if (teleDiskTrack.Sectors == 0xFF) // End of disk image { AaruConsole.DebugWriteLine("TeleDisk plugin", "End of disk image arrived"); AaruConsole.DebugWriteLine("TeleDisk plugin", "Total of {0} data sectors, for {1} bytes", totalSectors, _totalDiskSize); break; } for (byte processedSectors = 0; processedSectors < teleDiskTrack.Sectors; processedSectors++) { var teleDiskSector = new SectorHeader(); var teleDiskData = new DataHeader(); byte[] dataSizeBytes = new byte[2]; byte[] decodedData; teleDiskSector.Cylinder = (byte)stream.ReadByte(); teleDiskSector.Head = (byte)stream.ReadByte(); teleDiskSector.SectorNumber = (byte)stream.ReadByte(); teleDiskSector.SectorSize = (byte)stream.ReadByte(); teleDiskSector.Flags = (byte)stream.ReadByte(); teleDiskSector.Crc = (byte)stream.ReadByte(); AaruConsole.DebugWriteLine("TeleDisk plugin", "\tSector follows"); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tAddressMark cylinder: {0}", teleDiskSector.Cylinder); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tAddressMark head: {0}", teleDiskSector.Head); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tAddressMark sector number: {0}", teleDiskSector.SectorNumber); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tSector size: {0}", teleDiskSector.SectorSize); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tSector flags: 0x{0:X2}", teleDiskSector.Flags); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tSector CRC (plus headers): 0x{0:X2}", teleDiskSector.Crc); uint lba = (uint)((teleDiskSector.Cylinder * _header.Sides * _imageInfo.SectorsPerTrack) + (teleDiskSector.Head * _imageInfo.SectorsPerTrack) + (teleDiskSector.SectorNumber - 1)); if ((teleDiskSector.Flags & FLAGS_SECTOR_DATALESS) != FLAGS_SECTOR_DATALESS && (teleDiskSector.Flags & FLAGS_SECTOR_SKIPPED) != FLAGS_SECTOR_SKIPPED) { stream.Read(dataSizeBytes, 0, 2); teleDiskData.DataSize = BitConverter.ToUInt16(dataSizeBytes, 0); teleDiskData.DataSize--; // Sydex decided to including dataEncoding byte as part of it _imageInfo.ImageSize += teleDiskData.DataSize; teleDiskData.DataEncoding = (byte)stream.ReadByte(); byte[] data = new byte[teleDiskData.DataSize]; stream.Read(data, 0, teleDiskData.DataSize); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tData size (in-image): {0}", teleDiskData.DataSize); AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tData encoding: 0x{0:X2}", teleDiskData.DataEncoding); decodedData = DecodeTeleDiskData(teleDiskSector.SectorSize, teleDiskData.DataEncoding, data); byte tdSectorCalculatedCrc = (byte)(TeleDiskCrc(0, decodedData) & 0xFF); if (tdSectorCalculatedCrc != teleDiskSector.Crc) { AaruConsole.DebugWriteLine("TeleDisk plugin", "Sector {0}:{3}:{4} calculated CRC 0x{1:X2} differs from stored CRC 0x{2:X2}", teleDiskTrack.Cylinder, tdSectorCalculatedCrc, teleDiskSector.Crc, teleDiskTrack.Cylinder, teleDiskSector.SectorNumber); if ((teleDiskSector.Flags & FLAGS_SECTOR_NO_ID) != FLAGS_SECTOR_NO_ID) { _sectorsWhereCrcHasFailed.Add(lba); } } } else { decodedData = new byte[128 << teleDiskSector.SectorSize]; } AaruConsole.DebugWriteLine("TeleDisk plugin", "\t\tLBA: {0}", lba); if ((teleDiskSector.Flags & FLAGS_SECTOR_NO_ID) == FLAGS_SECTOR_NO_ID) { continue; } if (_sectorsData[teleDiskTrack.Cylinder][teleDiskTrack.Head][teleDiskSector.SectorNumber] != null) { AaruConsole.DebugWriteLine("TeleDisk plugin", (teleDiskSector.Flags & FLAGS_SECTOR_DUPLICATE) == FLAGS_SECTOR_DUPLICATE ? "\t\tSector {0} on cylinder {1} head {2} is duplicate, and marked so" : "\t\tSector {0} on cylinder {1} head {2} is duplicate, but is not marked so", teleDiskSector.SectorNumber, teleDiskSector.Cylinder, teleDiskSector.Head); } else { _sectorsData[teleDiskTrack.Cylinder][teleDiskTrack.Head][teleDiskSector.SectorNumber] = decodedData; _totalDiskSize += (uint)decodedData.Length; } } } var leadOutMs = new MemoryStream(); if (hasLeadOutOnHead0) { for (int i = 0; i < _sectorsData[totalCylinders - 1][0].Length; i++) { if (_sectorsData[totalCylinders - 1][0][i] != null) { leadOutMs.Write(_sectorsData[totalCylinders - 1][0][i], 0, _sectorsData[totalCylinders - 1][0][i].Length); } } } if (hasLeadOutOnHead1) { for (int i = 0; i < _sectorsData[totalCylinders - 1][1].Length; i++) { if (_sectorsData[totalCylinders - 1][1][i] != null) { leadOutMs.Write(_sectorsData[totalCylinders - 1][1][i], 0, _sectorsData[totalCylinders - 1][1][i].Length); } } } if (leadOutMs.Length != 0) { _leadOut = leadOutMs.ToArray(); _imageInfo.ReadableMediaTags.Add(MediaTagType.Floppy_LeadOut); } _imageInfo.Sectors = _imageInfo.Cylinders * _imageInfo.Heads * _imageInfo.SectorsPerTrack; _imageInfo.MediaType = DecodeTeleDiskDiskType(); _imageInfo.XmlMediaType = XmlMediaType.BlockMedia; AaruConsole.VerboseWriteLine("TeleDisk image contains a disk of type {0}", _imageInfo.MediaType); if (!string.IsNullOrEmpty(_imageInfo.Comments)) { AaruConsole.VerboseWriteLine("TeleDisk comments: {0}", _imageInfo.Comments); } _inStream.Dispose(); stream.Dispose(); return(true); }