unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, VirtualTrees, StrUtils, ExtCtrls; type TForm1 = class(TForm) vst: TVirtualStringTree; list: TListBox; Splitter1: TSplitter; procedure FormCreate(Sender: TObject); procedure listClick(Sender: TObject); procedure vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); private public end; TSwapList = class; TSwapItem = class name: String; size: Integer; parent: TSwapList; end; TSwapList = class(TSwapItem) childs: array of TSwapItem; count: Integer; constructor Create; function AddElem(name: String; size: Integer): Integer; function AddArray(name: String; count: Integer): Integer; function CloseArray: TSwapList; function Child(index: Integer): TSwapItem; end; TType = record name: String; SwapList: TSwapList; end; TTypes = array of TType; PNodeData = ^TNodeData; TNodeData = record TypeName: String; Address: Integer; Size: Integer; end; var Form1: TForm1; Types: TTypes; descfile: Text; implementation {$R *.dfm} 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 TForm1.FormCreate(Sender: TObject); var state: Integer; line, datas: String; i: Integer; current_list: TSwapList; begin VST.NodeDataSize := SizeOf(TNodeData); state := 0; current_list := nil; AssignFile(descfile, ExtractFilePath(Application.ExeName)+'\templates.txt.gz'); Reset(descfile); while not EoF(descfile) do begin ReadLn(descfile, line); if state = 0 then begin if Pos('gSwapCodes_', line) = 1 then begin SetLength(Types, Length(Types) + 1); Types[High(Types)].name := MidStr(line, Pos('_', line)+1, 4); Types[High(Types)].SwapList := TSwapList.Create; Types[High(Types)].SwapList.parent := nil; current_list := Types[High(Types)].SwapList; state := 1; datas := MidStr(line, Pos('db ', line) + 3, PosEx(' ', line, Pos('db ', line) + 3) - Pos('db ', line) - 3 ); if datas = 'SWAPC_8BYTE' then current_list.AddElem('SWAPC_8BYTE', 8) else if datas = 'SWAPC_4BYTE' then current_list.AddElem('SWAPC_4BYTE', 4) else if datas = 'SWAPC_2BYTE' then current_list.AddElem('SWAPC_2BYTE', 2) else if datas = 'SWAPC_1BYTE' then current_list.AddElem('SWAPC_1BYTE', 1); end; if Pos('gTemplate_', line) = 1 then begin datas := MidStr(line, Pos('_', line)+1, 4); for i := 0 to High(Types) do if Types[i].name = datas then Break; if i < Length(Types) then begin if Pos('"', line) = 0 then ReadLn(descfile, line); datas := MidStr(line, Pos('"', line) + 1, PosEx('"', line, Pos('"', line) + 1) - (Pos('"', line) + 1) ); Types[i].name := Types[i].name + ' - ' + datas; end; end; end else begin if PosEx(' ', line, Pos(' d', line) + 4) > 0 then datas := MidStr(line, Pos(' d', line) + 4, PosEx(' ', line, Pos(' d', line) + 4) - (Pos(' d', line) + 4) ) else datas := MidStr(line, Pos(' d', line) + 4, Length(line) - Pos(' d', line) ); if datas = 'SWAPC_8BYTE' then current_list.AddElem('SWAPC_8BYTE', 8) else if datas = 'SWAPC_4BYTE' then current_list.AddElem('SWAPC_4BYTE', 4) else if datas = 'SWAPC_2BYTE' then current_list.AddElem('SWAPC_2BYTE', 2) else if datas = 'SWAPC_1BYTE' then current_list.AddElem('SWAPC_1BYTE', 1) else if datas = 'SWAPC_FIXARR_S' then begin ReadLn(descfile, line); if Pos('h', line) > 0 then datas := MidStr(line, Pos('db ', line) + 3, Pos('h', line) - (Pos('db ', line) + 3) ) else datas := MidStr(line, Pos('db ', line) + 3, Length(Line) - (Pos('db ', line) + 2) ); i := current_list.AddArray('SWAPC_FIXARR_S', StrToInt('$'+datas)); current_list := TSwapList(current_list.Child(i)); Inc(State); end else if datas = 'SWAPC_FIXARR_E' then begin Dec(State); current_list := current_list.CloseArray; end else if datas = 'SWAPC_VARARR_S' then begin ReadLn(descfile, line); datas := MidStr(line, Pos(' d', line) + 4, Length(line) - (Pos(' d', line) + 3)); if datas = 'SWAPC_8BYTE' then i := current_list.AddArray('SWAPC_VARARR_S', 8) else if datas = 'SWAPC_4BYTE' then i := current_list.AddArray('SWAPC_VARARR_S', 4) else if datas = 'SWAPC_2BYTE' then i := current_list.AddArray('SWAPC_VARARR_S', 2) else if datas = 'SWAPC_1BYTE' then i := current_list.AddArray('SWAPC_VARARR_S', 1); current_list := TSwapList(current_list.Child(i)); end else if datas = 'SWAPC_VARARR_E' then begin Dec(State); current_list := current_list.CloseArray; end else if datas = 'SWAPC_TMPL_PTR' then begin ReadLn(descfile, line); datas := MidStr(line, Pos('dd ', line) + 4, 4); current_list.AddElem('SWAPC_TMPL_PTR: ' + datas, 4); end; end; end; CloseFile(descfile); list.Items.Clear; for i := 0 to High(Types) do list.Items.Add(Types[i].name); end; { TSwapList } function TSwapList.AddArray(name: String; count: Integer): Integer; begin SetLength(childs, Length(childs) + 1); Result := High(childs); childs[Result] := TSwapList.Create; childs[Result].name := name; childs[Result].size := 0; childs[Result].parent := Self; TSwapList(childs[Result]).count := count; end; function TSwapList.AddElem(name: String; size: Integer): Integer; begin SetLength(childs, Length(childs) + 1); Result := High(childs); childs[Result] := TSwapItem.Create; childs[Result].name := name; childs[Result].size := size; childs[Result].parent := Self; Self.size := Self.size + size; end; function TSwapList.Child(index: Integer): TSwapItem; begin Result := childs[index]; end; function TSwapList.CloseArray: TSwapList; begin if Self.name = 'SWAPC_FIXARR_S' then begin Self.size := Self.size * Self.count; Self.parent.size := Self.parent.size + Self.size; end else Self.size := Self.count; Result := Self.parent; end; constructor TSwapList.Create; begin SetLength(childs, 0); count := -1; end; procedure TForm1.listClick(Sender: TObject); var i: LongWord; Data: TNodeData; node: PVirtualNode; name: String; procedure AddChilds(parent: PVirtualNode; SwapList: TSwapList; address: Integer); var i: Integer; begin if Length(SwapList.childs) > 0 then begin for i := 0 to High(SwapList.childs) do begin data.TypeName := SwapList.Child(i).name; data.Size := SwapList.Child(i).size; data.Address := address; address := address + data.Size; node := AddVSTEntry(VST, parent, data); if SwapList.Child(i) is TSwapList then AddChilds(node, TSwapList(SwapList.Child(i)), address); end; end; end; begin VST.Clear; VST.BeginUpdate; name := list.Items.Strings[list.ItemIndex]; for i := 0 to High(Types) do if Types[i].name = name then Break; if i < Length(Types) then begin AddChilds(nil, Types[i].SwapList, 0); end; VST.EndUpdate; end; procedure TForm1.vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var data: PNodeData; begin data := vst.GetNodeData(node); if TextType = ttNormal then begin case Column of 0: CellText := data.TypeName; 1: CellText := '0x' + IntToHex(data.Address, 8); 2: CellText := IntToStr(data.Size); end; end; end; end.