UNIT Unit2_functions; INTERFACE USES Classes, SysUtils, StrUtils, Math, Unit3_data, Unit4_Exporters; FUNCTION LoadDatInfos(filename:String):Boolean; FUNCTION LoadDatFile(fileid:LongWord):Tdata; FUNCTION LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean; FUNCTION LoadRawFilePart(address,size:LongWord; target:Pointer):Boolean; FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String; FUNCTION FormatFileSize(size:LongWord):String; FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String; FUNCTION ExportFile(fileid:LongWord; convert:Boolean):Integer; FUNCTION GetWinFileName(fileid:LongWord; substring:String):String; FUNCTION GetExtractPath:String; IMPLEMENTATION FUNCTION LoadDatInfos(filename:String):Boolean; VAR i:LongWord; dat_file:TFileStream; BEGIN Result:=True; IF Length(filename)>0 THEN dat_file.Free; dat_filename:=filename; dat_file:=TFileStream.Create(filename, fmOpenRead); dat_file.Read(dat_header,SizeOf(dat_header)); FOR i:=0 TO High(dat_header.Ident) DO IF dat_header.Ident[i]<>header_ident1[i] THEN BEGIN Result:=False; Exit; END; { FOR i:=0 TO High(dat_header.Ident2) DO IF dat_header.Ident2[i]<>header_ident2[i] THEN BEGIN Result:=False; Exit; END; } SetLength(dat_filesmap,dat_header.Files); SetLength(dat_files,dat_header.Files); FOR i:=0 TO dat_header.Files-1 DO dat_file.Read(dat_filesmap[i],SizeOf(dat_filesmap[i])); FOR i:=0 TO dat_header.Files-1 DO BEGIN dat_files[i].Extension:=dat_filesmap[i].Extension; dat_files[i].Extension:=ReverseString(dat_files[i].Extension); dat_files[i].Size:=dat_filesmap[i].FileSize; dat_files[i].FileType:=dat_filesmap[i].FileType; dat_files[i].DatAddr:=dat_filesmap[i].DataAddr-8+dat_header.DataAddr; IF (dat_filesmap[i].FileType AND $01)=0 THEN BEGIN dat_file.Seek(dat_filesmap[i].NameAddr+dat_header.NamesAddr,soFromBeginning); SetLength(dat_files[i].Name,100); dat_file.Read(dat_files[i].Name[1],100); dat_files[i].Name:=MidStr(dat_files[i].Name,1+4,Pos(#0,dat_files[i].Name)-1-4); END ELSE BEGIN dat_files[i].Name:=''; END; dat_files[i].FileName:=FormatNumber(i,5,'0')+'-'+dat_files[i].Name+'.'+dat_files[i].Extension; END; dat_file.Seek($40+dat_header.Files*$14,soFromBeginning); SetLength(dat_namedfilesmap,dat_header.NamedFiles); FOR i:=0 TO dat_header.NamedFiles-1 DO dat_file.Read(dat_namedfilesmap[i],SizeOf(dat_namedfilesmap[i])); dat_file.Seek($40+dat_header.Files*$14+dat_header.NamedFiles*$8,soFromBeginning); SetLength(dat_extensionsmap,dat_header.Extensions); FOR i:=0 TO dat_header.Extensions-1 DO dat_file.Read(dat_extensionsmap[i],SizeOf(dat_extensionsmap[i])); dat_file.Free; END; FUNCTION LoadDatFile(fileid:LongWord):Tdata; VAR dat_file:TFileStream; BEGIN dat_file:=TFileStream.Create(dat_filename, fmOpenRead); dat_file.Seek(dat_files[fileid].DatAddr,soFromBeginning); SetLength(Result,dat_files[fileid].Size); dat_file.Read(Result[0],dat_files[fileid].Size); dat_file.Free; END; FUNCTION LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean; VAR dat_file:TFileStream; BEGIN dat_file:=TFileStream.Create(dat_filename, fmOpenRead); Result:=True; dat_file.Seek(dat_files[fileid].DatAddr+offset,soFromBeginning); dat_file.Read(target^,size); dat_file.Free; END; FUNCTION LoadRawFilePart(address,size:LongWord; target:Pointer):Boolean; VAR filestream:TFileStream; BEGIN Result:=True; filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenRead); filestream.Seek(address,soFromBeginning); filestream.Read(target^,size); filestream.Free; END; FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String; BEGIN Result:=AnsiReplaceStr(Format('%'+IntToStr(width)+'u',[value]),' ',leadingzeros); END; FUNCTION FormatFileSize(size:LongWord):String; BEGIN IF size>=1024*1024*1024 THEN BEGIN Result:=FloatToStrF(size/1024/1024/1024,ffFixed,5,1)+' GB'; END ELSE BEGIN IF size>=1024*1024 THEN BEGIN Result:=FloatToStrF(size/1024/1024,ffFixed,5,1)+' MB'; END ELSE BEGIN IF size>=1024 THEN BEGIN Result:=FloatToStrF(size/1024,ffFixed,5,1)+' KB'; END ELSE BEGIN Result:=IntToStr(size)+' B'; END; END; END; END; FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String; VAR string_build,ascii_version:String; i:LongWord; BEGIN string_build:=''; ascii_version:=''; FOR i:=0 TO High(data) DO BEGIN IF NOT HexOnly THEN IF (i MOD 16)=0 THEN string_build:=string_build+'0x'+IntToHex(i,6)+' '; string_build:=string_build+IntToHex(data[i],2); IF NOT HexOnly THEN BEGIN IF data[i]>=32 THEN ascii_version:=ascii_version+Chr(data[i]) ELSE ascii_version:=ascii_version+'.'; IF ((i+1) MOD 2)=0 THEN string_build:=string_build+#32; IF ((i+1) MOD 16)=0 THEN BEGIN string_build:=string_build+#32+ascii_version+CrLf; ascii_version:=''; END; END; END; Result:=string_build; END; FUNCTION ExportFile(fileid:LongWord; convert:Boolean):Integer; VAR i:Byte; BEGIN Result:=export_noerror; ExportDefFileHeader(fileid); IF (dat_files[fileid].FileType AND $02)=0 THEN BEGIN ExportDatFile(fileid); FOR i:=1 TO Length(ExportHandlers)+1 DO BEGIN IF i<=Length(ExportHandlers) THEN BEGIN IF ExportHandlers[i].Ext=dat_files[fileid].Extension THEN BEGIN IF ExportHandlers[i].needed THEN BEGIN CASE ExportHandlers[i].Handler(fileid,convert) OF 0: Result:=0; ELSE Result:=export_handlererror; END; END; Break; END; END ELSE BEGIN Result:=export_nohandler; END; END; END; END; FUNCTION GetWinFileName(fileid:LongWord; substring:String):String; VAR name:String; BEGIN name:=dat_files[fileid].Name; name:=AnsiReplaceStr(name,'\','__'); name:=AnsiReplaceStr(name,'/','__'); name:=AnsiReplaceStr(name,'>','__'); name:=AnsiReplaceStr(name,'<','__'); Result:=FormatNumber(fileid,5,'0')+'-'+name+'.'+substring+'.'+dat_files[fileid].Extension; END; FUNCTION GetExtractPath:String; BEGIN Result:=ExtractFilePath(dat_filename)+'\extracted_'+ExtractFileName(dat_filename); END; END.