UNIT Unit9_data_structures; INTERFACE USES SysUtils, Classes, Unit3_data, Dialogs, StrUtils; TYPE Tstructure_entry=RECORD name:String; offset:LongWord; datatype:Word; // 1..4 : Integer[1..4] dec // 5..8 : Integer[1..4] hex // 9 : float // 10 : bitset // 11 : raw-addr // 12 : dat-file-ID // 13..16: Signed Integer[1..4] // 17 : level-ID // 100..300: dat-file-name[0..200] // 1000..9999: Unused data[0-8999] // 10000+: string[0+] description:String; END; TStructDefSub=RECORD SubName:String; SubDesc:String; Entries:Array OF TStructure_entry; END; TStructDef=RECORD Data:Boolean; Global:Array OF TStructure_entry; Subs:Array OF TStructDefSub; END; THandler=FUNCTION(fileid:LongWord):TRawList; TRawListHandlers=RECORD Ext:String[4]; needed:Boolean; Handler:THandler; END; VAR RawListHandlers:Array OF TRawListHandlers; Raws:String; FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef; FUNCTION GetDataType(typeid:Word):String; FUNCTION GetTypeDataLength(datatype:Word):Word; IMPLEMENTATION USES Unit2_functions, Unit15_Classes, Forms; FUNCTION GetTypeDataLength(datatype:Word):Word; BEGIN CASE datatype OF 1..4: Result:=datatype; 5..8: Result:=datatype-4; 9: Result:=4; 10: Result:=1; 11: Result:=4; 12: Result:=4; 13..16: Result:=datatype-12; 17: Result:=4; 100..300: Result:=datatype-100; 1000..9999: Result:=datatype-1000; 10000..65535: Result:=datatype-10000; END; END; FUNCTION GetDataType(typeid:Word):String; BEGIN CASE typeid OF 1..4: Result:='Int'+IntToStr(typeid*8); 5..8: Result:='Int'+IntToStr((typeid-4)*8); 9: Result:='Float'; 10: Result:='BitSet'; 11: Result:='Raw-Address'; 12: Result:='.dat-file-ID'; 13..16: Result:='SignedInt'+IntToStr((typeid-12)*8); 17: Result:='LevelID'; 100..300: Result:='.dat-file-name('+IntToStr(typeid-100)+')'; 1000..9999: Result:='Unused('+IntToStr(typeid-1000)+')'; 10000..65535: Result:='String('+IntToStr(typeid-10000)+')'; END; END; FUNCTION AGDB(fileid:LongWord):TRawList; VAR link:LongWord; links:LongWord; i:LongWord; BEGIN IF NOT OniDataConnection.OSisMac THEN BEGIN OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links); links:=links*2; SetLength(Result,links); FOR i:=0 TO links-1 DO BEGIN Result[i].src_offset:=$20+i*4; OniDataConnection.LoadDatFilePart(fileid,$20+i*4,4,@link); Result[i].raw_addr:=link; Result[i].raw_size:=0{????????????????????????????????}; Result[i].loc_sep:=False; END; END; END; FUNCTION AKVA(fileid:LongWord):TRawList; VAR link:LongWord; links:LongWord; i:LongWord; BEGIN IF NOT OniDataConnection.OSisMac THEN BEGIN OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links); SetLength(Result,links); FOR i:=0 TO links-1 DO BEGIN Result[i].src_offset:=$20+i*$74+$24; OniDataConnection.LoadDatFilePart(fileid,$20+i*$74+$24,4,@link); Result[i].raw_addr:=link; OniDataConnection.LoadDatFilePart(fileid,$20+i*$74+$28,4,@link); Result[i].raw_size:=link; Result[i].loc_sep:=False; END; END; END; FUNCTION BINA(fileid:LongWord):TRawList; VAR link:LongWord; datasize:LongWord; BEGIN OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link); OniDataConnection.LoadDatFilePart(fileid,$08,4,@datasize); SetLength(Result,1); Result[0].src_offset:=$0C; Result[0].raw_addr:=link; Result[0].raw_size:=datasize; Result[0].loc_sep:=OniDataConnection.OSisMac; END; FUNCTION OSBD(fileid:LongWord):TRawList; VAR link:LongWord; datasize:LongWord; BEGIN OniDataConnection.LoadDatFilePart(fileid,$08,4,@datasize); OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link); SetLength(Result,1); Result[0].src_offset:=$0C; Result[0].raw_addr:=link; Result[0].raw_size:=datasize; Result[0].loc_sep:=OniDataConnection.OSisMac; END; FUNCTION SNDD(fileid:LongWord):TRawList; VAR link:LongWord; datasize:LongWord; BEGIN SetLength(Result,1); IF NOT OniDataConnection.OSisMac THEN BEGIN OniDataConnection.LoadDatFilePart(fileid,$40,4,@datasize); OniDataConnection.LoadDatFilePart(fileid,$44,4,@link); Result[0].src_offset:=$44; END ELSE BEGIN OniDataConnection.LoadDatFilePart(fileid,$10,4,@datasize); OniDataConnection.LoadDatFilePart(fileid,$14,4,@link); Result[0].src_offset:=$14; END; Result[0].raw_addr:=link; Result[0].raw_size:=datasize; Result[0].loc_sep:=False; END; FUNCTION SUBT(fileid:LongWord):TRawList; VAR baselink,lastlink:LongWord; links:LongWord; j,k:LongWord; data:Tdata; BEGIN OniDataConnection.LoadDatFilePart(fileid,$18,4,@baselink); OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links); IF links>0 THEN BEGIN OniDataConnection.LoadDatFilePart(fileid,$20+(links-1)*4,4,@lastlink); SetLength(data,lastlink+1024); TOniDataDat(OniDataConnection).LoadRawOffset(false, baselink,lastlink+1024,data); // OniDataConnection.LoadRawFile(fileid,$1C,baselink,lastlink+1024,False,@data[0]); k:=0; FOR j:=0 TO 1024 DO BEGIN IF (data[lastlink+j]=$00) OR (j=1024) THEN BEGIN IF j<1024 THEN BEGIN IF k=0 THEN BEGIN k:=1; END ELSE BEGIN SetLength(Result,1); Result[0].src_offset:=$18; Result[0].raw_addr:=baselink; Result[0].raw_size:=lastlink+j; Break; END; END; END; END; END; END; FUNCTION TRAM(fileid:LongWord):TRawList; VAR i:Integer; link:LongWord; frames:Word; tempb:Byte; tempw:Word; templ:LongWord; data:Tdata; offset:Word; frame_count:Byte; BEGIN SetLength(Result,13); OniDataConnection.LoadDatFilePart(fileid,$16C,2,@frames); {y-pos} OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link); Result[0].src_offset:=$0C; Result[0].raw_addr:=link; Result[0].raw_size:=frames*4; {x-z-pos} OniDataConnection.LoadDatFilePart(fileid,$10,4,@link); Result[1].src_offset:=$10; Result[1].raw_addr:=link; Result[1].raw_size:=frames*8; {attacks} OniDataConnection.LoadDatFilePart(fileid,$182,1,@tempb); OniDataConnection.LoadDatFilePart(fileid,$14,4,@link); Result[2].src_offset:=$14; Result[2].raw_addr:=link; Result[2].raw_size:=tempb*32; {damage} OniDataConnection.LoadDatFilePart(fileid,$183,1,@tempb); OniDataConnection.LoadDatFilePart(fileid,$18,4,@link); Result[3].src_offset:=$18; Result[3].raw_addr:=link; Result[3].raw_size:=tempb*8; {motionblur} OniDataConnection.LoadDatFilePart(fileid,$184,1,@tempb); OniDataConnection.LoadDatFilePart(fileid,$1C,4,@link); Result[4].src_offset:=$1C; Result[4].raw_addr:=link; Result[4].raw_size:=tempb*8; {shortcut} OniDataConnection.LoadDatFilePart(fileid,$185,1,@tempb); OniDataConnection.LoadDatFilePart(fileid,$20,4,@link); Result[5].src_offset:=$20; Result[5].raw_addr:=link; Result[5].raw_size:=tempb*8; {throw} OniDataConnection.LoadDatFilePart(fileid,$24,4,@link); Result[6].src_offset:=$24; Result[6].raw_addr:=link; IF link>0 THEN Result[6].raw_size:=24 ELSE Result[6].raw_size:=0; {footstep} OniDataConnection.LoadDatFilePart(fileid,$186,1,@tempb); OniDataConnection.LoadDatFilePart(fileid,$28,4,@link); Result[7].src_offset:=$28; Result[7].raw_addr:=link; Result[7].raw_size:=tempb*4; {particle} OniDataConnection.LoadDatFilePart(fileid,$187,1,@tempb); OniDataConnection.LoadDatFilePart(fileid,$2C,4,@link); Result[8].src_offset:=$2C; Result[8].raw_addr:=link; Result[8].raw_size:=tempb*24; {position} OniDataConnection.LoadDatFilePart(fileid,$30,4,@link); Result[9].src_offset:=$30; Result[9].raw_addr:=link; Result[9].raw_size:=frames*8; {particle} OniDataConnection.LoadDatFilePart(fileid,$154,2,@tempw); OniDataConnection.LoadDatFilePart(fileid,$38,4,@link); Result[11].src_offset:=$38; Result[11].raw_addr:=link; Result[11].raw_size:=tempw*34; {extent} OniDataConnection.LoadDatFilePart(fileid,$138,4,@templ); OniDataConnection.LoadDatFilePart(fileid,$13C,4,@link); Result[12].src_offset:=$13C; Result[12].raw_addr:=link; Result[12].raw_size:=templ*12; OniDataConnection.LoadDatFilePart(fileid,$34,4,@link); IF link>0 THEN BEGIN OniDataConnection.LoadDatFilePart(fileid,$160,2,@tempw); frame_count:=0; i:=0; SetLength(data,$FFFF); TOniDataDat(OniDataConnection).LoadRawOffset(false,link,$FFFF,data); offset:=data[$24]+data[$25]*256; WHILE (offset+i0) AND (temps[1]<>'#') THEN BEGIN IF temps[1]='*' THEN BEGIN fields:=Explode(temps,#9); CASE Length(fields) OF 1..2: BEGIN current_type:=1; current_base:=0; SetLength(Result.Subs, Length(Result.Subs)+1); Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],2,Length(fields[0])-1); IF Length(fields)=2 THEN Result.Subs[High(Result.Subs)].SubDesc:=fields[1]; END; 3: BEGIN current_type:=1; current_base:=HexToLong(fields[2]); SetLength(Result.Subs, Length(Result.Subs)+1); Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],2,Length(fields[0])-1); Result.Subs[High(Result.Subs)].SubDesc:=fields[1]; END; 6: BEGIN current_type:=2; current_base:=HexToLong(fields[2]); current_package:=0; current_package_size:=StrToInt(fields[5]); IF fields[4][1]<>'$' THEN BEGIN CASE StrToInt(fields[4]) OF 1: packages:=data[HexToLong(fields[3])]; 2: packages:=data[HexToLong(fields[3])]+data[HexToLong(fields[3])+1]*256; 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; END; END ELSE BEGIN packages:=HexToLong(fields[4]); END; SetLength(Result.Subs, Length(Result.Subs)+packages); FOR current_package:=0 TO packages-1 DO BEGIN Result.Subs[High(Result.Subs)-packages+current_package+1].SubName:= MidStr(fields[0],2,Length(fields[0])-1)+'['+IntToStr(current_package)+']'+ '#'+IntToHex(current_base+current_package*current_package_size,8)+ '#'+IntToHex(current_package_size,8); Result.Subs[High(Result.Subs)-packages+current_package+1].SubDesc:= fields[1]; END; END; END; END ELSE BEGIN fields:=Explode(temps,#9); IF (Length(fields)=3) OR (Length(fields)=4) THEN BEGIN IF NOT AppSettings.HideUnusedData OR ((StrToInt(fields[2])<1000) OR (StrToInt(fields[2])>9999)) THEN BEGIN structentry.name:=fields[0]; structentry.datatype:=StrToInt(fields[2]); IF Length(fields)=4 THEN structentry.description:=fields[3] ELSE structentry.description:=''; IF current_type IN [0,1] THEN BEGIN structentry.offset:=HexToLong(fields[1])+current_base; IF Length(Result.Subs)=0 THEN BEGIN SetLength(Result.Global,Length(Result.Global)+1); Result.Global[High(Result.Global)]:=structentry; END ELSE BEGIN SetLength(Result.Subs[High(Result.Subs)].Entries,Length(Result.Subs[High(Result.Subs)].Entries)+1); Result.Subs[High(Result.Subs)].Entries[High(Result.Subs[High(Result.Subs)].Entries)]:=structentry; END; END ELSE BEGIN FOR current_package:=0 TO packages-1 DO BEGIN structentry.offset:=current_base+current_package*current_package_size+HexToLong(fields[1]); WITH Result.Subs[High(Result.Subs)-packages+current_package+1] DO BEGIN SetLength(Entries,Length(Entries)+1); Entries[High(Entries)]:=structentry; END; END; END; END; END; END; END; END; END; CloseFile(deffile); END; END; BEGIN Raws:=''; // InsertRawListHandler('AGDB',True,AGDB); InsertRawListHandler('AKVA',True,AKVA); InsertRawListHandler('BINA',True,BINA); InsertRawListHandler('OSBD',True,OSBD); InsertRawListHandler('SNDD',True,SNDD); InsertRawListHandler('SUBT',True,SUBT); InsertRawListHandler('TRAM',True,TRAM); InsertRawListHandler('TXMP',True,TXMP); END.