From 520cb4343b52cad6acc2496d7a4933958368b721 Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Fri, 18 Jul 2025 14:59:35 +0300 Subject: [PATCH] new_mount_system --- fpPS4.lpi | 8 + gui/cfg_edit.lfm | 422 ++++++++++++++++++++---------------- gui/cfg_edit.pas | 351 +++++++++++++----------------- gui/form_filler.pas | 262 ++++++++++++++++++++++ gui/game_edit.lfm | 381 ++++++++++++++++++++++++++------ gui/game_edit.pas | 421 +++++++++++++---------------------- gui/game_info.pas | 91 ++++---- gui/game_mount.pas | 248 +++++++++++++++++++++ gui/game_run.pas | 107 +++++---- gui/main.lfm | 29 ++- gui/main.pas | 86 +++++--- icons/Add_04_16.png | Bin 0 -> 369 bytes icons/Folder_19_16.png | Bin 0 -> 606 bytes icons/Remove_01_16.png | Bin 0 -> 233 bytes sys/kern/kern_exec.pas | 14 +- sys/kern/subr_backtrace.pas | 11 +- sys/vfs/vfs_mount.pas | 23 +- sys/vfs/vfs_mountroot.pas | 25 ++- 18 files changed, 1603 insertions(+), 876 deletions(-) create mode 100644 gui/form_filler.pas create mode 100644 gui/game_mount.pas create mode 100644 icons/Add_04_16.png create mode 100644 icons/Folder_19_16.png create mode 100644 icons/Remove_01_16.png diff --git a/fpPS4.lpi b/fpPS4.lpi index e61286e3..ac90d60e 100644 --- a/fpPS4.lpi +++ b/fpPS4.lpi @@ -1643,6 +1643,14 @@ + + + + + + + + diff --git a/gui/cfg_edit.lfm b/gui/cfg_edit.lfm index cb0de1f8..d3dd412a 100644 --- a/gui/cfg_edit.lfm +++ b/gui/cfg_edit.lfm @@ -1,28 +1,36 @@ object frmCfgEditor: TfrmCfgEditor - Left = 448 - Height = 319 - Top = 198 - Width = 400 + Left = 629 + Height = 339 + Top = 127 + Width = 459 Caption = 'Config Editor' - ClientHeight = 319 - ClientWidth = 400 + ClientHeight = 339 + ClientWidth = 459 Position = poMainFormCenter - LCLVersion = '3.6.0.0' + LCLVersion = '3.8.0.0' object EditPages: TPageControl - Left = 0 - Height = 270 - Top = 0 - Width = 397 - ActivePage = Tab_PS4System + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = BtnOk + Left = 5 + Height = 289 + Top = 5 + Width = 449 + ActivePage = Tab_MainInfo Align = alCustom Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 5 + BorderSpacing.Top = 5 + BorderSpacing.Right = 5 BorderSpacing.Bottom = 10 - TabIndex = 5 + TabIndex = 0 TabOrder = 0 object Tab_MainInfo: TTabSheet Caption = 'Main' - ClientHeight = 242 - ClientWidth = 389 + ClientHeight = 261 + ClientWidth = 441 object Label1: TLabel AnchorSideLeft.Control = Tab_MainInfo AnchorSideTop.Control = Tab_MainInfo @@ -31,7 +39,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 15 Top = 10 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -42,35 +50,16 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideLeft.Control = Tab_MainInfo AnchorSideTop.Control = Label1 AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Tab_MainInfo - AnchorSideRight.Side = asrBottom + AnchorSideRight.Control = BtnExpLog Left = 10 Height = 23 Top = 35 - Width = 369 + Width = 396 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 - BorderSpacing.Right = 10 TabOrder = 0 end - object Edt_MainInfo_fork_proc: TCheckBox - AnchorSideLeft.Control = Tab_MainInfo - AnchorSideTop.Control = Edt_MainInfo_data - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Tab_MainInfo - AnchorSideRight.Side = asrBottom - Left = 10 - Height = 19 - Top = 184 - Width = 369 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 - BorderSpacing.Right = 10 - Caption = 'Run in a separate process' - TabOrder = 4 - end object Label2: TLabel AnchorSideLeft.Control = Tab_MainInfo AnchorSideTop.Control = Edt_MainInfo_LogFile @@ -80,60 +69,12 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 15 Top = 68 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 BorderSpacing.Right = 10 - Caption = 'Default System Firmware folder:' - end - object Edt_MainInfo_system: TEdit - AnchorSideLeft.Control = Tab_MainInfo - AnchorSideTop.Control = Label2 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Tab_MainInfo - AnchorSideRight.Side = asrBottom - Left = 10 - Height = 23 - Top = 93 - Width = 369 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 - BorderSpacing.Right = 10 - TabOrder = 2 - end - object Label3: TLabel - AnchorSideLeft.Control = Tab_MainInfo - AnchorSideTop.Control = Edt_MainInfo_system - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Tab_MainInfo - AnchorSideRight.Side = asrBottom - Left = 10 - Height = 15 - Top = 126 - Width = 369 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 - BorderSpacing.Right = 10 - Caption = 'Default System data folder:' - end - object Edt_MainInfo_data: TEdit - AnchorSideLeft.Control = Tab_MainInfo - AnchorSideTop.Control = Label3 - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Tab_MainInfo - AnchorSideRight.Side = asrBottom - Left = 10 - Height = 23 - Top = 151 - Width = 369 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 - BorderSpacing.Right = 10 - TabOrder = 3 + Caption = 'Default Firmware folder:' end object BtnLogOpen: TButton AnchorSideTop.Control = Edt_MainInfo_LogFile @@ -141,7 +82,7 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Edt_MainInfo_LogFile AnchorSideBottom.Side = asrBottom - Left = 343 + Left = 370 Height = 21 Top = 36 Width = 35 @@ -154,49 +95,140 @@ object frmCfgEditor: TfrmCfgEditor TabOrder = 1 OnClick = BtnLogOpenClick end - object BtnSysOpen: TButton - AnchorSideTop.Control = Edt_MainInfo_system - AnchorSideRight.Control = Edt_MainInfo_system + object BtnExpLog: TSpeedButton + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Edt_MainInfo_LogFile + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = Tab_MainInfo AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Edt_MainInfo_system - AnchorSideBottom.Side = asrBottom - Left = 343 - Height = 21 - Top = 94 - Width = 35 - Anchors = [akTop, akRight, akBottom] + AnchorSideBottom.Control = Edt_MainInfo_LogFile + AnchorSideBottom.Side = asrCenter + Left = 411 + Height = 20 + Top = 36 + Width = 20 + Anchors = [akTop, akRight] AutoSize = True - BorderSpacing.Top = 1 - BorderSpacing.Right = 1 - BorderSpacing.Bottom = 1 - Caption = '...' - TabOrder = 5 - OnClick = BtnSysOpenClick + BorderSpacing.Left = 5 + BorderSpacing.Right = 10 + Images = frmMain.SmallImageList + ImageIndex = 0 + OnClick = BtnExpLogClick end - object BtnDataOpen: TButton - AnchorSideTop.Control = Edt_MainInfo_data - AnchorSideRight.Control = Edt_MainInfo_data + object Edt_MainInfo_FirmwareList: TListBox + AnchorSideLeft.Control = Tab_MainInfo + AnchorSideTop.Control = BtnAddFw + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Tab_MainInfo AnchorSideRight.Side = asrBottom - AnchorSideBottom.Control = Edt_MainInfo_data + AnchorSideBottom.Control = Tab_MainInfo AnchorSideBottom.Side = asrBottom - Left = 343 - Height = 21 - Top = 152 - Width = 35 - Anchors = [akTop, akRight, akBottom] + Left = 10 + Height = 102 + Top = 149 + Width = 421 + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Left = 10 + BorderSpacing.Top = 3 + BorderSpacing.Right = 10 + BorderSpacing.Bottom = 10 + ItemHeight = 0 + TabOrder = 3 + end + object BtnAddFw: TSpeedButton + AnchorSideLeft.Control = Edt_MainInfo_FirmwareList + AnchorSideTop.Control = Edt_MainInfo_DefaultFirmware + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Tab_MainInfo + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Edt_MainInfo_FirmwareList + Left = 10 + Height = 20 + Top = 126 + Width = 20 AutoSize = True - BorderSpacing.Top = 1 - BorderSpacing.Right = 1 - BorderSpacing.Bottom = 1 - Caption = '...' - TabOrder = 6 - OnClick = BtnDataOpenClick + BorderSpacing.Top = 10 + BorderSpacing.Right = 5 + Images = frmMain.SmallImageList + ImageIndex = 1 + OnClick = BtnAddFwClick + end + object BtnRemFw: TSpeedButton + AnchorSideLeft.Control = BtnAddFw + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = BtnAddFw + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = Tab_MainInfo + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Edt_MainInfo_FirmwareList + Left = 35 + Height = 20 + Top = 126 + Width = 20 + AutoSize = True + Images = frmMain.SmallImageList + ImageIndex = 2 + OnClick = BtnRemFwClick + end + object Label3: TLabel + AnchorSideLeft.Control = BtnRemFw + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Edt_MainInfo_LogFile + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Tab_MainInfo + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Edt_MainInfo_FirmwareList + Left = 65 + Height = 15 + Top = 124 + Width = 366 + Anchors = [akLeft, akRight, akBottom] + BorderSpacing.Left = 10 + BorderSpacing.Right = 10 + BorderSpacing.Bottom = 10 + Caption = 'Firmware folder list:' + end + object Edt_MainInfo_DefaultFirmware: TComboBox + AnchorSideLeft.Control = Tab_MainInfo + AnchorSideTop.Control = Label2 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = BtnExpSys + Left = 10 + Height = 23 + Top = 93 + Width = 396 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + ItemHeight = 15 + TabOrder = 2 + OnGetItems = Edt_MainInfo_DefaultFirmwareGetItems + end + object BtnExpSys: TSpeedButton + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Edt_MainInfo_DefaultFirmware + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = Tab_MainInfo + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Edt_MainInfo_LogFile + AnchorSideBottom.Side = asrCenter + Left = 411 + Height = 20 + Top = 94 + Width = 20 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Left = 5 + BorderSpacing.Right = 10 + Images = frmMain.SmallImageList + ImageIndex = 0 + OnClick = BtnExpSysClick end end object Tab_BootparamInfo: TTabSheet Caption = 'Bootparam' - ClientHeight = 242 - ClientWidth = 389 + ClientHeight = 261 + ClientWidth = 441 object Edt_BootparamInfo_neo: TCheckBox AnchorSideLeft.Control = Tab_BootparamInfo AnchorSideTop.Control = Tab_BootparamInfo @@ -205,7 +237,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 10 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -222,7 +254,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 39 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -239,7 +271,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 68 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -256,7 +288,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 97 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -273,7 +305,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 126 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -290,7 +322,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 155 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -307,7 +339,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 184 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -318,8 +350,8 @@ object frmCfgEditor: TfrmCfgEditor end object Tab_JIT: TTabSheet Caption = 'JIT' - ClientHeight = 242 - ClientWidth = 389 + ClientHeight = 261 + ClientWidth = 441 object Edt_JITInfo_print_asm: TCheckBox AnchorSideLeft.Control = Tab_JIT AnchorSideTop.Control = Tab_JIT @@ -328,7 +360,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 10 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -345,7 +377,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 39 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -362,7 +394,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 68 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -379,7 +411,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 19 Top = 97 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -390,23 +422,24 @@ object frmCfgEditor: TfrmCfgEditor end object Tab_Misc: TTabSheet Caption = 'Misc' - ClientHeight = 242 - ClientWidth = 389 + ClientHeight = 261 + ClientWidth = 441 object Edt_MiscInfo_strict_ps4_freq: TCheckBox AnchorSideLeft.Control = Tab_Misc - AnchorSideTop.Control = Tab_Misc + AnchorSideTop.Control = Edt_MiscInfo_fork_proc + AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Tab_Misc AnchorSideRight.Side = asrBottom Left = 10 Height = 19 - Top = 10 - Width = 369 + Top = 39 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 BorderSpacing.Right = 10 Caption = 'Strict rdtsc timer frequency' - TabOrder = 0 + TabOrder = 1 end object Edt_MiscInfo_renderdoc_capture: TCheckBox AnchorSideLeft.Control = Tab_Misc @@ -416,20 +449,39 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideRight.Side = asrBottom Left = 10 Height = 19 - Top = 39 - Width = 369 + Top = 68 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 BorderSpacing.Right = 10 Caption = 'Use renderdoc capture' - TabOrder = 1 + TabOrder = 2 + end + object Edt_MiscInfo_fork_proc: TCheckBox + AnchorSideLeft.Control = Tab_Misc + AnchorSideTop.Control = Tab_Misc + AnchorSideRight.Control = Tab_Misc + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Tab_MainInfo + AnchorSideBottom.Side = asrBottom + Left = 10 + Height = 19 + Top = 10 + Width = 421 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + BorderSpacing.Bottom = 10 + Caption = 'Run in a separate process' + TabOrder = 0 end end object Tab_Vulkan: TTabSheet Caption = 'Vulkan' - ClientHeight = 242 - ClientWidth = 389 + ClientHeight = 261 + ClientWidth = 441 object Edt_VulkanInfo_device_cmb: TComboBox AnchorSideLeft.Control = Tab_Vulkan AnchorSideTop.Control = Label4 @@ -439,7 +491,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 23 Top = 35 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -456,7 +508,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 15 Top = 10 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -472,7 +524,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 165 Top = 68 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] AutoFill = True AutoSize = True @@ -489,7 +541,7 @@ object frmCfgEditor: TfrmCfgEditor ChildSizing.Layout = cclTopToBottomThenLeftToRight ChildSizing.ControlsPerLine = 7 ClientHeight = 145 - ClientWidth = 365 + ClientWidth = 417 ColumnLayout = clVerticalThenHorizontal Columns = 2 Items.Strings = ( @@ -516,22 +568,36 @@ object frmCfgEditor: TfrmCfgEditor end object Tab_PS4System: TTabSheet Caption = 'PS4 System' - ClientHeight = 242 - ClientWidth = 389 + ClientHeight = 261 + ClientWidth = 441 object PanelHalf: TPanel AnchorSideLeft.Control = Tab_PS4System AnchorSideLeft.Side = asrCenter - AnchorSideRight.Control = Tab_PS4System AnchorSideRight.Side = asrCenter - Left = 188 - Height = 49 - Top = 64 + Left = 214 + Height = 26 + Top = 151 Width = 12 - Anchors = [akTop, akLeft, akRight] BevelOuter = bvNone Enabled = False TabOrder = 0 end + object Label5: TLabel + AnchorSideLeft.Control = Tab_PS4System + AnchorSideTop.Control = Edt_PS4SystemService_SystemName + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = Tab_PS4System + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 15 + Top = 68 + Width = 421 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Language:' + end object Edt_PS4SystemService_Language: TComboBox AnchorSideLeft.Control = Tab_PS4System AnchorSideTop.Control = Label5 @@ -541,7 +607,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 23 Top = 93 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -591,7 +657,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 23 Top = 151 - Width = 168 + Width = 194 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -613,7 +679,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 15 Top = 126 - Width = 168 + Width = 194 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -627,10 +693,10 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Tab_PS4System AnchorSideRight.Side = asrBottom - Left = 210 + Left = 236 Height = 23 Top = 151 - Width = 169 + Width = 195 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -650,10 +716,10 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Tab_PS4System AnchorSideRight.Side = asrBottom - Left = 210 + Left = 236 Height = 15 Top = 126 - Width = 169 + Width = 195 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -668,7 +734,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 15 Top = 184 - Width = 168 + Width = 194 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -683,7 +749,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 23 Top = 209 - Width = 168 + Width = 194 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -704,29 +770,13 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 15 Top = 10 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 BorderSpacing.Right = 10 Caption = 'System Name:' end - object Label5: TLabel - AnchorSideLeft.Control = Tab_PS4System - AnchorSideTop.Control = Edt_PS4SystemService_SystemName - AnchorSideTop.Side = asrBottom - AnchorSideRight.Control = Tab_PS4System - AnchorSideRight.Side = asrBottom - Left = 10 - Height = 15 - Top = 68 - Width = 369 - Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 - BorderSpacing.Right = 10 - Caption = 'Language:' - end object Edt_PS4SystemService_SystemName: TEdit AnchorSideLeft.Control = Tab_PS4System AnchorSideTop.Control = Label9 @@ -736,7 +786,7 @@ object frmCfgEditor: TfrmCfgEditor Left = 10 Height = 23 Top = 35 - Width = 369 + Width = 421 Anchors = [akTop, akLeft, akRight] BorderSpacing.Left = 10 BorderSpacing.Top = 10 @@ -752,9 +802,9 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Owner AnchorSideBottom.Side = asrBottom - Left = 315 + Left = 374 Height = 25 - Top = 284 + Top = 304 Width = 75 Anchors = [akRight, akBottom] AutoSize = True @@ -772,7 +822,7 @@ object frmCfgEditor: TfrmCfgEditor AnchorSideBottom.Side = asrBottom Left = 10 Height = 25 - Top = 284 + Top = 304 Width = 75 Anchors = [akLeft, akBottom] AutoSize = True diff --git a/gui/cfg_edit.pas b/gui/cfg_edit.pas index 90b78175..877972a3 100644 --- a/gui/cfg_edit.pas +++ b/gui/cfg_edit.pas @@ -6,12 +6,15 @@ interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls, - ExtCtrls, + ExtCtrls, Buttons, + + lclintf, Vulkan, vDevice, - game_info; + game_info, + form_filler; type TVulkanDevGuid=class(TComponent) @@ -31,11 +34,14 @@ type { TfrmCfgEditor } TfrmCfgEditor = class(TForm) + BtnExpSys: TSpeedButton; + BtnRemFw: TSpeedButton; BtnCancel: TButton; - BtnSysOpen: TButton; + BtnAddFw: TSpeedButton; BtnOk: TButton; BtnLogOpen: TButton; - BtnDataOpen: TButton; + Edt_MainInfo_DefaultFirmware: TComboBox; + Edt_MiscInfo_fork_proc: TCheckBox; Edt_PS4SystemService_SystemName: TEdit; Edt_PS4SystemService_ButtonAssign: TComboBox; Edt_PS4SystemService_TimeFormat: TComboBox; @@ -54,12 +60,9 @@ type Edt_BootparamInfo_print_pmap: TCheckBox; Edt_BootparamInfo_print_jit_preload: TCheckBox; Edt_JITInfo_memory_guard: TCheckBox; - Edt_MainInfo_fork_proc: TCheckBox; Edt_MainInfo_LogFile: TEdit; Edt_BootparamInfo_neo: TCheckBox; EditPages: TPageControl; - Edt_MainInfo_system: TEdit; - Edt_MainInfo_data: TEdit; Edt_MiscInfo_renderdoc_capture: TCheckBox; Label1: TLabel; Label2: TLabel; @@ -70,20 +73,23 @@ type Label7: TLabel; Label8: TLabel; Label9: TLabel; + Edt_MainInfo_FirmwareList: TListBox; PanelHalf: TPanel; + BtnExpLog: TSpeedButton; Tab_PS4System: TTabSheet; Tab_Vulkan: TTabSheet; Tab_Misc: TTabSheet; Tab_JIT: TTabSheet; Tab_MainInfo: TTabSheet; Tab_BootparamInfo: TTabSheet; + procedure BtnAddFwClick(Sender: TObject); procedure BtnCancelClick(Sender: TObject); - procedure BtnDataOpenClick(Sender: TObject); + procedure BtnExpLogClick(Sender: TObject); + procedure BtnExpSysClick(Sender: TObject); procedure BtnOkClick(Sender: TObject); procedure BtnLogOpenClick(Sender: TObject); - procedure BtnSysOpenClick(Sender: TObject); - procedure PageInit(const TabName:RawByteString;obj:TAbstractObject); - procedure PageSave(const TabName:RawByteString;obj:TAbstractObject); + procedure BtnRemFwClick(Sender: TObject); + procedure Edt_MainInfo_DefaultFirmwareGetItems(Sender: TObject); procedure VulkanInit; procedure FormInit; procedure FormSave; @@ -108,6 +114,7 @@ uses TypInfo, Rtti, + ms_shell_hack, ps4_libSceSystemService; var @@ -142,71 +149,120 @@ begin Close; end; -procedure DoOpenFile(Edit:TEdit); +function DoOpenFile(const Input,InitialDir:RawByteString):RawByteString; var d:TOpenDialog; + Cookie:Pointer; begin + Cookie:=RegisterDllHack; + + Result:=Input; d:=nil; try d:=TOpenDialog.Create(nil); - d.InitialDir:=Edit.Text; + d.InitialDir:=InitialDir; d.Options:=[ofPathMustExist,ofEnableSizing,ofViewDetail]; if d.Execute then begin - Edit.Text:=d.FileName; + Result:=d.FileName; end; except // end; FreeAndNil(d); + + UnregisterDllHack(Cookie); end; -procedure DoOpenDir(Edit:TEdit); +function DoOpenDir(const Input,InitialDir:RawByteString):RawByteString; var d:TSelectDirectoryDialog; + Cookie:Pointer; begin + Cookie:=RegisterDllHack; + + Result:=Input; d:=nil; try d:=TSelectDirectoryDialog.Create(nil); - d.InitialDir:=Edit.Text; + d.InitialDir:=InitialDir; d.Options:=[ofPathMustExist,ofEnableSizing,ofViewDetail]; if d.Execute then begin - Edit.Text:=d.FileName; + Result:=d.FileName; end; except // end; FreeAndNil(d); + + UnregisterDllHack(Cookie); end; procedure TfrmCfgEditor.BtnLogOpenClick(Sender: TObject); begin - DoOpenFile(Edt_MainInfo_LogFile); + Edt_MainInfo_LogFile.Text:=DoOpenFile(Edt_MainInfo_LogFile.Text,Edt_MainInfo_LogFile.Text); end; -procedure TfrmCfgEditor.BtnSysOpenClick(Sender: TObject); +procedure TfrmCfgEditor.BtnAddFwClick(Sender:TObject); +var + new:RawByteString; begin - DoOpenDir(Edt_MainInfo_system); + new:=DoOpenDir('',''); + if (new='') then Exit; + + Edt_MainInfo_FirmwareList .Items.Add(new); + Edt_MainInfo_DefaultFirmware.Items.Add(new); end; -procedure TfrmCfgEditor.BtnDataOpenClick(Sender: TObject); +procedure TfrmCfgEditor.BtnRemFwClick(Sender: TObject); +var + i:Integer; begin - DoOpenDir(Edt_MainInfo_data); + i:=Edt_MainInfo_FirmwareList.ItemIndex; + if (i>=0) and (i0) then + begin + //preload + For i:=0 to Edt_MainInfo_FirmwareList.Items.Count-1 do + begin + S:=Edt_MainInfo_FirmwareList.Items.Strings[i]; + Edt_MainInfo_DefaultFirmware.Items.Add(S); + end; end; +end; - TMyButtonControl=class(TButtonControl) - public - property Checked; +function OpenFolderOfFile(APath:RawByteString): Boolean; +begin + APath:=ExtractFilePath(APath); + if (Trim(APath)='') then + begin + APath:=GetCurrentDir; end; + Result:=OpenDocument(APath); +end; -//src: TComboBox; +procedure TfrmCfgEditor.BtnExpLogClick(Sender: TObject); +begin + OpenFolderOfFile(Edt_MainInfo_LogFile.Text); +end; + +procedure TfrmCfgEditor.BtnExpSysClick(Sender: TObject); +begin + OpenDocument(Edt_MainInfo_DefaultFirmware.Text); +end; Function TVulkanDevGuid.GetText:RawByteString; var @@ -279,8 +335,19 @@ begin end; // +type + TCfgFormData=class(TFormDataProvider) + procedure SetText (control:TComponent;const Text:RawByteString); override; + function GetText (control:TComponent):RawByteString; override; + procedure SetInteger(control:TComponent;i:Integer); override; + function GetInteger(control:TComponent):Integer; override; + procedure SetBool (control:TComponent;B:Boolean); override; + function GetBool (control:TComponent):Boolean; override; + procedure SetClass (control:TComponent;Obj:TObject); override; + procedure GetClass (control:TComponent;Obj:TObject); override; + end; -procedure SetText(control:TComponent;const Text:RawByteString); +procedure TCfgFormData.SetText(control:TComponent;const Text:RawByteString); begin if (control is TVulkanDevGuid) then begin @@ -292,7 +359,7 @@ begin end; end; -function GetText(control:TComponent):RawByteString; +function TCfgFormData.GetText(control:TComponent):RawByteString; begin Result:=''; if (control is TVulkanDevGuid) then @@ -307,7 +374,7 @@ end; // -procedure SetInteger(control:TComponent;i:Integer); +procedure TCfgFormData.SetInteger(control:TComponent;i:Integer); begin if (control is TVulkanAppFlags) then begin @@ -337,7 +404,7 @@ begin end; end; -function GetInteger(control:TComponent):Integer; +function TCfgFormData.GetInteger(control:TComponent):Integer; begin Result:=0; if (control is TVulkanAppFlags) then @@ -352,7 +419,7 @@ end; // -procedure SetBool(control:TComponent;B:Boolean); +procedure TCfgFormData.SetBool(control:TComponent;B:Boolean); begin if control.InheritsFrom(TButtonControl) then begin @@ -360,7 +427,7 @@ begin end; end; -function GetBool(control:TComponent):Boolean; +function TCfgFormData.GetBool(control:TComponent):Boolean; begin Result:=False; if control.InheritsFrom(TButtonControl) then @@ -369,114 +436,48 @@ begin end; end; +procedure TCfgFormData.SetClass(control:TComponent;Obj:TObject); +var + A:TStringArray; + i:Integer; +begin + if control.InheritsFrom(TListBox) then + begin + A:=TStringArray(Obj); + + if (Length(A.values)>0) then + For i:=0 to High(A.values) do + begin + TListBox(control).Items.Add(A.values[i]); + end; + + end; +end; + +procedure TCfgFormData.GetClass(control:TComponent;Obj:TObject); +var + A:TStringArray; + i,c:Integer; +begin + if control.InheritsFrom(TListBox) then + begin + A:=TStringArray(Obj); + + c:=TListBox(control).Items.Count; + + SetLength(A.values,c); + + if (c>0) then + For i:=0 to c-1 do + begin + A.values[i]:=TListBox(control).Items.Strings[i]; + end; + + end; +end; + // -procedure TfrmCfgEditor.PageInit(const TabName:RawByteString;obj:TAbstractObject); -var - i:TRttiPropertyIterator; - p:TRttiProperty; - TypeKind:TTypeKind; - - cname:RawByteString; - control:TComponent; -begin - - i:=obj.GetPropertyIterator; - try - while (i.GetProperty<>nil) do - begin - - p:=i.GetProperty; - - cname:='Edt_'+TabName+'_'+p.Name; - control:=FindComponent(cname); - Assert(control<>nil,cname); - if (control=nil) then Exit; - - TypeKind:=p.PropertyType.TypeKind; - case TypeKind of - - tkSString, - tkLString, - tkAString: - begin - SetText(control,p.GetValue(obj).AsString); - end; - - tkInteger: - begin - SetInteger(control,p.GetValue(obj).AsInteger); - end; - - tkBool: - begin - SetBool(control,p.GetValue(obj).AsBoolean); - end; - - else - Assert(false); - end; - - i.Next; - end; - finally - i.free; - end; -end; - -procedure TfrmCfgEditor.PageSave(const TabName:RawByteString;obj:TAbstractObject); -var - i:TRttiPropertyIterator; - p:TRttiProperty; - TypeKind:TTypeKind; - - cname:RawByteString; - control:TComponent; -begin - - i:=obj.GetPropertyIterator; - try - while (i.GetProperty<>nil) do - begin - - p:=i.GetProperty; - - cname:='Edt_'+TabName+'_'+p.Name; - control:=FindComponent(cname); - Assert(control<>nil,cname); - if (control=nil) then Exit; - - TypeKind:=p.PropertyType.TypeKind; - case TypeKind of - - tkSString, - tkLString, - tkAString: - begin - p.SetValue(obj,GetText(control)); - end; - - tkInteger: - begin - p.SetValue(obj,GetInteger(control)); - end; - - tkBool: - begin - p.SetValue(obj,GetBool(control)); - end; - - else - Assert(false); - end; - - i.Next; - end; - finally - i.free; - end; -end; - Function GetApiVersionStr(apiVersion:TVkUInt32):RawByteString; begin Result:=IntToStr(VK_API_VERSION_MAJOR(apiVersion))+'.'+ @@ -561,80 +562,30 @@ end; procedure TfrmCfgEditor.FormInit; var - i:TRttiPropertyIterator; - p:TRttiProperty; - obj:TObject; + Provider:TCfgFormData; begin VulkanInit; EditPages.ActivePageIndex:=0; - i:=FConfigInfo.GetPropertyIterator; - try - while (i.GetProperty<>nil) do - begin + Provider:=TCfgFormData.Create; - p:=i.GetProperty; + FormLoad(Self,Provider,FConfigInfo); - case p.PropertyType.TypeKind of - - tkClass: - begin - obj:=p.GetValue(FConfigInfo).AsObject; - - if (obj<>nil) then - if obj.InheritsFrom(TAbstractObject) then - begin - PageInit(p.Name,TAbstractObject(obj)); - end; - end; - - else; - end; - - i.Next; - end; - finally - i.free; - end; + Provider.Free; Show; end; procedure TfrmCfgEditor.FormSave; var - i:TRttiPropertyIterator; - p:TRttiProperty; - obj:TObject; + Provider:TCfgFormData; begin - i:=FConfigInfo.GetPropertyIterator; - try - while (i.GetProperty<>nil) do - begin + Provider:=TCfgFormData.Create; - p:=i.GetProperty; + form_filler.FormSave(Self,Provider,FConfigInfo); - case p.PropertyType.TypeKind of - - tkClass: - begin - obj:=p.GetValue(FConfigInfo).AsObject; - - if (obj<>nil) then - if obj.InheritsFrom(TAbstractObject) then - begin - PageSave(p.Name,TAbstractObject(obj)); - end; - end; - - else; - end; - - i.Next; - end; - finally - i.free; - end; + Provider.Free; end; end. diff --git a/gui/form_filler.pas b/gui/form_filler.pas new file mode 100644 index 00000000..18e7fcc6 --- /dev/null +++ b/gui/form_filler.pas @@ -0,0 +1,262 @@ +unit form_filler; + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, + SysUtils, + Controls, + StdCtrls, + TypInfo, + Rtti, + game_info; + +type + TFormDataProvider=class + procedure SetText (control:TComponent;const Text:RawByteString); virtual; abstract; + function GetText (control:TComponent):RawByteString; virtual; abstract; + procedure SetInteger(control:TComponent;i:Integer); virtual; abstract; + function GetInteger(control:TComponent):Integer; virtual; abstract; + procedure SetBool (control:TComponent;B:Boolean); virtual; abstract; + function GetBool (control:TComponent):Boolean; virtual; abstract; + procedure SetClass (control:TComponent;Obj:TObject); virtual; abstract; + procedure GetClass (control:TComponent;Obj:TObject); virtual; abstract; + end; + +type + TMyControl=class(TControl) + public + property Text; + end; + + TMyButtonControl=class(TButtonControl) + public + property Checked; + end; + +procedure PageLoad(Parent:TComponent; + const TabName:RawByteString; + Provider:TFormDataProvider; + src:TAbstractObject); + +procedure FormLoad(Parent:TComponent; + Provider:TFormDataProvider; + src:TAbstractObject); + +procedure PageSave(Parent:TComponent; + const TabName:RawByteString; + Provider:TFormDataProvider; + dst:TAbstractObject); + +procedure FormSave(Parent:TComponent; + Provider:TFormDataProvider; + dst:TAbstractObject); + +implementation + +procedure PageLoad(Parent:TComponent; + const TabName:RawByteString; + Provider:TFormDataProvider; + src:TAbstractObject); +var + i:TRttiPropertyIterator; + p:TRttiProperty; + TypeKind:TTypeKind; + + cname:RawByteString; + control:TComponent; +begin + + i:=src.GetPropertyIterator; + try + while (i.GetProperty<>nil) do + begin + + p:=i.GetProperty; + + cname:='Edt_'+TabName+'_'+p.Name; + control:=Parent.FindComponent(cname); + Assert(control<>nil,'Control:'+cname+' not found!'); + if (control=nil) then Exit; + + TypeKind:=p.PropertyType.TypeKind; + case TypeKind of + + tkSString, + tkLString, + tkAString: + begin + Provider.SetText(control,p.GetValue(src).AsString); + end; + + tkInteger: + begin + Provider.SetInteger(control,p.GetValue(src).AsInteger); + end; + + tkBool: + begin + Provider.SetBool(control,p.GetValue(src).AsBoolean); + end; + + tkClass: + begin + Provider.SetClass(control,p.GetValue(src).AsObject); + end; + + else + Assert(false); + end; + + i.Next; + end; + finally + i.free; + end; +end; + +procedure FormLoad(Parent:TComponent; + Provider:TFormDataProvider; + src:TAbstractObject); +var + i:TRttiPropertyIterator; + p:TRttiProperty; + obj:TObject; +begin + i:=src.GetPropertyIterator; + try + while (i.GetProperty<>nil) do + begin + + p:=i.GetProperty; + + case p.PropertyType.TypeKind of + + tkClass: + begin + obj:=p.GetValue(src).AsObject; + + if (obj<>nil) then + if obj.InheritsFrom(TAbstractObject) then + begin + PageLoad(Parent,p.Name,Provider,TAbstractObject(obj)); + end; + end; + + else; + end; + + i.Next; + end; + finally + i.free; + end; + +end; + +////////////// + +procedure PageSave(Parent:TComponent; + const TabName:RawByteString; + Provider:TFormDataProvider; + dst:TAbstractObject); +var + i:TRttiPropertyIterator; + p:TRttiProperty; + TypeKind:TTypeKind; + + cname:RawByteString; + control:TComponent; +begin + + i:=dst.GetPropertyIterator; + try + while (i.GetProperty<>nil) do + begin + + p:=i.GetProperty; + + cname:='Edt_'+TabName+'_'+p.Name; + control:=Parent.FindComponent(cname); + Assert(control<>nil,cname); + if (control=nil) then Exit; + + TypeKind:=p.PropertyType.TypeKind; + case TypeKind of + + tkSString, + tkLString, + tkAString: + begin + p.SetValue(dst,Provider.GetText(control)); + end; + + tkInteger: + begin + p.SetValue(dst,Provider.GetInteger(control)); + end; + + tkBool: + begin + p.SetValue(dst,Provider.GetBool(control)); + end; + + tkClass: + begin + Provider.GetClass(control,p.GetValue(dst).AsObject); + end; + + else + Assert(false); + end; + + i.Next; + end; + finally + i.free; + end; +end; + +procedure FormSave(Parent:TComponent; + Provider:TFormDataProvider; + dst:TAbstractObject); +var + i:TRttiPropertyIterator; + p:TRttiProperty; + obj:TObject; +begin + i:=dst.GetPropertyIterator; + try + while (i.GetProperty<>nil) do + begin + + p:=i.GetProperty; + + case p.PropertyType.TypeKind of + + tkClass: + begin + obj:=p.GetValue(dst).AsObject; + + if (obj<>nil) then + if obj.InheritsFrom(TAbstractObject) then + begin + PageSave(Parent,p.Name,Provider,TAbstractObject(obj)); + end; + end; + + else; + end; + + i.Next; + end; + finally + i.free; + end; +end; + + +end. + diff --git a/gui/game_edit.lfm b/gui/game_edit.lfm index 0f5bacfe..d251fc91 100644 --- a/gui/game_edit.lfm +++ b/gui/game_edit.lfm @@ -1,85 +1,342 @@ object frmGameEditor: TfrmGameEditor - Left = 501 - Height = 319 - Top = 124 - Width = 397 + Left = 318 + Height = 311 + Top = 113 + Width = 467 Caption = 'Game editor' - ClientHeight = 319 - ClientWidth = 397 + ClientHeight = 311 + ClientWidth = 467 OnClose = FormClose Position = poMainFormCenter - LCLVersion = '3.6.0.0' + LCLVersion = '3.8.0.0' object EditPages: TPageControl AnchorSideBottom.Control = BtnOk Left = 0 - Height = 274 + Height = 266 Top = 0 - Width = 397 - ActivePage = TabMain + Width = 467 + ActivePage = TabFolders Align = alCustom Anchors = [akTop, akLeft, akRight, akBottom] BorderSpacing.Bottom = 10 - TabIndex = 0 + TabIndex = 1 TabOrder = 0 object TabMain: TTabSheet Caption = 'Main' - ClientHeight = 246 - ClientWidth = 389 - object GridMain: TStringGrid - Left = 0 - Height = 246 - Top = 0 - Width = 389 - Align = alClient - AutoFillColumns = True - ColCount = 2 - FixedRows = 0 - Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goEditing, goThumbTracking, goSmoothScroll] - RowCount = 1 + ClientHeight = 238 + ClientWidth = 459 + object Label1: TLabel + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = TabMain + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 15 + Top = 10 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Name:' + end + object Edt_GameInfo_Name: TEdit + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Label1 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 23 + Top = 35 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + MaxLength = 65 TabOrder = 0 - TitleStyle = tsNative - OnEditingDone = GridEditingDone - OnSelectEditor = GridSelectEditor - ColWidths = ( - 64 - 321 - ) + end + object Label2: TLabel + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Edt_GameInfo_Name + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 15 + Top = 68 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'TitleId:' + end + object Edt_GameInfo_TitleId: TEdit + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Label2 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 23 + Top = 93 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + MaxLength = 65 + ReadOnly = True + TabOrder = 1 + end + object Label3: TLabel + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Edt_GameInfo_TitleId + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = PanelHalf + Left = 10 + Height = 15 + Top = 126 + Width = 203 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Master version:' + end + object Edt_GameInfo_Version: TEdit + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Label3 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = PanelHalf + Left = 10 + Height = 23 + Top = 151 + Width = 203 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + MaxLength = 65 + ReadOnly = True + TabOrder = 2 + end + object Label4: TLabel + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Edt_GameInfo_Version + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 15 + Top = 184 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Exec command:' + end + object Edt_GameInfo_Exec: TEdit + AnchorSideLeft.Control = TabMain + AnchorSideTop.Control = Label4 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 23 + Top = 209 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + MaxLength = 65 + TabOrder = 5 + end + object PanelHalf: TPanel + AnchorSideLeft.Control = TabMain + AnchorSideLeft.Side = asrCenter + AnchorSideRight.Side = asrCenter + Left = 223 + Height = 23 + Top = 151 + Width = 12 + BevelOuter = bvNone + Enabled = False + TabOrder = 4 + TabStop = True + end + object Label7: TLabel + AnchorSideLeft.Control = PanelHalf + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Edt_GameInfo_TitleId + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 245 + Height = 15 + Top = 126 + Width = 204 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Application version:' + end + object Edt_GameInfo_AppVer: TEdit + AnchorSideLeft.Control = PanelHalf + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Label3 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = TabMain + AnchorSideRight.Side = asrBottom + Left = 245 + Height = 23 + Top = 151 + Width = 204 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + MaxLength = 65 + ReadOnly = True + TabOrder = 3 end end - object TabMounts: TTabSheet - Caption = 'Mounts' - ClientHeight = 246 - ClientWidth = 389 - object GridMounts: TStringGrid - Left = 0 - Height = 246 - Top = 0 - Width = 389 - Align = alClient - AutoFillColumns = True - ColCount = 2 - FixedRows = 0 - Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goEditing, goThumbTracking, goSmoothScroll] - RowCount = 1 + object TabFolders: TTabSheet + Caption = 'Folders' + ClientHeight = 238 + ClientWidth = 459 + object Label5: TLabel + AnchorSideLeft.Control = TabFolders + AnchorSideTop.Control = TabFolders + AnchorSideRight.Control = TabFolders + AnchorSideRight.Side = asrBottom + Left = 10 + Height = 15 + Top = 10 + Width = 439 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Game:' + end + object Edt_MountList_game: TEdit + AnchorSideLeft.Control = TabFolders + AnchorSideTop.Control = Label5 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = BtnExpGame + Left = 10 + Height = 23 + Top = 35 + Width = 414 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 TabOrder = 0 - TitleStyle = tsNative - OnEditingDone = GridEditingDone - OnSelectEditor = GridSelectEditor - ColWidths = ( - 64 - 304 - ) + OnExit = Edt_MountList_gameExit + end + object BtnGameOpen: TButton + AnchorSideTop.Control = Edt_MountList_game + AnchorSideRight.Control = Edt_MountList_game + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Control = Edt_MountList_game + AnchorSideBottom.Side = asrBottom + Left = 388 + Height = 21 + Top = 36 + Width = 35 + Anchors = [akTop, akRight, akBottom] + AutoSize = True + BorderSpacing.Top = 1 + BorderSpacing.Right = 1 + BorderSpacing.Bottom = 1 + Caption = '...' + TabOrder = 1 + OnClick = BtnGameOpenClick + end + object BtnExpGame: TSpeedButton + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Edt_MountList_game + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = TabFolders + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Side = asrCenter + Left = 429 + Height = 20 + Top = 36 + Width = 20 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Left = 5 + BorderSpacing.Right = 10 + Images = frmMain.SmallImageList + ImageIndex = 0 + OnClick = BtnExpGameClick + end + object Label6: TLabel + AnchorSideTop.Control = Edt_MountList_game + AnchorSideTop.Side = asrBottom + AnchorSideRight.Side = asrBottom + Left = 8 + Height = 15 + Top = 68 + Width = 451 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + BorderSpacing.Right = 10 + Caption = 'Firmware:' + end + object Edt_MountList_firmware: TComboBox + AnchorSideLeft.Control = TabFolders + AnchorSideTop.Control = Label6 + AnchorSideTop.Side = asrBottom + AnchorSideRight.Control = BtnExpFw + Left = 10 + Height = 23 + Top = 93 + Width = 414 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Left = 10 + BorderSpacing.Top = 10 + ItemHeight = 15 + TabOrder = 2 + OnGetItems = Edt_MountList_firmwareGetItems + end + object BtnExpFw: TSpeedButton + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Edt_MountList_firmware + AnchorSideTop.Side = asrCenter + AnchorSideRight.Control = TabFolders + AnchorSideRight.Side = asrBottom + AnchorSideBottom.Side = asrCenter + Left = 429 + Height = 20 + Top = 94 + Width = 20 + Anchors = [akTop, akRight] + AutoSize = True + BorderSpacing.Left = 5 + BorderSpacing.Right = 10 + Images = frmMain.SmallImageList + ImageIndex = 0 + OnClick = BtnExpFwClick end end object TabParamSfo: TTabSheet Caption = 'param.sfo' - ClientHeight = 246 - ClientWidth = 389 + ClientHeight = 238 + ClientWidth = 459 object GridParamSfo: TStringGrid Left = 0 - Height = 246 + Height = 238 Top = 0 - Width = 389 + Width = 459 Align = alClient AutoFillColumns = True ColCount = 2 @@ -88,11 +345,9 @@ object frmGameEditor: TfrmGameEditor RowCount = 1 TabOrder = 0 TitleStyle = tsNative - OnEditingDone = GridEditingDone - OnSelectEditor = GridSelectEditor ColWidths = ( 64 - 304 + 374 ) end end @@ -103,7 +358,7 @@ object frmGameEditor: TfrmGameEditor AnchorSideBottom.Side = asrBottom Left = 10 Height = 25 - Top = 284 + Top = 276 Width = 75 Anchors = [akLeft, akBottom] AutoSize = True @@ -121,9 +376,9 @@ object frmGameEditor: TfrmGameEditor AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = Owner AnchorSideBottom.Side = asrBottom - Left = 312 + Left = 382 Height = 25 - Top = 284 + Top = 276 Width = 75 Anchors = [akRight, akBottom] AutoSize = True diff --git a/gui/game_edit.pas b/gui/game_edit.pas index f3c457c1..cd3e6c9e 100644 --- a/gui/game_edit.pas +++ b/gui/game_edit.pas @@ -6,11 +6,14 @@ interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls, - StdCtrls, Grids, + StdCtrls, Grids, Buttons, + + LCLIntf, ms_shell_hack, game_info, + form_filler, param_sfo_gui; type @@ -18,34 +21,49 @@ type { TfrmGameEditor } TfrmGameEditor = class(TForm) + BtnExpGame: TSpeedButton; + BtnExpFw: TSpeedButton; + BtnGameOpen: TButton; BtnOk: TButton; BtnCancel: TButton; EditPages: TPageControl; - GridMain: TStringGrid; - GridMounts: TStringGrid; + Edt_GameInfo_Name: TEdit; + Edt_GameInfo_Exec: TEdit; + Edt_GameInfo_TitleId: TEdit; + Edt_GameInfo_Version: TEdit; + Edt_GameInfo_AppVer: TEdit; + Edt_MountList_game: TEdit; + Edt_MountList_firmware: TComboBox; GridParamSfo: TStringGrid; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + Label4: TLabel; + Label5: TLabel; + Label6: TLabel; + Label7: TLabel; + PanelHalf: TPanel; TabMain: TTabSheet; - TabMounts: TTabSheet; + TabFolders: TTabSheet; TabParamSfo: TTabSheet; + procedure BtnExpFwClick(Sender: TObject); + procedure BtnExpGameClick(Sender: TObject); + procedure BtnGameOpenClick(Sender: TObject); procedure BtnOkClick(Sender: TObject); procedure BtnCancelClick(Sender: TObject); + procedure Edt_MountList_firmwareGetItems(Sender: TObject); + procedure Edt_MountList_gameExit(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; + Fgame:RawByteString; public - OnSave :TNotifyEvent; - Item :TGameItem; - ParamSfo:TParamSfoFile; + OnSave :TNotifyEvent; + FConfigInfo:TConfigInfo; + FItem :TGameItem; + FParamSfo :TParamSfoFile; end; var @@ -61,147 +79,32 @@ uses { 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); +function DoOpenDir(const Input,InitialDir:RawByteString):RawByteString; var d:TSelectDirectoryDialog; Cookie:Pointer; begin Cookie:=RegisterDllHack; + Result:=Input; d:=nil; - try d:=TSelectDirectoryDialog.Create(nil); - - with TMyStringGrid(Editor.Parent) do - begin - d.InitialDir:=Cells[1,aRow]; - end; - + d.InitialDir:=InitialDir; d.Options:=[ofPathMustExist,ofEnableSizing,ofViewDetail]; - if d.Execute then - with TMyStringGrid(Editor.Parent) do begin - Cells[1,aRow]:=d.FileName; + Result:=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); +procedure AddRow(Grid:TStringGrid;const name,value:RawByteString;obj:TObject); var i:Integer; begin @@ -209,69 +112,45 @@ begin Grid.RowCount:=i+1; Grid.Cells[0,i]:=name; Grid.Cells[1,i]:=value; - Grid.Objects[0,i]:=info; + Grid.Objects[0,i]:=obj; +end; + +type + TGameFormData=class(TFormDataProvider) + procedure SetText(control:TComponent;const Text:RawByteString); override; + function GetText(control:TComponent):RawByteString; override; + end; + +procedure TGameFormData.SetText(control:TComponent;const Text:RawByteString); +begin + if control.InheritsFrom(TControl) then + begin + TMyControl(control).Text:=Text; + end; +end; + +function TGameFormData.GetText(control:TComponent):RawByteString; +begin + Result:=''; + if control.InheritsFrom(TControl) then + begin + Result:=TMyControl(control).Text; + end; end; procedure TfrmGameEditor.FormInit(UpdateTitle:Boolean); var - fip:TFieldInfoPath; - - i:TRttiPropertyIterator; - p:TRttiProperty; + Provider:TGameFormData; begin EditPages.ActivePageIndex:=0; - GridMain.Clear; - GridMounts.Clear; + Provider:=TGameFormData.Create; - //TypInfo.SetRawByteStrProp(); + FormLoad(Self,Provider,FItem); - //AddRow(GridMain,'Name:',nil); + Provider.Free; - // - 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); @@ -280,52 +159,13 @@ end; procedure TfrmGameEditor.FormSave; var - i:TRttiPropertyIterator; - p:TRttiProperty; + Provider:TGameFormData; begin - i:=Item.FGameInfo.GetPropertyIterator; - try - while (i.GetProperty<>nil) do - begin + Provider:=TGameFormData.Create; - p:=i.GetProperty; - p.SetValue(Item.FGameInfo,GridMain.Cells[1,i.i]); + form_filler.FormSave(Self,Provider,FItem); - 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; + Provider.Free; end; procedure TfrmGameEditor.LoadParamSfo(UpdateTitle:Boolean); @@ -333,40 +173,39 @@ var i:Integer; V:RawByteString; begin - V:=GetGridVal(GridMounts,Fapp0_row); + V:=Edt_MountList_game.Text; + if (Fgame=V) then Exit; - if (Fapp0p=V) then Exit; + FreeAndNil(FParamSfo); - FreeAndNil(ParamSfo); + FParamSfo:=LoadParamSfoFile(ExcludeTrailingPathDelimiter(V)+ + DirectorySeparator+ + 'sce_sys'+ + DirectorySeparator+ + 'param.sfo'); - ParamSfo:=LoadParamSfoFile(ExcludeTrailingPathDelimiter(V)+ - DirectorySeparator+ - 'sce_sys'+ - DirectorySeparator+ - 'param.sfo'); - - Fapp0p:=V; + Fgame:=V; GridParamSfo.Clear; - if (ParamSfo=nil) then + if (FParamSfo=nil) then begin - SetGridVal(GridMain,FTitleId_row,'???'); - SetGridVal(GridMain,FVersion_row,'???'); + Edt_GameInfo_TitleId.Text:='???'; + Edt_GameInfo_Version.Text:='???'; Exit; end; - if (Length(ParamSfo.params)=0) then Exit; - For i:=0 to High(ParamSfo.params) do + if (Length(FParamSfo.params)=0) then Exit; + For i:=0 to High(FParamSfo.params) do begin - if (ParamSfo.params[i].format=SFO_FORMAT_UINT32) then + if (FParamSfo.params[i].format=SFO_FORMAT_UINT32) then begin - V:='0x'+HexStr(ParamSfo.params[i].GetUInt,8); + V:='0x'+HexStr(FParamSfo.params[i].GetUInt,8); end else begin - V:=Trim(ParamSfo.params[i].GetString); + V:=Trim(FParamSfo.params[i].GetString); end; - AddRow(GridParamSfo,ParamSfo.params[i].name,V,nil); + AddRow(GridParamSfo,FParamSfo.params[i].name,V,nil); end; GridParamSfo.AutoSizeColumn(0); @@ -374,34 +213,45 @@ begin // if not UpdateTitle then Exit; - V:=ParamSfo.GetString('TITLE'); - SetGridVal(GridMain,FName_row,V); + V:=FParamSfo.GetString('TITLE'); + Edt_GameInfo_Name.Text:=V; - V:=ParamSfo.GetString('TITLE_ID'); - SetGridVal(GridMain,FTitleId_row,V); + V:=FParamSfo.GetString('TITLE_ID'); + Edt_GameInfo_TitleId.Text:=V; - V:=ParamSfo.GetString('APP_VER'); - SetGridVal(GridMain,FVersion_row,V); + V:=FParamSfo.GetString('VERSION'); + Edt_GameInfo_Version.Text:=V; + + V:=FParamSfo.GetString('APP_VER'); + Edt_GameInfo_AppVer.Text:=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); +procedure TfrmGameEditor.Edt_MountList_gameExit(Sender: TObject); begin LoadParamSfo(True); end; +procedure TfrmGameEditor.BtnGameOpenClick(Sender: TObject); +var + new:RawByteString; +begin + new:=DoOpenDir('',Edt_MountList_game.Text); + if (new='') then Exit; + + Edt_MountList_game.Text:=new; + LoadParamSfo(True); +end; + +procedure TfrmGameEditor.BtnExpGameClick(Sender: TObject); +begin + OpenDocument(Edt_MountList_game.Text); +end; + +procedure TfrmGameEditor.BtnExpFwClick(Sender: TObject); +begin + OpenDocument(Edt_MountList_firmware.Text); +end; + procedure TfrmGameEditor.BtnOkClick(Sender: TObject); begin FormSave; @@ -418,20 +268,41 @@ begin Close; end; +procedure TfrmGameEditor.Edt_MountList_firmwareGetItems(Sender: TObject); +var + i,c:Integer; + S:RawByteString; +begin + if (FConfigInfo<>nil) then + begin + c:=FConfigInfo.MainInfo.FirmwareList.GetArrayCount; + if (c<>0) and (Edt_MountList_firmware.Items.Count<>c) then + begin + Edt_MountList_firmware.Items.Clear; + //preload + For i:=0 to c-1 do + begin + S:=FConfigInfo.MainInfo.FirmwareList.values[i]; + Edt_MountList_firmware.Items.Add(S); + end; + end; + end; +end; + procedure TfrmGameEditor.FormClose(Sender:TObject;var CloseAction:TCloseAction); begin - if (Item<>nil) then + if (FItem<>nil) then begin - if Item.FLock then + if FItem.FLock then begin - Item.FLock:=False; + FItem.FLock:=False; end else begin - FreeAndNil(Item); + FreeAndNil(FItem); end; end; // - FreeAndNil(ParamSfo); + FreeAndNil(FParamSfo); // CloseAction:=caFree; end; diff --git a/gui/game_info.pas b/gui/game_info.pas index 79cc413a..85edb7d3 100644 --- a/gui/game_info.pas +++ b/gui/game_info.pas @@ -99,6 +99,18 @@ type Destructor Destroy(); override; end; + TStringArray=class(TAbstractArray) + values:array of RawByteString; + // + Destructor Destroy; override; + // + Function GetArrayCount:SizeInt; override; + Function GetArrayItem(i:SizeInt):TValue; override; + Function AddObject:TAbstractObject; override; + Function AddArray :TAbstractArray; override; + procedure AddValue(Value:TValue); override; + end; + TBootParamInfo=class(TAbstractObject) private FNeo :Boolean; @@ -135,26 +147,28 @@ type TMainInfo=class(TAbstractObject) private - FLogFile :RawByteString; - Fsystem :RawByteString; - Fdata :RawByteString; - Ffork_proc:Boolean; + FLogFile :RawByteString; + FDefaultFirmware:RawByteString; + FFirmwareList :TStringArray; published - property LogFile :RawByteString read FLogFile write FLogFile; - property system :RawByteString read Fsystem write Fsystem; - property data :RawByteString read Fdata write Fdata; - property fork_proc:Boolean read Ffork_proc write Ffork_proc; + property LogFile :RawByteString read FLogFile write FLogFile; + property DefaultFirmware:RawByteString read FDefaultFirmware write FDefaultFirmware; + property FirmwareList :TStringArray read FFirmwareList write FFirmwareList; public Constructor Create; override; end; TMiscInfo=class(TAbstractObject) private + Ffork_proc :Boolean; Fstrict_ps4_freq :Boolean; Frenderdoc_capture:Boolean; published + property fork_proc :Boolean read Ffork_proc write Ffork_proc; property strict_ps4_freq :Boolean read Fstrict_ps4_freq write Fstrict_ps4_freq; property renderdoc_capture:Boolean read Frenderdoc_capture write Frenderdoc_capture; + public + Constructor Create; override; end; TVulkanInfo=class(TAbstractObject) @@ -183,18 +197,6 @@ type Constructor Create; override; end; - TStringArray=class(TAbstractArray) - values:array of RawByteString; - // - Destructor Destroy; override; - // - Function GetArrayCount:SizeInt; override; - Function GetArrayItem(i:SizeInt):TValue; override; - Function AddObject:TAbstractObject; override; - Function AddArray :TAbstractArray; override; - procedure AddValue(Value:TValue); override; - end; - TPS4LoadExec=class(TAbstractObject) private FPath:RawByteString; @@ -227,27 +229,25 @@ type FName :RawByteString; FTitleId:RawByteString; FVersion:RawByteString; + FAppVer :RawByteString; FExec :RawByteString; - FParam :RawByteString; published property Name :RawByteString read FName write FName; property TitleId:RawByteString read FTitleId write FTitleId; property Version:RawByteString read FVersion write FVersion; + property AppVer :RawByteString read FAppVer write FAppVer; property Exec :RawByteString read FExec write FExec; - property Param :RawByteString read FParam write FParam; public Constructor Create; override; end; TMountList=class(TAbstractObject) private - Fapp0 :RawByteString; - Fsystem:RawByteString; - Fdata :RawByteString; + Fgame :RawByteString; + Ffirmware:RawByteString; published - property app0 :RawByteString read Fapp0 write Fapp0 ; - property system:RawByteString read Fsystem write Fsystem; - property data :RawByteString read Fdata write Fdata ; + property game :RawByteString read Fgame write Fgame ; + property firmware:RawByteString read Ffirmware write Ffirmware; public Constructor Create; override; end; @@ -264,10 +264,16 @@ type TGameStartupInfo=class(TAbstractObject) public - FReader :Boolean; - FPipe :THandle; - FConfInfo:TConfigInfo; - FGameItem:TGameItem; + FReader :Boolean; + FPipe :THandle; + FConfInfo :TConfigInfo; + FGameItem :TGameItem; + FLocalDir :RawByteString; + FhasParamSfo:Integer; + published + property Pipe :THandle read FPipe write FPipe; + property LocalDir:RawByteString read FLocalDir write FLocalDir; + property hasParamSfo:Integer read FhasParamSfo write FhasParamSfo; public Constructor Create(Reader:Boolean); reintroduce; Destructor Destroy; override; @@ -1091,9 +1097,13 @@ end; Constructor TMainInfo.Create; begin inherited; - FLogFile:='log.txt'; - Fsystem :=DirectorySeparator+'system'; - Fdata :=DirectorySeparator+'data'; + FLogFile :='log.txt'; + FDefaultFirmware:=DirectorySeparator+'firmware'; +end; + +Constructor TMiscInfo.Create; +begin + inherited; Ffork_proc:=True; end; @@ -1152,14 +1162,14 @@ begin FExec:='/app0/eboot.bin'; FTitleId:='???'; FVersion:='???'; + FAppVer :='???'; end; Constructor TMountList.Create; begin inherited; - Fapp0 :=DirectorySeparator; - Fsystem:=DirectorySeparator+'system'; - Fdata :=DirectorySeparator+'data'; + Fgame :=DirectorySeparator; + Ffirmware:=DirectorySeparator+'firmware'; end; // @@ -1187,15 +1197,14 @@ end; Procedure TGameStartupInfo.Serialize(Stream:TStream); begin - Stream.Write(FPipe,SizeOf(THandle)); + inherited Serialize(Stream); FConfInfo.Serialize(Stream); FGameItem.Serialize(Stream); end; Procedure TGameStartupInfo.Deserialize(Stream:TStream); begin - FPipe:=0; - Stream.Read(FPipe,SizeOf(THandle)); + inherited Deserialize(Stream); FConfInfo.Deserialize(Stream); FGameItem.Deserialize(Stream); end; diff --git a/gui/game_mount.pas b/gui/game_mount.pas new file mode 100644 index 00000000..2b5d40f0 --- /dev/null +++ b/gui/game_mount.pas @@ -0,0 +1,248 @@ +unit game_mount; + +{$mode ObjFPC}{$H+} + +interface + +uses + game_info; + +var + g_LocalDir:RawByteString=''; + +procedure InitMount(GameStartupInfo:TGameStartupInfo); + +implementation + +uses + sysutils, + errno, + vfs_mountroot, + subr_backtrace; + +function get_errno_str(err:Integer):RawByteString; +begin + case err of + EPERM :Result:='Operation not permitted'; + ENOENT :Result:='No such file or directory'; + EACCES :Result:='Permission denied'; + EEXIST :Result:='Directory exists'; + ENOTDIR:Result:='Not a directory'; + else + Result:=IntToStr(err); + end; +end; + +function mount_mkdir(path:PChar):Integer; +begin + Result:=vfs_mountroot.mount_mkdir(path); + if (Result<>0) then + begin + print_error_td('[mkdir error]'+#13#10+ + ' path:"'+path+'"'#13#10+ + ' err:'+get_errno_str(Result) + ,True); + end; +end; + +function mount_into_sandbox(fstype,fspath,from,opts:PChar;flags:QWORD;ignore:Boolean):Integer; +begin + Result:=vfs_mountroot.mount_into_sandbox(fstype,fspath,from,opts,flags); + if (Result<>0) and (not ignore) then + begin + print_error_td('[mount error]'+#13#10+ + ' from:"'+from+'"'#13#10+ + ' to:"'+fspath+'"'#13#10+ + ' err:'+get_errno_str(Result) + ,True); + end; +end; + +function unix_to_host(const name:RawByteString):RawByteString; +var + i:Integer; +begin + Result:=name; + if (DirectorySeparator<>'/') then + For i:=1 to Length(Result) do + begin + if (Result[i]='/') then + begin + Result[i]:=DirectorySeparator; + end; + end; +end; + +const + MM_CREATE =-1; + MM_GAME =0; + MM_FIRMWARE=1; + MM_LOCAL =2; + MM_LAST =2; + +type + t_mnt_flags=Set of (mfReadOnly,mfIgnoreErr,mfForceDir); + +type + pp_mount_dir=^p_mount_dir; + p_mount_dir=^t_mount_dir; + t_mount_dir=object + dst :pchar; + src :pchar; + mode :Shortint; + flags :t_mnt_flags; + term :Boolean; + childs:p_mount_dir; + end; + + t_mount_dir_iterator=object + _curr:pp_mount_dir; + stack:array[0..3] of p_mount_dir; + function curr:p_mount_dir; inline; + procedure init(dir:p_mount_dir); inline; + function next(err:Integer):Boolean; inline; + end; + +function t_mount_dir_iterator.curr:p_mount_dir; inline; +begin + Result:=_curr^; +end; + +procedure t_mount_dir_iterator.init(dir:p_mount_dir); inline; +begin + stack[0]:=dir; + _curr:=@stack[0]; +end; + +function t_mount_dir_iterator.next(err:Integer):Boolean; inline; +var + prev:p_mount_dir; +begin + if (_curr=nil) then Exit(False); + + prev:=_curr^; + + if (err=0) and (prev^.childs<>nil) then + begin + _curr:=_curr+1; //down + _curr^:=prev^.childs; + end else + begin + _curr^:=prev+1; //next + end; + + repeat + + if (_curr^^.term) then + begin + if (_curr=@stack[0]) then + begin + _curr:=nil; + Exit(False); + end else + begin + _curr :=_curr -1; //up + _curr^:=_curr^+1; //next + end; + end else + begin + Exit(True); + end; + + until false; + +end; + +const + SYSTEM_COMMON_DIRS:array[0..12] of t_mount_dir=( + (dst:'/%s/common/cert' ;src:'%s/system/common/cert' ;mode:MM_FIRMWARE;flags:[mfReadOnly]), // CA_LIST.cer + (dst:'/%s/common/etc' ;src:'%s/system/common/etc' ;mode:MM_FIRMWARE;flags:[mfReadOnly,mfIgnoreErr]), + (dst:'/%s/common/font' ;src:'%s/preinst/common/font' ;mode:MM_FIRMWARE;flags:[mfReadOnly]), // *.ttf + (dst:'/%s/common/font2' ;src:'%s/system/common/font2' ;mode:MM_FIRMWARE;flags:[mfReadOnly]), + (dst:'/%s/common/httpcache' ;src:'%s/system_data/common/httpcache';mode:MM_LOCAL ;flags:[mfForceDir]), + (dst:'/%s/common/lib' ;src:'%s/system/common/lib' ;mode:MM_FIRMWARE;flags:[mfReadOnly]), + (dst:'/%s/common/mms' ;src:'%s/system_data/common/mms/' ;mode:MM_LOCAL ;flags:[mfForceDir]), // av_content.db + (dst:'/%s/common/mms_ro' ;src:'%s/system/common/mms_ro' ;mode:MM_FIRMWARE;flags:[mfReadOnly,mfIgnoreErr]), // template_content.db + (dst:'/%s/common/playready' ;src:'%s/user/common/playready' ;mode:MM_LOCAL ;flags:[mfReadOnly,mfForceDir ]), + (dst:'/%s/common/text_layout' ;src:'%s/system/common/text_layout' ;mode:MM_FIRMWARE;flags:[mfReadOnly,mfIgnoreErr]), + (dst:'/%s/common/text_to_speech';src:'%s/system/common/text_to_speech';mode:MM_FIRMWARE;flags:[mfReadOnly,mfIgnoreErr]), + (dst:'/%s/common/webkit' ;src:'%s/system/common/webkit' ;mode:MM_FIRMWARE;flags:[mfReadOnly,mfIgnoreErr]), + (term:True) + ); + + SYSTEM_DIRS:array[0..5] of t_mount_dir=( + (dst:'/%s/becore' ;src:'' ;mode:MM_CREATE ;flags:[]), // system app only + (dst:'/%s/common' ;src:'' ;mode:MM_CREATE ;flags:[];childs:@SYSTEM_COMMON_DIRS), + (dst:'/%s/common_temp';src:'' ;mode:MM_CREATE ;flags:[]), + (dst:'/%s/priv' ;src:'%s/system/priv';mode:MM_FIRMWARE;flags:[mfReadOnly]), // system app only + (dst:'/%s/sqlite' ;src:'' ;mode:MM_CREATE ;flags:[]), + (term:True) + ); + + SANDBOX_DIRS:array[0..7] of t_mount_dir=( + (dst:'/app0' ;src:'%s' ;mode:MM_GAME ;flags:[mfReadOnly]), + (dst:'/av_contents';src:'%s/user/av_contents';mode:MM_LOCAL ;flags:[mfForceDir]), + (dst:'/data' ;src:'%s/user/data' ;mode:MM_LOCAL ;flags:[mfForceDir]), + (dst:'/host' ;src:'' ;mode:MM_CREATE;flags:[mfReadOnly]), + (dst:'/hostapp' ;src:'' ;mode:MM_CREATE;flags:[mfReadOnly]), + (dst:'/system_tmp' ;src:'%s/system_tmp' ;mode:MM_LOCAL ;flags:[mfForceDir]), + (dst:'/%s' ;src:'' ;mode:MM_CREATE;flags:[mfReadOnly];childs:@SYSTEM_DIRS), + (term:True) + ); + +procedure InitMount(GameStartupInfo:TGameStartupInfo); +var + err:Integer; + + fs_iterator:t_mount_dir_iterator; + + fs_source:array[0..MM_LAST] of RawByteString; + fs_dst:RawByteString; + fs_src:RawByteString; +begin + + //temp hack + err:=mount_into_sandbox('ufs','/savedata0','savedata',nil,0,True); + + fs_source[MM_GAME ]:=ExcludeTrailingPathDelimiter(GameStartupInfo.FGameItem.FMountList.game ); + fs_source[MM_FIRMWARE]:=ExcludeTrailingPathDelimiter(GameStartupInfo.FGameItem.FMountList.firmware); + fs_source[MM_LOCAL ]:=ExcludeTrailingPathDelimiter(GameStartupInfo.LocalDir); + + g_LocalDir:=GameStartupInfo.LocalDir; + + //--sandbox-- + fs_iterator.init(@SANDBOX_DIRS); + repeat + + with fs_iterator.curr^ do + begin + + fs_dst:=Format(dst,['system']); + + if (mode=MM_CREATE) then + begin + err:=mount_mkdir(pchar(fs_dst)); + end else + begin + fs_src:=Format(unix_to_host(src),[fs_source[mode]]); + + if (mfForceDir in flags) then + begin + ForceDirectories(fs_src); + end; + + err:=mount_into_sandbox('ufs',pchar(fs_dst),pchar(fs_src),nil,ord(mfReadOnly in flags)*MNT_RDONLY,mfIgnoreErr in flags); + end; + + end; + + until (not fs_iterator.next(err)); + //--sandbox-- + + //UPDATE: sandbox root IS NOT read-only + //err:=vfs_mount_path('ufs','/','/',nil,MNT_RDONLY or MNT_UPDATE); + +end; + +end. + diff --git a/gui/game_run.pas b/gui/game_run.pas index 9bd86728..ad241db1 100644 --- a/gui/game_run.pas +++ b/gui/game_run.pas @@ -16,7 +16,8 @@ uses host_ipc, host_ipc_interface, md_host_ipc, - game_info; + game_info, + game_mount; type TGameRunConfig=record @@ -25,6 +26,7 @@ type FConfInfo:TConfigInfo; FGameItem:TGameItem; + FhasParamSfo:Integer; end; TGameProcessSimple=class(TGameProcess) @@ -39,10 +41,9 @@ function run_item(const cfg:TGameRunConfig):TGameProcess; implementation uses + errno, sys_sysinit, - kern_param, kern_exec, - vfs_mountroot, sys_crt, //<- init writeln redirect sys_tty, md_exception, //<- install custom @@ -200,7 +201,7 @@ var curr:PPChar; begin if (argv=nil) then Exit; - curr:=argv+1; //skip exec + curr:=argv; while (curr^<>nil) do begin FreeMem(curr^); @@ -253,10 +254,9 @@ begin Result:=1; //init - argc:=1; + argc:=0; argv:=AllocMem(SizeOf(Pointer)*2); - argv[0]:=nil; //exec place - argv[1]:=nil; //truncate + argv[0]:=nil; //truncate curr:=@params[1]; last:=curr; @@ -336,11 +336,22 @@ begin Result:=argc; end; +function get_errno_str(err:Integer):RawByteString; +begin + case err of + EPERM :Result:='Operation not permitted'; + ENOENT :Result:='No such file or directory'; + EACCES :Result:='Permission denied'; + EEXIST :Result:='Directory exists'; + ENOTDIR:Result:='Not a directory'; + else + Result:=IntToStr(err); + end; +end; + procedure prepare(GameStartupInfo:TGameStartupInfo); SysV_ABI_CDecl; var err:Integer; - len:Integer; - exec:array[0..PATH_MAX] of Char; argv:PPChar; i,argc:Integer; Item:TGameItem; @@ -367,8 +378,8 @@ begin Item:=GameStartupInfo.FGameItem; g_appinfo.mmap_flags:=1; //is_big_app ??? - g_appinfo.CUSANAME:=Item.FGameInfo.TitleId; - //g_appinfo.hasParamSfo:=1; TODO: check + g_appinfo.CUSANAME :=Item.FGameInfo.TitleId; + g_appinfo.hasParamSfo:=GameStartupInfo.hasParamSfo; //g_appinfo.debug_level:=1; g_appinfo.titleWorkaround.version:=69; @@ -383,51 +394,23 @@ begin kern_reserve_2mb_page(0,M2MB_DEFAULT); /// - Writeln('Name :',Item.FGameInfo.Name ); - Writeln('TitleId:',Item.FGameInfo.TitleId); - Writeln('Version:',Item.FGameInfo.Version); - Writeln('Exec :',Item.FGameInfo.Exec ); - Writeln('Param :',Item.FGameInfo.Param ); + Writeln('Name :',Item.FGameInfo.Name ); + Writeln('TitleId :',Item.FGameInfo.TitleId ); + Writeln('Version :',Item.FGameInfo.Version ); + Writeln('AppVer :',Item.FGameInfo.AppVer ); + Writeln('Exec :',Item.FGameInfo.Exec ); - Writeln('app0 :',Item.FMountList.app0 ); - Writeln('system :',Item.FMountList.system); - Writeln('data :',Item.FMountList.data ); + Writeln('game :',Item.FMountList.game ); + Writeln('firmware:',Item.FMountList.firmware ); - //temp hack - err:=vfs_mount_mkdir('ufs','/savedata0' ,'savedata',nil,0); + Writeln('LocalDir:',GameStartupInfo.LocalDir ); - //fs guest host - err:=vfs_mount_mkdir('ufs','/app0' ,pchar(Item.FMountList.app0 ),nil,MNT_RDONLY); - if (err<>0) then - begin - print_error_td('error mount "'+Item.FMountList.app0+'" to "/app0" code='+IntToStr(err)); - end; - - err:=vfs_mount_mkdir('ufs','/system',pchar(Item.FMountList.system),nil,MNT_RDONLY); - if (err<>0) then - begin - print_error_td('error mount "'+Item.FMountList.system+'" to "/system" code='+IntToStr(err)); - end; - - err:=vfs_mount_mkdir('ufs','/data' ,pchar(Item.FMountList.data ),nil,0); - if (err<>0) then - begin - print_error_td('error mount "'+Item.FMountList.data+'" to "/data" code='+IntToStr(err)); - end; + InitMount(GameStartupInfo); ///argv argv:=nil; - argc:=parse_params(Item.FGameInfo.Param,argv); - - FillChar(exec,SizeOf(exec),0); - - len:=Length(Item.FGameInfo.Exec); - if (len>PATH_MAX) then len:=PATH_MAX; - - Move(pchar(Item.FGameInfo.Exec)^,exec,len); - - argv[0]:=@exec; + argc:=parse_params(Item.FGameInfo.Exec,argv); Writeln('main_thread:',HexStr(curkthread)); @@ -443,19 +426,28 @@ begin Flush(stdout); - err:=main_execve(argv[0],argv,nil); - - //free data - free_params(argv); + if (argv[0]=nil) then + begin + err:=ENOENT; + end else + begin + err:=main_execve(argv[0],argv,nil); + end; if (err=0) then begin + //free data + free_params(argv); + //jump to code main_switch_context; end else if (err<>0) then begin - print_error_td('error execve "'+exec+'" code='+IntToStr(err)); + print_error_td('[execve error]'+#13#10+ + ' cmd:"'+argv[0]+'"'#13#10+ + ' err:'+get_errno_str(err) + ,False); end; // @@ -529,7 +521,7 @@ begin parent:=md_pidfd_open(md_getppid); - pipefd:=GameStartupInfo.FPipe; + pipefd:=GameStartupInfo.Pipe; pipefd:=md_pidfd_getfd(parent,pipefd); kipc:=THostIpcPipeKERN.Create; @@ -575,12 +567,15 @@ begin GameStartupInfo.FConfInfo:=cfg.FConfInfo; GameStartupInfo.FGameItem:=cfg.FGameItem; + GameStartupInfo.LocalDir :=GetAppConfigDir(False); + GameStartupInfo.hasParamSfo:=cfg.FhasParamSfo; + SetStdHandle(STD_OUTPUT_HANDLE,cfg.hOutput); SetStdHandle(STD_ERROR_HANDLE ,cfg.hError ); fork_info:=Default(t_fork_proc); - if cfg.FConfInfo.MainInfo.fork_proc then + if cfg.FConfInfo.MiscInfo.fork_proc then begin Result:=TGameProcessPipe.Create; Result.g_fork:=True; diff --git a/gui/main.lfm b/gui/main.lfm index f3a545fb..8728fd13 100644 --- a/gui/main.lfm +++ b/gui/main.lfm @@ -1,7 +1,7 @@ object frmMain: TfrmMain - Left = 334 + Left = 682 Height = 343 - Top = 200 + Top = 344 Width = 623 Caption = 'fpPS4' ClientHeight = 343 @@ -293,4 +293,29 @@ object frmMain: TfrmMain 57E7E20D65ED54000000000000000000C8C8FF01EBADDADA } end + object SmallImageList: TImageList + AllocBy = 3 + Left = 320 + Top = 144 + Bitmap = { + 4C7A030000001000000010000000290200000000000078DAED93CB4B1B5114C6 + 071F8821A96EBA145CF40F9042ABD82E04DDB40B77FE012E2A0ABA75D5AE440A + 2E9A165C145C088281C49828BED0344C7C558AF8689399D816A241F0912E9A68 + 20A966F279CFD4C943329371845221073EEEBD33F777CF771F0700873B48743F + 782F4C94A7020E0E8A4497E94870708FF4F0C44AC97D20F52BA388BFFF3277BD + 42224E74D75AA99FCBEA9594082130517E699427295E6E7E3FDE7A05C159A1ED + DF59C95475ADCABC7F419705527409385F5195F47B81F92F93457DB579E9331E + 91DD2EFC98AD933D517BBAD3C9D6F764FD6BB021EF6384575F2219139096FEB0 + 3680C38D0E843E3514E5292FB114F1080F765F724B115E7991D9B71A4F5E292F + 317BD30FE5B9D4D23819F5B37766D6E4697DF21C110719E393E7524BE3B494A4 + FB67EFA82CA5767E7FF307A0849CEB3A12D16F2CBF85EDC96CA535D4EE38BCD6 + 9E61BECFD567FAFB7C0B8293E675ADDAF8ECE0AA597D6D1FF8DAE2B45FDA0BE5 + 3DF0B5C683EE9A4D9EE72A8AD517CD11274D6F44B7E544AE1997E5988D5F2BEC + FF1AB69EA6D878D7933489FAB7E589C3CF3576E8CBA0BE213EE8058425E3BC7F + 1EF83AA38BCFDD2FC9DEF7FC023B53C09613F6DE6717B9FF6C3D8D31AD7C0A87 + 4D3BF0651CD81803D64781D51160F963413F325F84033F0C783F14E4C9539E7F + E659E1ECBDCDF9FEBB1B63BACE4F239F2EDEF30E581C32CE2FBC05E6060CF1B6 + EEA7D9F7CBFA5C294A718BFAD7D27DA87F4DFF3AEABF14FF26AE007B18885F + } + end end diff --git a/gui/main.pas b/gui/main.pas index d1668978..ab0f12d0 100644 --- a/gui/main.pas +++ b/gui/main.pas @@ -30,6 +30,9 @@ uses cfg_edit, game_run, + param_sfo_gui, + playgo_chunk_gui, + host_ipc_interface; type @@ -77,6 +80,7 @@ type TfrmMain = class(TForm) MainImageList: TImageList; + SmallImageList: TImageList; MIFind: TMenuItem; MIShowExplorer: TMenuItem; MIDevide3: TMenuItem; @@ -132,6 +136,7 @@ type FGameList :TGameList; FGameProcess:TGameProcess; FGameItem :TGameItem; + FParamSfo :TParamSfoFile; FConfigInfo:TConfigInfo; @@ -183,8 +188,6 @@ var implementation uses - param_sfo_gui, - playgo_chunk_gui, game_find, @@ -491,6 +494,15 @@ begin end; end; +function LoadParamSfoFile2(const game:RawByteString):TParamSfoFile; +begin + Result:=LoadParamSfoFile(ExcludeTrailingPathDelimiter(game)+ + DirectorySeparator+ + 'sce_sys'+ + DirectorySeparator+ + 'param.sfo'); +end; + function TfrmMain.OnParamSfoInit(mlen:DWORD;buf:Pointer):Ptruint; //PARAM_SFO_INIT var ParamSfo:TParamSfoFile; @@ -500,13 +512,14 @@ begin if (FGameItem=nil) then Exit; - V:=FGameItem.MountList.app0; - - ParamSfo:=LoadParamSfoFile(ExcludeTrailingPathDelimiter(V)+ - DirectorySeparator+ - 'sce_sys'+ - DirectorySeparator+ - 'param.sfo'); + if (FParamSfo=nil) then + begin + ParamSfo:=LoadParamSfoFile2(FGameItem.MountList.game); + FParamSfo:=ParamSfo; + end else + begin + ParamSfo:=FParamSfo; + end; if (ParamSfo=nil) then begin @@ -540,7 +553,7 @@ begin if (FGameItem=nil) then Exit; - V:=FGameItem.MountList.app0; + V:=FGameItem.MountList.game; playgo_file:=LoadPlaygoFile(ExcludeTrailingPathDelimiter(V)+ DirectorySeparator+ @@ -646,8 +659,7 @@ begin Item:=TGameItem.Create; FGameItem.CopyTo(Item); - Item.GameInfo.Exec :=data.Path; - Item.GameInfo.Param:=encode_shell(data.argv); + Item.GameInfo.Exec:=encode_shell(data.Path)+' '+encode_shell(data.argv); cfg.hOutput:=FAddHandle; cfg.hError :=FAddHandle; @@ -717,7 +729,7 @@ begin // FGrid.Cells[0,i]:=Item.FGameInfo.Name; FGrid.Cells[1,i]:=Item.FGameInfo.TitleId; - FGrid.Cells[2,i]:=Item.FGameInfo.Version; + FGrid.Cells[2,i]:=Item.FGameInfo.AppVer; // FGrid.Objects[0,i]:=Item; end; @@ -734,7 +746,7 @@ begin // FGrid.Cells[0,i]:=Item.FGameInfo.Name; FGrid.Cells[1,i]:=Item.FGameInfo.TitleId; - FGrid.Cells[2,i]:=Item.FGameInfo.Version; + FGrid.Cells[2,i]:=Item.FGameInfo.AppVer; // FGrid.Objects[0,i]:=Item; // @@ -752,7 +764,7 @@ begin // FGrid.Cells[0,i]:=Item.FGameInfo.Name; FGrid.Cells[1,i]:=Item.FGameInfo.TitleId; - FGrid.Cells[2,i]:=Item.FGameInfo.Version; + FGrid.Cells[2,i]:=Item.FGameInfo.AppVer; end; procedure TGameList.UpdateItem(Item:TGameItem); @@ -764,7 +776,7 @@ begin // FGrid.Cells[0,i]:=Item.FGameInfo.Name; FGrid.Cells[1,i]:=Item.FGameInfo.TitleId; - FGrid.Cells[2,i]:=Item.FGameInfo.Version; + FGrid.Cells[2,i]:=Item.FGameInfo.AppVer; end; procedure TGameList.DelItem(Item:TGameItem); @@ -1163,7 +1175,7 @@ begin TITLE :=FGameItem.FGameInfo.Name; TITLE_ID:=FGameItem.FGameInfo.TitleId; - APP_VER :=FGameItem.FGameInfo.Version; + APP_VER :=FGameItem.FGameInfo.AppVer; if (TITLE='') then begin @@ -1241,10 +1253,10 @@ var begin form:=TfrmGameEditor.Create(Self); - form.Item:=TGameItem.Create; + form.FConfigInfo:=FConfigInfo; + form.FItem :=TGameItem.Create; - form.Item.FMountList.system:=FConfigInfo.MainInfo.system; - form.Item.FMountList.data :=FConfigInfo.MainInfo.data; + form.FItem.FMountList.firmware:=FConfigInfo.MainInfo.DefaultFirmware; form.OnSave:=@Self.DoAdd; @@ -1270,12 +1282,12 @@ begin begin form:=TfrmGameEditor.Create(Self); - form.Item:=TGameItem.Create; + form.FConfigInfo:=FConfigInfo; + form.FItem :=TGameItem.Create; - form.Item.FMountList.system:=FConfigInfo.MainInfo.system; - form.Item.FMountList.data :=FConfigInfo.MainInfo.data; + form.FItem.FMountList.firmware:=FConfigInfo.MainInfo.DefaultFirmware; - form.Item.FMountList.app0:=d.FileName; + form.FItem.FMountList.game:=d.FileName; form.OnSave:=@Self.DoAdd; @@ -1304,13 +1316,14 @@ begin form:=TfrmGameEditor.Create(Self); - form.Item:=Item; + form.FConfigInfo:=FConfigInfo; + form.FItem:=Item; Item.FLock:=True; form.OnSave:=@Self.DoEdit; - form.FormInit(False); + form.FormInit(True); end; procedure TfrmMain.TBConfigClick(Sender: TObject); @@ -1376,10 +1389,10 @@ begin if Length(S)nil); if Item.FLock then Exit; @@ -1419,6 +1436,8 @@ begin begin Item.FLock:=True; FGameItem:=Item; + FParamSfo:=ParamSfo; + ParamSfo:=nil; SetButtonsState(mdsStarted); @@ -1427,6 +1446,8 @@ begin FGameProcess.g_ipc.FHandler:=IpcHandler; end; end; + + FreeAndNil(ParamSfo); end; procedure TfrmMain.TBPlayClick(Sender: TObject); @@ -1487,6 +1508,7 @@ begin FGameItem.FLock:=False; FGameItem:=nil; end; + FreeAndNil(FParamSfo); // CloseMainWindows; // @@ -1577,9 +1599,9 @@ var begin form:=TfrmGameEditor(Sender); - Item:=form.Item; + Item:=form.FItem; - form.Item:=nil; + form.FItem:=nil; FGameList.InsertItem(Item); // @@ -1593,11 +1615,11 @@ var begin form:=TfrmGameEditor(Sender); - Item:=form.Item; + Item:=form.FItem; Item.FLock:=False; - form.Item:=nil; + form.FItem:=nil; FGameList.UpdateItem(Item); // diff --git a/icons/Add_04_16.png b/icons/Add_04_16.png new file mode 100644 index 0000000000000000000000000000000000000000..2e984c0fa05f3ee309237f9d8f15bc585cd65778 GIT binary patch literal 369 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ z@ErkR#;MwT(m+AU64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1UvdAc}; zSoEHqXq$D|L7?^iny?_%8mUJAq~^Ozf(jn$Svqh{KekliftrH2nacH!lbL72rlo~x zetGQ@q#*I;`k76?e@y$%wqxsx_lbLM%ys$1z#!9pCf!E5^k<2@g9^Xdd1E1No3-VR z^Vf?rFr>2`;j>)FnUT)MaR2%oqnK?C&olWJFLBdsKeO@861I*f2TyN0p(B>S{rwC> z^n*gX!qe6rtlK;bP0l+XkKvt*L& literal 0 HcmV?d00001 diff --git a/icons/Folder_19_16.png b/icons/Folder_19_16.png new file mode 100644 index 0000000000000000000000000000000000000000..c268b9b08d93c23e6f7cb7b3db54f3b2955b5b19 GIT binary patch literal 606 zcmV-k0-^nhP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10qaRb zK~y-6rBh976JZ#f_hUD4leJYEl41x7ZLkW(lNkJHk=}|I!5;hzet?JvbMq$cL7{l| zSZEYfEcMVsE+z*HDz$E%1w^TvAa zD7xzti38G*e8W|Ajc%P=>t?`2VOg!+I4k0kx5+8XR+HAI40{xe`KDyk471S=|ez(3<#mm4?q1vN*DNW zHG_e;j@8|LJo#?p(c*6aKxm0G>vg1bfw?OgY_=4V?^a;96lO1_(XR_=oP`_AR~nca zPNHZ#m?&4!@B&PfD=69yCWn)VbTgOM71gl1yN~=(qRovYVi-xpu(aKTAvmNV+4T6r%Dv#w77n0shWt_uZ!c#60H4nJ z@ErkR#;MwT(m+AU64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1UjJY5_^ zEP9g@Bv_gGB@%hM&!o!#|M&O2caNG{+OhNM%iTX38yFaDIKToDy*)$v=#TI6%!lvS z^YGMP$VmBiXX)t&VjC4^|9Q<{*J~gpd4M+|Decc4t6IszxP+uXK0Uhv9rPI(wlJG7 USLU5i1+0) then + if (error<>0) and (mode=0) then begin - print_error_td('error execve "'+args^.fname+'" code='+IntToStr(error)); + print_error_td('error execve "'+args^.fname+'" code='+IntToStr(error),True); exec_free_args(args); @@ -1829,7 +1829,7 @@ done2: Exit(error); end; -function kern_execve(td:p_kthread;args:p_image_args):Integer; +function kern_execve(td:p_kthread;args:p_image_args;mode:Integer=0):Integer; var error:Integer; begin @@ -1837,7 +1837,7 @@ begin Assert((td^.td_pflags and TDP_EXECVMSPC)=0,'nested execve'); - error:=do_execve(td, args); + error:=do_execve(td, args, mode); if ((td^.td_pflags and TDP_EXECVMSPC)<>0) then begin @@ -1857,7 +1857,7 @@ begin if (error=0) then begin - error:=kern_execve(curkthread, @args); + error:=kern_execve(curkthread, @args, 1); end; Result:=(error); diff --git a/sys/kern/subr_backtrace.pas b/sys/kern/subr_backtrace.pas index 3eea0d86..2f194928 100644 --- a/sys/kern/subr_backtrace.pas +++ b/sys/kern/subr_backtrace.pas @@ -13,7 +13,7 @@ procedure print_frame(var f:text;frame:Pointer); procedure print_backtrace(var f:text;rip,rbp:Pointer;skipframes:sizeint); procedure print_backtrace_td(var f:text); -procedure print_error_td(const str:shortstring); +procedure print_error_td(const str:shortstring;resumable:Boolean=False); implementation @@ -315,14 +315,19 @@ begin print_backtrace(stderr,Pointer(td^.td_frame.tf_rip),Pointer(td^.td_frame.tf_rbp),0); end; -procedure print_error_td(const str:shortstring); +procedure print_error_td(const str:shortstring;resumable:Boolean=False); begin thread_suspend_all(p_host_ipc_td); Writeln(StdErr,str); + print_backtrace_td(StdErr); + p_host_ipc.error(str); - print_backtrace_td(StdErr); + if resumable then + begin + thread_resume_all(p_host_ipc_td); + end; end; end. diff --git a/sys/vfs/vfs_mount.pas b/sys/vfs/vfs_mount.pas index 7daee9f0..b7a63c2a 100644 --- a/sys/vfs/vfs_mount.pas +++ b/sys/vfs/vfs_mount.pas @@ -92,10 +92,10 @@ function vfs_donmount(fsflags:QWORD;fsoptions:p_uio):Integer; function dounmount(mp:p_mount;flags:Integer):Integer; -function mount_argb(ma:p_mntarg;flag:Integer;name:PChar):p_mntarg; -function mount_argf(ma:p_mntarg;name,fmt:PChar;const Args:Array of const):p_mntarg; register; +function mount_argb (ma:p_mntarg;flag:Integer;name:PChar):p_mntarg; +function mount_argf (ma:p_mntarg;name,fmt:PChar;const Args:Array of const):p_mntarg; register; function mount_argsu(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; -function mount_arg(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; +function mount_arg (ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg; procedure free_mntarg(ma:p_mntarg); function kernel_nmount(ma:p_mntarg;flags:QWORD):Integer; @@ -1028,6 +1028,7 @@ begin vput(vp); Exit(EINVAL); end; + mp:=vp^.v_mount; { * We only allow the filesystem to be reloaded if it @@ -1050,11 +1051,13 @@ begin vput(vp); Exit(error); end; + if (vfs_busy(mp, MBF_NOWAIT)<>0) then begin vput(vp); Exit(EBUSY); end; + VI_LOCK(vp); if ((vp^.v_iflag and VI_MOUNT)<>0) or (vp^.v_mountedhere<>nil) then begin @@ -1063,19 +1066,27 @@ begin vput(vp); Exit(EBUSY); end; + vp^.v_iflag:=vp^.v_iflag or VI_MOUNT; VI_UNLOCK(vp); VOP_UNLOCK(vp, 0); MNT_ILOCK(mp); mp^.mnt_flag:=mp^.mnt_flag and (not MNT_UPDATEMASK); - mp^.mnt_flag:=(mp^.mnt_flag or fsflags) and (MNT_RELOAD or MNT_FORCE or MNT_UPDATE or - MNT_SNAPSHOT or MNT_ROOTFS or MNT_UPDATEMASK or MNT_RDONLY); + mp^.mnt_flag:=(mp^.mnt_flag or fsflags) and + (MNT_RELOAD or + MNT_FORCE or + MNT_UPDATE or + MNT_SNAPSHOT or + MNT_ROOTFS or + MNT_UPDATEMASK or + MNT_RDONLY); if ((mp^.mnt_flag and MNT_ASYNC)=0) then begin mp^.mnt_kern_flag:=mp^.mnt_kern_flag and (not MNTK_ASYNC); end; + MNT_IUNLOCK(mp); mp^.mnt_optnew:=optlist^; vfs_mergeopts(mp^.mnt_optnew, mp^.mnt_opt); @@ -1143,6 +1154,7 @@ begin begin vfs_freeopts(mp^.mnt_opt); end; + mp^.mnt_opt:=mp^.mnt_optnew; optlist^:=nil; VFS_STATFS(mp, @mp^.mnt_stat); @@ -1224,6 +1236,7 @@ begin NDFREE(@nd, NDF_ONLY_PNBUF); vp:=nd.ni_vp; + if ((fsflags and MNT_UPDATE)=0) then begin pathbuf:=Default(t_mname); diff --git a/sys/vfs/vfs_mountroot.pas b/sys/vfs/vfs_mountroot.pas index 29e31213..1993c2d8 100644 --- a/sys/vfs/vfs_mountroot.pas +++ b/sys/vfs/vfs_mountroot.pas @@ -11,11 +11,14 @@ uses const MNT_RDONLY=vmount.MNT_RDONLY; + MNT_UPDATE=vmount.MNT_UPDATE; procedure vfs_mountroot(); -function vfs_mount_path (fstype,fspath,from,opts:PChar;flags:QWORD):Integer; -function vfs_mount_mkdir (fstype,fspath,from,opts:PChar;flags:QWORD):Integer; -function vfs_unmount_rmdir(path:PChar;flags:Integer):Integer; +function vfs_mount_path (fstype,fspath,from,opts:PChar;flags:QWORD):Integer; +function mount_mkdir (path:PChar):Integer; +function mount_rmdir (path:PChar):Integer; +function mount_into_sandbox (fstype,fspath,from,opts:PChar;flags:QWORD):Integer; +function unmount_from_sandbox(path:PChar;flags:Integer):Integer; implementation @@ -357,16 +360,26 @@ begin Result:=kernel_nmount(ma,flags); end; -function vfs_mount_mkdir(fstype,fspath,from,opts:PChar;flags:QWORD):Integer; +function mount_mkdir(path:PChar):Integer; +begin + Result:=kern_mkdir(path,UIO_SYSSPACE,&777); +end; + +function mount_rmdir(path:PChar):Integer; +begin +Result:=kern_rmdir(path,UIO_SYSSPACE); +end; + +function mount_into_sandbox(fstype,fspath,from,opts:PChar;flags:QWORD):Integer; begin Result:=kern_mkdir(fspath,UIO_SYSSPACE,&777); - if (Result=0) then + if (Result=0) or (Result=EEXIST) then begin Result:=vfs_mount_path(fstype,fspath,from,opts,flags); end; end; -function vfs_unmount_rmdir(path:PChar;flags:Integer):Integer; +function unmount_from_sandbox(path:PChar;flags:Integer):Integer; begin Result:=kern_unmount(path,flags); if (Result=0) then