FPPS4/gui/param_sfo_gui.pas

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.