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

Last change on this file since 28 was 28, checked in by alloc, 15 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.