mirror of https://github.com/red-prig/fpPS4.git
253 lines
4.5 KiB
Plaintext
253 lines
4.5 KiB
Plaintext
unit param_sfo_gui;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils;
|
|
|
|
const
|
|
//sfo_value_format
|
|
SFO_FORMAT_STRING_SPECIAL=$004;
|
|
SFO_FORMAT_STRING =$204;
|
|
SFO_FORMAT_UINT32 =$404;
|
|
|
|
SFO_MAGIC=$46535000;
|
|
|
|
SFO_HEADER_SIZE =$14;
|
|
SFO_TABLE_ENTRY_SIZE=$10;
|
|
|
|
type
|
|
t_sfo_header=packed record
|
|
magic :DWORD;
|
|
version :DWORD;
|
|
key_table_offset :DWORD;
|
|
value_table_offset:DWORD;
|
|
entry_count :DWORD;
|
|
end;
|
|
|
|
p_sfo_table_entry=^t_sfo_table_entry;
|
|
t_sfo_table_entry=packed record
|
|
key_offset :WORD; //<-key_table
|
|
format :WORD;
|
|
size :DWORD;
|
|
max_size :DWORD;
|
|
value_offset:DWORD; //<-value_table
|
|
end;
|
|
|
|
//
|
|
|
|
TParamSfoValue=packed object
|
|
format:ptruint;
|
|
name,value:RawByteString;
|
|
Function GetString:RawByteString;
|
|
Function GetUInt :DWORD;
|
|
end;
|
|
|
|
TParamSfoFile=class
|
|
params:array of TParamSfoValue;
|
|
Function GetString(const name:RawByteString):RawByteString;
|
|
Function GetUInt (const name:RawByteString):DWORD;
|
|
end;
|
|
|
|
function LoadParamSfoFile(const path:RawByteString):TParamSfoFile;
|
|
|
|
implementation
|
|
|
|
function LoadParamSfoFile(const path:RawByteString):TParamSfoFile;
|
|
Var
|
|
fd:THandle;
|
|
|
|
fsize:Int64;
|
|
|
|
i:DWORD;
|
|
|
|
key_table_size :DWORD;
|
|
value_table_size:DWORD;
|
|
|
|
hdr:t_sfo_header;
|
|
|
|
entry_table:p_sfo_table_entry;
|
|
key_table:PChar;
|
|
value_table:PByte;
|
|
|
|
size:DWORD;
|
|
name,value:RawByteString;
|
|
|
|
function load_chunk(offset,size:DWORD):Pointer;
|
|
begin
|
|
Result:=AllocMem(size);
|
|
FileSeek(fd,offset,fsFromBeginning);
|
|
if (FileRead(fd,Result^,size)<>size) then
|
|
begin
|
|
FreeMem(Result);
|
|
Result:=nil;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Result:=nil;
|
|
|
|
fd:=FileOpen(path,fmOpenRead);
|
|
if (fd=-1) then
|
|
begin
|
|
Writeln(StdErr,'Error open:',path);
|
|
Exit;
|
|
end;
|
|
|
|
hdr:=Default(t_sfo_header);
|
|
if (FileRead(fd,hdr,SizeOf(hdr))<>SizeOf(hdr)) then
|
|
begin
|
|
Writeln(StdErr,'Error read:',path);
|
|
FileClose(fd);
|
|
Exit;
|
|
end;
|
|
|
|
if (hdr.magic<>SFO_MAGIC) then
|
|
begin
|
|
Writeln(StdErr,'Invalid file:',path);
|
|
FileClose(fd);
|
|
Exit;
|
|
end;
|
|
|
|
entry_table:=load_chunk(SizeOf(hdr),hdr.entry_count*SizeOf(t_sfo_table_entry));
|
|
|
|
fsize:=FileSeek(fd,0,fsFromEnd);
|
|
|
|
if (hdr.key_table_offset>hdr.value_table_offset) then
|
|
begin
|
|
key_table_size :=fsize -hdr.key_table_offset;
|
|
value_table_size:=hdr.key_table_offset-hdr.value_table_offset;
|
|
end else
|
|
begin
|
|
key_table_size :=hdr.value_table_offset-hdr.key_table_offset;
|
|
value_table_size:=fsize -hdr.value_table_offset;
|
|
end;
|
|
|
|
key_table :=load_chunk(hdr.key_table_offset ,key_table_size);
|
|
value_table:=load_chunk(hdr.value_table_offset,value_table_size);
|
|
|
|
//
|
|
|
|
if (entry_table=nil) or
|
|
(key_table=nil) or
|
|
(value_table=nil) then
|
|
begin
|
|
Writeln(StdErr,'Error read:',path);
|
|
|
|
FreeMem(entry_table);
|
|
FreeMem(key_table);
|
|
FreeMem(value_table);
|
|
|
|
FileClose(fd);
|
|
Exit;
|
|
end;
|
|
|
|
Result:=TParamSfoFile.Create;
|
|
|
|
if (hdr.entry_count<>0) then
|
|
begin
|
|
SetLength(Result.params,hdr.entry_count);
|
|
|
|
For i:=0 to hdr.entry_count-1 do
|
|
begin
|
|
name :=PChar(key_table+entry_table[i].key_offset);
|
|
|
|
value:='';
|
|
size:=entry_table[i].max_size;
|
|
SetLength(value,size);
|
|
Move(PChar(value_table+entry_table[i].value_offset)^,PChar(value)^,size);
|
|
|
|
Result.params[i].format:=entry_table[i].format;
|
|
Result.params[i].name :=name;
|
|
Result.params[i].value :=value;
|
|
end;
|
|
end;
|
|
|
|
FreeMem(entry_table);
|
|
FreeMem(key_table);
|
|
FreeMem(value_table);
|
|
|
|
FileClose(fd);
|
|
end;
|
|
|
|
//
|
|
|
|
Function TParamSfoValue.GetString:RawByteString;
|
|
var
|
|
D:DWORD;
|
|
begin
|
|
Result:='';
|
|
case format of
|
|
SFO_FORMAT_STRING_SPECIAL,
|
|
SFO_FORMAT_STRING :Result:=value;
|
|
SFO_FORMAT_UINT32 :
|
|
begin
|
|
D:=PDWORD(PChar(value))^;
|
|
Result:=UIntToStr(D);
|
|
end;
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
Function TParamSfoValue.GetUInt:DWORD;
|
|
var
|
|
D:DWORD;
|
|
begin
|
|
Result:=0;
|
|
case format of
|
|
SFO_FORMAT_STRING_SPECIAL,
|
|
SFO_FORMAT_STRING :
|
|
begin
|
|
D:=0;
|
|
TryStrToDWord(value,D);
|
|
Result:=D;
|
|
end;
|
|
SFO_FORMAT_UINT32 :
|
|
begin
|
|
D:=PDWORD(PChar(value))^;
|
|
Result:=D;
|
|
end;
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
Function TParamSfoFile.GetString(const name:RawByteString):RawByteString;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
Result:='';
|
|
if (Self=nil) then Exit;
|
|
if (Length(params)=0) then Exit;
|
|
For i:=0 to High(params) do
|
|
begin
|
|
if (params[i].name=name) then
|
|
begin
|
|
Result:=params[i].GetString;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Function TParamSfoFile.GetUInt(const name:RawByteString):DWORD;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
Result:=0;
|
|
if (Self=nil) then Exit;
|
|
if (Length(params)=0) then Exit;
|
|
For i:=0 to High(params) do
|
|
begin
|
|
if (params[i].name=name) then
|
|
begin
|
|
Result:=params[i].GetUInt;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|
|
|