source: oup/releases/0.29a/Unit9_data_structures.pas@ 455

Last change on this file since 455 was 28, checked in by alloc, 18 years ago
File size: 18.7 KB
Line 
1UNIT Unit9_data_structures;
2INTERFACE
3USES SysUtils, ABSMain, DB, ABSDecUtil, Classes, Unit3_data, Dialogs, StrUtils;
4
5TYPE
6 Tstructure_entry=RECORD
7 name:String;
8 offset:LongWord;
9 datatype:Word; // 1..4 : Integer[1..4] dec
10 // 5..8 : Integer[1..4] hex
11 // 9 : float
12 // 10 : bitset
13 // 11 : raw-addr
14 // 12 : dat-file-ID
15 // 13..16: Signed Integer[1..4]
16 // 1000..9999: Unused data[0-8999]
17 // 10000+: string[0+]
18 description:String;
19 END;
20 TStructDefSub=RECORD
21 SubName:String;
22 Entries:Array OF TStructure_entry;
23 END;
24 TStructDef=RECORD
25 Data:Boolean;
26 Global:Array OF TStructure_entry;
27 Subs:Array OF TStructDefSub;
28 END;
29 Tstructure_info=RECORD
30 extension:String;
31 typedesc:String;
32 entries:Array OF Tstructure_entry;
33 END;
34 Tstructures=Array OF Tstructure_info;
35 THandler=FUNCTION(fileid:LongWord):TRawList;
36 TRawListHandlers=RECORD
37 Ext:String[4];
38 needed:Boolean;
39 Handler:THandler;
40 END;
41
42VAR
43 structure_infos:Tstructures;
44 RawListHandlers:Array OF TRawListHandlers;
45
46
47FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef;
48FUNCTION GetDataType(typeid:Word):String;
49FUNCTION GetStructureInfoId(ext:String):Integer;
50FUNCTION GetTypeDataLength(datatype:Word):Word;
51FUNCTION GetRawInfo(fileid,dat_offset:LongWord):TRawInfo;
52FUNCTION GetRawList(fileid:LongWord):TRawList;
53
54PROCEDURE LoadStructureDefinitions(defdir:String);
55
56
57IMPLEMENTATION
58USES Unit2_functions, Forms;
59
60FUNCTION GetTypeDataLength(datatype:Word):Word;
61 BEGIN
62 CASE datatype OF
63 1..4: Result:=datatype;
64 5..8: Result:=datatype-4;
65 9: Result:=4;
66 10: Result:=1;
67 11: Result:=4;
68 12: Result:=4;
69 13..16: Result:=datatype-12;
70 1000..9999: Result:=datatype-1000;
71 10000..65535: Result:=datatype-10000;
72 END;
73 END;
74
75
76FUNCTION GetStructureInfoId(ext:String):Integer;
77 VAR
78 i:Integer;
79 BEGIN
80 FOR i:=0 TO High(structure_infos) DO BEGIN
81 IF structure_infos[i].extension=ext THEN BEGIN
82 Result:=i;
83 Exit;
84 END;
85 END;
86 Result:=-1;
87 END;
88
89
90FUNCTION GetDataType(typeid:Word):String;
91 BEGIN
92 CASE typeid OF
93 1..4: Result:='Int'+IntToStr(typeid*8);
94 5..8: Result:='Int'+IntToStr((typeid-4)*8);
95 9: Result:='Float';
96 10: Result:='BitSet';
97 11: Result:='Raw-Address';
98 12: Result:='.dat-file-ID';
99 13..16: Result:='SignedInt'+IntToStr((typeid-12)*8);
100 1000..9999: Result:='Unused('+IntToStr(typeid-1000)+')';
101 10000..65535: Result:='String('+IntToStr(typeid-10000)+')';
102 END;
103 END;
104
105
106FUNCTION GetRawInfo(fileid,dat_offset:LongWord):TRawInfo;
107 VAR
108 i:LongWord;
109 raw_list:TRawList;
110 BEGIN
111 raw_list:=GetRawList(fileid);
112 Result.src_id:=0;
113 Result.src_offset:=0;
114 Result.raw_addr:=0;
115 Result.raw_size:=0;
116 FOR i:=0 TO High(raw_list) DO BEGIN
117 IF raw_list[i].src_offset=dat_offset THEN BEGIN
118 Result.src_id:=fileid;
119 Result.src_offset:=raw_list[i].src_offset;
120 Result.raw_addr:=raw_list[i].raw_addr;
121 Result.raw_size:=raw_list[i].raw_size;
122 Result.loc_sep:=raw_list[i].loc_sep;
123 Break;
124 END;
125 END;
126 END;
127
128FUNCTION GetRawList(fileid:LongWord):TRawList;
129 VAR
130 i:LongWord;
131 Query:TABSQuery;
132 BEGIN
133 IF opened_state=opened_dat THEN BEGIN
134 FOR i:=0 TO High(RawListHandlers) DO
135 IF UpperCase(RawListHandlers[i].Ext)=UpperCase(dat_files[fileid].extension) THEN
136 IF RawListHandlers[i].needed THEN BEGIN
137 Result:=RawListHandlers[i].Handler(fileid);
138 Break;
139 END ELSE
140 Break;
141 END ELSE BEGIN
142 SetLength(Result,0);
143 Query.SQL.Text:='SELECT [src_link_offset],[size] FROM rawmap WHERE [src_id]='+IntToStr(fileid)+' ORDER BY src_link_offset ASC;';
144 Query.Open;
145 IF Query.RecordCount>0 THEN BEGIN
146 Query.First;
147 SetLength(Result,Query.RecordCount);
148 i:=0;
149 REPEAT
150 Result[i].src_id:=fileid;
151 Result[i].src_offset:=Query.FieldByName('src_link_offset').AsInteger;
152 Result[i].raw_addr:=0;
153 Result[i].raw_size:=Query.FieldByName('size').AsInteger;
154 Inc(i);
155 Query.Next;
156 UNTIL Query.EOF;
157 END;
158 Query.Close;
159 END;
160 END;
161
162
163FUNCTION AGDB(fileid:LongWord):TRawList;
164 VAR
165 link:LongWord;
166 links:LongWord;
167 i:LongWord;
168 BEGIN
169 IF NOT dat_os_mac THEN BEGIN
170 LoadDatFilePart(fileid,$1C,4,@links);
171 links:=links*2;
172 SetLength(Result,links);
173 FOR i:=0 TO links-1 DO BEGIN
174 Result[i].src_offset:=$20+i*4;
175 LoadDatFilePart(fileid,$20+i*4,4,@link);
176 Result[i].raw_addr:=link;
177 Result[i].raw_size:=0{????????????????????????????????};
178 Result[i].loc_sep:=False;
179 END;
180 END;
181 END;
182FUNCTION AKVA(fileid:LongWord):TRawList;
183 VAR
184 link:LongWord;
185 links:LongWord;
186 i:LongWord;
187 BEGIN
188 IF NOT dat_os_mac THEN BEGIN
189 LoadDatFilePart(fileid,$1C,4,@links);
190 SetLength(Result,links);
191 FOR i:=0 TO links-1 DO BEGIN
192 Result[i].src_offset:=$20+i*$74+$24;
193 LoadDatFilePart(fileid,$20+i*$74+$24,4,@link);
194 Result[i].raw_addr:=link;
195 LoadDatFilePart(fileid,$20+i*$74+$28,4,@link);
196 Result[i].raw_size:=link;
197 Result[i].loc_sep:=False;
198 END;
199 END;
200 END;
201FUNCTION BINA(fileid:LongWord):TRawList;
202 VAR
203 link:LongWord;
204 datasize:LongWord;
205 BEGIN
206 LoadDatFilePart(fileid,$0C,4,@link);
207 LoadDatFilePart(fileid,$08,4,@datasize);
208 SetLength(Result,1);
209 Result[0].src_offset:=$0C;
210 Result[0].raw_addr:=link;
211 Result[0].raw_size:=datasize;
212 Result[0].loc_sep:=dat_os_mac;
213 END;
214FUNCTION OSBD(fileid:LongWord):TRawList;
215 VAR
216 link:LongWord;
217 datasize:LongWord;
218 BEGIN
219 LoadDatFilePart(fileid,$08,4,@datasize);
220 LoadDatFilePart(fileid,$0C,4,@link);
221 SetLength(Result,1);
222 Result[0].src_offset:=$0C;
223 Result[0].raw_addr:=link;
224 Result[0].raw_size:=datasize;
225 Result[0].loc_sep:=dat_os_mac;
226 END;
227FUNCTION SNDD(fileid:LongWord):TRawList;
228 VAR
229 link:LongWord;
230 datasize:LongWord;
231 BEGIN
232 IF NOT dat_os_mac THEN BEGIN
233 LoadDatFilePart(fileid,$40,4,@datasize);
234 LoadDatFilePart(fileid,$44,4,@link);
235 Result[0].src_offset:=$44;
236 END ELSE BEGIN
237 LoadDatFilePart(fileid,$10,4,@datasize);
238 LoadDatFilePart(fileid,$14,4,@link);
239 Result[0].src_offset:=$14;
240 END;
241 SetLength(Result,1);
242 Result[0].raw_addr:=link;
243 Result[0].raw_size:=datasize;
244 Result[0].loc_sep:=False;
245 END;
246FUNCTION SUBT(fileid:LongWord):TRawList;
247 VAR
248 baselink,link:LongWord;
249 links:LongWord;
250 i,j,k:LongWord;
251 data:Tdata;
252 BEGIN
253 LoadDatFilePart(fileid,$18,4,@baselink);
254 LoadDatFilePart(fileid,$1C,4,@links);
255 IF links>0 THEN BEGIN
256 LoadDatFilePart(fileid,$20+(links-1)*4,4,@link);
257 SetLength(data,link+1024);
258 LoadRawFile(fileid,$1C,baselink,link+1024,False,@data[0]);
259 k:=0;
260 FOR j:=0 TO 1024 DO BEGIN
261 IF (data[link+j]=$00) OR (j=1024) THEN BEGIN
262 IF j<1024 THEN BEGIN
263 IF k=0 THEN BEGIN
264 k:=1;
265 END ELSE BEGIN
266 SetLength(Result,1);
267 Result[0].src_offset:=$18;
268 Result[0].raw_addr:=baselink;
269 Result[0].raw_size:=link+j;
270 Break;
271 END;
272 END;
273 END;
274 END;
275 END;
276 END;
277FUNCTION TRAM(fileid:LongWord):TRawList;
278 VAR
279 i:Byte;
280 link:LongWord;
281 frames:Word;
282 tempb:Byte;
283 tempw:Word;
284 templ:LongWord;
285 data:Tdata;
286 offset:Word;
287 BEGIN
288 SetLength(Result,13);
289 LoadDatFilePart(fileid,$16C,2,@frames);
290 {y-pos}
291 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 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 LoadDatFilePart(fileid,$182,1,@tempb);
302 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 LoadDatFilePart(fileid,$183,1,@tempb);
308 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 LoadDatFilePart(fileid,$184,1,@tempb);
314 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 LoadDatFilePart(fileid,$185,1,@tempb);
320 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 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 LoadDatFilePart(fileid,$186,1,@tempb);
334 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 LoadDatFilePart(fileid,$187,1,@tempb);
340 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 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 LoadDatFilePart(fileid,$154,2,@tempw);
351 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 LoadDatFilePart(fileid,$138,4,@templ);
357 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 LoadDatFilePart(fileid,$34,4,@link);
363 tempw:=0;
364 IF link>0 THEN BEGIN
365 {BODY ANIMATIONS PART DECODE!!!}
366 SetLength(data,$FFFF);
367 LoadRawFile(fileid,$34,link,$FFFF,False,@data[0]);
368 offset:=data[24]+data[25]*255;
369 {}
370 END;
371 Result[10].src_offset:=$34;
372 Result[10].raw_addr:=link;
373 Result[10].raw_size:=tempw;
374 END;
375FUNCTION TXMP(fileid:LongWord):TRawList;
376 VAR
377 link_pc:LongWord;
378 link_mac:LongWord;
379 x,y:Word;
380 storetype:Byte;
381 datasize:LongWord;
382 BEGIN
383 LoadDatFilePart(fileid,$8C,SizeOf(x),@x);
384 LoadDatFilePart(fileid,$8E,SizeOf(y),@y);
385 LoadDatFilePart(fileid,$90,SizeOf(storetype),@storetype);
386 LoadDatFilePart(fileid,$9C,4,@link_pc);
387 LoadDatFilePart(fileid,$A0,4,@link_mac);
388 CASE storetype OF
389 0,1,2: datasize:=x*y*2;
390 8: datasize:=x*y*4;
391 9: datasize:=x*y DIV 2;
392 END;
393 SetLength(Result,1);
394 IF NOT dat_os_mac THEN BEGIN
395 Result[0].src_offset:=$9C;
396 Result[0].raw_addr:=link_pc
397 END ELSE BEGIN
398 Result[0].src_offset:=$A0;
399 Result[0].raw_addr:=link_mac;
400 END;
401 Result[0].raw_size:=datasize;
402 Result[0].loc_sep:=dat_os_mac;
403 END;
404
405
406
407PROCEDURE AddEntry(_ext:String; _name:String; _offset:LongWord; _datatype:Word; _description:String);
408 VAR
409 sid:Integer;
410 BEGIN
411 sid:=GetStructureInfoId(_ext);
412 IF sid>=0 THEN BEGIN
413 WITH structure_infos[sid] DO BEGIN
414 SetLength(entries,Length(entries)+1);
415 WITH entries[High(entries)] DO BEGIN
416 name:=_name;
417 offset:=_offset;
418 datatype:=_datatype;
419 description:=_description;
420 END;
421 END;
422 END;
423 END;
424
425PROCEDURE AddExtension(_ext:String; _typedesc:String);
426 BEGIN
427 IF GetStructureInfoId(_ext)<0 THEN BEGIN
428 SetLength(structure_infos,Length(structure_infos)+1);
429 WITH structure_infos[High(structure_infos)] DO BEGIN
430 extension:=_ext;
431 typedesc:=_typedesc;
432 END;
433 END;
434 END;
435
436PROCEDURE InsertRawListHandler(ext:String; needed:Boolean; handler:THandler);
437 BEGIN
438 SetLength(RawListHandlers,Length(RawListHandlers)+1);
439 RawListHandlers[High(RawListHandlers)].Ext:=ext;
440 RawListHandlers[High(RawListHandlers)].needed:=needed;
441 RawListHandlers[High(RawListHandlers)].handler:=handler;
442 END;
443
444
445
446FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef;
447 VAR
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:TStringList;
455 filename:String;
456 ext:String[4];
457 temps:String;
458 data:TData;
459 BEGIN
460 SetLength(Result.Global,0);
461 SetLength(Result.Subs,0);
462 Result.Data:=False;
463 ext:=GetFileInfo(fileid).Extension;
464 filename:=ExtractFilePath(Application.ExeName)+'\StructDefs\'+ext+'.txt';
465 IF FileExists(filename) THEN BEGIN
466 data:=LoadDatFile(fileid);
467 AssignFile(deffile,filename);
468 Reset(deffile);
469 current_type:=0;
470 Result.Data:=True;
471 IF NOT EoF(deffile) THEN BEGIN
472 ReadLn(deffile,temps);
473 WHILE NOT EoF(deffile) DO BEGIN
474 ReadLn(deffile,temps);
475 IF Length(temps)>0 THEN BEGIN
476 IF temps[1]='*' THEN BEGIN
477 fields:=Explode(temps,'#');
478 CASE Length(fields) OF
479 1: BEGIN
480 current_type:=1;
481 current_base:=0;
482 SetLength(Result.Subs, Length(Result.Subs)+1);
483 Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],1,Length(fields[0])-1);
484 END;
485 2: BEGIN
486 current_type:=1;
487 current_base:=HexToLong(fields[1]);
488 SetLength(Result.Subs, Length(Result.Subs)+1);
489 Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],1,Length(fields[0])-1);
490 END;
491 5: BEGIN
492 current_type:=2;
493 current_base:=HexToLong(fields[1]);
494 current_package:=0;
495 current_package_size:=StrToInt(fields[4]);
496 CASE StrToInt(fields[3]) OF
497 1: packages:=data[HexToLong(fields[2])];
498 2: packages:=data[HexToLong(fields[2])]+data[HexToLong(fields[2])+1]*256;
499 4: packages:=data[HexToLong(fields[2])]+data[HexToLong(fields[2])+1]*256+data[HexToLong(fields[2])+2]*256*256+data[HexToLong(fields[2])+3]*256*256*256;
500 END;
501 SetLength(Result.Subs, Length(Result.Subs)+packages);
502 FOR current_package:=0 TO packages-1 DO BEGIN
503 Result.Subs[High(Result.Subs)-packages+current_package+1].SubName:=MidStr(fields[0],1,Length(fields[0])-1)+'['+IntToStr(current_package)+']';
504 END;
505 END;
506 END;
507 END ELSE BEGIN
508 fields:=Explode(temps,#9);
509 IF (Length(fields)=3) OR (Length(fields)=4) THEN BEGIN
510 structentry.name:=fields[0];
511 structentry.datatype:=StrToInt(fields[2]);
512 IF Length(fields)=4 THEN
513 structentry.description:=fields[3]
514 ELSE
515 structentry.description:='';
516 IF current_type IN [0,1] THEN BEGIN
517 structentry.offset:=HexToLong(fields[1])+current_base;
518 IF Length(Result.Subs)=0 THEN BEGIN
519 SetLength(Result.Global,Length(Result.Global)+1);
520 Result.Global[High(Result.Global)]:=structentry;
521 END ELSE BEGIN
522 SetLength(Result.Subs[High(Result.Subs)].Entries,Length(Result.Subs[High(Result.Subs)].Entries)+1);
523 Result.Subs[High(Result.Subs)].Entries[High(Result.Subs[High(Result.Subs)].Entries)]:=structentry;
524 END;
525 END ELSE BEGIN
526 FOR current_package:=0 TO packages-1 DO BEGIN
527 structentry.offset:=current_base+current_package*current_package_size+HexToLong(fields[1]);
528 WITH Result.Subs[High(Result.Subs)-packages+current_package+1] DO BEGIN
529 SetLength(Entries,Length(Entries)+1);
530 Entries[High(Entries)]:=structentry;
531 END;
532 END;
533 END;
534 END;
535 END;
536 END;
537 END;
538 END;
539 CloseFile(deffile);
540 END;
541 END;
542
543
544
545PROCEDURE LoadStructureDefinitionFile(filename:String);
546 VAR
547 temps:String;
548 deffile:Text;
549 ext:String;
550 fields:TStringList;
551 fieldname:String;
552 fieldoffset:LongWord;
553 fieldtype:Word;
554 fielddesc:String;
555 BEGIN
556 ext:=MidStr(ExtractFileName(filename),1,4);
557 AssignFile(deffile,filename);
558 Reset(deffile);
559 IF NOT EoF(deffile) THEN BEGIN
560 ReadLn(deffile,temps);
561 AddExtension(ext,temps);
562 WHILE NOT EoF(deffile) DO BEGIN
563 ReadLn(deffile,temps);
564 fields:=Explode(temps,#9);
565 IF (Length(fields)=3) OR (Length(fields)=4) THEN BEGIN
566 fieldname:=fields[0];
567 fieldoffset:=HexToLong(fields[1]);
568 fieldtype:=StrToInt(fields[2]);
569 IF Length(fields)=4 THEN
570 fielddesc:=fields[3]
571 ELSE
572 fielddesc:='';
573// ShowMessage(fieldname+' - '+IntToHex(fieldoffset,4)+' - '+IntToStr(fieldtype)+' - '+fielddesc);
574 AddEntry(ext,fieldname,fieldoffset,fieldtype,fielddesc);
575 END;
576 END;
577 END;
578 CloseFile(deffile);
579 END;
580
581PROCEDURE LoadStructureDefinitions(defdir:String);
582 VAR
583 SR:TSearchRec;
584 BEGIN
585 IF DirectoryExists(defdir) THEN BEGIN
586 IF FindFirst(defdir+'\*.txt', faAnyFile, SR)=0 THEN BEGIN
587 REPEAT
588 IF (SR.Attr AND faDirectory) <> faDirectory THEN BEGIN
589 LoadStructureDefinitionFile(defdir+'\'+SR.Name);
590 END;
591 UNTIL FindNext(SR)<>0;
592 END;
593 FindClose(SR);
594 END;
595 END;
596
597BEGIN
598// InsertRawListHandler('AGDB',True,AGDB);
599 InsertRawListHandler('AKVA',True,AKVA);
600 InsertRawListHandler('BINA',True,BINA);
601 InsertRawListHandler('OSBD',True,OSBD);
602 InsertRawListHandler('SNDD',True,SNDD);
603 InsertRawListHandler('SUBT',True,SUBT);
604 InsertRawListHandler('TRAM',True,TRAM);
605 InsertRawListHandler('TXMP',True,TXMP);
606END.
Note: See TracBrowser for help on using the repository browser.