Files
Aaru/Aaru.Gui/ViewModels/Windows/ViewSectorViewModel.cs
2026-04-03 08:39:01 +02:00

326 lines
8.9 KiB
C#

// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : ViewSectorViewModel.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : GUI view models.
//
// --[ Description ] ----------------------------------------------------------
//
// View model and code for the sector viewing window.
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General public License for more details.
//
// You should have received a copy of the GNU General public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2026 Natalia Portillo
// ****************************************************************************/
using System.Collections.Generic;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Metadata;
using Aaru.Gui.Controls;
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using JetBrains.Annotations;
using Spectre.Console;
namespace Aaru.Gui.ViewModels.Windows;
public sealed partial class ViewSectorViewModel : ViewModelBase
{
readonly IMediaImage _inputFormat;
[ObservableProperty]
List<ColorRange> _highlightRanges;
[ObservableProperty]
bool _longSectorVisible;
[ObservableProperty]
string _printHexText;
[ObservableProperty]
byte[] _sectorData;
[ObservableProperty]
string _totalSectorsText;
// TODO: Show message when sector was not dumped
public ViewSectorViewModel([NotNull] IMediaImage inputFormat)
{
_inputFormat = inputFormat;
ErrorNumber errno = inputFormat.ReadSectorLong(0, false, out _, out _);
LongSectorVisible = errno == ErrorNumber.NoError;
TotalSectorsText = $"of {inputFormat.Info.Sectors}";
SectorNumber = 0;
}
public bool LongSectorChecked
{
get;
set
{
SetProperty(ref field, value);
ReadSectorAt((long)SectorNumber);
}
}
public double SectorNumber
{
get;
set
{
SetProperty(ref field, value);
ReadSectorAt((long)SectorNumber);
}
}
void ReadSectorAt(long displaySector)
{
bool negative = displaySector < 0;
ulong sectorAddress = negative ? (ulong)-displaySector : (ulong)displaySector;
ErrorNumber errno = LongSectorChecked
? _inputFormat.ReadSectorLong(sectorAddress, negative, out byte[] sector, out _)
: _inputFormat.ReadSector(sectorAddress, negative, out sector, out _);
if(errno != ErrorNumber.NoError) return;
SectorData = sector;
ColorSector();
}
void ColorSector()
{
if(SectorData.LongLength == 2064 && LongSectorChecked)
{
// DVD sector
ColorRange dvd_id_si = new ColorRange
{
Color = Brushes.DeepPink,
Start = 0,
End = 0
};
ColorRange dvd_id_sn = new ColorRange
{
Color = Brushes.Yellow,
Start = 1,
End = 3
};
ColorRange dvd_ied = new ColorRange
{
Color = Brushes.Green,
Start = 4,
End = 5
};
ColorRange dvd_cprmai = new ColorRange
{
Color = Brushes.Orange,
Start = 6,
End = 11
};
if (_inputFormat.Info.MediaType is CommonTypes.MediaType.GOD or CommonTypes.MediaType.WOD){
dvd_cprmai = new ColorRange
{
Color = Brushes.Orange,
Start = 2054,
End = 2059
};
}
ColorRange dvd_edc = new ColorRange
{
Color = Brushes.LimeGreen,
Start = 2060,
End = 2063
};
HighlightRanges = [dvd_id_si, dvd_id_sn, dvd_ied, dvd_cprmai, dvd_edc];
return;
}
// Not a standard CD sector
if(SectorData.Length != 2352) return;
// Not a data sector
if(SectorData[0] != 0x00 ||
SectorData[1] != 0xFF ||
SectorData[2] != 0xFF ||
SectorData[3] != 0xFF ||
SectorData[4] != 0xFF ||
SectorData[5] != 0xFF ||
SectorData[6] != 0xFF ||
SectorData[7] != 0xFF ||
SectorData[8] != 0xFF ||
SectorData[9] != 0xFF ||
SectorData[10] != 0xFF ||
SectorData[11] != 0x00)
return;
List<ColorRange> ranges = [];
var sync = new ColorRange
{
Color = Brushes.DeepPink,
Start = 0,
End = 11
};
// Synchronization field
ranges.Add(sync);
var msf = new ColorRange
{
Color = Brushes.Orange,
Start = 12,
End = 14
};
// Block MSF address
ranges.Add(msf);
var mode = new ColorRange
{
Color = Brushes.Yellow,
Start = 15,
End = 15
};
// Data mode
ranges.Add(mode);
ColorRange edc;
ColorRange ecc_P;
ColorRange ecc_Q;
switch(SectorData[15])
{
// MODE 1
case 1:
edc = new ColorRange
{
Color = Brushes.LimeGreen,
Start = 2064,
End = 2067
};
ecc_P = new ColorRange
{
Color = Brushes.Cyan,
Start = 2076,
End = 2247
};
ecc_Q = new ColorRange
{
Color = Brushes.Blue,
Start = 2248,
End = 2351
};
// EDC
ranges.Add(edc);
// P parity symbols
ranges.Add(ecc_P);
// Q parity symbols
ranges.Add(ecc_Q);
break;
// MODE 2
case 2:
// MODE 2 FORM 2
if((SectorData[18] & 0x20) == 0x20)
{
var subheader = new ColorRange
{
Color = Brushes.Red,
Start = 16,
End = 23
};
edc = new ColorRange
{
Color = Brushes.LimeGreen,
Start = 2348,
End = 2351
};
// Subheader
ranges.Add(subheader);
// EDC
ranges.Add(edc);
}
// MODE 2 FORM 1
else
{
var subheader = new ColorRange
{
Color = Brushes.Red,
Start = 16,
End = 23
};
edc = new ColorRange
{
Color = Brushes.LimeGreen,
Start = 2072,
End = 2075
};
ecc_P = new ColorRange
{
Color = Brushes.Cyan,
Start = 2076,
End = 2247
};
ecc_Q = new ColorRange
{
Color = Brushes.Blue,
Start = 2248,
End = 2351
};
// Subheader
ranges.Add(subheader);
// EDC
ranges.Add(edc);
// P parity symbols
ranges.Add(ecc_P);
// Q parity symbols
ranges.Add(ecc_Q);
}
break;
}
HighlightRanges = ranges;
}
}