source: oup/_old_/Code/DataStructures.pas@ 165

Last change on this file since 165 was 92, checked in by alloc, 18 years ago

Rev86 was first after multi-cons

File size: 17.4 KB
Line 
1unit DataStructures;
2
3interface
4
5uses SysUtils, Classes, Data, Dialogs, StrUtils, OniDataClass;
6
7type
8 Tstructure_entry = record
9 Name: String;
10 offset: LongWord;
11 datatype: Word; // 1..4 : Integer[1..4] dec
12 // 5..8 : Integer[1..4] hex
13 // 9 : float
14 // 10 : bitset
15 // 11 : raw-addr
16 // 12 : dat-file-ID
17 // 13..16: Signed Integer[1..4]
18 // 17 : level-ID
19 // 100..300: dat-file-name[0..200]
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 TStructure_entry;
29 end;
30
31 TStructDef = record
32 Data: Boolean;
33 Global: array of TStructure_entry;
34 Subs: array of TStructDefSub;
35 end;
36 THandler = function(connection: TOniData; fileid: LongWord): TRawList;
37
38 TRawListHandlers = record
39 Ext: String[4];
40 needed: Boolean;
41 Handler: THandler;
42 end;
43
44var
45 RawListHandlers: array of TRawListHandlers;
46 Raws: String;
47
48
49function LoadStructureDefinition(connection: TOniData; fileid: LongWord): TStructDef;
50function GetDataType(typeid: Word): String;
51function GetTypeDataLength(datatype: Word): Word;
52
53implementation
54
55uses Functions, Forms, Template;
56
57
58
59
60function GetTypeDataLength(datatype: Word): Word;
61begin
62 case datatype of
63 1..4:
64 Result := datatype;
65 5..8:
66 Result := datatype - 4;
67 9:
68 Result := 4;
69 10:
70 Result := 1;
71 11:
72 Result := 4;
73 12:
74 Result := 4;
75 13..16:
76 Result := datatype - 12;
77 17:
78 Result := 4;
79 100..300:
80 Result := datatype - 100;
81 1000..9999:
82 Result := datatype - 1000;
83 10000..65535:
84 Result := datatype - 10000;
85 end;
86end;
87
88
89
90
91function GetDataType(typeid: Word): String;
92begin
93 case typeid of
94 1..4:
95 Result := 'Int' + IntToStr(typeid * 8);
96 5..8:
97 Result := 'Int' + IntToStr((typeid - 4) * 8);
98 9:
99 Result := 'Float';
100 10:
101 Result := 'BitSet';
102 11:
103 Result := 'Raw-Address';
104 12:
105 Result := '.dat-file-ID';
106 13..16:
107 Result := 'SignedInt' + IntToStr((typeid - 12) * 8);
108 17:
109 Result := 'LevelID';
110 100..300:
111 Result := '.dat-file-name(' + IntToStr(typeid - 100) + ')';
112 1000..9999:
113 Result := 'Unused(' + IntToStr(typeid - 1000) + ')';
114 10000..65535:
115 Result := 'String(' + IntToStr(typeid - 10000) + ')';
116 end;
117end;
118
119
120
121
122function AGDB(connection: TOniData; fileid: LongWord): TRawList;
123var
124 link: LongWord;
125 links: LongWord;
126 i: LongWord;
127begin
128 if not connection.OSisMac then
129 begin
130 connection.LoadDatFilePart(fileid, $1C, 4, @links);
131 links := links * 2;
132 SetLength(Result, links);
133 for i := 0 to links - 1 do
134 begin
135 Result[i].src_offset := $20 + i * 4;
136 connection.LoadDatFilePart(fileid, $20 + i * 4, 4, @link);
137 Result[i].raw_addr := link;
138 Result[i].raw_size := 32;
139 Result[i].loc_sep := False;
140 end;
141 end;
142end;
143
144
145
146
147function AKVA(connection: TOniData; fileid: LongWord): TRawList;
148var
149 link: LongWord;
150 links: LongWord;
151 i: LongWord;
152begin
153 if not connection.OSisMac then
154 begin
155 connection.LoadDatFilePart(fileid, $1C, 4, @links);
156 SetLength(Result, links);
157 for i := 0 to links - 1 do
158 begin
159 Result[i].src_offset := $20 + i * $74 + $24;
160 connection.LoadDatFilePart(fileid, $20 + i * $74 + $24, 4, @link);
161 Result[i].raw_addr := link;
162 connection.LoadDatFilePart(fileid, $20 + i * $74 + $28, 4, @link);
163 Result[i].raw_size := link;
164 Result[i].loc_sep := False;
165 end;
166 end;
167end;
168
169
170
171
172function BINA(connection: TOniData; fileid: LongWord): TRawList;
173var
174 link: LongWord;
175 datasize: LongWord;
176begin
177 connection.LoadDatFilePart(fileid, $0C, 4, @link);
178 connection.LoadDatFilePart(fileid, $08, 4, @datasize);
179 SetLength(Result, 1);
180 Result[0].src_offset := $0C;
181 Result[0].raw_addr := link;
182 Result[0].raw_size := datasize;
183 Result[0].loc_sep := connection.OSisMac;
184end;
185
186
187
188
189function OSBD(connection: TOniData; fileid: LongWord): TRawList;
190var
191 link: LongWord;
192 datasize: LongWord;
193begin
194 connection.LoadDatFilePart(fileid, $08, 4, @datasize);
195 connection.LoadDatFilePart(fileid, $0C, 4, @link);
196 SetLength(Result, 1);
197 Result[0].src_offset := $0C;
198 Result[0].raw_addr := link;
199 Result[0].raw_size := datasize;
200 Result[0].loc_sep := connection.OSisMac;
201end;
202
203
204
205
206function SNDD(connection: TOniData; fileid: LongWord): TRawList;
207var
208 link: LongWord;
209 datasize: LongWord;
210begin
211 SetLength(Result, 1);
212 if not connection.OSisMac then
213 begin
214 connection.LoadDatFilePart(fileid, $40, 4, @datasize);
215 connection.LoadDatFilePart(fileid, $44, 4, @link);
216 Result[0].src_offset := $44;
217 end
218 else
219 begin
220 connection.LoadDatFilePart(fileid, $10, 4, @datasize);
221 connection.LoadDatFilePart(fileid, $14, 4, @link);
222 Result[0].src_offset := $14;
223 end;
224 Result[0].raw_addr := link;
225 Result[0].raw_size := datasize;
226 Result[0].loc_sep := False;
227end;
228
229
230
231
232function SUBT(connection: TOniData; fileid: LongWord): TRawList;
233var
234 baselink, lastlink: LongWord;
235 links: LongWord;
236 j, k: LongWord;
237 Data: Tdata;
238begin
239 connection.LoadDatFilePart(fileid, $18, 4, @baselink);
240 connection.LoadDatFilePart(fileid, $1C, 4, @links);
241 if links > 0 then
242 begin
243 connection.LoadDatFilePart(fileid, $20 + (links - 1) * 4, 4, @lastlink);
244 SetLength(Data, lastlink + 1024);
245 TOniDataDat(connection).LoadRawOffset(False,
246 baselink, lastlink + 1024, Data);
247 // connection.LoadRawFile(fileid,$1C,baselink,lastlink+1024,False,@data[0]);
248 k := 0;
249 for j := 0 to 1024 do
250 begin
251 if (Data[lastlink + j] = $00) or (j = 1024) then
252 begin
253 if j < 1024 then
254 begin
255 if k = 0 then
256 begin
257 k := 1;
258 end
259 else
260 begin
261 SetLength(Result, 1);
262 Result[0].src_offset := $18;
263 Result[0].raw_addr := baselink;
264 Result[0].raw_size := lastlink + j;
265 Break;
266 end;
267 end;
268 end;
269 end;
270 end;
271end;
272
273
274
275
276function TRAM(connection: TOniData; fileid: LongWord): TRawList;
277var
278 i: Integer;
279 link: LongWord;
280 frames: Word;
281 tempb: Byte;
282 tempw: Word;
283 templ: LongWord;
284 Data: Tdata;
285 offset: Word;
286 frame_count: Byte;
287begin
288 SetLength(Result, 13);
289 connection.LoadDatFilePart(fileid, $16C, 2, @frames);
290 {y-pos}
291 connection.LoadDatFilePart(fileid, $0C, 4, @link);
292 Result[0].src_offset := $0C;
293 Result[0].raw_addr := link;
294 Result[0].raw_size := frames * 4;
295 {x-z-pos}
296 connection.LoadDatFilePart(fileid, $10, 4, @link);
297 Result[1].src_offset := $10;
298 Result[1].raw_addr := link;
299 Result[1].raw_size := frames * 8;
300 {attacks}
301 connection.LoadDatFilePart(fileid, $182, 1, @tempb);
302 connection.LoadDatFilePart(fileid, $14, 4, @link);
303 Result[2].src_offset := $14;
304 Result[2].raw_addr := link;
305 Result[2].raw_size := tempb * 32;
306 {damage}
307 connection.LoadDatFilePart(fileid, $183, 1, @tempb);
308 connection.LoadDatFilePart(fileid, $18, 4, @link);
309 Result[3].src_offset := $18;
310 Result[3].raw_addr := link;
311 Result[3].raw_size := tempb * 8;
312 {motionblur}
313 connection.LoadDatFilePart(fileid, $184, 1, @tempb);
314 connection.LoadDatFilePart(fileid, $1C, 4, @link);
315 Result[4].src_offset := $1C;
316 Result[4].raw_addr := link;
317 Result[4].raw_size := tempb * 8;
318 {shortcut}
319 connection.LoadDatFilePart(fileid, $185, 1, @tempb);
320 connection.LoadDatFilePart(fileid, $20, 4, @link);
321 Result[5].src_offset := $20;
322 Result[5].raw_addr := link;
323 Result[5].raw_size := tempb * 8;
324 {throw}
325 connection.LoadDatFilePart(fileid, $24, 4, @link);
326 Result[6].src_offset := $24;
327 Result[6].raw_addr := link;
328 if link > 0 then
329 Result[6].raw_size := 24
330 else
331 Result[6].raw_size := 0;
332 {footstep}
333 connection.LoadDatFilePart(fileid, $186, 1, @tempb);
334 connection.LoadDatFilePart(fileid, $28, 4, @link);
335 Result[7].src_offset := $28;
336 Result[7].raw_addr := link;
337 Result[7].raw_size := tempb * 4;
338 {particle}
339 connection.LoadDatFilePart(fileid, $187, 1, @tempb);
340 connection.LoadDatFilePart(fileid, $2C, 4, @link);
341 Result[8].src_offset := $2C;
342 Result[8].raw_addr := link;
343 Result[8].raw_size := tempb * 24;
344 {position}
345 connection.LoadDatFilePart(fileid, $30, 4, @link);
346 Result[9].src_offset := $30;
347 Result[9].raw_addr := link;
348 Result[9].raw_size := frames * 8;
349 {particle}
350 connection.LoadDatFilePart(fileid, $154, 2, @tempw);
351 connection.LoadDatFilePart(fileid, $38, 4, @link);
352 Result[11].src_offset := $38;
353 Result[11].raw_addr := link;
354 Result[11].raw_size := tempw * 34;
355 {extent}
356 connection.LoadDatFilePart(fileid, $138, 4, @templ);
357 connection.LoadDatFilePart(fileid, $13C, 4, @link);
358 Result[12].src_offset := $13C;
359 Result[12].raw_addr := link;
360 Result[12].raw_size := templ * 12;
361
362 connection.LoadDatFilePart(fileid, $34, 4, @link);
363 if link > 0 then
364 begin
365 connection.LoadDatFilePart(fileid, $160, 2, @tempw);
366 frame_count := 0;
367 i := 0;
368 SetLength(Data, $FFFF);
369 TOniDataDat(connection).LoadRawOffset(False, link, $FFFF, Data);
370 offset := Data[$24] + Data[$25] * 256;
371 while (offset + i < Length(Data)) and (frame_count < frames - 1) do
372 begin
373 Inc(i, tempw);
374 frame_count := frame_count + Data[offset + i];
375 Inc(i);
376 end;
377 if offset + i < Length(Data) then
378 begin
379 Inc(i, tempw);
380 Result[10].raw_size := offset + i;
381 end
382 else
383 begin
384 Result[10].raw_size := 0;
385 end;
386 end;
387 Result[10].src_offset := $34;
388 Result[10].raw_addr := link;
389end;
390
391
392
393
394function TXMP(connection: TOniData; fileid: LongWord): TRawList;
395var
396 link_pc: LongWord;
397 link_mac: LongWord;
398 x, y: Word;
399 storetype: Byte;
400 datasize: LongWord;
401begin
402 connection.LoadDatFilePart(fileid, $8C, SizeOf(x), @x);
403 connection.LoadDatFilePart(fileid, $8E, SizeOf(y), @y);
404 connection.LoadDatFilePart(fileid, $90, SizeOf(storetype), @storetype);
405 connection.LoadDatFilePart(fileid, $9C, 4, @link_pc);
406 connection.LoadDatFilePart(fileid, $A0, 4, @link_mac);
407 case storetype of
408 0, 1, 2:
409 datasize := x * y * 2;
410 8:
411 datasize := x * y * 4;
412 9:
413 datasize := x * y div 2;
414 end;
415 SetLength(Result, 1);
416 if not connection.OSisMac then
417 begin
418 Result[0].src_offset := $9C;
419 Result[0].raw_addr := link_pc;
420 end
421 else
422 begin
423 Result[0].src_offset := $A0;
424 Result[0].raw_addr := link_mac;
425 end;
426 Result[0].raw_size := datasize;
427 Result[0].loc_sep := connection.OSisMac;
428end;
429
430
431
432
433procedure InsertRawListHandler(ext: String; needed: Boolean; handler: THandler);
434begin
435 SetLength(RawListHandlers, Length(RawListHandlers) + 1);
436 RawListHandlers[High(RawListHandlers)].Ext := ext;
437 RawListHandlers[High(RawListHandlers)].needed := needed;
438 RawListHandlers[High(RawListHandlers)].handler := handler;
439 Raws := Raws + ext;
440 AddToolListEntry('rawedit', '', ext);
441end;
442
443
444
445
446function LoadStructureDefinition(connection: TOniData; fileid: LongWord): TStructDef;
447var
448 i: LongWord;
449 current_type: Byte; //0: Global, 1: Undynamic, 2: Dynamic
450 current_base, current_package, current_package_size: LongWord;
451 packages: LongWord;
452 deffile: Text;
453 structentry: TStructure_Entry;
454 fields: TStringArray;
455 filename: String;
456 ext: String[4];
457 temps: String;
458 Data: TData;
459begin
460 SetLength(Result.Global, 0);
461 SetLength(Result.Subs, 0);
462 Result.Data := False;
463 ext := connection.GetFileInfo(fileid).Extension;
464 filename := ExtractFilePath(Application.ExeName) + '\StructDefs\' + ext + '.txt';
465 if FileExists(filename) then
466 begin
467 Data := connection.LoadDatFile(fileid);
468 AssignFile(deffile, filename);
469 Reset(deffile);
470 current_type := 0;
471 Result.Data := True;
472 if not EOF(deffile) then
473 begin
474 ReadLn(deffile, temps);
475 while not EOF(deffile) do
476 begin
477 ReadLn(deffile, temps);
478 if (Length(temps) > 0) and (temps[1] <> '#') then
479 begin
480 if temps[1] = '*' then
481 begin
482 fields := Explode(temps, #9);
483 case Length(fields) of
484 1..2:
485 begin
486 current_type := 1;
487 current_base := 0;
488 SetLength(Result.Subs, Length(Result.Subs) + 1);
489 Result.Subs[High(Result.Subs)].SubName :=
490 MidStr(fields[0], 2, Length(fields[0]) - 1);
491 if Length(fields) = 2 then
492 Result.Subs[High(Result.Subs)].SubDesc := fields[1];
493 end;
494 3:
495 begin
496 current_type := 1;
497 current_base := HexToLong(fields[2]);
498 SetLength(Result.Subs, Length(Result.Subs) + 1);
499 Result.Subs[High(Result.Subs)].SubName :=
500 MidStr(fields[0], 2, Length(fields[0]) - 1);
501 Result.Subs[High(Result.Subs)].SubDesc := fields[1];
502 end;
503 6:
504 begin
505 current_type := 2;
506 current_base := HexToLong(fields[2]);
507 current_package := 0;
508 current_package_size := StrToInt(fields[5]);
509 if fields[4][1] <> '$' then
510 begin
511 case StrToInt(fields[4]) of
512 1:
513 packages := Data[HexToLong(fields[3])];
514 2:
515 packages := Data[HexToLong(fields[3])] + Data[HexToLong(fields[3]) + 1] * 256;
516 4:
517 packages := Data[HexToLong(fields[3])] + Data[HexToLong(fields[3]) + 1] *
518 256 + Data[HexToLong(fields[3]) + 2] * 256 * 256 + Data[HexToLong(fields[3]) + 3] * 256 * 256 * 256;
519 end;
520 end
521 else
522 begin
523 packages := HexToLong(fields[4]);
524 end;
525 SetLength(Result.Subs, Length(Result.Subs) + packages);
526 for current_package := 0 to packages - 1 do
527 begin
528 Result.Subs[High(Result.Subs) - packages +
529 current_package + 1].SubName :=
530 MidStr(fields[0], 2, Length(fields[0]) - 1) +
531 '[' + IntToStr(current_package) + ']' + '#' +
532 IntToHex(current_base + current_package * current_package_size, 8) +
533 '#' + IntToHex(current_package_size, 8);
534 Result.Subs[High(Result.Subs) - packages +
535 current_package + 1].SubDesc :=
536 fields[1];
537 end;
538 end;
539 end;
540 end
541 else
542 begin
543 fields := Explode(temps, #9);
544 if (Length(fields) = 3) or (Length(fields) = 4) then
545 begin
546 if not AppSettings.HideUnusedData or
547 ((StrToInt(fields[2]) < 1000) or (StrToInt(fields[2]) > 9999)) then
548 begin
549 structentry.Name := fields[0];
550 structentry.datatype := StrToInt(fields[2]);
551 if Length(fields) = 4 then
552 structentry.description := fields[3]
553 else
554 structentry.description := '';
555 if current_type in [0, 1] then
556 begin
557 structentry.offset := HexToLong(fields[1]) + current_base;
558 if Length(Result.Subs) = 0 then
559 begin
560 SetLength(Result.Global, Length(Result.Global) + 1);
561 Result.Global[High(Result.Global)] := structentry;
562 end
563 else
564 begin
565 SetLength(Result.Subs[High(Result.Subs)].Entries,
566 Length(Result.Subs[High(Result.Subs)].Entries) + 1);
567 Result.Subs[High(Result.Subs)].Entries[High(
568 Result.Subs[High(Result.Subs)].Entries)] := structentry;
569 end;
570 end
571 else
572 begin
573 for current_package := 0 to packages - 1 do
574 begin
575 structentry.offset :=
576 current_base + current_package * current_package_size + HexToLong(fields[1]);
577 with Result.Subs[High(Result.Subs) - packages + current_package + 1] do
578 begin
579 SetLength(Entries, Length(Entries) + 1);
580 Entries[High(Entries)] := structentry;
581 end;
582 end;
583 end;
584 end;
585 end;
586 end;
587 end;
588 end;
589 end;
590 CloseFile(deffile);
591 end;
592end;
593
594
595begin
596 Raws := '';
597 InsertRawListHandler('AGDB',False,AGDB);
598 InsertRawListHandler('AKVA', True, AKVA);
599 InsertRawListHandler('BINA', True, BINA);
600 InsertRawListHandler('OSBD', True, OSBD);
601 InsertRawListHandler('SNDD', True, SNDD);
602 InsertRawListHandler('SUBT', True, SUBT);
603 InsertRawListHandler('TRAM', True, TRAM);
604 InsertRawListHandler('TXMP', True, TXMP);
605end.
Note: See TracBrowser for help on using the repository browser.