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

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