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

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