- Timestamp:
- Mar 30, 2016, 10:50:22 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UBlockMap.pas
r3 r6 6 6 7 7 uses 8 Classes, SysUtils, Graphics, Math ;8 Classes, SysUtils, Graphics, Math, Contnrs, Dialogs; 9 9 10 10 type 11 11 TSectorState = (bsNone, bsOk, bsDamaged); 12 13 TChange = class 14 Index: Integer; 15 Value: TSectorState; 16 end; 12 17 13 18 { TBlockMap } … … 18 23 FDrawSize: TPoint; 19 24 FSectorPerBlock: Integer; 20 FSectors: array of TSectorState; 21 FBlocks: array of TSectorState; 25 FSectorCount: Integer; 26 FBlockCount: Integer; 27 FChanges: TObjectList; // TObjectList<TChange> 22 28 function GetBlockCount: Integer; 23 29 function GetSector(Index: Integer): TSectorState; 24 function GetSectorCount: Integer;25 30 procedure SetBlockCount(AValue: Integer); 26 31 procedure SetBlockSize(AValue: TPoint); … … 30 35 procedure SetSectorPerBlock(AValue: Integer); 31 36 procedure UpdateBlockSize; 32 procedure UpdateBlocks; 37 function FindChange(Index: Integer): TChange; 38 function GetCombinedSectors(StartIndex, EndIndex: Integer): TSectorState; 33 39 public 34 40 ItemsCount: TPoint; 35 function CombineSectors(From, Count: Integer): TSectorState;36 41 procedure Draw(Canvas: TCanvas); 37 42 procedure Clear; 38 43 constructor Create; 44 destructor Destroy; override; 39 45 property BlockSize: TPoint read FBlockSize write SetBlockSize; 40 46 property DrawSize: TPoint read FDrawSize write SetDrawSize; 41 47 property SectorPerBlock: Integer read FSectorPerBlock write SetSectorPerBlock; 42 property SectorCount: Integer read GetSectorCount write SetSectorCount;48 property SectorCount: Integer read FSectorCount write SetSectorCount; 43 49 property BlockCount: Integer read GetBlockCount; 44 50 property Sectors[Index: Integer]: TSectorState read GetSector write SetSector; … … 48 54 implementation 49 55 56 resourcestring 57 SBlockSizeZeroNotAllowed = 'BlockSize can''t be set to 0'; 58 SIndexOutOfRange = 'Index %d out of range'; 59 SEmptyChangesList = 'Empty changes list'; 60 SUnexpectedCombination = 'Unexpected combination'; 61 50 62 { TBlockMap } 51 63 52 function TBlockMap.GetSectorCount: Integer;53 begin54 Result := Length(FSectors);55 end;56 57 64 procedure TBlockMap.SetBlockCount(AValue: Integer); 58 65 begin 59 SetLength(FBlocks, AValue); 66 if FBlockCount = AValue then Exit; 67 FBlockCount := AValue; 60 68 end; 61 69 … … 64 72 if (FBlockSize.X = AValue.X) and (FBlockSize.Y = AValue.Y) then Exit; 65 73 if (AValue.X = 0) or (AValue.Y = 0) then 66 raise Exception.Create( 'BlockSize can''t be set to 0');74 raise Exception.Create(SBlockSizeZeroNotAllowed); 67 75 FBlockSize := AValue; 68 76 end; … … 76 84 77 85 function TBlockMap.GetSector(Index: Integer): TSectorState; 78 begin 79 Result := FSectors[Index]; 86 var 87 Change: TChange; 88 begin 89 if Index < FSectorCount then begin 90 Change := FindChange(Index); 91 if Assigned(Change) then Result := Change.Value 92 else raise Exception.Create(SIndexOutOfRange); 93 end else raise Exception.Create(SIndexOutOfRange); 80 94 end; 81 95 82 96 function TBlockMap.GetBlockCount: Integer; 83 97 begin 84 Result := Length(FBlocks);98 Result := FBlockCount; 85 99 end; 86 100 87 101 procedure TBlockMap.SetSector(Index: Integer; AValue: TSectorState); 88 102 var 89 BlockIndex: Integer; 90 begin 91 FSectors[Index] := AValue; 92 93 // Update block 94 BlockIndex := Index div FSectorPerBlock; 95 if (AValue = bsDamaged) then FBlocks[BlockIndex] := bsDamaged 96 else if (AValue = bsOk) and (FBlocks[BlockIndex] = bsNone) then 97 FBlocks[BlockIndex] := bsOk; 103 LeftBeforeSame, RightBeforeSame: Boolean; 104 LeftAfterSame, RightAfterSame: Boolean; 105 Change: TChange; 106 ChangeIndex: Integer; 107 begin 108 Change := FindChange(Index); 109 if Assigned(Change) then begin 110 if Change.Value = AValue then Exit; 111 112 ChangeIndex := FChanges.IndexOf(Change); 113 // Before 114 if ChangeIndex > 0 then begin 115 if (Index - TChange(FChanges[ChangeIndex]).Index) > 0 then LeftBeforeSame := True 116 else LeftBeforeSame := TChange(FChanges[ChangeIndex - 1]).Value = Change.Value; 117 end else begin 118 LeftBeforeSame := Change.Value = bsNone; 119 end; 120 if ChangeIndex < (FChanges.Count - 1) then begin 121 if (TChange(FChanges[ChangeIndex]).Index - Index) > 0 then RightBeforeSame := True 122 else RightBeforeSame := TChange(FChanges[ChangeIndex + 1]).Value = Change.Value; 123 end else begin 124 RightBeforeSame := Change.Value = bsNone; 125 end; 126 // After 127 if ChangeIndex > 0 then begin 128 if (Index - TChange(FChanges[ChangeIndex]).Index) > 0 then LeftAfterSame := True 129 else LeftAfterSame := TChange(FChanges[ChangeIndex - 1]).Value = AValue; 130 end else begin 131 LeftAfterSame := AValue = bsNone; 132 end; 133 if ChangeIndex < (FChanges.Count - 1) then begin 134 if (TChange(FChanges[ChangeIndex]).Index - Index) > 0 then RightAfterSame := True 135 else RightAfterSame := TChange(FChanges[ChangeIndex + 1]).Value = AValue; 136 end else begin 137 RightAfterSame := AValue = bsNone; 138 end; 139 140 // Update items 141 if not LeftBeforeSame and not RightBeforeSame and not LeftAfterSame and not RightAfterSame then begin 142 Change.Value := AValue 143 end else 144 if not LeftBeforeSame and not RightBeforeSame and not LeftAfterSame and RightAfterSame then begin 145 FChanges.Delete(ChangeIndex + 1); 146 Change.Value := AValue; 147 end else 148 if not LeftBeforeSame and not RightBeforeSame and LeftAfterSame and not RightAfterSame then begin 149 FChanges.Delete(ChangeIndex); 150 end else 151 if not LeftBeforeSame and not RightBeforeSame and LeftAfterSame and RightAfterSame then begin 152 FChanges.Delete(ChangeIndex + 1); 153 FChanges.Delete(ChangeIndex); 154 end else 155 if not LeftBeforeSame and RightBeforeSame and not LeftAfterSame and not RightAfterSame then begin 156 FChanges.Insert(ChangeIndex + 1, TChange.Create); 157 TChange(FChanges[ChangeIndex + 1]).Index := Index + 1; 158 TChange(FChanges[ChangeIndex + 1]).Value := Change.Value; 159 Change.Value := AValue; 160 end else 161 if not LeftBeforeSame and RightBeforeSame and LeftAfterSame and not RightAfterSame then begin 162 Change.Index := Index + 1; 163 end else 164 if not LeftBeforeSame and RightBeforeSame and not LeftAfterSame and not RightAfterSame then begin 165 FChanges.Insert(ChangeIndex, TChange.Create); 166 TChange(FChanges[ChangeIndex]).Index := Index; 167 TChange(FChanges[ChangeIndex]).Value := AValue; 168 end else 169 if LeftBeforeSame and not RightBeforeSame and not LeftAfterSame and RightAfterSame then begin 170 TChange(FChanges[ChangeIndex + 1]).Index := Index; 171 end else 172 if LeftBeforeSame and RightBeforeSame and not LeftAfterSame and not RightAfterSame then begin 173 if ChangeIndex > 0 then begin 174 FChanges.Insert(ChangeIndex, TChange.Create); 175 TChange(FChanges[ChangeIndex]).Index := Index; 176 TChange(FChanges[ChangeIndex]).Value := AValue; 177 end; 178 FChanges.Insert(ChangeIndex + 1, TChange.Create); 179 TChange(FChanges[ChangeIndex + 1]).Index := Index + 1; 180 TChange(FChanges[ChangeIndex + 1]).Value := Change.Value; 181 if ChangeIndex = 0 then 182 TChange(FChanges[ChangeIndex]).Value := AValue; 183 end else raise Exception.Create(SUnexpectedCombination); 184 end else raise Exception.Create(Format(SIndexOutOfRange, [Index])); 98 185 end; 99 186 100 187 procedure TBlockMap.SetSectorCount(AValue: Integer); 101 begin 102 if Length(FSectors) = AValue then Exit; 103 SetLength(FSectors, AValue); 188 var 189 I: Integer; 190 begin 191 if FSectorCount = AValue then Exit; 192 if (FChanges.Count = 0) and (AValue > 0) then begin 193 FChanges.Add(TChange.Create); 194 TChange(FChanges[0]).Index := 0; 195 TChange(FChanges[0]).Value := bsNone; 196 end; 197 FSectorCount := AValue; 198 199 // Cut changes outside of max sector count 200 I := FChanges.Count - 1; 201 while TChange(FChanges[I]).Index >= FSectorCount do Dec(I); 202 if TChange(FChanges[I]).Index >= FSectorCount then FChanges.Count := I; 203 104 204 UpdateBlockSize; 105 205 end; … … 117 217 FSectorPerBlock := Ceil(SectorCount / (ItemsCount.X * ItemsCount.Y)); 118 218 SetBlockCount(Ceil(SectorCount / FSectorPerBlock)); 119 UpdateBlocks; 120 end; 121 122 procedure TBlockMap.UpdateBlocks; 123 var 124 I: Integer; 125 begin 126 for I := 0 to BlockCount - 1 do 127 FBlocks[I] := CombineSectors(I * FSectorPerBlock, FSectorPerBlock); 128 end; 129 130 function TBlockMap.CombineSectors(From, Count: Integer): TSectorState; 131 var 132 I: Integer; 133 UpTo: Integer; 219 end; 220 221 function TBlockMap.FindChange(Index: Integer): TChange; 222 var 223 LeftIndex, MiddleIndex, RightIndex: Integer; 224 begin 225 if Fchanges.Count = 0 then raise Exception.Create(SEmptyChangesList); 226 if FChanges.Count = 1 then begin 227 Result := TChange(FChanges[0]); 228 Exit; 229 end; 230 Result := nil; 231 LeftIndex := 0; 232 RightIndex := FChanges.Count - 1; 233 while (LeftIndex <= RightIndex) do begin 234 MiddleIndex := LeftIndex + (RightIndex - LeftIndex) div 2; 235 if (TChange(FChanges[MiddleIndex]).Index <= Index) and 236 ((FChanges.Count = (MiddleIndex + 1)) or 237 (TChange(FChanges[MiddleIndex + 1]).Index > Index)) then begin 238 Result := TChange(FChanges[MiddleIndex]); 239 Break; 240 end; 241 // Cut interval in half and use nearest section 242 if TChange(FChanges[MiddleIndex]).Index < Index then begin 243 if MiddleIndex = LeftIndex then Inc(LeftIndex) 244 else LeftIndex := MiddleIndex 245 end else begin 246 if MiddleIndex = RightIndex then Dec(RightIndex) 247 else RightIndex := MiddleIndex 248 end; 249 end; 250 end; 251 252 function TBlockMap.GetCombinedSectors(StartIndex, EndIndex: Integer 253 ): TSectorState; 254 var 255 Change: TChange; 256 ChangeIndex: Integer; 134 257 begin 135 258 Result := bsNone; 136 UpTo := From + Count - 1; 137 if UpTo >= SectorCount then Upto := SectorCount - 1; 138 for I := From to UpTo do begin 139 140 if (Result = bsNone) and (Sectors[I] = bsOk) then Result := bsOk 141 else if (Result = bsOk) and (Sectors[I] = bsDamaged) then Result := bsDamaged; 259 Change := FindChange(StartIndex); 260 if Assigned(Change) then begin 261 ChangeIndex := FChanges.IndexOf(Change); 262 while (ChangeIndex < FChanges.Count) and 263 (TChange(FChanges[ChangeIndex]).Index <= EndIndex) do begin 264 if (Result = bsNone) and (TChange(FChanges[ChangeIndex]).Value = bsOk) then Result := bsOk 265 else if TChange(FChanges[ChangeIndex]).Value = bsDamaged then Result := bsDamaged; 266 Inc(ChangeIndex); 267 end; 142 268 end; 143 269 end; … … 161 287 Rect := Bounds((I mod ItemsCount.X) * BlockSize.X, 162 288 (I div ItemsCount.X) * BlockSize.Y, BlockSize.X - 1, BlockSize.Y - 1); 163 BlockState := FBlocks[I];289 BlockState := GetCombinedSectors(I * SectorPerBlock, (I + 1) * SectorPerBlock); 164 290 if BlockState = bsOk then Canvas.Brush.Color := clGreen 165 291 else if BlockState = bsDamaged then Canvas.Brush.Color := clRed … … 172 298 173 299 procedure TBlockMap.Clear; 174 var 175 I: Integer; 176 begin 177 for I := 0 to SectorCount - 1 do 178 FSectors[I] := bsNone; 300 begin 301 FChanges.Clear; 302 if FSectorCount > 0 then begin 303 FChanges.Add(TChange.Create); 304 TChange(FChanges[0]).Index := 0; 305 TChange(FChanges[0]).Value := bsNone; 306 end; 179 307 end; 180 308 181 309 constructor TBlockMap.Create; 182 310 begin 311 FChanges := TObjectList.Create; 183 312 FBlockSize := Point(12, 12); 184 313 SectorPerBlock := 1; 314 FSectorCount := 0; 315 end; 316 317 destructor TBlockMap.Destroy; 318 begin 319 FreeAndNil(FChanges); 320 inherited Destroy; 185 321 end; 186 322 -
trunk/UDriveScan.pas
r5 r6 54 54 implementation 55 55 56 resourcestring 57 SUnknownRunMode = 'Unknown run mode'; 58 56 59 57 60 { TScanThread } … … 82 85 procedure TDriveScan.Start; 83 86 begin 84 ScanThread := TScanThread.Create(True); 85 ScanThread.Scan := Self; 86 ScanThread.Start; 87 if Terminated then begin 88 Terminated := False; 89 ScanThread := TScanThread.Create(True); 90 ScanThread.Scan := Self; 91 ScanThread.Start; 92 end; 87 93 end; 88 94 … … 120 126 if Mode = rmRead then RealSize := F.Read(Buffer[0], SectorSize) 121 127 else if Mode = rmWrite then RealSize := F.Write(Buffer[0], SectorSize) 122 else raise Exception.Create( 'Unknwon run mode');128 else raise Exception.Create(SUnknownRunMode); 123 129 end; 124 130 finally … … 144 150 procedure TDriveScan.Stop; 145 151 begin 146 Terminated := True; 147 ScanThread.Terminate; 148 ScanThread.WaitFor; 149 FreeAndNil(ScanThread); 152 if not Terminated then begin 153 Terminated := True; 154 ScanThread.Terminate; 155 ScanThread.WaitFor; 156 FreeAndNil(ScanThread); 157 end; 150 158 end; 151 159 … … 160 168 destructor TDriveScan.Destroy; 161 169 begin 170 Stop; 162 171 FreeAndNil(BlockMap); 163 172 FreeAndNil(Lock); -
trunk/UFormMain.pas
r5 r6 120 120 DriveScan.Drive := EditDrive.Text; 121 121 DriveScan.SectorSize := Project.SectorSize; 122 DriveScan.Terminated := False;123 122 DriveScan.Mode := TRunMode(ComboBoxRunMode.ItemIndex); 124 123 DriveScan.WritePattern := StrToInt(EditPattern.Text); … … 145 144 procedure TFormMain.FormClose(Sender: TObject; var CloseAction: TCloseAction); 146 145 begin 147 DriveScan.Terminated := True;148 146 end; 149 147 150 148 procedure TFormMain.FormDestroy(Sender: TObject); 151 149 begin 150 Timer1.Enabled := False; 152 151 FreeAndNil(Project); 153 152 FreeAndNil(DriveScan); … … 208 207 procedure TFormMain.UpdateInterface; 209 208 begin 210 AScanStart.Enabled := DriveScan.Terminated = True; 211 AScanStop.Enabled := DriveScan.Terminated = False; 209 if Assigned(DriveScan) then begin 210 AScanStart.Enabled := DriveScan.Terminated = True; 211 AScanStop.Enabled := DriveScan.Terminated = False; 212 end; 212 213 end; 213 214
Note:
See TracChangeset
for help on using the changeset viewer.