source: oup/current/Unit9_data_structures.pas @ 10

Last change on this file since 10 was 10, checked in by alloc, 17 years ago
  • Property svn:executable set to *
File size: 16.6 KB
Line 
1UNIT Unit9_data_structures;
2INTERFACE
3USES SysUtils, 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                      // 17    : level-ID
17                      // 100..300: dat-file-name[0..200]
18                      // 1000..9999: Unused data[0-8999]
19                      // 10000+: string[0+]
20      description:String;
21    END;
22  TStructDefSub=RECORD
23      SubName:String;
24      SubDesc:String;
25      Entries:Array OF TStructure_entry;
26    END;
27  TStructDef=RECORD
28      Data:Boolean;
29      Global:Array OF TStructure_entry;
30      Subs:Array OF TStructDefSub;
31    END;
32  THandler=FUNCTION(fileid:LongWord):TRawList;
33  TRawListHandlers=RECORD
34    Ext:String[4];
35    needed:Boolean;
36    Handler:THandler;
37  END;
38
39VAR
40  RawListHandlers:Array OF TRawListHandlers;
41  Raws:String;
42
43
44FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef;
45FUNCTION GetDataType(typeid:Word):String;
46FUNCTION GetTypeDataLength(datatype:Word):Word;
47
48IMPLEMENTATION
49USES Unit2_functions, Unit15_Classes, Forms;
50
51FUNCTION GetTypeDataLength(datatype:Word):Word;
52  BEGIN
53    CASE datatype OF
54      1..4: Result:=datatype;
55      5..8: Result:=datatype-4;
56      9: Result:=4;
57      10: Result:=1;
58      11: Result:=4;
59      12: Result:=4;
60      13..16: Result:=datatype-12;
61      17: Result:=4;
62      100..300: Result:=datatype-100;
63      1000..9999: Result:=datatype-1000;
64      10000..65535: Result:=datatype-10000;
65    END;
66  END;
67
68FUNCTION GetDataType(typeid:Word):String;
69  BEGIN
70    CASE typeid OF
71      1..4: Result:='Int'+IntToStr(typeid*8);
72      5..8: Result:='Int'+IntToStr((typeid-4)*8);
73      9: Result:='Float';
74      10: Result:='BitSet';
75      11: Result:='Raw-Address';
76      12: Result:='.dat-file-ID';
77      13..16: Result:='SignedInt'+IntToStr((typeid-12)*8);
78      17: Result:='LevelID';
79      100..300: Result:='.dat-file-name('+IntToStr(typeid-100)+')';
80      1000..9999: Result:='Unused('+IntToStr(typeid-1000)+')';
81      10000..65535: Result:='String('+IntToStr(typeid-10000)+')';
82    END;
83  END;
84
85
86
87
88FUNCTION AGDB(fileid:LongWord):TRawList;
89  VAR
90    link:LongWord;
91    links:LongWord;
92    i:LongWord;
93  BEGIN
94    IF NOT OniDataConnection.OSisMac THEN BEGIN
95      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
96      links:=links*2;
97      SetLength(Result,links);
98      FOR i:=0 TO links-1 DO BEGIN
99        Result[i].src_offset:=$20+i*4;
100        OniDataConnection.LoadDatFilePart(fileid,$20+i*4,4,@link);
101        Result[i].raw_addr:=link;
102        Result[i].raw_size:=0{????????????????????????????????};
103        Result[i].loc_sep:=False;
104      END;
105    END;
106  END;
107FUNCTION AKVA(fileid:LongWord):TRawList;
108  VAR
109    link:LongWord;
110    links:LongWord;
111    i:LongWord;
112  BEGIN
113    IF NOT OniDataConnection.OSisMac THEN BEGIN
114      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
115      SetLength(Result,links);
116      FOR i:=0 TO links-1 DO BEGIN
117        Result[i].src_offset:=$20+i*$74+$24;
118        OniDataConnection.LoadDatFilePart(fileid,$20+i*$74+$24,4,@link);
119        Result[i].raw_addr:=link;
120        OniDataConnection.LoadDatFilePart(fileid,$20+i*$74+$28,4,@link);
121        Result[i].raw_size:=link;
122        Result[i].loc_sep:=False;
123      END;
124    END;
125  END;
126FUNCTION BINA(fileid:LongWord):TRawList;
127  VAR
128    link:LongWord;
129    datasize:LongWord;
130  BEGIN
131    OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link);
132    OniDataConnection.LoadDatFilePart(fileid,$08,4,@datasize);
133    SetLength(Result,1);
134    Result[0].src_offset:=$0C;
135    Result[0].raw_addr:=link;
136    Result[0].raw_size:=datasize;
137    Result[0].loc_sep:=OniDataConnection.OSisMac;
138  END;
139FUNCTION OSBD(fileid:LongWord):TRawList;
140  VAR
141    link:LongWord;
142    datasize:LongWord;
143  BEGIN
144    OniDataConnection.LoadDatFilePart(fileid,$08,4,@datasize);
145    OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link);
146    SetLength(Result,1);
147    Result[0].src_offset:=$0C;
148    Result[0].raw_addr:=link;
149    Result[0].raw_size:=datasize;
150    Result[0].loc_sep:=OniDataConnection.OSisMac;
151  END;
152FUNCTION SNDD(fileid:LongWord):TRawList;
153  VAR
154    link:LongWord;
155    datasize:LongWord;
156  BEGIN
157    SetLength(Result,1);
158    IF NOT OniDataConnection.OSisMac THEN BEGIN
159      OniDataConnection.LoadDatFilePart(fileid,$40,4,@datasize);
160      OniDataConnection.LoadDatFilePart(fileid,$44,4,@link);
161      Result[0].src_offset:=$44;
162    END ELSE BEGIN
163      OniDataConnection.LoadDatFilePart(fileid,$10,4,@datasize);
164      OniDataConnection.LoadDatFilePart(fileid,$14,4,@link);
165      Result[0].src_offset:=$14;
166    END;
167    Result[0].raw_addr:=link;
168    Result[0].raw_size:=datasize;
169    Result[0].loc_sep:=False;
170  END;
171FUNCTION SUBT(fileid:LongWord):TRawList;
172  VAR
173    baselink,lastlink:LongWord;
174    links:LongWord;
175    j,k:LongWord;
176    data:Tdata;
177  BEGIN
178    OniDataConnection.LoadDatFilePart(fileid,$18,4,@baselink);
179    OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
180    IF links>0 THEN BEGIN
181      OniDataConnection.LoadDatFilePart(fileid,$20+(links-1)*4,4,@lastlink);
182      SetLength(data,lastlink+1024);
183        TOniDataDat(OniDataConnection).LoadRawOffset(false, baselink,lastlink+1024,data); 
184//      OniDataConnection.LoadRawFile(fileid,$1C,baselink,lastlink+1024,False,@data[0]);
185      k:=0;
186      FOR j:=0 TO 1024 DO BEGIN
187        IF (data[lastlink+j]=$00) OR (j=1024) THEN BEGIN
188          IF j<1024 THEN BEGIN
189            IF k=0 THEN BEGIN
190              k:=1;
191            END ELSE BEGIN
192              SetLength(Result,1);
193              Result[0].src_offset:=$18;
194              Result[0].raw_addr:=baselink;
195              Result[0].raw_size:=lastlink+j;
196              Break;
197            END;
198          END;
199        END;
200      END;
201    END;
202  END;
203FUNCTION TRAM(fileid:LongWord):TRawList;
204  VAR
205    i:Integer;
206    link:LongWord;
207    frames:Word;
208    tempb:Byte;
209    tempw:Word;
210    templ:LongWord;
211    data:Tdata;
212    offset:Word;
213    frame_count:Byte;
214  BEGIN
215    SetLength(Result,13);
216    OniDataConnection.LoadDatFilePart(fileid,$16C,2,@frames);
217    {y-pos}
218    OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link);
219    Result[0].src_offset:=$0C;
220    Result[0].raw_addr:=link;
221    Result[0].raw_size:=frames*4;
222    {x-z-pos}
223    OniDataConnection.LoadDatFilePart(fileid,$10,4,@link);
224    Result[1].src_offset:=$10;
225    Result[1].raw_addr:=link;
226    Result[1].raw_size:=frames*8;
227    {attacks}
228    OniDataConnection.LoadDatFilePart(fileid,$182,1,@tempb);
229    OniDataConnection.LoadDatFilePart(fileid,$14,4,@link);
230    Result[2].src_offset:=$14;
231    Result[2].raw_addr:=link;
232    Result[2].raw_size:=tempb*32;
233    {damage}
234    OniDataConnection.LoadDatFilePart(fileid,$183,1,@tempb);
235    OniDataConnection.LoadDatFilePart(fileid,$18,4,@link);
236    Result[3].src_offset:=$18;
237    Result[3].raw_addr:=link;
238    Result[3].raw_size:=tempb*8;
239    {motionblur}
240    OniDataConnection.LoadDatFilePart(fileid,$184,1,@tempb);
241    OniDataConnection.LoadDatFilePart(fileid,$1C,4,@link);
242    Result[4].src_offset:=$1C;
243    Result[4].raw_addr:=link;
244    Result[4].raw_size:=tempb*8;
245    {shortcut}
246    OniDataConnection.LoadDatFilePart(fileid,$185,1,@tempb);
247    OniDataConnection.LoadDatFilePart(fileid,$20,4,@link);
248    Result[5].src_offset:=$20;
249    Result[5].raw_addr:=link;
250    Result[5].raw_size:=tempb*8;
251    {throw}
252    OniDataConnection.LoadDatFilePart(fileid,$24,4,@link);
253    Result[6].src_offset:=$24;
254    Result[6].raw_addr:=link;
255    IF link>0 THEN
256      Result[6].raw_size:=24
257    ELSE
258      Result[6].raw_size:=0;
259    {footstep}
260    OniDataConnection.LoadDatFilePart(fileid,$186,1,@tempb);
261    OniDataConnection.LoadDatFilePart(fileid,$28,4,@link);
262    Result[7].src_offset:=$28;
263    Result[7].raw_addr:=link;
264    Result[7].raw_size:=tempb*4;
265    {particle}
266    OniDataConnection.LoadDatFilePart(fileid,$187,1,@tempb);
267    OniDataConnection.LoadDatFilePart(fileid,$2C,4,@link);
268    Result[8].src_offset:=$2C;
269    Result[8].raw_addr:=link;
270    Result[8].raw_size:=tempb*24;
271    {position}
272    OniDataConnection.LoadDatFilePart(fileid,$30,4,@link);
273    Result[9].src_offset:=$30;
274    Result[9].raw_addr:=link;
275    Result[9].raw_size:=frames*8;
276    {particle}
277    OniDataConnection.LoadDatFilePart(fileid,$154,2,@tempw);
278    OniDataConnection.LoadDatFilePart(fileid,$38,4,@link);
279    Result[11].src_offset:=$38;
280    Result[11].raw_addr:=link;
281    Result[11].raw_size:=tempw*34;
282    {extent}
283    OniDataConnection.LoadDatFilePart(fileid,$138,4,@templ);
284    OniDataConnection.LoadDatFilePart(fileid,$13C,4,@link);
285    Result[12].src_offset:=$13C;
286    Result[12].raw_addr:=link;
287    Result[12].raw_size:=templ*12;
288
289    OniDataConnection.LoadDatFilePart(fileid,$34,4,@link);
290    IF link>0 THEN BEGIN
291      OniDataConnection.LoadDatFilePart(fileid,$160,2,@tempw);
292      frame_count:=0;
293      i:=0;
294      SetLength(data,$FFFF);
295      TOniDataDat(OniDataConnection).LoadRawOffset(false,link,$FFFF,data); 
296      offset:=data[$24]+data[$25]*256;
297      WHILE (offset+i<Length(data)) AND (frame_count<frames-1) DO BEGIN
298        Inc(i,tempw);
299        frame_count:=frame_count+data[offset+i];
300        Inc(i);
301      END;
302      IF offset+i<Length(data) THEN BEGIN
303        Inc(i,tempw);
304        Result[10].raw_size:=offset+i;
305      END ELSE BEGIN
306        Result[10].raw_size:=0;
307      END;
308    END;
309    Result[10].src_offset:=$34;
310    Result[10].raw_addr:=link;
311  END;
312FUNCTION TXMP(fileid:LongWord):TRawList;
313  VAR
314    link_pc:LongWord;
315    link_mac:LongWord;
316    x,y:Word;
317    storetype:Byte;
318    datasize:LongWord;
319  BEGIN
320    OniDataConnection.LoadDatFilePart(fileid,$8C,SizeOf(x),@x);
321    OniDataConnection.LoadDatFilePart(fileid,$8E,SizeOf(y),@y);
322    OniDataConnection.LoadDatFilePart(fileid,$90,SizeOf(storetype),@storetype);
323    OniDataConnection.LoadDatFilePart(fileid,$9C,4,@link_pc);
324    OniDataConnection.LoadDatFilePart(fileid,$A0,4,@link_mac);
325    CASE storetype OF
326      0,1,2: datasize:=x*y*2;
327      8: datasize:=x*y*4;
328      9: datasize:=x*y DIV 2;
329    END;
330    SetLength(Result,1);
331    IF NOT OniDataConnection.OSisMac THEN BEGIN
332      Result[0].src_offset:=$9C;
333      Result[0].raw_addr:=link_pc
334    END ELSE BEGIN
335      Result[0].src_offset:=$A0;
336      Result[0].raw_addr:=link_mac;
337    END;
338    Result[0].raw_size:=datasize;
339    Result[0].loc_sep:=OniDataConnection.OSisMac;
340  END;
341
342
343PROCEDURE InsertRawListHandler(ext:String; needed:Boolean; handler:THandler);
344  BEGIN
345    SetLength(RawListHandlers,Length(RawListHandlers)+1);
346    RawListHandlers[High(RawListHandlers)].Ext:=ext;
347    RawListHandlers[High(RawListHandlers)].needed:=needed;
348    RawListHandlers[High(RawListHandlers)].handler:=handler;
349    Raws:=Raws+ext;
350  END;
351
352
353
354FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef;
355  VAR
356    i:LongWord;
357    current_type:Byte; //0: Global, 1: Undynamic, 2: Dynamic
358    current_base,current_package,current_package_size:LongWord;
359    packages:LongWord;
360    deffile:Text;
361    structentry:TStructure_Entry;
362    fields:TStringArray;
363    filename:String;
364    ext:String[4];
365    temps:String;
366    data:TData;
367  BEGIN
368    SetLength(Result.Global,0);
369    SetLength(Result.Subs,0);
370    Result.Data:=False;
371    ext:=OniDataConnection.GetFileInfo(fileid).Extension;
372    filename:=ExtractFilePath(Application.ExeName)+'\StructDefs\'+ext+'.txt';
373    IF FileExists(filename) THEN BEGIN
374      data:=OniDataConnection.LoadDatFile(fileid);
375      AssignFile(deffile,filename);
376      Reset(deffile);
377      current_type:=0;
378      Result.Data:=True;
379      IF NOT EoF(deffile) THEN BEGIN
380        ReadLn(deffile,temps);
381        WHILE NOT EoF(deffile) DO BEGIN
382          ReadLn(deffile,temps);
383          IF (Length(temps)>0) AND (temps[1]<>'#') THEN BEGIN
384            IF temps[1]='*' THEN BEGIN
385              fields:=Explode(temps,#9);
386              CASE Length(fields) OF
387                1..2: BEGIN
388                     current_type:=1;
389                     current_base:=0;
390                     SetLength(Result.Subs, Length(Result.Subs)+1);
391                     Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],2,Length(fields[0])-1);
392                     IF Length(fields)=2 THEN
393                       Result.Subs[High(Result.Subs)].SubDesc:=fields[1];
394                   END;
395                3: BEGIN
396                     current_type:=1;
397                     current_base:=HexToLong(fields[2]);
398                     SetLength(Result.Subs, Length(Result.Subs)+1);
399                     Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],2,Length(fields[0])-1);
400                     Result.Subs[High(Result.Subs)].SubDesc:=fields[1];
401                   END;
402                6: BEGIN
403                     current_type:=2;
404                     current_base:=HexToLong(fields[2]);
405                     current_package:=0;
406                     current_package_size:=StrToInt(fields[5]);
407                     IF fields[4][1]<>'$' THEN BEGIN
408                       CASE StrToInt(fields[4]) OF
409                         1: packages:=data[HexToLong(fields[3])];
410                         2: packages:=data[HexToLong(fields[3])]+data[HexToLong(fields[3])+1]*256;
411                         4: packages:=data[HexToLong(fields[3])]+data[HexToLong(fields[3])+1]*256+data[HexToLong(fields[3])+2]*256*256+data[HexToLong(fields[3])+3]*256*256*256;
412                       END;
413                     END ELSE BEGIN
414                       packages:=HexToLong(fields[4]);
415                     END;
416                     SetLength(Result.Subs, Length(Result.Subs)+packages);
417                     FOR current_package:=0 TO packages-1 DO BEGIN
418                       Result.Subs[High(Result.Subs)-packages+current_package+1].SubName:=
419                           MidStr(fields[0],2,Length(fields[0])-1)+'['+IntToStr(current_package)+']'+
420                           '#'+IntToHex(current_base+current_package*current_package_size,8)+
421                           '#'+IntToHex(current_package_size,8);
422                       Result.Subs[High(Result.Subs)-packages+current_package+1].SubDesc:=
423                           fields[1];
424                     END;
425                   END;
426              END;
427            END ELSE BEGIN
428              fields:=Explode(temps,#9);
429              IF (Length(fields)=3) OR (Length(fields)=4) THEN BEGIN
430                IF NOT AppSettings.HideUnusedData OR ((StrToInt(fields[2])<1000) OR (StrToInt(fields[2])>9999)) THEN BEGIN 
431                  structentry.name:=fields[0];
432                  structentry.datatype:=StrToInt(fields[2]);
433                  IF Length(fields)=4 THEN
434                    structentry.description:=fields[3]
435                  ELSE
436                    structentry.description:='';
437                  IF current_type IN [0,1] THEN BEGIN
438                    structentry.offset:=HexToLong(fields[1])+current_base;
439                    IF Length(Result.Subs)=0 THEN BEGIN
440                      SetLength(Result.Global,Length(Result.Global)+1);
441                      Result.Global[High(Result.Global)]:=structentry;
442                    END ELSE BEGIN
443                      SetLength(Result.Subs[High(Result.Subs)].Entries,Length(Result.Subs[High(Result.Subs)].Entries)+1);
444                      Result.Subs[High(Result.Subs)].Entries[High(Result.Subs[High(Result.Subs)].Entries)]:=structentry;
445                    END;
446                  END ELSE BEGIN
447                    FOR current_package:=0 TO packages-1 DO BEGIN
448                      structentry.offset:=current_base+current_package*current_package_size+HexToLong(fields[1]);
449                      WITH Result.Subs[High(Result.Subs)-packages+current_package+1] DO BEGIN
450                        SetLength(Entries,Length(Entries)+1);
451                        Entries[High(Entries)]:=structentry;
452                      END;
453                    END;
454                  END;
455                END;
456              END;
457            END;
458          END;
459        END;
460      END;
461      CloseFile(deffile);
462    END;
463  END;
464
465
466BEGIN
467  Raws:='';
468//  InsertRawListHandler('AGDB',True,AGDB);
469  InsertRawListHandler('AKVA',True,AKVA);
470  InsertRawListHandler('BINA',True,BINA);
471  InsertRawListHandler('OSBD',True,OSBD);
472  InsertRawListHandler('SNDD',True,SNDD);
473  InsertRawListHandler('SUBT',True,SUBT);
474  InsertRawListHandler('TRAM',True,TRAM);
475  InsertRawListHandler('TXMP',True,TXMP);
476END.
Note: See TracBrowser for help on using the repository browser.