mirror of https://github.com/red-prig/fpPS4.git
441 lines
7.9 KiB
Plaintext
441 lines
7.9 KiB
Plaintext
unit game_edit;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls,
|
|
StdCtrls, Grids,
|
|
|
|
ms_shell_hack,
|
|
|
|
game_info,
|
|
param_sfo_gui;
|
|
|
|
type
|
|
|
|
{ TfrmGameEditor }
|
|
|
|
TfrmGameEditor = class(TForm)
|
|
BtnOk: TButton;
|
|
BtnCancel: TButton;
|
|
EditPages: TPageControl;
|
|
GridMain: TStringGrid;
|
|
GridMounts: TStringGrid;
|
|
GridParamSfo: TStringGrid;
|
|
TabMain: TTabSheet;
|
|
TabMounts: TTabSheet;
|
|
TabParamSfo: TTabSheet;
|
|
procedure BtnOkClick(Sender: TObject);
|
|
procedure BtnCancelClick(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
|
procedure FormInit(UpdateTitle:Boolean);
|
|
procedure FormSave;
|
|
procedure LoadParamSfo(UpdateTitle:Boolean);
|
|
procedure GridSelectEditor(Sender:TObject;aCol,aRow:Integer;var Editor:TWinControl);
|
|
procedure GridEditingDone(Sender: TObject);
|
|
private
|
|
Fapp0_row :Integer;
|
|
FName_row :Integer;
|
|
FTitleId_row:Integer;
|
|
FVersion_row:Integer;
|
|
|
|
Fapp0p:RawByteString;
|
|
public
|
|
OnSave :TNotifyEvent;
|
|
Item :TGameItem;
|
|
ParamSfo:TParamSfoFile;
|
|
end;
|
|
|
|
var
|
|
frmGameEditor: TfrmGameEditor;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
uses
|
|
TypInfo,
|
|
Rtti;
|
|
|
|
{ TfrmGameEditor }
|
|
|
|
type
|
|
TFieldInfo=class(TComponent)
|
|
procedure SelectEditor(Grid:TStringGrid;aCol,aRow:Integer;var Editor:TWinControl); virtual; abstract;
|
|
end;
|
|
|
|
TFieldInfoPath=class(TFieldInfo)
|
|
procedure SelectEditor(Grid:TStringGrid;aCol,aRow:Integer;var Editor:TWinControl); override;
|
|
end;
|
|
|
|
TButtonPath=class(TButton)
|
|
public
|
|
aRow:Integer;
|
|
Form :TWinControl;
|
|
Editor:TWinControl;
|
|
procedure EditorExit(Sender:TObject);
|
|
procedure OpenDir(Sender:TObject);
|
|
end;
|
|
|
|
procedure TButtonPath.EditorExit(Sender:TObject);
|
|
begin
|
|
Editor.OnEnter:=nil;
|
|
Editor.OnExit :=nil;
|
|
if not Focused then
|
|
begin
|
|
Hide;
|
|
end;
|
|
end;
|
|
|
|
type
|
|
TMyStringGrid=class(TStringGrid)
|
|
function NewBtn:TButtonPath;
|
|
procedure EditorDirEnter(Sender:TObject);
|
|
end;
|
|
|
|
procedure TButtonPath.OpenDir(Sender:TObject);
|
|
var
|
|
d:TSelectDirectoryDialog;
|
|
Cookie:Pointer;
|
|
begin
|
|
Cookie:=RegisterDllHack;
|
|
|
|
d:=nil;
|
|
|
|
try
|
|
d:=TSelectDirectoryDialog.Create(nil);
|
|
|
|
with TMyStringGrid(Editor.Parent) do
|
|
begin
|
|
d.InitialDir:=Cells[1,aRow];
|
|
end;
|
|
|
|
d.Options:=[ofPathMustExist,ofEnableSizing,ofViewDetail];
|
|
|
|
if d.Execute then
|
|
with TMyStringGrid(Editor.Parent) do
|
|
begin
|
|
Cells[1,aRow]:=d.FileName;
|
|
end;
|
|
|
|
except
|
|
//
|
|
end;
|
|
FreeAndNil(d);
|
|
|
|
UnregisterDllHack(Cookie);
|
|
|
|
TfrmGameEditor(Self.Form).LoadParamSfo(True);
|
|
|
|
Hide;
|
|
end;
|
|
|
|
function TMyStringGrid.NewBtn:TButtonPath;
|
|
var
|
|
i:Integer;
|
|
btn:TButtonPath;
|
|
begin
|
|
btn:=nil;
|
|
|
|
if (ComponentCount<>0) then
|
|
for i:=0 to ComponentCount-1 do
|
|
begin
|
|
if Components[i] is TButtonPath then
|
|
begin
|
|
btn:=TButtonPath(Components[i]);
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
if (btn=nil) then
|
|
begin
|
|
btn:=TButtonPath.Create(Self);
|
|
|
|
btn.Form:=TWinControl(Self.Tag);
|
|
|
|
btn.AutoSize:=True;
|
|
btn.Caption:='...';
|
|
|
|
btn.Parent:=Self;
|
|
|
|
btn.BorderSpacing.Top :=-3;
|
|
btn.BorderSpacing.Right :=-3;
|
|
btn.BorderSpacing.Bottom:=-3;
|
|
end;
|
|
|
|
btn.aRow:=Self.Row;
|
|
|
|
btn.AnchorSide[akTop].Side:=asrTop;
|
|
btn.AnchorSide[akTop].Control:=Editor;
|
|
|
|
btn.AnchorSide[akRight].Side:=asrBottom;
|
|
btn.AnchorSide[akRight].Control:=Editor;
|
|
|
|
btn.AnchorSide[akBottom].Side:=asrBottom;
|
|
btn.AnchorSide[akBottom].Control:=Editor;
|
|
|
|
btn.Anchors:=[akTop,akRight,akBottom];
|
|
|
|
btn.Editor:=Editor;
|
|
|
|
Result:=btn;
|
|
end;
|
|
|
|
procedure TMyStringGrid.EditorDirEnter(Sender:TObject);
|
|
var
|
|
btn:TButtonPath;
|
|
begin
|
|
btn:=NewBtn;
|
|
|
|
btn.OnClick:=@btn.OpenDir;
|
|
|
|
Editor.OnExit:=@btn.EditorExit;
|
|
|
|
btn.Show;
|
|
end;
|
|
|
|
procedure TFieldInfoPath.SelectEditor(Grid:TStringGrid;aCol,aRow:Integer;var Editor:TWinControl);
|
|
begin
|
|
Editor.OnEnter:=@TMyStringGrid(Grid).EditorDirEnter;
|
|
end;
|
|
|
|
procedure AddRow(Grid:TStringGrid;const name,value:RawByteString;info:TFieldInfo);
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Grid.RowCount;
|
|
Grid.RowCount:=i+1;
|
|
Grid.Cells[0,i]:=name;
|
|
Grid.Cells[1,i]:=value;
|
|
Grid.Objects[0,i]:=info;
|
|
end;
|
|
|
|
procedure TfrmGameEditor.FormInit(UpdateTitle:Boolean);
|
|
var
|
|
fip:TFieldInfoPath;
|
|
|
|
i:TRttiPropertyIterator;
|
|
p:TRttiProperty;
|
|
begin
|
|
EditPages.ActivePageIndex:=0;
|
|
|
|
GridMain.Clear;
|
|
GridMounts.Clear;
|
|
|
|
//TypInfo.SetRawByteStrProp();
|
|
|
|
//AddRow(GridMain,'Name:',nil);
|
|
|
|
//
|
|
fip:=TFieldInfoPath.Create(Self);
|
|
//
|
|
|
|
i:=Item.FGameInfo.GetPropertyIterator;
|
|
try
|
|
while (i.GetProperty<>nil) do
|
|
begin
|
|
|
|
p:=i.GetProperty;
|
|
case p.Name of
|
|
'Name' :FName_row :=GridMain.RowCount;
|
|
'TitleId':FTitleId_row:=GridMain.RowCount;
|
|
'Version':FVersion_row:=GridMain.RowCount;
|
|
else;
|
|
end;
|
|
|
|
AddRow(GridMain,p.Name+':',p.GetValue(Item.FGameInfo).AsString,nil);
|
|
|
|
i.Next;
|
|
end;
|
|
finally
|
|
i.free;
|
|
end;
|
|
|
|
i:=Item.FMountList.GetPropertyIterator;
|
|
try
|
|
while (i.GetProperty<>nil) do
|
|
begin
|
|
|
|
p:=i.GetProperty;
|
|
|
|
case p.Name of
|
|
'app0':Fapp0_row:=GridMounts.RowCount;
|
|
else;
|
|
end;
|
|
|
|
AddRow(GridMounts,'/'+p.Name,p.GetValue(Item.FMountList).AsString,fip);
|
|
|
|
i.Next;
|
|
end;
|
|
finally
|
|
i.free;
|
|
end;
|
|
|
|
LoadParamSfo(UpdateTitle);
|
|
|
|
Show;
|
|
end;
|
|
|
|
procedure TfrmGameEditor.FormSave;
|
|
var
|
|
i:TRttiPropertyIterator;
|
|
p:TRttiProperty;
|
|
begin
|
|
i:=Item.FGameInfo.GetPropertyIterator;
|
|
try
|
|
while (i.GetProperty<>nil) do
|
|
begin
|
|
|
|
p:=i.GetProperty;
|
|
p.SetValue(Item.FGameInfo,GridMain.Cells[1,i.i]);
|
|
|
|
i.Next;
|
|
end;
|
|
finally
|
|
i.free;
|
|
end;
|
|
|
|
i:=Item.FMountList.GetPropertyIterator;
|
|
try
|
|
while (i.GetProperty<>nil) do
|
|
begin
|
|
|
|
p:=i.GetProperty;
|
|
p.SetValue(Item.FMountList,GridMounts.Cells[1,i.i]);
|
|
|
|
i.Next;
|
|
end;
|
|
finally
|
|
i.free;
|
|
end;
|
|
|
|
end;
|
|
|
|
function GetGridVal(Grid:TStringGrid;ARow:Integer):RawByteString;
|
|
begin
|
|
Result:='';
|
|
if (ARow<0) and (ARow>=Grid.RowCount) then Exit;
|
|
//
|
|
Result:=Grid.Cells[1,ARow];
|
|
end;
|
|
|
|
procedure SetGridVal(Grid:TStringGrid;ARow:Integer;const value:RawByteString);
|
|
begin
|
|
if (ARow<0) and (ARow>=Grid.RowCount) then Exit;
|
|
//
|
|
Grid.Cells[1,ARow]:=value;
|
|
end;
|
|
|
|
procedure TfrmGameEditor.LoadParamSfo(UpdateTitle:Boolean);
|
|
var
|
|
i:Integer;
|
|
V:RawByteString;
|
|
begin
|
|
V:=GetGridVal(GridMounts,Fapp0_row);
|
|
|
|
if (Fapp0p=V) then Exit;
|
|
|
|
FreeAndNil(ParamSfo);
|
|
|
|
ParamSfo:=LoadParamSfoFile(ExcludeTrailingPathDelimiter(V)+
|
|
DirectorySeparator+
|
|
'sce_sys'+
|
|
DirectorySeparator+
|
|
'param.sfo');
|
|
|
|
Fapp0p:=V;
|
|
|
|
GridParamSfo.Clear;
|
|
|
|
if (ParamSfo=nil) then
|
|
begin
|
|
SetGridVal(GridMain,FTitleId_row,'???');
|
|
SetGridVal(GridMain,FVersion_row,'???');
|
|
Exit;
|
|
end;
|
|
|
|
if (Length(ParamSfo.params)=0) then Exit;
|
|
For i:=0 to High(ParamSfo.params) do
|
|
begin
|
|
if (ParamSfo.params[i].format=SFO_FORMAT_UINT32) then
|
|
begin
|
|
V:='0x'+HexStr(ParamSfo.params[i].GetUInt,8);
|
|
end else
|
|
begin
|
|
V:=Trim(ParamSfo.params[i].GetString);
|
|
end;
|
|
AddRow(GridParamSfo,ParamSfo.params[i].name,V,nil);
|
|
end;
|
|
|
|
GridParamSfo.AutoSizeColumn(0);
|
|
|
|
//
|
|
if not UpdateTitle then Exit;
|
|
|
|
V:=ParamSfo.GetString('TITLE');
|
|
SetGridVal(GridMain,FName_row,V);
|
|
|
|
V:=ParamSfo.GetString('TITLE_ID');
|
|
SetGridVal(GridMain,FTitleId_row,V);
|
|
|
|
V:=ParamSfo.GetString('APP_VER');
|
|
SetGridVal(GridMain,FVersion_row,V);
|
|
end;
|
|
|
|
procedure TfrmGameEditor.GridSelectEditor(Sender:TObject;aCol,aRow:Integer;var Editor:TWinControl);
|
|
var
|
|
obj:TObject;
|
|
begin
|
|
obj:=TStringGrid(Sender).Objects[0,aRow];
|
|
if (obj=nil) then Exit;
|
|
if not obj.InheritsFrom(TFieldInfo) then Exit;
|
|
//
|
|
TStringGrid(Sender).Tag:=PtrInt(Self);
|
|
//
|
|
TFieldInfo(obj).SelectEditor(TStringGrid(Sender),aCol,aRow,Editor);
|
|
end;
|
|
|
|
procedure TfrmGameEditor.GridEditingDone(Sender: TObject);
|
|
begin
|
|
LoadParamSfo(True);
|
|
end;
|
|
|
|
procedure TfrmGameEditor.BtnOkClick(Sender: TObject);
|
|
begin
|
|
FormSave;
|
|
Hide;
|
|
if Assigned(OnSave) then
|
|
begin
|
|
OnSave(Self);
|
|
end;
|
|
Close;
|
|
end;
|
|
|
|
procedure TfrmGameEditor.BtnCancelClick(Sender: TObject);
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TfrmGameEditor.FormClose(Sender:TObject;var CloseAction:TCloseAction);
|
|
begin
|
|
if (Item<>nil) then
|
|
begin
|
|
if Item.FLock then
|
|
begin
|
|
Item.FLock:=False;
|
|
end else
|
|
begin
|
|
FreeAndNil(Item);
|
|
end;
|
|
end;
|
|
//
|
|
FreeAndNil(ParamSfo);
|
|
//
|
|
CloseAction:=caFree;
|
|
end;
|
|
|
|
end.
|
|
|