source: oup/current/Global/DatStructureLoader.pas @ 113

Last change on this file since 113 was 113, checked in by alloc, 15 years ago
File size: 8.7 KB
Line 
1unit DatStructureLoader;
2
3interface
4
5type
6  TStructureEntry = record
7    Name:     String;
8    offset:   Integer;
9    datatype: Word;
10      // 1..4  : Integer[1..4] dec
11      // 5..8  : Integer[1..4] hex
12      // 9     : float
13      // 10    : bitset
14      // 11    : raw-addr
15      // 12    : untyped-dat-file-ID-link
16      // 13..16: Signed Integer[1..4]
17      // 17    : level-ID
18      // 100..300: dat-file-name[0..200]
19      // 501..614: typed-dat-file-ID-link
20      // 1000..9999: Unused data[0-8999]
21      // 10000+: string[0+]
22    description: String;
23  end;
24
25  TStructDefSub = record
26    SubName: String;
27    SubDesc: String;
28    Entries: array of TStructureEntry;
29  end;
30
31  TStructDef = record
32    Data:   Boolean;
33    Global: array of TStructureEntry;
34    Subs:   array of TStructDefSub;
35  end;
36
37
38function LoadStructureDefinition(ConnectionID, FileID: Integer): TStructDef;
39function GetDataType(TypeID: Word): String;
40function GetDataTypeLength(DataType: Word): Word;
41
42implementation
43
44uses
45  SysUtils, Classes, Functions, ConnectionManager, TypeDefs, Forms, StrUtils, Data;
46
47type
48  TStringArray = array of String;
49
50function GetDataTypeLength(DataType: Word): Word;
51begin
52  case datatype of
53    1..4:
54      Result := datatype;
55    5..8:
56      Result := datatype - 4;
57    9:
58      Result := 4;
59    10:
60      Result := 1;
61    11:
62      Result := 4;
63    12:
64      Result := 4;
65    13..16:
66      Result := datatype - 12;
67    17:
68      Result := 4;
69    100..300:
70      Result := datatype - 100;
71    500..614:
72      Result := 4;
73    1000..9999:
74      Result := datatype - 1000;
75    10000..65535:
76      Result := datatype - 10000;
77  end;
78end;
79
80
81
82function GetDataType(typeid: Word): String;
83begin
84  case typeid of
85    1..4:
86      Result := 'Int' + IntToStr(typeid * 8);
87    5..8:
88      Result := 'Int' + IntToStr((typeid - 4) * 8);
89    9:
90      Result := 'Float';
91    10:
92      Result := 'BitSet';
93    11:
94      Result := 'Raw-Address';
95    12:
96      Result := '.dat-file-ID';
97    13..16:
98      Result := 'SignedInt' + IntToStr((typeid - 12) * 8);
99    17:
100      Result := 'LevelID';
101    100..300:
102      Result := '.dat-file-name(' + IntToStr(typeid - 100) + ')';
103    1000..9999:
104      Result := 'Unused(' + IntToStr(typeid - 1000) + ')';
105    10000..65535:
106      Result := 'String(' + IntToStr(typeid - 10000) + ')';
107  end;
108end;
109
110
111
112function Explode(_string: String; delimiter: Char): TStringArray;
113var
114  start, len: Word;
115begin
116  SetLength(Result, 0);
117  start := 1;
118  while PosEx(delimiter, _string, start) > 0 do
119  begin
120    SetLength(Result, Length(Result) + 1);
121    len := PosEx(delimiter, _string, start) - start;
122    Result[High(Result)] := MidStr(_string, start, len);
123    start := start + len + 1;
124  end;
125  SetLength(Result, Length(Result) + 1);
126  Result[High(Result)] := MidStr(_string, start, Length(_string) - start + 1);
127end;
128
129
130
131function LoadStructureDefinition(ConnectionID, FileID: Integer): TStructDef;
132var
133  current_type: Byte; //0: Global, 1: Undynamic, 2: Dynamic
134  current_base, current_package, current_package_size: Integer;
135  packages: Integer;
136  deffile: Text;
137  structentry: TStructureEntry;
138  fields: TStringArray;
139  filename: String;
140  ext:    String[4];
141  temps:  String;
142  Data:   TByteData;
143begin
144  SetLength(Result.Global, 0);
145  SetLength(Result.Subs, 0);
146  Result.Data := False;
147  ext      := ConManager.Connection[ConnectionID].GetFileInfo(fileid).Extension;
148  filename := ExtractFilePath(Application.ExeName) + '\StructDefs\' + ext + '.txt';
149  if FileExists(filename) then
150  begin
151    ConManager.Connection[ConnectionID].LoadDatFile(FileID, Data);
152    AssignFile(deffile, filename);
153    Reset(deffile);
154    current_type := 0;
155    Result.Data  := True;
156    if not EOF(deffile) then
157    begin
158      ReadLn(deffile, temps);
159      while not EOF(deffile) do
160      begin
161        ReadLn(deffile, temps);
162        if (Length(temps) > 0) and (temps[1] <> '#') then
163        begin
164          if temps[1] = '*' then
165          begin
166            fields := Explode(temps, #9);
167            case Length(fields) of
168              1..2:
169              begin
170                current_type := 1;
171                current_base := 0;
172                SetLength(Result.Subs, Length(Result.Subs) + 1);
173                Result.Subs[High(Result.Subs)].SubName :=
174                  MidStr(fields[0], 2, Length(fields[0]) - 1);
175                if Length(fields) = 2 then
176                  Result.Subs[High(Result.Subs)].SubDesc := fields[1];
177              end;
178              3:
179              begin
180                current_type := 1;
181                current_base := StrToInt(fields[2]);
182                SetLength(Result.Subs, Length(Result.Subs) + 1);
183                Result.Subs[High(Result.Subs)].SubName :=
184                  MidStr(fields[0], 2, Length(fields[0]) - 1);
185                Result.Subs[High(Result.Subs)].SubDesc := fields[1];
186              end;
187              6:
188              begin
189                current_type    := 2;
190                current_base    := StrToInt(fields[2]);
191                current_package := 0;
192                current_package_size := StrToInt(fields[5]);
193                if fields[4][1] <> '$' then
194                begin
195                  case StrToInt(fields[4]) of
196                    1:
197                      packages := Data[StrToInt(fields[3])];
198                    2:
199                      packages := Data[StrToInt(fields[3])] + Data[StrToInt(fields[3]) + 1] * 256;
200                    4:
201                      packages := Data[StrToInt(fields[3])] + Data[StrToInt(fields[3]) + 1] *
202                        256 + Data[StrToInt(fields[3]) + 2] * 256 * 256 + Data[StrToInt(fields[3]) + 3] * 256 * 256 * 256;
203                  end;
204                end
205                else
206                begin
207                  packages := StrToInt(fields[4]);
208                end;
209                SetLength(Result.Subs, Length(Result.Subs) + packages);
210                for current_package := 0 to packages - 1 do
211                begin
212                  Result.Subs[High(Result.Subs) - packages +
213                    current_package + 1].SubName :=
214                    MidStr(fields[0], 2, Length(fields[0]) - 1) +
215                    '[' + IntToStr(current_package) + ']' + '#' +
216                    IntToHex(current_base + current_package * current_package_size, 8) +
217                    '#' + IntToHex(current_package_size, 8);
218                  Result.Subs[High(Result.Subs) - packages +
219                    current_package + 1].SubDesc :=
220                    fields[1];
221                end;
222              end;
223            end;
224          end
225          else
226          begin
227            fields := Explode(temps, #9);
228            if (Length(fields) = 3) or (Length(fields) = 4) then
229            begin
230              if not AppSettings.HideUnusedData or
231                ((StrToInt(fields[2]) < 1000) or (StrToInt(fields[2]) > 9999)) then
232              begin
233                structentry.Name     := fields[0];
234                structentry.datatype := StrToInt(fields[2]);
235                if Length(fields) = 4 then
236                  structentry.description := fields[3]
237                else
238                  structentry.description := '';
239                if current_type in [0, 1] then
240                begin
241                  structentry.offset := StrToInt(fields[1]) + current_base;
242                  if Length(Result.Subs) = 0 then
243                  begin
244                    SetLength(Result.Global, Length(Result.Global) + 1);
245                    Result.Global[High(Result.Global)] := structentry;
246                  end
247                  else
248                  begin
249                    SetLength(Result.Subs[High(Result.Subs)].Entries,
250                      Length(Result.Subs[High(Result.Subs)].Entries) + 1);
251                    Result.Subs[High(Result.Subs)].Entries[High(
252                      Result.Subs[High(Result.Subs)].Entries)] := structentry;
253                  end;
254                end
255                else
256                begin
257                  for current_package := 0 to packages - 1 do
258                  begin
259                    structentry.offset :=
260                      current_base + current_package * current_package_size + StrToInt(fields[1]);
261                    with Result.Subs[High(Result.Subs) - packages + current_package + 1] do
262                    begin
263                      SetLength(Entries, Length(Entries) + 1);
264                      Entries[High(Entries)] := structentry;
265                    end;
266                  end;
267                end;
268              end;
269            end;
270          end;
271        end;
272      end;
273    end;
274    CloseFile(deffile);
275  end;
276end;
277
278
279end.
Note: See TracBrowser for help on using the repository browser.