Skip to content

Commit 6712c85

Browse files
committed
Support v5 variant sector info
1 parent f440bb4 commit 6712c85

File tree

4 files changed

+151
-53
lines changed

4 files changed

+151
-53
lines changed

Source/DiskImageManager.res

0 Bytes
Binary file not shown.

Source/DskImage.pas

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ TDSKSide = class(TObject)
122122
function GetLargestTrackSize: integer;
123123
function HasDataRate: boolean;
124124
function HasRecordingMode: boolean;
125+
function HasVariantSectors: boolean;
125126

126127
property HighTrackCount: byte read GetHighTrackCount;
127128
property ParentDisk: TDSKDisk read FParentDisk;
@@ -156,7 +157,8 @@ TDSKTrack = class(TObject)
156157
procedure Format(Formatter: TDSKFormatSpecification);
157158
procedure Unformat;
158159
function GetTrackSizeFromSectors: word;
159-
function GetFirstLogicalSector(): TDSKSector;
160+
function GetFirstLogicalSector: TDSKSector;
161+
function HasMultiSectoredSector: boolean;
160162

161163
property IsFormatted: boolean read GetIsFormatted;
162164
property LowSectorID: byte read GetLowSectorID;
@@ -191,6 +193,7 @@ TDSKSector = class(TObject)
191193
function GetFillByte: integer;
192194
function GetModChecksum(ModValue: integer): integer;
193195
function FindText(Text: string; CaseSensitive: boolean): integer;
196+
function GetCopyCount: integer;
194197

195198
procedure FillSector(Filler: byte);
196199
procedure ResetFDC;
@@ -452,7 +455,7 @@ function TDSKImage.HasV5Extensions: boolean;
452455
Side: TDSKSide;
453456
begin
454457
for Side in Disk.Side do
455-
if Side.HasDataRate or Side.HasDataRate then
458+
if Side.HasDataRate or Side.HasDataRate or Side.HasVariantSectors then
456459
begin
457460
Result := True;
458461
exit;
@@ -1210,6 +1213,20 @@ function TDSKSide.HasRecordingMode: boolean;
12101213
Result := False;
12111214
end;
12121215

1216+
function TDSKSide.HasVariantSectors: boolean;
1217+
var
1218+
Track: TDSKTrack;
1219+
Sector: TDSKSector;
1220+
begin
1221+
for Track in self.Track do
1222+
for Sector in Track.Sector do
1223+
if Sector.GetCopyCount > 1 then
1224+
begin
1225+
Result := True;
1226+
exit;
1227+
end;
1228+
Result := False;
1229+
end;
12131230

12141231
procedure TDSKSide.SetTracks(NewTracks: byte);
12151232
var
@@ -1277,6 +1294,19 @@ function TDSKTrack.GetFirstLogicalSector: TDSKSector;
12771294
Result := Sector;
12781295
end;
12791296

1297+
function TDSKTrack.HasMultiSectoredSector: boolean;
1298+
var
1299+
CheckSector: TDSKSector;
1300+
begin
1301+
Result := False;
1302+
for CheckSector in Sector do
1303+
if CheckSector.GetCopyCount > 1 then
1304+
begin
1305+
Result := True;
1306+
exit;
1307+
end;
1308+
end;
1309+
12801310
function TDSKTrack.GetIsFormatted: boolean;
12811311
begin
12821312
Result := Sectors > 0;
@@ -1388,6 +1418,16 @@ function TDSKSector.GetStatus: TDSKSectorStatus;
13881418
end;
13891419
end;
13901420

1421+
function TDSKSector.GetCopyCount: integer;
1422+
var
1423+
DeclaredSize: integer;
1424+
begin
1425+
Result := 1;
1426+
DeclaredSize := FDCSectorSizes[FDCSize];
1427+
if DataSize mod DeclaredSize <> 0 then exit;
1428+
Result := DataSize div DeclaredSize;
1429+
end;
1430+
13911431
// Get filler byte or -1 if in use, -2 if unformatted
13921432
function TDSKSector.GetFillByte: integer;
13931433
var

Source/Main.lfm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
object frmMain: TfrmMain
2-
Left = 1280
2+
Left = 1691
33
Height = 384
4-
Top = 394
4+
Top = 650
55
Width = 556
66
AllowDropFiles = True
7-
ClientHeight = 364
8-
ClientWidth = 556
7+
ClientHeight = 0
8+
ClientWidth = 0
99
Color = clBtnFace
1010
Font.CharSet = ANSI_CHARSET
1111
Font.Pitch = fpVariable

Source/Main.pas

Lines changed: 105 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,19 @@ TfrmMain = class(TForm)
125125
function AddTree(Parent: TTreeNode; Text: string; ImageIdx: integer; NodeObject: TObject): TTreeNode;
126126
function AddListInfo(Key: string; Value: string): TListItem;
127127
function AddListTrack(Track: TDSKTrack; ShowModulation: boolean; ShowDataRate: boolean): TListItem;
128-
function AddListSector(Sector: TDSKSector): TListItem;
128+
function AddListSector(Sector: TDSKSector; ShowCopies: boolean): TListItem;
129129
function AddListSides(Side: TDSKSide): TListItem;
130-
procedure SetListSimple;
131130
function GetSelectedSector(Sender: TObject): TDSKSector;
132131
function GetTitle(Data: TTreeNode): string;
133132
function GetCurrentImage: TDSKImage;
134133
function IsDiskNode(Node: TTreeNode): boolean;
135134
function AddColumn(Caption: string): TListColumn;
136135
function AddColumns(Captions: array of string): TListColumnArray;
137136
function FindTreeNodeFromData(Node: TTreeNode; Data: TObject): TTreeNode;
137+
function MapByte(Raw: byte): string;
138+
139+
procedure WriteSectorLine(Offset: integer; SecHex: string; SecData: string);
140+
procedure SetListSimple;
138141
procedure OnApplicationDropFiles(Sender: TObject; const FileNames: array of string);
139142
procedure UpdateRecentFilesMenu;
140143
public
@@ -587,19 +590,30 @@ procedure TfrmMain.RefreshListMessages(Messages: TStringList);
587590
procedure TfrmMain.RefreshListImage(Image: TDSKImage);
588591
var
589592
SIdx: integer;
590-
ImageFormat, Protection: string;
593+
Side: TDSKSide;
594+
ImageFormat, Protection, Features: string;
591595
begin
592596
SetListSimple;
593597
if Image <> nil then
594598
with Image do
595599
begin
596600
AddListInfo('Creator', Creator);
597-
ImageFormat := DSKImageFormats[FileFormat];
598601

602+
ImageFormat := DSKImageFormats[FileFormat];
599603
if Image.HasV5Extensions then ImageFormat := ImageFormat + ' v5';
600604
if Corrupt then ImageFormat := ImageFormat + ' (Corrupt)';
601-
602605
AddListInfo('Image Format', ImageFormat);
606+
607+
Features := '';
608+
for Side in Image.Disk.Side do
609+
begin
610+
if Side.HasDataRate then Features := Features + 'Data Rate, ';
611+
if Side.HasRecordingMode then Features := Features + 'Recording Mode, ';
612+
if Side.HasVariantSectors then Features := Features + 'Variant Sectors, ';
613+
end;
614+
if not Features.IsEmpty then
615+
AddListInfo('V5 features', Features.Substring(0, Features.Length - 2));
616+
603617
AddListInfo('Sides', StrInt(Disk.Sides));
604618
if Disk.Sides > 0 then
605619
begin
@@ -770,17 +784,21 @@ procedure TfrmMain.RefreshListSector(Track: TDSKTrack);
770784
lvwMain.PopupMenu := popSector;
771785

772786
AddColumns(['Sector', 'Track', 'Side', 'ID', 'FDC size', 'FDC flags', 'Data size']);
787+
788+
if Track.HasMultiSectoredSector then
789+
AddColumn('Copies');
790+
773791
with lvwMain.Columns.Add do
774792
begin
775793
Caption := 'Status';
776794
AutoSize := True;
777795
end;
778796

779797
for Sector in Track.Sector do
780-
AddListSector(Sector);
798+
AddListSector(Sector, Track.HasMultiSectoredSector);
781799
end;
782800

783-
function TfrmMain.AddListSector(Sector: TDSKSector): TListItem;
801+
function TfrmMain.AddListSector(Sector: TDSKSector; ShowCopies: boolean): TListItem;
784802
var
785803
NewListItem: TListItem;
786804
begin
@@ -789,28 +807,32 @@ function TfrmMain.AddListSector(Sector: TDSKSector): TListItem;
789807
begin
790808
Caption := StrInt(Sector.Sector);
791809
Data := Sector;
792-
SubItems.Add(StrInt(Sector.Track));
793-
SubItems.Add(StrInt(Sector.Side));
794-
SubItems.Add(StrInt(Sector.ID));
795-
SubItems.Add(StrInt(Sector.FDCSize));
796-
SubItems.Add(Format('%d, %d', [Sector.FDCStatus[1], Sector.FDCStatus[2]]));
797-
if (Sector.DataSize <> Sector.AdvertisedSize) then
798-
SubItems.Add(Format('%d (%d)', [Sector.DataSize, Sector.AdvertisedSize]))
799-
else
800-
SubItems.Add(StrInt(Sector.DataSize));
801-
SubItems.Add(DSKSectorStatus[Sector.Status]);
810+
with SubItems do
811+
begin
812+
Add(StrInt(Sector.Track));
813+
Add(StrInt(Sector.Side));
814+
Add(StrInt(Sector.ID));
815+
Add(Format('%d (%d)', [Sector.FDCSize, FDCSectorSizes[Sector.FDCSize]]));
816+
Add(Format('%d, %d', [Sector.FDCStatus[1], Sector.FDCStatus[2]]));
817+
if (Sector.DataSize <> Sector.AdvertisedSize) then
818+
Add(Format('%d (%d)', [Sector.DataSize, Sector.AdvertisedSize]))
819+
else
820+
Add(StrInt(Sector.DataSize));
821+
if ShowCopies then
822+
Add(StrInt(Sector.GetCopyCount));
823+
Add(DSKSectorStatus[Sector.Status]);
824+
end;
802825
end;
803826
Result := NewListItem;
804827
end;
805828

806829
procedure TfrmMain.RefreshListSectorData(Sector: TDSKSector);
807830
var
808-
Idx, LastIdx: integer;
831+
Idx, RowOffset, Offset, TrueSectorSize, VariantNumber: integer;
809832
Raw: byte;
810-
SecData, SecHex, NextChar: string;
833+
HasVariants: boolean;
834+
RowData, RowHex: string;
811835
begin
812-
SecData := '';
813-
SecHex := '';
814836
lvwMain.Font := Settings.SectorFont;
815837

816838
with lvwMain.Columns do
@@ -835,44 +857,80 @@ procedure TfrmMain.RefreshListSectorData(Sector: TDSKSector);
835857
end;
836858
end;
837859

860+
RowOffset := 0;
861+
RowData := '';
862+
RowHex := '';
863+
864+
HasVariants := Sector.GetCopyCount > 1;
865+
TrueSectorSize := FDCSectorSizes[Sector.FDCSize];
866+
VariantNumber := 0;
867+
868+
Offset := 0;
869+
838870
for Idx := 0 to Sector.DataSize - 1 do
839871
begin
840-
if (Idx mod Settings.BytesPerLine = 0) and (Idx > 0) then
841-
begin
872+
// If we're starting a new sector variant label it
873+
if HasVariants and (Idx mod TrueSectorSize = 0) then
842874
with lvwMain.Items.Add do
843875
begin
844-
Caption := StrInt(Idx - Settings.BytesPerLine);
845-
Subitems.Add(SecHex);
846-
Subitems.Add(SecData);
876+
Inc(VariantNumber);
877+
Subitems.Add('Sector variant #' + IntToStr(VariantNumber));
847878
end;
848-
SecData := '';
849-
SecHex := '';
850-
LastIdx := Idx;
879+
880+
// Emit a new line every X bytes depending on setting
881+
if (Offset mod Settings.BytesPerLine = 0) and (Offset > 0) then
882+
begin
883+
WriteSectorLine(RowOffset, RowHex, RowData);
884+
RowOffset := Offset;
885+
RowData := '';
886+
RowHex := '';
851887
end;
852888

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

855-
NextChar := Chr(Raw);
856-
if (Settings.Mapping = 'None') and (Raw > 127) then NextChar := Settings.UnknownASCII;
857-
if (Settings.Mapping = '437') then NextChar := CP437ToUTF8(NextChar);
858-
if (Settings.Mapping = '850') then NextChar := CP850ToUTF8(NextChar);
859-
if (Settings.Mapping = '1252') then NextChar := CP1252ToUTF8(NextChar);
895+
// Flush and reset the offset for every variant sector
896+
if HasVariants and (Offset = TrueSectorSize) then
897+
begin
898+
WriteSectorLine(RowOffset, RowHex, RowData);
899+
RowOffset := 0;
900+
RowData := '';
901+
RowHex := '';
902+
Offset := 0;
903+
end;
904+
end;
860905

861-
if Raw <= 31 then
862-
SecData := SecData + Settings.UnknownASCII
863-
else
864-
SecData := SecData + NextChar;
906+
// Flush any leftover gathered data
907+
if RowData <> '' then
908+
WriteSectorLine(RowOffset, RowHex, RowData);
909+
end;
910+
911+
procedure TfrmMain.WriteSectorLine(Offset: integer; SecHex: string; SecData: string);
912+
begin
913+
with lvwMain.Items.Add do
914+
begin
915+
Caption := StrInt(Offset);
916+
Subitems.Add(SecHex);
917+
Subitems.Add(SecData);
918+
end;
919+
end;
865920

866-
SecHex := SecHex + StrHex(Raw) + ' ';
921+
function TfrmMain.MapByte(Raw: byte): string;
922+
begin
923+
if Raw <= 31 then
924+
begin
925+
Result := Settings.UnknownASCII;
926+
exit;
867927
end;
868928

869-
if SecData <> '' then
870-
with lvwMain.Items.Add do
871-
begin
872-
Caption := StrInt(LastIdx);
873-
Subitems.Add(SecHex);
874-
Subitems.Add(SecData);
875-
end;
929+
Result := Chr(Raw);
930+
if (Settings.Mapping = 'None') and (Raw > 127) then Result := Settings.UnknownASCII;
931+
if (Settings.Mapping = '437') then Result := CP437ToUTF8(Result);
932+
if (Settings.Mapping = '850') then Result := CP850ToUTF8(Result);
933+
if (Settings.Mapping = '1252') then Result := CP1252ToUTF8(Result);
876934
end;
877935

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

0 commit comments

Comments
 (0)