Skip to content

Commit

Permalink
Support v5 variant sector info
Browse files Browse the repository at this point in the history
  • Loading branch information
damieng committed Feb 24, 2023
1 parent f440bb4 commit 6712c85
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 53 deletions.
Binary file modified Source/DiskImageManager.res
Binary file not shown.
44 changes: 42 additions & 2 deletions Source/DskImage.pas
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ TDSKSide = class(TObject)
function GetLargestTrackSize: integer;
function HasDataRate: boolean;
function HasRecordingMode: boolean;
function HasVariantSectors: boolean;

property HighTrackCount: byte read GetHighTrackCount;
property ParentDisk: TDSKDisk read FParentDisk;
Expand Down Expand Up @@ -156,7 +157,8 @@ TDSKTrack = class(TObject)
procedure Format(Formatter: TDSKFormatSpecification);
procedure Unformat;
function GetTrackSizeFromSectors: word;
function GetFirstLogicalSector(): TDSKSector;
function GetFirstLogicalSector: TDSKSector;
function HasMultiSectoredSector: boolean;

property IsFormatted: boolean read GetIsFormatted;
property LowSectorID: byte read GetLowSectorID;
Expand Down Expand Up @@ -191,6 +193,7 @@ TDSKSector = class(TObject)
function GetFillByte: integer;
function GetModChecksum(ModValue: integer): integer;
function FindText(Text: string; CaseSensitive: boolean): integer;
function GetCopyCount: integer;

procedure FillSector(Filler: byte);
procedure ResetFDC;
Expand Down Expand Up @@ -452,7 +455,7 @@ function TDSKImage.HasV5Extensions: boolean;
Side: TDSKSide;
begin
for Side in Disk.Side do
if Side.HasDataRate or Side.HasDataRate then
if Side.HasDataRate or Side.HasDataRate or Side.HasVariantSectors then
begin
Result := True;
exit;
Expand Down Expand Up @@ -1210,6 +1213,20 @@ function TDSKSide.HasRecordingMode: boolean;
Result := False;
end;

function TDSKSide.HasVariantSectors: boolean;
var
Track: TDSKTrack;
Sector: TDSKSector;
begin
for Track in self.Track do
for Sector in Track.Sector do
if Sector.GetCopyCount > 1 then
begin
Result := True;
exit;
end;
Result := False;
end;

procedure TDSKSide.SetTracks(NewTracks: byte);
var
Expand Down Expand Up @@ -1277,6 +1294,19 @@ function TDSKTrack.GetFirstLogicalSector: TDSKSector;
Result := Sector;
end;

function TDSKTrack.HasMultiSectoredSector: boolean;
var
CheckSector: TDSKSector;
begin
Result := False;
for CheckSector in Sector do
if CheckSector.GetCopyCount > 1 then
begin
Result := True;
exit;
end;
end;

function TDSKTrack.GetIsFormatted: boolean;
begin
Result := Sectors > 0;
Expand Down Expand Up @@ -1388,6 +1418,16 @@ function TDSKSector.GetStatus: TDSKSectorStatus;
end;
end;

function TDSKSector.GetCopyCount: integer;
var
DeclaredSize: integer;
begin
Result := 1;
DeclaredSize := FDCSectorSizes[FDCSize];
if DataSize mod DeclaredSize <> 0 then exit;
Result := DataSize div DeclaredSize;
end;

// Get filler byte or -1 if in use, -2 if unformatted
function TDSKSector.GetFillByte: integer;
var
Expand Down
8 changes: 4 additions & 4 deletions Source/Main.lfm
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
object frmMain: TfrmMain
Left = 1280
Left = 1691
Height = 384
Top = 394
Top = 650
Width = 556
AllowDropFiles = True
ClientHeight = 364
ClientWidth = 556
ClientHeight = 0
ClientWidth = 0
Color = clBtnFace
Font.CharSet = ANSI_CHARSET
Font.Pitch = fpVariable
Expand Down
152 changes: 105 additions & 47 deletions Source/Main.pas
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,19 @@ TfrmMain = class(TForm)
function AddTree(Parent: TTreeNode; Text: string; ImageIdx: integer; NodeObject: TObject): TTreeNode;
function AddListInfo(Key: string; Value: string): TListItem;
function AddListTrack(Track: TDSKTrack; ShowModulation: boolean; ShowDataRate: boolean): TListItem;
function AddListSector(Sector: TDSKSector): TListItem;
function AddListSector(Sector: TDSKSector; ShowCopies: boolean): TListItem;
function AddListSides(Side: TDSKSide): TListItem;
procedure SetListSimple;
function GetSelectedSector(Sender: TObject): TDSKSector;
function GetTitle(Data: TTreeNode): string;
function GetCurrentImage: TDSKImage;
function IsDiskNode(Node: TTreeNode): boolean;
function AddColumn(Caption: string): TListColumn;
function AddColumns(Captions: array of string): TListColumnArray;
function FindTreeNodeFromData(Node: TTreeNode; Data: TObject): TTreeNode;
function MapByte(Raw: byte): string;

procedure WriteSectorLine(Offset: integer; SecHex: string; SecData: string);
procedure SetListSimple;
procedure OnApplicationDropFiles(Sender: TObject; const FileNames: array of string);
procedure UpdateRecentFilesMenu;
public
Expand Down Expand Up @@ -587,19 +590,30 @@ procedure TfrmMain.RefreshListMessages(Messages: TStringList);
procedure TfrmMain.RefreshListImage(Image: TDSKImage);
var
SIdx: integer;
ImageFormat, Protection: string;
Side: TDSKSide;
ImageFormat, Protection, Features: string;
begin
SetListSimple;
if Image <> nil then
with Image do
begin
AddListInfo('Creator', Creator);
ImageFormat := DSKImageFormats[FileFormat];

ImageFormat := DSKImageFormats[FileFormat];
if Image.HasV5Extensions then ImageFormat := ImageFormat + ' v5';
if Corrupt then ImageFormat := ImageFormat + ' (Corrupt)';

AddListInfo('Image Format', ImageFormat);

Features := '';
for Side in Image.Disk.Side do
begin
if Side.HasDataRate then Features := Features + 'Data Rate, ';
if Side.HasRecordingMode then Features := Features + 'Recording Mode, ';
if Side.HasVariantSectors then Features := Features + 'Variant Sectors, ';
end;
if not Features.IsEmpty then
AddListInfo('V5 features', Features.Substring(0, Features.Length - 2));

AddListInfo('Sides', StrInt(Disk.Sides));
if Disk.Sides > 0 then
begin
Expand Down Expand Up @@ -770,17 +784,21 @@ procedure TfrmMain.RefreshListSector(Track: TDSKTrack);
lvwMain.PopupMenu := popSector;

AddColumns(['Sector', 'Track', 'Side', 'ID', 'FDC size', 'FDC flags', 'Data size']);

if Track.HasMultiSectoredSector then
AddColumn('Copies');

with lvwMain.Columns.Add do
begin
Caption := 'Status';
AutoSize := True;
end;

for Sector in Track.Sector do
AddListSector(Sector);
AddListSector(Sector, Track.HasMultiSectoredSector);
end;

function TfrmMain.AddListSector(Sector: TDSKSector): TListItem;
function TfrmMain.AddListSector(Sector: TDSKSector; ShowCopies: boolean): TListItem;
var
NewListItem: TListItem;
begin
Expand All @@ -789,28 +807,32 @@ function TfrmMain.AddListSector(Sector: TDSKSector): TListItem;
begin
Caption := StrInt(Sector.Sector);
Data := Sector;
SubItems.Add(StrInt(Sector.Track));
SubItems.Add(StrInt(Sector.Side));
SubItems.Add(StrInt(Sector.ID));
SubItems.Add(StrInt(Sector.FDCSize));
SubItems.Add(Format('%d, %d', [Sector.FDCStatus[1], Sector.FDCStatus[2]]));
if (Sector.DataSize <> Sector.AdvertisedSize) then
SubItems.Add(Format('%d (%d)', [Sector.DataSize, Sector.AdvertisedSize]))
else
SubItems.Add(StrInt(Sector.DataSize));
SubItems.Add(DSKSectorStatus[Sector.Status]);
with SubItems do
begin
Add(StrInt(Sector.Track));
Add(StrInt(Sector.Side));
Add(StrInt(Sector.ID));
Add(Format('%d (%d)', [Sector.FDCSize, FDCSectorSizes[Sector.FDCSize]]));
Add(Format('%d, %d', [Sector.FDCStatus[1], Sector.FDCStatus[2]]));
if (Sector.DataSize <> Sector.AdvertisedSize) then
Add(Format('%d (%d)', [Sector.DataSize, Sector.AdvertisedSize]))
else
Add(StrInt(Sector.DataSize));
if ShowCopies then
Add(StrInt(Sector.GetCopyCount));
Add(DSKSectorStatus[Sector.Status]);
end;
end;
Result := NewListItem;
end;

procedure TfrmMain.RefreshListSectorData(Sector: TDSKSector);
var
Idx, LastIdx: integer;
Idx, RowOffset, Offset, TrueSectorSize, VariantNumber: integer;
Raw: byte;
SecData, SecHex, NextChar: string;
HasVariants: boolean;
RowData, RowHex: string;
begin
SecData := '';
SecHex := '';
lvwMain.Font := Settings.SectorFont;

with lvwMain.Columns do
Expand All @@ -835,44 +857,80 @@ procedure TfrmMain.RefreshListSectorData(Sector: TDSKSector);
end;
end;

RowOffset := 0;
RowData := '';
RowHex := '';

HasVariants := Sector.GetCopyCount > 1;
TrueSectorSize := FDCSectorSizes[Sector.FDCSize];
VariantNumber := 0;

Offset := 0;

for Idx := 0 to Sector.DataSize - 1 do
begin
if (Idx mod Settings.BytesPerLine = 0) and (Idx > 0) then
begin
// If we're starting a new sector variant label it
if HasVariants and (Idx mod TrueSectorSize = 0) then
with lvwMain.Items.Add do
begin
Caption := StrInt(Idx - Settings.BytesPerLine);
Subitems.Add(SecHex);
Subitems.Add(SecData);
Inc(VariantNumber);
Subitems.Add('Sector variant #' + IntToStr(VariantNumber));
end;
SecData := '';
SecHex := '';
LastIdx := Idx;

// Emit a new line every X bytes depending on setting
if (Offset mod Settings.BytesPerLine = 0) and (Offset > 0) then
begin
WriteSectorLine(RowOffset, RowHex, RowData);
RowOffset := Offset;
RowData := '';
RowHex := '';
end;

// Gather up the data for the next line we'll write
Raw := Sector.Data[Idx];
RowData := RowData + MapByte(Raw);
RowHex := RowHex + StrHex(Raw) + ' ';
Inc(Offset);

NextChar := Chr(Raw);
if (Settings.Mapping = 'None') and (Raw > 127) then NextChar := Settings.UnknownASCII;
if (Settings.Mapping = '437') then NextChar := CP437ToUTF8(NextChar);
if (Settings.Mapping = '850') then NextChar := CP850ToUTF8(NextChar);
if (Settings.Mapping = '1252') then NextChar := CP1252ToUTF8(NextChar);
// Flush and reset the offset for every variant sector
if HasVariants and (Offset = TrueSectorSize) then
begin
WriteSectorLine(RowOffset, RowHex, RowData);
RowOffset := 0;
RowData := '';
RowHex := '';
Offset := 0;
end;
end;

if Raw <= 31 then
SecData := SecData + Settings.UnknownASCII
else
SecData := SecData + NextChar;
// Flush any leftover gathered data
if RowData <> '' then
WriteSectorLine(RowOffset, RowHex, RowData);
end;

procedure TfrmMain.WriteSectorLine(Offset: integer; SecHex: string; SecData: string);
begin
with lvwMain.Items.Add do
begin
Caption := StrInt(Offset);
Subitems.Add(SecHex);
Subitems.Add(SecData);
end;
end;

SecHex := SecHex + StrHex(Raw) + ' ';
function TfrmMain.MapByte(Raw: byte): string;
begin
if Raw <= 31 then
begin
Result := Settings.UnknownASCII;
exit;
end;

if SecData <> '' then
with lvwMain.Items.Add do
begin
Caption := StrInt(LastIdx);
Subitems.Add(SecHex);
Subitems.Add(SecData);
end;
Result := Chr(Raw);
if (Settings.Mapping = 'None') and (Raw > 127) then Result := Settings.UnknownASCII;
if (Settings.Mapping = '437') then Result := CP437ToUTF8(Result);
if (Settings.Mapping = '850') then Result := CP850ToUTF8(Result);
if (Settings.Mapping = '1252') then Result := CP1252ToUTF8(Result);
end;

// Menu: Help > About
Expand Down Expand Up @@ -1130,7 +1188,7 @@ procedure TfrmMain.SaveImageAs(Image: TDSKImage; Copy: boolean; NewName: string)
begin
AbandonSave := False;
if Image.HasV5Extensions and (MessageDlg(
'This image has modulation or data rate info that "Standard DSK format" does not support. ' +
'This image has modulation, data rate that "Standard DSK format" does not support. ' +
'Save anyway and lose this information?', mtWarning, [mbYes, mbNo], 0) <> mrOk) then
AbandonSave := True;

Expand Down

0 comments on commit 6712c85

Please sign in to comment.