unit Tool_BinEdit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Wrapgrid, StdCtrls, Grids, StrUtils, MPHexEditor, ExtCtrls, Clipbrd, Data, Code_Functions, Code_DataStructures, Code_Exporters, Code_OniDataClass, Menus, Math, VirtualTrees, VTHeaderPopup; type TForm_BinEdit = class(TForm) Splitter1: TSplitter; panel_data: TPanel; hex: TMPHexEditor; Splitter2: TSplitter; panel_files: TPanel; list: TListBox; panel_extension: TPanel; lbl_filter: TLabel; combo_extension: TComboBox; Bevel1: TBevel; panel_imexport: TPanel; btn_export: TButton; btn_import: TButton; opend: TOpenDialog; saved: TSaveDialog; value_viewer: TWrapGrid; Splitter3: TSplitter; value_viewer_context: TPopupMenu; value_viewer_context_copy: TMenuItem; value_viewer_context_copyashex: TMenuItem; value_viewer_context_copyasdec: TMenuItem; value_viewer_context_copyasfloat: TMenuItem; value_viewer_context_copyasbitset: TMenuItem; value_viewer_context_copyasstring: TMenuItem; check_zerobyte: TCheckBox; edit_filtername: TEdit; check_filtername: TCheckBox; VST: TVirtualStringTree; VTHPopup: TVTHeaderPopupMenu; procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure VSTDblClick(Sender: TObject); procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree; const Column: TColumnIndex; Visible: Boolean); procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex; OldPosition: Integer); procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure LoadDat(_fileid: LongWord); procedure LoadFileNames; procedure check_filternameClick(Sender: TObject); procedure check_zerobyteClick(Sender: TObject); procedure combo_extensionClick(Sender: TObject); procedure panel_extensionResize(Sender: TObject); procedure listClick(Sender: TObject); procedure Recreatelist; procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure value_viewerDblClick(Sender: TObject); procedure value_viewer_context_copyClick(Sender: TObject); procedure value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure value_viewer_contextPopup(Sender: TObject); procedure btn_importClick(Sender: TObject); procedure btn_exportClick(Sender: TObject); procedure panel_imexportResize(Sender: TObject); function Save: Boolean; procedure FormClose(Sender: TObject; var Action: TCloseAction); function GetValue(datatype: Word; offset: LongWord): String; procedure WriteStructureInfos; //(structinfoid:Integer); procedure hexSelectionChanged(Sender: TObject); procedure hexChange(Sender: TObject); procedure FormResize(Sender: TObject); procedure ClearStructViewer; procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure FormCreate(Sender: TObject); procedure ClearValues; procedure WriteValues; procedure SetNewValue(datatype: Word; offset: LongWord; Value: String); procedure listMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private fileid: LongWord; public end; var Form_BinEdit: TForm_BinEdit; implementation {$R *.dfm} uses Main, Helper_ValueEdit, Tool_Rawedit; type PNodeData = ^TNodeData; TNodeData = record Caption: String; Offset: LongInt; DataType: Word; Value: String; Description: String; end; function AddVSTEntry(AVST: TCustomVirtualStringTree; ANode: PVirtualNode; ARecord: TNodeData): PVirtualNode; var Data: PNodeData; begin Result := AVST.AddChild(ANode); Data := AVST.GetNodeData(Result); AVST.ValidateNode(Result, False); Data^ := ARecord; end; procedure TForm_BinEdit.LoadDat(_fileid: LongWord); var i: LongWord; mem: TMemoryStream; Data: Tdata; begin if hex.Modified then begin if not Save then begin for i := 0 to list.Count - 1 do begin if OniDataConnection.ExtractFileID(list.Items.Strings[i]) = fileid then begin list.ItemIndex := i; Exit; end; end; end; end; fileid := _fileid; for i := 0 to list.Count - 1 do if OniDataConnection.ExtractFileID(list.Items.Strings[i]) = fileid then begin list.ItemIndex := i; Break; end; Self.ClearStructViewer; Data := OniDataConnection.LoadDatFile(fileid); if Length(Data) > 0 then begin mem := TMemoryStream.Create; mem.Write(Data[0], Length(Data)); mem.Seek(0, soFromBeginning); hex.LoadFromStream(mem); mem.Free; WriteStructureInfos; end else begin ClearValues; hex.DataSize := 0; end; end; procedure TForm_BinEdit.Recreatelist; var i: LongWord; exts: TStringArray; begin combo_extension.Items.Clear; combo_extension.Items.Add('_All files_ (' + IntToStr( OniDataConnection.GetFilesCount) + ')'); exts := OniDataConnection.GetExtensionsList; for i := 0 to High(exts) do combo_extension.Items.Add(exts[i]); combo_extension.ItemIndex := 0; combo_extensionClick(Self); end; procedure TForm_BinEdit.LoadFileNames; var Extension: String[4]; no_zero_bytes: Boolean; pattern: String; files: TStringArray; i: LongWord; begin Extension := MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex], 1, 4); no_zero_bytes := not check_zerobyte.Checked; pattern := ''; if check_filtername.Checked then pattern := edit_filtername.Text; if Extension = '_All' then Extension := ''; files := OniDataConnection.GetFilesList(extension, pattern, no_zero_bytes); list.Items.Clear; if Length(files) > 0 then for i := 0 to High(files) do list.Items.Add(files[i]); end; procedure TForm_BinEdit.panel_extensionResize(Sender: TObject); begin combo_extension.Width := panel_extension.Width - 5; edit_filtername.Width := panel_extension.Width - 5; end; procedure TForm_BinEdit.combo_extensionClick(Sender: TObject); begin LoadFileNames; end; procedure TForm_BinEdit.check_zerobyteClick(Sender: TObject); begin LoadFileNames; end; procedure TForm_BinEdit.check_filternameClick(Sender: TObject); begin edit_filtername.Enabled := not check_filtername.Checked; LoadFileNames; end; procedure TForm_BinEdit.listClick(Sender: TObject); begin LoadDat(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex])); end; procedure TForm_BinEdit.listMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var pt: TPoint; begin pt.X := x; pt.Y := y; list.ItemIndex := list.ItemAtPos(pt, true); if list.ItemIndex > -1 then Self.listClick(Self); end; function IntToBin(Value: Byte): String; var i: Byte; begin Result := ''; for i := 7 downto 0 do begin Result := Result + IntToStr((Value shr i) and $01); end; end; function TForm_BinEdit.GetValue(datatype: Word; offset: LongWord): String; var Data: Tdata; i: Word; begin case datatype of 1: Result := IntToStr(hex.Data[offset]); 2: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256); 3: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256); 4: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256); 5: Result := '0x' + IntToHex(hex.Data[offset], 2); 6: Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256, 4); 7: Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256, 6); 8: Result := '0x' + IntToHex(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256, 8); 9: begin SetLength(Data, 4); Data[0] := hex.Data[offset]; Data[1] := hex.Data[offset + 1]; Data[2] := hex.Data[offset + 2]; Data[3] := hex.Data[offset + 3]; Result := FloatToStr(Decode_Float(Data)); end; 10: Result := IntToBin(hex.Data[offset]); 11: Result := '0x' + IntToHex(OniDataConnection.GetRawInfo(fileid, offset).raw_addr, 8); 12: Result := FormatNumber(hex.Data[offset + 1] + hex.Data[offset + 2] * 256 + hex.Data[offset + 3] * 256 * 256, 5, '0'); 13: Result := IntToStr(hex.Data[offset]); 14: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256); 15: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256); 16: Result := IntToStr(hex.Data[offset] + hex.Data[offset + 1] * 256 + hex.Data[offset + 2] * 256 * 256 + hex.Data[offset + 3] * 256 * 256 * 256); 17: Result := IntToStr((hex.Data[offset + 3]) div 2); 100..300: begin Result := ''; for i := 1 to datatype - 100 do begin if hex.Data[offset + i - 1] >= 32 then Result := Result + Chr(hex.Data[offset + i - 1]) else Break; end; end; 1000..9999: begin Result := ''; for i := 1 to datatype - 1000 do begin if hex.Data[offset + i - 1] >= 32 then Result := Result + Chr(hex.Data[offset + i - 1]) else Result := Result + '.'; end; end; 10000..65535: begin Result := ''; for i := 1 to datatype - 10000 do begin if hex.Data[offset + i - 1] >= 32 then Result := Result + Chr(hex.Data[offset + i - 1]) else Result := Result + '.'; end; end; end; end; procedure TForm_BinEdit.WriteStructureInfos; var i, j: LongWord; pdata: PNodeData; Data: TNodeData; node: PVirtualNode; structs: TStructDef; begin VST.BeginUpdate; if VST.RootNodeCount = 0 then begin structs := LoadStructureDefinition(fileid); if structs.Data then begin if Length(structs.Global) > 0 then begin for i := 0 to High(structs.Global) do begin Data.Caption := structs.Global[i].Name; Data.Offset := structs.Global[i].offset; Data.DataType := structs.Global[i].datatype; Data.Value := GetValue(structs.Global[i].datatype, structs.Global[i].offset); Data.Description := structs.Global[i].description; AddVSTEntry(VST, nil, Data); end; end; if Length(structs.Subs) > 0 then begin for i := 0 to High(structs.Subs) do begin with structs.Subs[i] do begin if Length(Entries) > 0 then begin if Pos('#', SubName) > 0 then begin Data.Offset := HexToLong(MidStr(SubName, Pos('#', SubName) + 1, 8)); Data.Value := MidStr(SubName, PosEx('#', SubName, Pos('#', SubName) + 1) + 1, 8); Data.Caption := MidStr(SubName, 1, Pos('#', SubName) - 1); Data.Description := SubDesc; end else begin Data.Caption := SubName; Data.Description := SubDesc; Data.Offset := 0; Data.Value := ''; end; Data.DataType := 0; node := AddVSTEntry(VST, nil, Data); Data.Description := ''; for j := 0 to High(Entries) do begin Data.Caption := Entries[j].Name; Data.Offset := Entries[j].offset; Data.DataType := Entries[j].datatype; Data.Value := GetValue(Entries[j].datatype, Entries[j].offset); Data.Description := Entries[j].description; AddVSTEntry(VST, node, Data); end; end; end; end; end; end; if VST.RootNodeCount > 0 then VST.FocusedNode := VST.GetFirst; end else begin Node := VST.GetFirst; while Assigned(Node) do begin pdata := VST.GetNodeData(Node); if pdata.DataType > 0 then pdata.Value := GetValue(pdata.Datatype, pdata.Offset); Node := VST.GetNext(Node); end; end; VST.EndUpdate; end; procedure TForm_BinEdit.ClearValues; var i: Byte; begin for i := 1 to value_viewer.RowCount - 1 do begin value_viewer.Cells[1, i] := ''; end; end; procedure TForm_BinEdit.WriteValues; var i, j: Byte; Data: Tdata; str: String; Value: LongWord; begin for i := 1 to value_viewer.RowCount - 1 do begin if value_viewer.Cells[0, i] = '1 byte, unsigned' then begin if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not ((hex.SelStart + 1) > hex.DataSize) then begin Value := hex.Data[hex.SelStart]; value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 2); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = '2 bytes, unsigned' then begin if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not ((hex.SelStart + 2) > hex.DataSize) then begin Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256; value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 4); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = '4 bytes, unsigned' then begin if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not ((hex.SelStart + 4) > hex.DataSize) then begin Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 + hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256; value_viewer.Cells[1, i] := IntToStr(Value) + ' / 0x' + IntToHex(Value, 8); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = 'Bitset' then begin if (hex.SelCount <= 8) then begin if hex.SelCount = 0 then begin SetLength(Data, 1); Data[0] := hex.Data[hex.SelStart]; end else begin SetLength(Data, hex.SelCount); for j := 0 to hex.SelCount - 1 do Data[j] := hex.Data[hex.SelStart + j]; end; value_viewer.Cells[1, i] := DataToBin(Data); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = 'Float' then begin if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not ((hex.SelStart + 4) > hex.DataSize) then begin SetLength(Data, 4); for j := 0 to 3 do Data[j] := hex.Data[hex.SelStart + j]; value_viewer.Cells[1, i] := FloatToStr(Decode_Float(Data)); end else value_viewer.Cells[1, i] := ''; end; if value_viewer.Cells[0, i] = 'Selected length' then begin value_viewer.Cells[1, i] := IntToStr(hex.SelCount) + ' bytes'; end; if value_viewer.Cells[0, i] = 'String' then begin j := 0; str := ''; if hex.SelCount = 0 then begin while (hex.Data[hex.SelStart + j] > 0) and ((hex.SelStart + j) < hex.DataSize) do begin if hex.Data[hex.selstart + j] >= 32 then str := str + Char(hex.Data[hex.SelStart + j]) else str := str + '.'; Inc(j); end; end else begin for j := 0 to hex.SelCount - 1 do if hex.Data[hex.selstart + j] >= 32 then str := str + Char(hex.Data[hex.SelStart + j]) else if hex.Data[hex.selstart + j] > 0 then str := str + '.' else Break; end; value_viewer.Cells[1, i] := str; end; end; end; procedure TForm_BinEdit.FormCreate(Sender: TObject); begin Self.Caption := ''; fileid := 0; VST.NodeDataSize := SizeOf(TNodeData); value_viewer.ColCount := 2; value_viewer.RowCount := 8; value_viewer.FixedRows := 1; value_viewer.Cells[0, 0] := 'Type'; value_viewer.Cells[1, 0] := 'Value'; value_viewer.Cells[0, 1] := '1 byte, unsigned'; value_viewer.Cells[0, 2] := '2 bytes, unsigned'; value_viewer.Cells[0, 3] := '4 bytes, unsigned'; value_viewer.Cells[0, 4] := 'Bitset'; value_viewer.Cells[0, 5] := 'Float'; value_viewer.Cells[0, 6] := 'String'; value_viewer.Cells[0, 7] := 'Selected length'; value_viewer.ColWidths[0] := 100; value_viewer.ColWidths[1] := value_viewer.Width - 150; hex.Height := panel_data.Height - 215; // value_viewer.Font.Charset := AppSettings.CharSet; VST.Font.Charset := AppSettings.CharSet; hex.Translation := tkAsIs; hex.Font.Charset := AppSettings.CharSet; // end; function TForm_BinEdit.Save: Boolean; var mem: TMemoryStream; Data: Tdata; i: LongWord; begin case MessageBox(Self.Handle, PChar('Save changes to file ' + OniDataConnection.GetFileInfo(fileid).FileName + '?'), PChar('Data changed...'), MB_YESNOCANCEL) of idYes: begin mem := TMemoryStream.Create; hex.SaveToStream(mem); mem.Seek(0, soFromBeginning); SetLength(Data, mem.Size); mem.Read(Data[0], mem.Size); mem.Free; OniDataConnection.UpdateDatFile(fileid, Data); hex.Modified := False; for i := 0 to hex.Datasize - 1 do hex.ByteChanged[i] := False; Result := True; end; idNo: Result := True; idCancel: begin Result := False; end; end; end; procedure TForm_BinEdit.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin if hex.Modified then begin if not Save then CanClose := False; end; end; procedure TForm_BinEdit.ClearStructViewer; begin VST.Clear; end; procedure TForm_BinEdit.FormResize(Sender: TObject); begin if Self.Width >= 650 then begin end else Self.Width := 650; if Self.Height >= 450 then begin end else Self.Height := 450; end; procedure TForm_BinEdit.hexChange(Sender: TObject); begin ClearValues; if hex.DataSize > 0 then begin WriteStructureInfos; WriteValues; end; end; procedure TForm_BinEdit.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); var temps: String; begin if (Shift = [ssCtrl]) and (Key = Ord('C')) then begin if hex.SelCount > 0 then begin if hex.InCharField then Clipboard.AsText := hex.SelectionAsText else Clipboard.AsText := hex.SelectionAsHex; end; end; if (Shift = [ssCtrl]) and (Key = Ord('V')) then begin { temps:=Clipboard.AsText; IF hex.SelStart+Length(temps)>hex.DataSize THEN SetLength(temps, hex.DataSize-hex.SelStart); hex.Sel hex.SelCount:=Length(temps); hex.ReplaceSelection(temps,Length(temps)); } end; end; procedure TForm_BinEdit.hexSelectionChanged(Sender: TObject); var selstart: Integer; node: PVirtualNode; pdata: PNodeData; begin if hex.DataSize > 0 then begin WriteValues; selstart := hex.SelStart; if VST.RootNodeCount > 0 then begin Node := VST.GetFirst; while Assigned(Node) do begin pdata := VST.GetNodeData(Node); if pdata.DataType > 0 then begin if ((selstart - pdata.Offset) < GetTypeDataLength(pdata.DataType)) and ((selstart - pdata.Offset) >= 0) then begin VST.FocusedNode := Node; VST.Selected[Node] := True; Break; end; end; Node := VST.GetNext(Node); end; end; end; end; procedure TForm_BinEdit.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; procedure TForm_BinEdit.panel_imexportResize(Sender: TObject); begin btn_import.Width := panel_imexport.Width - 8; btn_export.Width := panel_imexport.Width - 8; end; procedure TForm_BinEdit.btn_exportClick(Sender: TObject); begin saved.Filter := 'Files of matching extension (*.' + OniDataConnection.GetFileInfo( fileid).Extension + ')|*.' + OniDataConnection.GetFileInfo(fileid).Extension + '|All files|*.*'; saved.DefaultExt := OniDataConnection.GetFileInfo(fileid).Extension; if saved.Execute then begin ExportDatFile(fileid, saved.FileName); end; end; procedure TForm_BinEdit.btn_importClick(Sender: TObject); var fs: TFileStream; begin opend.Filter := 'Files of matching extension (*.' + OniDataConnection.GetFileInfo( fileid).Extension + ')|*.' + OniDataConnection.GetFileInfo(fileid).Extension + '|All files|*.*'; if opend.Execute then begin fs := TFileStream.Create(opend.FileName, fmOpenRead); if fs.Size <> hex.DataSize then begin ShowMessage('Can''t import ' + ExtractFilename(opend.FileName) + ', file has to have same size as file in .dat.' + CrLf + 'Size of file in .dat: ' + FormatFileSize(hex.datasize) + CrLf + 'Size of chosen file: ' + FormatFileSize(fs.Size)); end else begin hex.LoadFromStream(fs); hex.Modified := True; end; fs.Free; end; end; procedure TForm_BinEdit.value_viewer_contextPopup(Sender: TObject); var i: Byte; begin for i := 0 to value_viewer_context.Items.Count - 1 do value_viewer_context.Items.Items[i].Visible := False; with value_viewer do begin if (Col = 1) and (Row > 0) and (Length(Cells[Col, Row]) > 0) then begin if Pos(' byte', Cells[0, Row]) = 2 then begin value_viewer_context.Items.Find('Copy to &clipboard').Visible := True; value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible := True; value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible := True; end; if Pos('Float', Cells[0, Row]) = 1 then value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible := True; if Pos('Bitset', Cells[0, Row]) = 1 then value_viewer_context.Items.Find( 'Copy to clipboard (as &bitset)').Visible := True; if Pos('String', Cells[0, Row]) = 1 then value_viewer_context.Items.Find( 'Copy to clipboard (as &string)').Visible := True; if Pos('Selected length', Cells[0, Row]) = 1 then value_viewer_context.Items.Find('Copy to &clipboard').Visible := True; end; end; end; procedure TForm_BinEdit.value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var ACol, ARow: Integer; begin if Button = mbRight then begin value_viewer.MouseToCell(x, y, ACol, ARow); if ARow > 0 then begin value_viewer.Col := ACol; value_viewer.Row := ARow; end; end; end; procedure TForm_BinEdit.value_viewer_context_copyClick(Sender: TObject); var Name: String; Value: LongWord; begin Name := TMenuItem(Sender).Name; if Pos('asstring', Name) > 0 then begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end else if Pos('asfloat', Name) > 0 then begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end else if Pos('asbitset', Name) > 0 then begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end else if (Pos('ashex', Name) > 0) or (Pos('asdec', Name) > 0) then begin if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then begin if ((hex.SelCount = 1) or (hex.SelCount = 0)) and not ((hex.SelStart + 1) > hex.DataSize) then Value := hex.Data[hex.SelStart]; end; if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then begin if ((hex.SelCount = 2) or (hex.SelCount = 0)) and not ((hex.SelStart + 2) > hex.DataSize) then Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256; end; if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then begin if ((hex.SelCount = 4) or (hex.SelCount = 0)) and not ((hex.SelStart + 4) > hex.DataSize) then Value := hex.Data[hex.SelStart] + hex.Data[hex.SelStart + 1] * 256 + hex.Data[hex.SelStart + 2] * 256 * 256 + hex.Data[hex.SelStart + 3] * 256 * 256 * 256; end; if Pos('asdec', Name) > 0 then begin Clipboard.AsText := IntToStr(Value); end else begin if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then Clipboard.AsText := '0x' + IntToHex(Value, 2); if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then Clipboard.AsText := '0x' + IntToHex(Value, 4); if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then Clipboard.AsText := '0x' + IntToHex(Value, 8); end; end else begin Clipboard.AsText := value_viewer.Cells[value_viewer.Col, value_viewer.Row]; end; end; procedure TForm_BinEdit.VSTDblClick(Sender: TObject); var node: PVirtualNode; nodedata: PNodeData; id: Integer; begin if VST.FocusedColumn = 3 then begin node := VST.FocusedNode; nodedata := VST.GetNodeData(node); if not (nodedata.datatype in [11, 12]) and ((nodedata.DataType < 100) or (nodedata.DataType > 300)) then begin Form_ValueEdit.MakeVarInput(nodedata.Caption, nodedata.offset, nodedata.datatype, nodedata.Value, Self); end else begin if nodedata.DataType = 11 then begin if OniDataConnection.GetRawInfo(fileid, nodedata.offset).raw_size > 0 then begin if Form_Main.open_child('rawedit') then begin TForm_RawEdit(Form_Main.ActiveMDIChild).LoadRaw( OniDataConnection.GetRawInfo(fileid, nodedata.offset)); end; end; end; if nodedata.DataType = 12 then begin if (StrToInt(nodedata.Value) < OniDataConnection.GetFilesCount) and (StrToInt(nodedata.Value) > 0) and (StrToInt(nodedata.Value) <> fileid) then begin if OniDataConnection.GetFileInfo(StrToInt(nodedata.Value)).Size > 0 then begin if Form_Main.open_child('binedit') then begin TForm_BinEdit(Form_Main.ActiveMDIChild).LoadDat(StrToInt(nodedata.Value)); end; end else begin ShowMessage('Linked filed is a zero-byte-file'); end; end; end; if (nodedata.DataType >= 100) and (nodedata.DataType <= 300) then begin if Form_Main.open_child('binedit') then begin TForm_BinEdit(Form_Main.ActiveMDIChild).edit_filtername.Text := nodedata.Value; TForm_BinEdit(Form_Main.ActiveMDIChild).check_filtername.Checked := True; TForm_BinEdit(Form_Main.ActiveMDIChild).check_filternameClick(Self); end; end; end; end; end; procedure TForm_BinEdit.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); var Data: PNodeData; begin Data := VST.GetNodeData(node); if Data.DataType > 0 then begin hex.SelStart := Data.Offset; hex.SelEnd := Data.Offset + GetTypeDataLength(Data.DataType) - 1; end else begin hex.SelStart := Data.Offset; hex.SelEnd := Data.Offset + HexToLong(Data.Value) - 1; end; end; procedure TForm_BinEdit.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var Data: PNodeData; begin Data := Sender.GetNodeData(Node); CellText := ''; if TextType = ttNormal then begin case Column of 0: CellText := Data.Caption; 1: if Data.DataType > 0 then CellText := '0x' + IntToHex(Data.Offset, 8) else if Data.Offset > 0 then CellText := '0x' + IntToHex(Data.Offset, 8); 2: if Data.DataType > 0 then CellText := GetDataType(Data.DataType); 3: if Data.DataType > 0 then CellText := Data.Value //GetValue(data.DataType, data.Offset) else if Length(Data.Value) > 0 then CellText := IntToStr(HexToLong(Data.Value)) + ' Bytes'; 4: CellText := Data.Description; end; end; end; procedure TForm_BinEdit.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex; OldPosition: Integer); begin if Sender.Columns.Items[column].Position < 1 then Sender.Columns.Items[column].Position := OldPosition; end; procedure TForm_BinEdit.VTHPopupColumnChange(const Sender: TBaseVirtualTree; const Column: TColumnIndex; Visible: Boolean); begin if column = 0 then TVirtualStringTree(Sender).Header.Columns.Items[column].Options := TVirtualStringTree(Sender).Header.Columns.Items[column].Options + [coVisible]; end; procedure TForm_BinEdit.SetNewValue(datatype: Word; offset: LongWord; Value: String); var Data: Tdata; value_int: LongWord; value_float: Single; i: Word; begin case datatype of 1..4: begin value_int := StrToInt(Value); SetLength(Data, datatype); for i := 0 to datatype - 1 do begin Data[i] := value_int mod 256; value_int := value_int div 256; end; end; 5..8: begin value_int := StrToInt('$' + Value); SetLength(Data, datatype - 4); for i := 0 to datatype - 5 do begin Data[i] := value_int mod 256; value_int := value_int div 256; end; end; 9: begin value_float := StrToFloat(Value); Data := Encode_Float(value_float); end; 10: begin value_int := BinToInt(Value); SetLength(Data, 1); Data[0] := value_int; end; 10000..65535: begin SetLength(Data, datatype - 10000); for i := 1 to datatype - 10000 do begin if i <= Length(Value) then Data[i - 1] := Ord(Value[i]) else Data[i - 1] := 0; end; end; end; for i := 0 to High(Data) do begin if hex.Data[offset + i] <> Data[i] then hex.ByteChanged[offset + i] := True; hex.Data[offset + i] := Data[i]; end; hex.Modified := True; hexChange(Self); hex.Repaint; end; procedure TForm_BinEdit.value_viewerDblClick(Sender: TObject); var offset: LongWord; datatype: Word; objectname: String; Value: String; begin if (value_viewer.Col = 1) and (Length(value_viewer.Cells[1, value_viewer.Row]) > 0) then begin offset := hex.SelStart; if value_viewer.Cells[0, value_viewer.Row] = '1 byte, unsigned' then datatype := 1; if value_viewer.Cells[0, value_viewer.Row] = '2 bytes, unsigned' then datatype := 2; if value_viewer.Cells[0, value_viewer.Row] = '4 bytes, unsigned' then datatype := 4; if value_viewer.Cells[0, value_viewer.Row] = 'Bitset' then datatype := 10; if value_viewer.Cells[0, value_viewer.Row] = 'Float' then datatype := 9; if value_viewer.Cells[0, value_viewer.Row] = 'Selected length' then Exit; if value_viewer.Cells[0, value_viewer.Row] = 'String' then begin if hex.SelCount > 0 then datatype := 10000 + hex.SelCount else datatype := 10000 + Length(value_viewer.Cells[1, value_viewer.Row]); end; objectname := ''; Value := GetValue(datatype, offset); Form_ValueEdit.MakeVarInput(objectname, offset, datatype, Value, Self); end; end; procedure TForm_BinEdit.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin if (Shift = [ssCtrl]) and (Key = 83) then if hex.Modified then if not Save then Exit; end; end.