source: oup/releases/0.34a/Global/DatStructureLoader.pas@ 961

Last change on this file since 961 was 200, 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 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.