object IList.this[int index] { get { return(this[index]); } set { MList <T> .VerifyValueType(value); this[index] = (T)value; } }
/// <summary> /// Создание MList, с копированием содержимого указанного объекта MList. Копируется только Count значений. Размер массива лежащего в основе MList будет Count. /// Если mlistToBeCopied == null, то возвращает null. /// </summary> /// <param name="arrayToBeCopied"></param> public static MList <T> FromMList(MList <T> mlistToBeCopied) { if (mlistToBeCopied == null) { return(null); } MList <T> r = new MList <T>(mlistToBeCopied.Cnt); r.Cnt = mlistToBeCopied.Cnt; r.Data = new T[mlistToBeCopied.Cnt]; Array.Copy(mlistToBeCopied.Data, 0, r.Data, 0, mlistToBeCopied.Cnt); return(r); }
public MList <TOutput> ConvertAll <TOutput>(Converter <T, TOutput> converter) { //if (converter == null) //{ // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter); //} MList <TOutput> list = new MList <TOutput>(Cnt); for (int i = 0; i < Cnt; i++) { list.Data[i] = converter(Data[i]); } list.Cnt = Cnt; return(list); }
public MList <T> GetRange(int index, int count) { //if ((index < 0) || (count < 0)) //{ // ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); //} //if ((this._size - index) < count) //{ // ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); //} MList <T> list = new MList <T>(count); Array.Copy(Data, index, list.Data, 0, count); list.Cnt = count; return(list); }
/// <summary> /// Создание MList с копированием или клонированием содержимого указанного объекта MList. /// </summary> /// <param name="mlistToBeCopied"></param> /// <param name="preserveCapacity"></param> public MList(MList <T> mlistToBeCopied, bool preserveCapacity, bool cloneItems) { this.Capacity = preserveCapacity ? mlistToBeCopied.Capacity : mlistToBeCopied.Cnt; this.Cnt = mlistToBeCopied.Cnt; Data = new T[this.Capacity]; if (cloneItems) { for (int i = 0; i < Cnt; i++) { Data[i] = (T)((ICloneable)mlistToBeCopied.Data[i]).Clone(); } } else { Array.Copy(mlistToBeCopied.Data, 0, Data, 0, mlistToBeCopied.Cnt); } }
public MList <T> FindAll(Predicate <T> match) { //if (match == null) //{ // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); //} MList <T> list = new MList <T>(); for (int i = 0; i < Cnt; i++) { if (match(Data[i])) { list.Add(Data[i]); } } return(list); }
public static bool Init(bool initFile, bool fileOutput, bool windowOutput, MList <string> windowOutputNormalx, MList <string> windowOutputErrorx, MsgType allowedMessagesFile, MsgType allowedMessagesWindow) { if (initialized) { return(true); } Log.allowedMessagesFile = allowedMessagesFile; Log.allowedMessagesWindow = allowedMessagesWindow; FileOutput = fileOutput; WinOutput = windowOutput; winOutputNormal = windowOutputNormalx; winOutputError = windowOutputErrorx; SetShortcuts(); LogFile = null; if (initFile) { LogPath = Path.GetDirectoryName(Application.ExecutablePath) + @"\Log\"; string s = LogPath + "SpectrumArchiveReader " + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + ".log"; if (!Directory.Exists(LogPath)) { try { DirectoryInfo di = Directory.CreateDirectory(LogPath); } catch (Exception e) { WriteMessage("При попытке создания директории Log возникло исключение: " + e.Message, MsgType.Fatal, true, false); return(false); } } try { LogFile = new StreamWriter(s); Trace?.Out($"Log initialized. Date: {DateTime.Now.ToString("dd.MM.yyyy")}. Version: {typeof(Log).Assembly.GetName().Version}"); } catch (Exception e) { WriteMessage("При попытке создания лог-файла возникло исключение: " + e.Message, MsgType.Fatal, true, false); return(false); } } initialized = true; return(true); }
public MList <DiskString> FindString(string str, int xor, int extendBy) { int last = Data.Length - str.Length; byte[] clip = new byte[str.Length]; byte[] clip1 = new byte[str.Length + extendBy * 2]; MList <DiskString> result = new MList <DiskString>(); for (int i = 0; i < last; i++) { for (int j = 0; j < str.Length; j++) { clip[j] = (byte)(Data[i + j] ^ xor); } string s0 = Encoding.ASCII.GetString(clip, 0, str.Length); if (s0.Equals(str, StringComparison.OrdinalIgnoreCase)) { DiskString ds = new DiskString(); ds.Image = this; ds.Track = i / SectorSize / SectorsOnTrack; ds.Sector = i / SectorSize - ds.Track * SectorsOnTrack; ds.Offset = i - ds.Track * SectorsOnTrack * SectorSize - ds.Sector * SectorSize; ds.Xor = xor; ds.File = GetFileByDiskAddress(ds.Track, ds.Sector); int start = Math.Max(0, i - extendBy); int end = Math.Min(i + str.Length + extendBy, Data.Length); for (int j = start, k = 0; j < end; j++, k++) { clip1[k] = (byte)(Data[j] ^ xor); } ds.Value = Encoding.ASCII.GetString(clip1, 0, end - start); result.Add(ds); } } return(result); }
public TrackFormat(int sectorCnt) { Layout = new MList <SectorInfo>(sectorCnt); FormatName = TrackFormatName.Unscanned; }
public void CopyTo(MList <T> dest) { dest.EnsureCapacity(Cnt); dest.Cnt = Cnt; Array.Copy(Data, 0, dest.Data, 0, Cnt); }
public void ParseCatalogue(int sectorNumber = 0, bool strictTrdosFormat = true) { if (Files == null) { Files = new MList <FileData>(); } else { Files.Clear(); } for (int i = 0, adr = sectorNumber * SectorSize; i < 128; i++, adr += 16) { if (Sectors == null || adr / SectorSize >= Sectors.Length) { break; } if (adr + 16 > Data.Length) { break; } if (Sectors[adr / SectorSize] != SectorProcessResult.Good) { continue; } if (strictTrdosFormat && Data[adr] == 0) { break; } if (AllBytes(Data, adr, 8, 0)) { continue; } FileData fileData = new FileData(); fileData.FileName = ReplaceZeroInString(Encoding.ASCII.GetString(Data, adr, 9)); fileData.Extension = fileData.FileName[8]; fileData.FileName = fileData.FileName.Substring(0, 8); fileData.Start = Data[adr + 9] + Data[adr + 10] * SectorSize; fileData.Length = Data[adr + 11] + Data[adr + 12] * SectorSize; fileData.Size = Data[adr + 13]; fileData.Sector = Data[adr + 14]; fileData.Track = Data[adr + 15]; int diskAddress = fileData.Track * SectorsOnTrack + fileData.Sector; int good = 0; int bad = 0; int unprocessed = 0; for (int j = diskAddress, last = Math.Min(Sectors.Length, diskAddress + fileData.Size); j < last; j++) { switch (Sectors[j]) { case SectorProcessResult.Unprocessed: unprocessed++; break; case SectorProcessResult.Good: good++; break; case SectorProcessResult.Bad: case SectorProcessResult.NoHeader: bad++; break; } } fileData.GoodSectors = good; fileData.BadSectors = bad; fileData.UnprocessedSectors = unprocessed; Files.Add(fileData); } if (Sectors.Length > sectorNumber + 8 && Sectors[sectorNumber + 8] == SectorProcessResult.Good) { Title = ReplaceZeroInString(Encoding.ASCII.GetString(Data, (sectorNumber + 8) * SectorSize + 245, 8)); Free8Sector = Data[(sectorNumber + 8) * SectorSize + 229] + Data[(sectorNumber + 8) * SectorSize + 230] * SectorSize; DeletedFiles8Sector = Data[(sectorNumber + 8) * SectorSize + 244]; FileCount8Sector = Data[(sectorNumber + 8) * SectorSize + 228]; switch (Data[(sectorNumber + 8) * SectorSize + 227]) { case 0x16: DiskType = DiskType.DS80; break; case 0x17: DiskType = DiskType.DS40; break; case 0x18: DiskType = DiskType.SS80; break; case 0x19: DiskType = DiskType.SS40; break; default: DiskType = DiskType.Unidentified; break; } } else { Title = null; Free8Sector = 0; DeletedFiles8Sector = 0; FileCount8Sector = 0; DiskType = DiskType.Unidentified; } catalogueParsed = true; }
public unsafe int ReadRandomSectors(TimeSpan timeout, int stopOnNthFail = 0) { int goodSectors = Params.Image.GoodSectors; int imageTracks = Params.Image.SizeTracks; try { bool useTimeout = timeout > TimeSpan.Zero; DateTime timeoutTime = DateTime.Now.Add(timeout); Timer sectorTimer = new Timer(); Random random = new Random(); MList <Point> sectorArray = new MList <Point>(Params.Image.SizeSectors); for (int track = Params.FirstTrack; track < Params.LastTrack; track++) { if (Params.Side == DiskSide.Side0 && track % 2 != 0) { continue; } if (Params.Side == DiskSide.Side1 && track % 2 != 1) { continue; } for (int sector = 0; sector < Params.Image[track].Layout.Cnt; sector++) { if (Params.Image[track][sector].ProcessResult != SectorProcessResult.Good) { sectorArray.Add(new Point(track, sector)); } } } int prevCylinder = -1; int failCounter = 0; while (sectorArray.Cnt > 0 && ((useTimeout && DateTime.Now < timeoutTime) || !useTimeout) && (stopOnNthFail == 0 || (failCounter < stopOnNthFail))) { int index = random.Next(sectorArray.Cnt); int track = sectorArray[index].X; int sectorIndex = sectorArray[index].Y; SectorInfo sector = Params.Image[track][sectorIndex]; TrackFormat tf = Params.Image[track]; int error = 23; Params.Map.MarkSectorAsProcessing(track, sectorIndex); bool badWritten = sector.ProcessResult == SectorProcessResult.Bad; for (int attempt = 0; attempt < Params.SectorReadAttempts; attempt++) { if (Aborted) { goto abort; } int cylinder = track / 2; if (cylinder == prevCylinder) { int tempCylinder = cylinder + (random.Next(2) == 0 ? -1 : 1); tempCylinder = Math.Max(0, tempCylinder); tempCylinder = Math.Min(tempCylinder, Params.LastTrack / 2); Driver.Seek(DriverHandle, tempCylinder * 2); if (Aborted) { goto abort; } Thread.Sleep(random.Next((int)TrackFormat.SpinTimeStandard)); // Ждем случайное время чтобы приехать на нужный цилиндр в случайной точке. } prevCylinder = cylinder; Driver.Seek(DriverHandle, track); if (Aborted) { goto abort; } WinApi.RtlZeroMemory(memoryHandle, (UIntPtr)sector.SizeBytes); sectorTimer.Start(); error = Driver.ReadSectorF(DriverHandle, memoryHandle, sector.Cylinder, sector.SectorNumber, sector.SizeCode, track & 1, sector.Head, 0x0a, 0xff); sectorTimer.Stop(); if (error == 0) { Params.Image.WriteGoodSector(memoryHandle, tf, sectorIndex); sectorArray.RemoveAt(index); failCounter = 0; timeoutTime = DateTime.Now.Add(timeout); break; } // Ошибка 27 может быть как в случае отсутствия заголовка, так и в случае когда заголовок имеет ошибку CRC. // Тут сложный вопрос что с этим делать: писать сектор как CrcError или как NoHeader. Пишется как NoHeader. // (проверить была ошибка CRC в заголовке или заголовок вообще не был найден можно сравнив sectorTimer.ElapsedMs с временем вращения tf.SpinTime) bool noHeader = error == 21 || error == 1112 || error == 27; Make30HeadPositionings(error, track); if (error == 23) { Params.Image.WriteBadSector(memoryHandle, tf, sectorIndex); badWritten = true; } else if (noHeader && !badWritten) { Params.Image.WriteNoHeader(memoryHandle, tf, sectorIndex); } } failCounter++; } return(Params.Image.GoodSectors - goodSectors); abort: Log.Info?.Out("Чтение прервано."); } finally { Params.Map?.ClearHighlight(MapCell.Processing); } return(Params.Image.GoodSectors - goodSectors); }
public unsafe int ReadRandomSectors(TimeSpan timeout, int stopOnNthFail = 0) { int goodSectors = Params.Image.GoodSectors; int imageTracks = Params.Image.SizeTracks; int *trackHead = stackalloc int[imageTracks]; for (int i = 0; i < imageTracks; i++) { trackHead[i] = -1; } try { bool useTimeout = timeout > TimeSpan.Zero; DateTime timeoutTime = DateTime.Now.Add(timeout); Timer sectorTimer = new Timer(); Random random = new Random(); UpperSideHead upperSideHead = Params.UpperSideHead; bool upperSideHeadScanned = false; MList <int> sectorArray = new MList <int>(Params.Image.SizeSectors); for (int i = Params.FirstSectorNum; i < Params.LastSectorNum; i++) { int track = i / Params.Image.SectorsOnTrack; if (Params.Side == DiskSide.Side0 && track % 2 != 0) { continue; } if (Params.Side == DiskSide.Side1 && track % 2 != 1) { continue; } if (Params.Image.Sectors[i] != SectorProcessResult.Good) { sectorArray.Add(i); } } int prevCylinder = -1; int failCounter = 0; while (sectorArray.Cnt > 0 && ((useTimeout && DateTime.Now < timeoutTime) || !useTimeout) && (stopOnNthFail == 0 || (failCounter < stopOnNthFail))) { int index = random.Next(sectorArray.Cnt); int sectorNum = sectorArray.Data[index]; int track = sectorNum / Params.SectorsOnTrack; SectorInfo sector = Params.Image.StandardFormat.Layout.Data[sectorNum - track * Params.SectorsOnTrack]; int error = 23; Params.Image.Map?.ClearHighlight(MapCell.Processing); Params.Image.Map?.MarkAsProcessing(sectorNum); if (Params.UpperSideHeadAutodetect && trackHead[track] != -1) { upperSideHead = (UpperSideHead)trackHead[track]; } if (Params.UpperSideHeadAutodetect && !upperSideHeadScanned && (track & 1) != 0 && trackHead[track] == -1) { UpperSideHead ush = upperSideHead; if (ScanHeadParameter(ref ush, track, Params.CurrentTrackFormat) == 0) { upperSideHead = ush; trackHead[track] = (int)upperSideHead; Log.Trace?.Out($"Параметр Head для трека {track} определен: {(int)upperSideHead}"); } else { Log.Trace?.Out($"Параметр Head для трека {track} определить не удалось."); } upperSideHeadScanned = true; } bool noHeader = false; bool badWritten = Params.Image.Sectors[sectorNum] == SectorProcessResult.Bad; for (int attempt = 0; attempt < Params.SectorReadAttempts; attempt++) { if (Aborted) { goto abort; } int cylinder = track / 2; if (cylinder == prevCylinder) { int tempCylinder = cylinder + (random.Next(2) == 0 ? -1 : 1); tempCylinder = Math.Max(0, tempCylinder); tempCylinder = Math.Min(tempCylinder, Params.LastTrack / 2); Driver.Seek(DriverHandle, tempCylinder * 2); if (Aborted) { goto abort; } Thread.Sleep(random.Next((int)TrackFormat.SpinTimeStandard)); // Ждем случайное время чтобы приехать на нужный цилиндр в случайной точке. } prevCylinder = cylinder; Driver.Seek(DriverHandle, track); if (Aborted) { goto abort; } sectorTimer.Start(); error = Driver.ReadSector(DriverHandle, memoryHandle, track, sector.SectorNumber, upperSideHead, sector.SizeCode); sectorTimer.Stop(); if (error == 0) { goto sectorReadSuccessfully; } noHeader = error == 21 || (error == 27 && sectorTimer.ElapsedMs > Params.CurrentTrackFormat.SpinTime); Make30HeadPositionings(error, track); if (error == 23) { Params.Image.WriteBadSectors(sectorNum, memoryHandle, 1, false); badWritten = true; } if (noHeader && track % 2 == 1 && Params.UpperSideHeadAutodetect && trackHead[track] == -1) { UpperSideHead ush = upperSideHead; if (ScanHeadParameter(ref ush, track, Params.CurrentTrackFormat) == 0) { upperSideHead = ush; trackHead[track] = (int)upperSideHead; Log.Trace?.Out($"Параметр Head для трека {track} определен: {(int)upperSideHead}"); attempt--; } else { Log.Trace?.Out($"Параметр Head для трека {track} определить не удалось."); } } } failCounter++; if (!badWritten) { Params.Image.WriteBadSectors(sectorNum, 1, noHeader); } continue; sectorReadSuccessfully: Params.Image.WriteGoodSectors(sectorNum, memoryHandle, 1); trackHead[track] = (int)upperSideHead; sectorArray.RemoveAt(index); failCounter = 0; timeoutTime = DateTime.Now.Add(timeout); } return(Params.Image.GoodSectors - goodSectors); abort: Log.Info?.Out("Чтение прервано."); } finally { Params.Image.Map?.ClearHighlight(MapCell.Processing); } return(Params.Image.GoodSectors - goodSectors); }
/// <summary> /// Копирование массива из MList. /// </summary> /// <param name="source"></param> public void CopyArray(MList <T> source) { EnsureCapacity(source.Cnt); Array.Copy(source.Data, 0, Data, 0, source.Cnt); Cnt = source.Cnt; }
public static string BuildMap(string title, string jsArray, string values, MList <HtmlMapPars> pars) { StringBuilder sb = new StringBuilder(); sb.AppendLine(@"<!DOCTYPE html> <html> <head> <meta charset=""UTF-8"" /> <meta name=""generator"" content=""Spectrum Archive Reader"">"); sb.AppendLine($" <title>{title}</title>"); sb.AppendLine(@" <style>"); for (int i = 0; i < pars.Cnt; i++) { sb.AppendLine($" .{pars[i].Char} {{ background-color: {pars[i].BackgroundColor}; }}"); } sb.AppendLine(@" .map td { width: 5px; height: 5px; min-width: 5px; min-height: 5px; } #statsTable tr { text-align: left; margin-top: 30px; } #statsTable { margin-top: 30px; } #legend div div { width: 15px; height: 15px; float: left; margin-right: 15px; } #legend { margin: 30px; } #tablediv table { border-spacing: 0px; } </style> </head> <body> <div id=""legend"" style=""display: none;"">"); for (int i = 0; i < pars.Cnt; i++) { sb.AppendLine($@" <div><div class=""{pars[i].Char}""></div>{pars[i].Description}</div>"); } sb.AppendLine(@" </div> <div id=""tablediv""><h1 align=""center"">Rendering HTML ...</h1></div>"); string indent = " "; sb.AppendLine(indent + indent + "<script>"); sb.AppendLine(indent + indent + indent + jsArray); sb.AppendLine(indent + indent + indent + values); sb.AppendLine(indent + indent + indent + @"var s = """"; for (var d = 0; d < disks.length; d++) { var pars = values[d]; s += ""<div>"" + pars[0] + "" | Title: "" + pars[1] + "" | Size: "" + pars[2] + "" | Good: "" + pars[3] + "" | Bad: "" + pars[4] + "" | Unprocessed: "" + pars[5] + "" | Files: "" + pars[6] + "" | Damaged: "" + pars[7] + "" | Non-Zero: "" + pars[8] + ""</div>""; s += ""<table class=\""map\"">""; var sectors = disks[d]; var trackCnt = sectors.length / 16; if (trackCnt * 16 < sectors.length) trackCnt++; for (var sec = 0; sec < 16; sec++) { s += ""<tr>""; for (var tr = 0; tr < trackCnt; tr++) { var sectorNum = tr * 16 + sec; if (sectorNum >= sectors.length) { s += ""<td class=\""u\""></td>""; } else { s += ""<td class=\"""" + sectors[sectorNum] + ""\""></td>""; } } s += ""</tr>""; } s += ""</table>""; } document.getElementById(""tablediv"").innerHTML = s; document.getElementById(""legend"").style.display = ""block""; var tdMouseMove = function(e) { var elem = document.elementFromPoint(e.clientX, e.clientY); if (elem.nodeName != ""TD"") return; elem.title = ""Track: "" + elem.cellIndex + "" | Sector: "" + elem.parentNode.rowIndex; } var maps = document.querySelectorAll("".map""); for (var i = 0; i < maps.length; i++) { maps[i].onmousemove = tdMouseMove; } </script>"); sb.AppendLine(indent + "</body>"); sb.AppendLine("</html>"); return(sb.ToString()); }
public void AssignArray(MList <T> list) { Data = list.Data; Cnt = list.Cnt; }
public TrackFormat(TrackFormatName formatName) { Layout = new MList <SectorInfo>(16); SetFormat(formatName); }
public void LoadFormatFromXml(string fileName) { int track = 0; MList <SectorInfo> layout = new MList <SectorInfo>(50); MList <SectorInfo> temp = new MList <SectorInfo>(50); using (XmlTextReader xml = new XmlTextReader(fileName)) { while (xml.Read()) { if (xml.NodeType == XmlNodeType.EndElement) { break; } if (xml.NodeType != XmlNodeType.Element) { continue; } if (xml.Name == "DiskFormat") { string name = xml.GetAttribute("Name"); if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(name)) { Name = name; } while (xml.Read()) { if (xml.NodeType == XmlNodeType.EndElement) { break; } if (xml.NodeType != XmlNodeType.Element) { continue; } switch (xml.Name) { case "Track": TrackFormat tf = Tracks[track]; tf.Layout.EnsureCapacity(Int32.Parse(xml.GetAttribute("SectorCount"))); layout.Cnt = 0; if (!xml.IsEmptyElement) { while (xml.Read()) { if (xml.NodeType == XmlNodeType.EndElement) { break; } if (xml.NodeType != XmlNodeType.Element) { continue; } switch (xml.Name) { case "Sector": SectorInfo s = new SectorInfo() { Cylinder = Int32.Parse(xml.GetAttribute("Cylinder")), Head = Int32.Parse(xml.GetAttribute("Head")), SectorNumber = Int32.Parse(xml.GetAttribute("Number")), SizeCode = Int32.Parse(xml.GetAttribute("Size")), TimeMs = Double.Parse(xml.GetAttribute("Time"), NumberStyles.Any, CultureInfo.InvariantCulture) }; layout.Add(s); break; } } } if (tf.Layout.Cnt > 0) { tf.Layout.CopyTo(temp); layout.CopyTo(tf.Layout); for (int i = 0; i < temp.Cnt; i++) { int index = tf.FindSectorIndex(temp[i].SectorNumber); if (index < 0) { Log.Info?.Out($"Сектор не найден. Трек: {track} | Сектор: {temp[i].SectorNumber}"); continue; } tf.Layout.Data[index].Data = temp[i].Data; tf.Layout.Data[index].ProcessResult = temp[i].ProcessResult; tf.Layout.Data[index].MapCellValue = temp[i].MapCellValue; tf.Layout.Data[index].TimeCalculated = false; } } else { layout.CopyTo(tf.Layout); for (int i = 0; i < layout.Cnt; i++) { tf.Layout.Data[i].MapCellValue = MapCell.Unprocessed; tf.Layout.Data[i].TimeCalculated = false; } } tf.FormatName = tf.GetFormatName(); tf.SpinTime = tf.GetSpinTime(); tf.MapModified = true; track++; break; } } } } } }
bool IList.Contains(object item) { return(MList <T> .IsCompatibleObject(item) && this.Contains((T)item)); }
void IList.Insert(int index, object item) { MList <T> .VerifyValueType(item); this.Insert(index, (T)item); }