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

Last change on this file since 653 was 204, checked in by alloc, 18 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 else
78 Result := 0;
79 end;
80end;
81
82
83
84function GetDataType(typeid: Word): String;
85begin
86 case typeid of
87 1..4:
88 Result := 'Int' + IntToStr(typeid * 8);
89 5..8:
90 Result := 'Int' + IntToStr((typeid - 4) * 8);
91 9:
92 Result := 'Float';
93 10:
94 Result := 'BitSet';
95 11:
96 Result := 'Raw-Address';
97 12:
98 Result := '.dat-file-ID';
99 13..16:
100 Result := 'SignedInt' + IntToStr((typeid - 12) * 8);
101 17:
102 Result := 'LevelID';
103 100..300:
104 Result := '.dat-file-name(' + IntToStr(typeid - 100) + ')';
105 1000..9999:
106 Result := 'Unused(' + IntToStr(typeid - 1000) + ')';
107 10000..65535:
108 Result := 'String(' + IntToStr(typeid - 10000) + ')';
109 end;
110end;
111
112
113
114function Explode(_string: String; delimiter: Char): TStringArray;
115var
116 start, len: Word;
117begin
118 SetLength(Result, 0);
119 start := 1;
120 while PosEx(delimiter, _string, start) > 0 do
121 begin
122 SetLength(Result, Length(Result) + 1);
123 len := PosEx(delimiter, _string, start) - start;
124 Result[High(Result)] := MidStr(_string, start, len);
125 start := start + len + 1;
126 end;
127 SetLength(Result, Length(Result) + 1);
128 Result[High(Result)] := MidStr(_string, start, Length(_string) - start + 1);
129end;
130
131
132
133function LoadStructureDefinition(ConnectionID, FileID: Integer): TStructDef;
134var
135 current_type: Byte; //0: Global, 1: Undynamic, 2: Dynamic
136 current_base, current_package, current_package_size: Integer;
137 packages: Integer;
138 deffile: Text;
139 structentry: TStructureEntry;
140 fields: TStringArray;
141 filename: String;
142 ext: String[4];
143 temps: String;
144 Data: TByteData;
145begin
146 SetLength(Result.Global, 0);
147 SetLength(Result.Subs, 0);
148 Result.Data := False;
149 ext := ConManager.Connection[ConnectionID].GetFileInfo(fileid).Extension;
150 filename := ExtractFilePath(Application.ExeName) + '\StructDefs\' + ext + '.txt';
151 if FileExists(filename) then
152 begin
153 ConManager.Connection[ConnectionID].LoadDatFile(FileID, Data);
154 AssignFile(deffile, filename);
155 Reset(deffile);
156 current_type := 0;
157 Result.Data := True;
158 if not EOF(deffile) then
159 begin
160 ReadLn(deffile, temps);
161 while not EOF(deffile) do
162 begin
163 ReadLn(deffile, temps);
164 if (Length(temps) > 0) and (temps[1] <> '#') then
165 begin
166 if temps[1] = '*' then
167 begin
168 fields := Explode(temps, #9);
169 case Length(fields) of
170 1..2:
171 begin
172 current_type := 1;
173 current_base := 0;
174 SetLength(Result.Subs, Length(Result.Subs) + 1);
175 Result.Subs[High(Result.Subs)].SubName :=
176 MidStr(fields[0], 2, Length(fields[0]) - 1);
177 if Length(fields) = 2 then
178 Result.Subs[High(Result.Subs)].SubDesc := fields[1];
179 end;
180 3:
181 begin
182 current_type := 1;
183 current_base := StrToInt(fields[2]);
184 SetLength(Result.Subs, Length(Result.Subs) + 1);
185 Result.Subs[High(Result.Subs)].SubName :=
186 MidStr(fields[0], 2, Length(fields[0]) - 1);
187 Result.Subs[High(Result.Subs)].SubDesc := fields[1];
188 end;
189 6:
190 begin
191 current_type := 2;
192 current_base := StrToInt(fields[2]);
193 current_package := 0;
194 current_package_size := StrToInt(fields[5]);
195 if fields[4][1] <> '$' then
196 begin
197 case StrToInt(fields[4]) of
198 1:
199 packages := Data[StrToInt(fields[3])];
200 2:
201 packages := Data[StrToInt(fields[3])] + Data[StrToInt(fields[3]) + 1] * 256;
202 4:
203 packages := Data[StrToInt(fields[3])] + Data[StrToInt(fields[3]) + 1] *
204 256 + Data[StrToInt(fields[3]) + 2] * 256 * 256 + Data[StrToInt(fields[3]) + 3] * 256 * 256 * 256;
205 end;
206 end
207 else
208 begin
209 packages := StrToInt(fields[4]);
210 end;
211 SetLength(Result.Subs, Length(Result.Subs) + packages);
212 for current_package := 0 to packages - 1 do
213 begin
214 Result.Subs[High(Result.Subs) - packages +
215 current_package + 1].SubName :=
216 MidStr(fields[0], 2, Length(fields[0]) - 1) +
217 '[' + IntToStr(current_package) + ']' + '#' +
218 IntToHex(current_base + current_package * current_package_size, 8) +
219 '#' + IntToHex(current_package_size, 8);
220 Result.Subs[High(Result.Subs) - packages +
221 current_package + 1].SubDesc :=
222 fields[1];
223 end;
224 end;
225 end;
226 end
227 else
228 begin
229 fields := Explode(temps, #9);
230 if (Length(fields) = 3) or (Length(fields) = 4) then
231 begin
232 if not AppSettings.HideUnusedData or
233 ((StrToInt(fields[2]) < 1000) or (StrToInt(fields[2]) > 9999)) then
234 begin
235 structentry.Name := fields[0];
236 structentry.datatype := StrToInt(fields[2]);
237 if Length(fields) = 4 then
238 structentry.description := fields[3]
239 else
240 structentry.description := '';
241 if current_type in [0, 1] then
242 begin
243 structentry.offset := StrToInt(fields[1]) + current_base;
244 if Length(Result.Subs) = 0 then
245 begin
246 SetLength(Result.Global, Length(Result.Global) + 1);
247 Result.Global[High(Result.Global)] := structentry;
248 end
249 else
250 begin
251 SetLength(Result.Subs[High(Result.Subs)].Entries,
252 Length(Result.Subs[High(Result.Subs)].Entries) + 1);
253 Result.Subs[High(Result.Subs)].Entries[High(
254 Result.Subs[High(Result.Subs)].Entries)] := structentry;
255 end;
256 end
257 else
258 begin
259 for current_package := 0 to packages - 1 do
260 begin
261 structentry.offset :=
262 current_base + current_package * current_package_size + StrToInt(fields[1]);
263 with Result.Subs[High(Result.Subs) - packages + current_package + 1] do
264 begin
265 SetLength(Entries, Length(Entries) + 1);
266 Entries[High(Entries)] := structentry;
267 end;
268 end;
269 end;
270 end;
271 end;
272 end;
273 end;
274 end;
275 end;
276 CloseFile(deffile);
277 end;
278end;
279
280
281end.
Note: See TracBrowser for help on using the repository browser.