mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-23 06:19:57 +00:00
+
This commit is contained in:
parent
8ac5b8743a
commit
260b053c5c
@ -31,7 +31,7 @@
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
</RequiredPackages>
|
||||
<Units Count="93">
|
||||
<Units Count="94">
|
||||
<Unit0>
|
||||
<Filename Value="fpPS4.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
@ -427,6 +427,10 @@
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="ps4_libSceScreenShot"/>
|
||||
</Unit92>
|
||||
<Unit93>
|
||||
<Filename Value="sys\sys_path.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit93>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -7,7 +7,7 @@ interface
|
||||
uses
|
||||
windows,
|
||||
sys_types,
|
||||
ps4_program,
|
||||
sys_path,
|
||||
Classes,
|
||||
SysUtils;
|
||||
|
||||
@ -339,12 +339,12 @@ begin
|
||||
end;
|
||||
|
||||
_sig_lock;
|
||||
rp:=_parse_filename(path);
|
||||
Result:=parse_filename(path,rp);
|
||||
_sig_unlock;
|
||||
|
||||
if (rp='') then
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Exit(_set_sce_errno(SCE_KERNEL_ERROR_EACCES));
|
||||
Exit(_set_sce_errno(px2sce(Result)));
|
||||
end;
|
||||
|
||||
_sig_lock;
|
||||
@ -628,10 +628,13 @@ begin
|
||||
stat^:=Default(SceKernelStat);
|
||||
|
||||
_sig_lock;
|
||||
rp:=_parse_filename(path);
|
||||
Result:=parse_filename(path,rp);
|
||||
_sig_unlock;
|
||||
|
||||
if (rp='') then Exit(_set_sce_errno(SCE_KERNEL_ERROR_EACCES));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Exit(_set_sce_errno(px2sce(Result)));
|
||||
end;
|
||||
|
||||
hfi:=Default(WIN32_FILE_ATTRIBUTE_DATA);
|
||||
err:=SwGetFileAttributes(rp,@hfi);
|
||||
@ -946,10 +949,13 @@ begin
|
||||
Writeln('sceKernelMkdir:',path,'(',OctStr(mode,3),')');
|
||||
|
||||
_sig_lock;
|
||||
fn:=_parse_filename(path);
|
||||
Result:=parse_filename(path,fn);
|
||||
_sig_unlock;
|
||||
|
||||
if (fn='') then Exit(_set_sce_errno(SCE_KERNEL_ERROR_EACCES));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Exit(_set_sce_errno(px2sce(Result)));
|
||||
end;
|
||||
|
||||
err:=SwCreateDir(fn);
|
||||
|
||||
@ -1004,10 +1010,13 @@ begin
|
||||
Writeln('mkdir:',path);
|
||||
|
||||
_sig_lock;
|
||||
fn:=_parse_filename(path);
|
||||
Result:=parse_filename(path,fn);
|
||||
_sig_unlock;
|
||||
|
||||
if (fn='') then Exit(_set_errno(EACCES));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Exit(_set_errno(Result));
|
||||
end;
|
||||
|
||||
err:=SwCreateDir(fn);
|
||||
|
||||
@ -1061,10 +1070,13 @@ begin
|
||||
Writeln('sceKernelCheckReachability:',path);
|
||||
|
||||
_sig_lock;
|
||||
fn:=_parse_filename(path);
|
||||
Result:=parse_filename(path,fn);
|
||||
_sig_unlock;
|
||||
|
||||
if (fn='') then Exit(_set_sce_errno(SCE_KERNEL_ERROR_EACCES));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Exit(_set_sce_errno(px2sce(Result)));
|
||||
end;
|
||||
|
||||
if FileExists(fn) or DirectoryExists(fn) then
|
||||
begin
|
||||
|
@ -37,6 +37,7 @@ function ps4_sceKernelGetCompiledSdkVersion(sdkVersion:PDWORD):Integer; SysV_AB
|
||||
implementation
|
||||
|
||||
uses
|
||||
sys_path,
|
||||
sys_kernel,
|
||||
sys_pthread,
|
||||
sys_signal;
|
||||
@ -409,7 +410,13 @@ begin
|
||||
|
||||
Writeln('Load Lib:',moduleFileName);
|
||||
|
||||
fn:=_parse_filename(moduleFileName);
|
||||
Result:=parse_filename(moduleFileName,fn);
|
||||
|
||||
if (Result<>0) then
|
||||
begin
|
||||
_sig_unlock;
|
||||
Exit(px2sce(Result));
|
||||
end;
|
||||
|
||||
node:=ps4_app.AcqureFileByName(ExtractFileName(fn));
|
||||
if (node<>nil) then
|
||||
|
361
ps4_program.pas
361
ps4_program.pas
@ -169,11 +169,6 @@ var
|
||||
|
||||
Procedure DumpExceptionCallStack(E: Exception);
|
||||
|
||||
Function FetchMount(path,point:PChar;mode:Integer):Integer;
|
||||
Function UnMountPath(path:PChar):Integer;
|
||||
|
||||
function _parse_filename(filename:PChar):RawByteString;
|
||||
|
||||
function GetSceProcParam:Pointer;
|
||||
function GetSceUserMainThreadName:PChar;
|
||||
function GetSceUserMainThreadPriority:PDWORD;
|
||||
@ -207,360 +202,6 @@ begin
|
||||
Writeln(StdErr,Report);
|
||||
end;
|
||||
|
||||
Procedure DoFixRelative(var Path:RawByteString);
|
||||
Var
|
||||
i,L,CF,PF:SizeInt;
|
||||
|
||||
Procedure _c; inline;
|
||||
begin
|
||||
Case (i-CF) of
|
||||
2:if (PWORD(@Path[CF])^=$2E2E) then //..
|
||||
begin
|
||||
i:=i-PF+1;
|
||||
L:=L-i;
|
||||
Delete(Path,PF,i);
|
||||
CF:=PF;
|
||||
i:=PF-1;
|
||||
end;
|
||||
1:if (Path[CF]='.') then //.
|
||||
begin
|
||||
Delete(Path,1,CF);
|
||||
L:=Length(Path);
|
||||
CF:=1;
|
||||
i:=1;
|
||||
end;
|
||||
end;
|
||||
PF:=CF;
|
||||
CF:=i+1;
|
||||
end;
|
||||
|
||||
begin
|
||||
PF:=1;
|
||||
CF:=1;
|
||||
i:=1;
|
||||
L:=Length(Path);
|
||||
While (i<=L) do
|
||||
begin
|
||||
if (Path[i]='/') then _c;
|
||||
Inc(i);
|
||||
end;
|
||||
_c;
|
||||
end;
|
||||
|
||||
Procedure DoDirSeparators(var Path:RawByteString); inline;
|
||||
var
|
||||
i:Integer;
|
||||
begin
|
||||
if ('/'<>DirectorySeparator) and (Path<>'') then
|
||||
For i:=1 to Length(Path) do
|
||||
if (Path[i]='/') then Path[i]:=DirectorySeparator;
|
||||
end;
|
||||
|
||||
Function IsSep(c:AnsiChar):Boolean; inline;
|
||||
begin
|
||||
Result:=False;
|
||||
Case c of
|
||||
'\',
|
||||
'/':Result:=True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function IncludeTrailingPathDelimiter(Const Path:RawByteString):RawByteString; inline;
|
||||
begin
|
||||
Result:=Path;
|
||||
if (Result='') or (not IsSep(Result[Length(Result)])) then Result:=Result+DirectorySeparator;
|
||||
end;
|
||||
|
||||
function PathConcat(Path,filename:RawByteString):RawByteString;
|
||||
begin
|
||||
Path:=Trim(Path);
|
||||
If (Path='') then Exit('');
|
||||
if (not IsSep(Path[Length(Path)])) then Path:=Path+DirectorySeparator;
|
||||
DoDirSeparators(filename);
|
||||
Result:=Path+filename;
|
||||
end;
|
||||
|
||||
const
|
||||
DIRNAME_MAXSIZE=32;
|
||||
MOUNT_MAXSIZE=16;
|
||||
|
||||
type
|
||||
TMountDir=array[0..DIRNAME_MAXSIZE-1] of AnsiChar;
|
||||
|
||||
var
|
||||
FMounts_lock:TRWLock;
|
||||
FMounts:array[0..15] of TMountDir;
|
||||
|
||||
const
|
||||
SCE_SAVE_DATA_ERROR_PARAMETER =-2137063424; // 0x809F0000
|
||||
SCE_SAVE_DATA_ERROR_EXISTS =-2137063417; // 0x809F0007
|
||||
SCE_SAVE_DATA_ERROR_NOT_FOUND =-2137063416; // 0x809f0008
|
||||
SCE_SAVE_DATA_ERROR_MOUNT_FULL =-2137063412; // 0x809F000C
|
||||
SCE_SAVE_DATA_ERROR_NOT_MOUNTED=-2137063420; // 0x809F0004
|
||||
SCE_SAVE_DATA_ERROR_INTERNAL =-2137063413; // 0x809f000b
|
||||
SCE_SAVE_DATA_ERROR_BUSY =-2137063421; // 0x809f0003
|
||||
|
||||
|
||||
SCE_SAVE_DATA_MOUNT_MODE_RDONLY =1; //Read-only
|
||||
SCE_SAVE_DATA_MOUNT_MODE_RDWR =2; //Read/write-enabled
|
||||
SCE_SAVE_DATA_MOUNT_MODE_CREATE =4; //Create new (error if save data directory already exists)
|
||||
SCE_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF=8; //Turn off corrupt flag (not recommended)
|
||||
SCE_SAVE_DATA_MOUNT_MODE_COPY_ICON =16; //Copy save_data.png in package as icon when newly creating save data
|
||||
SCE_SAVE_DATA_MOUNT_MODE_CREATE2 =32; //Create new (mount save data directory if it already exists)
|
||||
|
||||
Function FetchMount(path,point:PChar;mode:Integer):Integer;
|
||||
var
|
||||
sp:RawByteString;
|
||||
s:TMountDir;
|
||||
i,m:Integer;
|
||||
Label
|
||||
_exit;
|
||||
begin
|
||||
Result:=0;
|
||||
if (path=nil) or (point=nil) then Exit(SCE_SAVE_DATA_ERROR_PARAMETER);
|
||||
|
||||
s:=Default(TMountDir);
|
||||
MoveChar0(path^,s,DIRNAME_MAXSIZE);
|
||||
|
||||
i:=IndexChar(s,MOUNT_MAXSIZE,#0);
|
||||
if (i=0) then Exit(SCE_SAVE_DATA_ERROR_PARAMETER);
|
||||
|
||||
sp:=IncludeTrailingPathDelimiter(ps4_app.save_path)+s;
|
||||
|
||||
if (mode and SCE_SAVE_DATA_MOUNT_MODE_CREATE2)<>0 then
|
||||
begin
|
||||
if not ForceDirectories(ps4_app.save_path) then Exit(SCE_SAVE_DATA_ERROR_INTERNAL);
|
||||
CreateDir(sp);
|
||||
end else
|
||||
if (mode and SCE_SAVE_DATA_MOUNT_MODE_CREATE)<>0 then
|
||||
begin
|
||||
if not ForceDirectories(ps4_app.save_path) then Exit(SCE_SAVE_DATA_ERROR_INTERNAL);
|
||||
//if not CreateDir(sp) then Exit(SCE_SAVE_DATA_ERROR_EXISTS);
|
||||
CreateDir(sp);
|
||||
end else
|
||||
begin
|
||||
if not DirectoryExists(sp) then Exit(SCE_SAVE_DATA_ERROR_NOT_FOUND);
|
||||
end;
|
||||
|
||||
rwlock_wrlock(FMounts_lock);
|
||||
|
||||
m:=-1;
|
||||
For i:=0 to 15 do
|
||||
begin
|
||||
if (FMounts[i]='') then
|
||||
begin
|
||||
if (m=-1) then m:=i;
|
||||
end else
|
||||
begin
|
||||
if (FMounts[i]=s) then
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_BUSY;
|
||||
goto _exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (m<>-1) then
|
||||
begin
|
||||
FMounts[m]:=s;
|
||||
s:='/savedata'+IntToStr(m);
|
||||
Move(s,point^,MOUNT_MAXSIZE);
|
||||
end else
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_MOUNT_FULL;
|
||||
end;
|
||||
|
||||
_exit:
|
||||
rwlock_unlock(FMounts_lock);
|
||||
end;
|
||||
|
||||
Function UnMountId(id:Byte):Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
rwlock_wrlock(FMounts_lock);
|
||||
|
||||
if (FMounts[id]<>'') then
|
||||
begin
|
||||
FMounts[id]:='';
|
||||
end else
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_NOT_MOUNTED;
|
||||
end;
|
||||
|
||||
rwlock_unlock(FMounts_lock);
|
||||
end;
|
||||
|
||||
Function UnMountPath(path:PChar):Integer;
|
||||
var
|
||||
s:TMountDir;
|
||||
i:Integer;
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_PARAMETER;
|
||||
if (path=nil) then Exit;
|
||||
|
||||
s:=Default(TMountDir);
|
||||
MoveChar0(path^,s,MOUNT_MAXSIZE);
|
||||
|
||||
if (s[0]<>'/') then Exit;
|
||||
|
||||
i:=IndexChar(s,MOUNT_MAXSIZE,#0);
|
||||
|
||||
Case i of
|
||||
10:Case PQWORD(@s[1])^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case s[9] of
|
||||
'0'..'9':
|
||||
begin
|
||||
Result:=UnMountId(ord(s[9])-ord('0'));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
11:Case PQWORD(@s[1])^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case PWORD(PBYTE(@s)+9)^ of
|
||||
$3031, //10
|
||||
$3131, //11
|
||||
$3231, //12
|
||||
$3331, //13
|
||||
$3431, //14
|
||||
$3531: //15
|
||||
begin
|
||||
Result:=UnMountId(ord(s[10])-ord('0')+10);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
Function GetMount(id:Byte):RawByteString;
|
||||
begin
|
||||
rwlock_rdlock(FMounts_lock);
|
||||
Result:=FMounts[id];
|
||||
rwlock_unlock(FMounts_lock);
|
||||
end;
|
||||
|
||||
// /app0
|
||||
// /savedata0
|
||||
// /savedata15
|
||||
|
||||
function MountConcat(id:Byte;const filename:RawByteString):RawByteString;
|
||||
var
|
||||
s:RawByteString;
|
||||
begin
|
||||
s:=GetMount(id);
|
||||
if (s='') then Exit('');
|
||||
|
||||
s:=IncludeTrailingPathDelimiter(ps4_app.save_path)+s;
|
||||
|
||||
Result:=PathConcat(s,filename);
|
||||
end;
|
||||
|
||||
function _parse_cast(var pp,fp:PChar;var Path:RawByteString):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
Case (fp-pp) of
|
||||
0:pp:=fp+1; //next
|
||||
4:Case PDWORD(pp)^ of
|
||||
$30707061: //app0
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Path:=PathConcat(ps4_app.app_path,fp);
|
||||
Result:=1;
|
||||
end;
|
||||
else
|
||||
Result:=2;
|
||||
end;
|
||||
9:Case PQWORD(pp)^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case (pp+8)^ of
|
||||
'0'..'9':
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Path:=MountConcat(ord((pp+8)^)-ord('0'),fp);;
|
||||
Result:=1;
|
||||
end;
|
||||
else
|
||||
Result:=2;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
Result:=2;
|
||||
end;
|
||||
10:Case PQWORD(pp)^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case PWORD(pp+8)^ of
|
||||
$3031, //10
|
||||
$3131, //11
|
||||
$3231, //12
|
||||
$3331, //13
|
||||
$3431, //14
|
||||
$3531: //15
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Path:=MountConcat(ord((pp+9)^)-ord('0')+10,fp);
|
||||
//Result:=PathConcat(GetCurrentDir,fp);
|
||||
Result:=1;
|
||||
end;
|
||||
else
|
||||
Result:=2;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
Result:=2;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
//Writeln((fp-pp),'*',fp,'*',pp);
|
||||
Result:=2;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function _parse_filename(filename:PChar):RawByteString;
|
||||
var
|
||||
Path:RawByteString;
|
||||
pp,fp:PChar;
|
||||
|
||||
begin
|
||||
Result:='';
|
||||
//Writeln(filename);
|
||||
if (filename=nil) then Exit;
|
||||
Path:=filename;
|
||||
DoFixRelative(Path);
|
||||
fp:=PChar(Path);
|
||||
pp:=PChar(Path);
|
||||
While (fp^<>#0) do
|
||||
begin
|
||||
Case fp^ of
|
||||
'/':
|
||||
begin
|
||||
Case _parse_cast(pp,fp,Result) of
|
||||
1:Exit; //mapped
|
||||
2:Exit; //not mapped
|
||||
else;
|
||||
//next char
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Inc(fp);
|
||||
end;
|
||||
|
||||
Case _parse_cast(pp,fp,Result) of
|
||||
1:Exit; //mapped
|
||||
else;
|
||||
Exit; //not mapped
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
procedure TElfNodeList.Push_head(Node:TElf_node);
|
||||
@ -1647,7 +1288,5 @@ initialization
|
||||
ps4_app.libs.Init;
|
||||
ps4_app.elfs:=TIntegerHandles.Create;
|
||||
|
||||
rwlock_init(FMounts_lock);
|
||||
|
||||
end.
|
||||
|
||||
|
@ -189,6 +189,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
sys_path,
|
||||
sys_signal;
|
||||
|
||||
function ps4_sceSaveDataInitialize(params:Pointer):Integer; SysV_ABI_CDecl;
|
||||
@ -295,7 +296,7 @@ begin
|
||||
mountResult^:=Default(SceSaveDataMountResult);
|
||||
|
||||
_sig_lock;
|
||||
Result:=FetchMount(PChar(mount^.dirName),@mountResult^.mountPoint,mount^.mountMode);
|
||||
Result:=FetchSaveMount(PChar(mount^.dirName),@mountResult^.mountPoint,mount^.mountMode);
|
||||
_sig_unlock;
|
||||
|
||||
if (Result=0) and
|
||||
@ -312,7 +313,7 @@ begin
|
||||
mountResult^:=Default(SceSaveDataMountResult);
|
||||
|
||||
_sig_lock;
|
||||
Result:=FetchMount(PChar(mount^.dirName),@mountResult^.mountPoint,mount^.mountMode);
|
||||
Result:=FetchSaveMount(PChar(mount^.dirName),@mountResult^.mountPoint,mount^.mountMode);
|
||||
_sig_unlock;
|
||||
|
||||
if (Result=0) and
|
||||
@ -326,14 +327,14 @@ end;
|
||||
function ps4_sceSaveDataUmount(mountPoint:PSceSaveDataMountPoint):Integer; SysV_ABI_CDecl;
|
||||
begin
|
||||
_sig_lock;
|
||||
Result:=UnMountPath(PChar(mountPoint));
|
||||
Result:=UnMountSavePath(PChar(mountPoint));
|
||||
_sig_unlock;
|
||||
end;
|
||||
|
||||
function ps4_sceSaveDataUmountWithBackup(mountPoint:PSceSaveDataMountPoint):Integer; SysV_ABI_CDecl;
|
||||
begin
|
||||
_sig_lock;
|
||||
Result:=UnMountPath(PChar(mountPoint));
|
||||
Result:=UnMountSavePath(PChar(mountPoint));
|
||||
//backup this
|
||||
_sig_unlock;
|
||||
end;
|
||||
@ -413,6 +414,8 @@ begin
|
||||
|
||||
s:=IncludeTrailingPathDelimiter(ps4_app.save_path)+_convert_dir_name_search(@cond^.dirName);
|
||||
|
||||
_sig_lock;
|
||||
|
||||
ROut:=Default(TRawByteSearchRec);
|
||||
if (FindFirst(s,faDirectory,ROut)=0) then
|
||||
begin
|
||||
@ -477,6 +480,8 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
_sig_unlock;
|
||||
|
||||
end;
|
||||
|
||||
type
|
||||
|
393
sys/sys_path.pas
Normal file
393
sys/sys_path.pas
Normal file
@ -0,0 +1,393 @@
|
||||
unit sys_path;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes,
|
||||
SysUtils,
|
||||
RWLock,
|
||||
ps4_program,
|
||||
sys_kernel;
|
||||
|
||||
Function FetchSaveMount(path,point:PChar;mode:Integer):Integer;
|
||||
Function UnMountSavePath(path:PChar):Integer;
|
||||
|
||||
function parse_filename(filename:PChar;var r:RawByteString):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
SCE_SAVE_DATA_ERROR_PARAMETER =-2137063424; // 0x809F0000
|
||||
SCE_SAVE_DATA_ERROR_EXISTS =-2137063417; // 0x809F0007
|
||||
SCE_SAVE_DATA_ERROR_NOT_FOUND =-2137063416; // 0x809f0008
|
||||
SCE_SAVE_DATA_ERROR_MOUNT_FULL =-2137063412; // 0x809F000C
|
||||
SCE_SAVE_DATA_ERROR_NOT_MOUNTED=-2137063420; // 0x809F0004
|
||||
SCE_SAVE_DATA_ERROR_INTERNAL =-2137063413; // 0x809f000b
|
||||
SCE_SAVE_DATA_ERROR_BUSY =-2137063421; // 0x809f0003
|
||||
|
||||
SCE_SAVE_DATA_MOUNT_MODE_RDONLY =1; //Read-only
|
||||
SCE_SAVE_DATA_MOUNT_MODE_RDWR =2; //Read/write-enabled
|
||||
SCE_SAVE_DATA_MOUNT_MODE_CREATE =4; //Create new (error if save data directory already exists)
|
||||
SCE_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF=8; //Turn off corrupt flag (not recommended)
|
||||
SCE_SAVE_DATA_MOUNT_MODE_COPY_ICON =16; //Copy save_data.png in package as icon when newly creating save data
|
||||
SCE_SAVE_DATA_MOUNT_MODE_CREATE2 =32; //Create new (mount save data directory if it already exists)
|
||||
|
||||
DIRNAME_MAXSIZE=32;
|
||||
MOUNT_MAXSIZE =16;
|
||||
|
||||
type
|
||||
TMountDir=array[0..DIRNAME_MAXSIZE-1] of AnsiChar;
|
||||
|
||||
var
|
||||
FSaveMounts_lock:TRWLock;
|
||||
FSaveMounts:array[0..15] of TMountDir;
|
||||
|
||||
Procedure DoFixRelative(var Path:RawByteString);
|
||||
Var
|
||||
i,L,CF,PF:SizeInt;
|
||||
|
||||
Procedure _c; inline;
|
||||
begin
|
||||
Case (i-CF) of
|
||||
2:if (PWORD(@Path[CF])^=$2E2E) then //..
|
||||
begin
|
||||
i:=i-PF+1;
|
||||
L:=L-i;
|
||||
Delete(Path,PF,i);
|
||||
CF:=PF;
|
||||
i:=PF-1;
|
||||
end;
|
||||
1:if (Path[CF]='.') then //.
|
||||
begin
|
||||
Delete(Path,1,CF);
|
||||
L:=Length(Path);
|
||||
CF:=1;
|
||||
i:=1;
|
||||
end;
|
||||
end;
|
||||
PF:=CF;
|
||||
CF:=i+1;
|
||||
end;
|
||||
|
||||
begin
|
||||
PF:=1;
|
||||
CF:=1;
|
||||
i:=1;
|
||||
L:=Length(Path);
|
||||
While (i<=L) do
|
||||
begin
|
||||
if (Path[i]='/') then _c;
|
||||
Inc(i);
|
||||
end;
|
||||
_c;
|
||||
end;
|
||||
|
||||
Procedure DoDirSeparators(var Path:RawByteString); inline;
|
||||
var
|
||||
i:Integer;
|
||||
begin
|
||||
if ('/'<>DirectorySeparator) and (Path<>'') then
|
||||
For i:=1 to Length(Path) do
|
||||
if (Path[i]='/') then Path[i]:=DirectorySeparator;
|
||||
end;
|
||||
|
||||
Function IsSep(c:AnsiChar):Boolean; inline;
|
||||
begin
|
||||
Result:=False;
|
||||
Case c of
|
||||
'\',
|
||||
'/':Result:=True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function IncludeTrailingPathDelimiter(Const Path:RawByteString):RawByteString; inline;
|
||||
begin
|
||||
Result:=Path;
|
||||
if (Result='') or (not IsSep(Result[Length(Result)])) then Result:=Result+DirectorySeparator;
|
||||
end;
|
||||
|
||||
function PathConcat(Path,filename:RawByteString):RawByteString;
|
||||
begin
|
||||
Path:=Trim(Path);
|
||||
If (Path='') then Exit('');
|
||||
if (not IsSep(Path[Length(Path)])) then Path:=Path+DirectorySeparator;
|
||||
DoDirSeparators(filename);
|
||||
Result:=Path+filename;
|
||||
end;
|
||||
|
||||
Function FetchSaveMount(path,point:PChar;mode:Integer):Integer;
|
||||
var
|
||||
sp:RawByteString;
|
||||
s:TMountDir;
|
||||
i,m:Integer;
|
||||
Label
|
||||
_exit;
|
||||
begin
|
||||
Result:=0;
|
||||
if (path=nil) or (point=nil) then Exit(SCE_SAVE_DATA_ERROR_PARAMETER);
|
||||
|
||||
s:=Default(TMountDir);
|
||||
MoveChar0(path^,s,DIRNAME_MAXSIZE);
|
||||
|
||||
i:=IndexChar(s,MOUNT_MAXSIZE,#0);
|
||||
if (i=0) then Exit(SCE_SAVE_DATA_ERROR_PARAMETER);
|
||||
|
||||
sp:=IncludeTrailingPathDelimiter(ps4_app.save_path)+s;
|
||||
|
||||
if (mode and SCE_SAVE_DATA_MOUNT_MODE_CREATE2)<>0 then
|
||||
begin
|
||||
if not ForceDirectories(ps4_app.save_path) then Exit(SCE_SAVE_DATA_ERROR_INTERNAL);
|
||||
CreateDir(sp);
|
||||
end else
|
||||
if (mode and SCE_SAVE_DATA_MOUNT_MODE_CREATE)<>0 then
|
||||
begin
|
||||
if not ForceDirectories(ps4_app.save_path) then Exit(SCE_SAVE_DATA_ERROR_INTERNAL);
|
||||
//if not CreateDir(sp) then Exit(SCE_SAVE_DATA_ERROR_EXISTS);
|
||||
CreateDir(sp);
|
||||
end else
|
||||
begin
|
||||
if not DirectoryExists(sp) then Exit(SCE_SAVE_DATA_ERROR_NOT_FOUND);
|
||||
end;
|
||||
|
||||
rwlock_wrlock(FSaveMounts_lock);
|
||||
|
||||
m:=-1;
|
||||
For i:=0 to 15 do
|
||||
begin
|
||||
if (FSaveMounts[i]='') then
|
||||
begin
|
||||
if (m=-1) then m:=i;
|
||||
end else
|
||||
begin
|
||||
if (FSaveMounts[i]=s) then
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_BUSY;
|
||||
goto _exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (m<>-1) then
|
||||
begin
|
||||
FSaveMounts[m]:=s;
|
||||
s:='/savedata'+IntToStr(m);
|
||||
Move(s,point^,MOUNT_MAXSIZE);
|
||||
end else
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_MOUNT_FULL;
|
||||
end;
|
||||
|
||||
_exit:
|
||||
rwlock_unlock(FSaveMounts_lock);
|
||||
end;
|
||||
|
||||
Function UnMountId(id:Byte):Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
rwlock_wrlock(FSaveMounts_lock);
|
||||
|
||||
if (FSaveMounts[id]<>'') then
|
||||
begin
|
||||
FSaveMounts[id]:='';
|
||||
end else
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_NOT_MOUNTED;
|
||||
end;
|
||||
|
||||
rwlock_unlock(FSaveMounts_lock);
|
||||
end;
|
||||
|
||||
Function UnMountSavePath(path:PChar):Integer;
|
||||
var
|
||||
s:TMountDir;
|
||||
i:Integer;
|
||||
begin
|
||||
Result:=SCE_SAVE_DATA_ERROR_PARAMETER;
|
||||
if (path=nil) then Exit;
|
||||
|
||||
s:=Default(TMountDir);
|
||||
MoveChar0(path^,s,MOUNT_MAXSIZE);
|
||||
|
||||
if (s[0]<>'/') then Exit;
|
||||
|
||||
i:=IndexChar(s,MOUNT_MAXSIZE,#0);
|
||||
|
||||
Case i of
|
||||
10:Case PQWORD(@s[1])^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case s[9] of
|
||||
'0'..'9':
|
||||
begin
|
||||
Result:=UnMountId(ord(s[9])-ord('0'));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
11:Case PQWORD(@s[1])^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case PWORD(PBYTE(@s)+9)^ of
|
||||
$3031, //10
|
||||
$3131, //11
|
||||
$3231, //12
|
||||
$3331, //13
|
||||
$3431, //14
|
||||
$3531: //15
|
||||
begin
|
||||
Result:=UnMountId(ord(s[10])-ord('0')+10);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
Function GetSaveMount(id:Byte):RawByteString;
|
||||
begin
|
||||
rwlock_rdlock(FSaveMounts_lock);
|
||||
Result:=FSaveMounts[id];
|
||||
rwlock_unlock(FSaveMounts_lock);
|
||||
end;
|
||||
|
||||
// /app0
|
||||
// /savedata0
|
||||
// /savedata15
|
||||
|
||||
function MountSaveConcat(id:Byte;const filename:RawByteString):RawByteString;
|
||||
var
|
||||
s:RawByteString;
|
||||
begin
|
||||
s:=GetSaveMount(id);
|
||||
if (s='') then Exit('');
|
||||
|
||||
s:=IncludeTrailingPathDelimiter(ps4_app.save_path)+s;
|
||||
|
||||
Result:=PathConcat(s,filename);
|
||||
end;
|
||||
|
||||
const
|
||||
P_ERR =-1;
|
||||
P_NEXT =0;
|
||||
P_MOUNT=1;
|
||||
|
||||
function _parse_cast(var pp,fp:PChar;var Path:RawByteString):Integer;
|
||||
begin
|
||||
Result:=P_NEXT;
|
||||
Case (fp-pp) of
|
||||
0:pp:=fp+1; //next
|
||||
3:Case (PDWORD(pp)^ and $00FFFFFF) of
|
||||
$00766564: //dev
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Result:=P_ERR; //TODO
|
||||
end;
|
||||
else
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
4:Case PDWORD(pp)^ of
|
||||
$30707061: //app0
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Path:=PathConcat(ps4_app.app_path,fp);
|
||||
Result:=P_MOUNT;
|
||||
end;
|
||||
else
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
9:Case PQWORD(pp)^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case (pp+8)^ of
|
||||
'0'..'9':
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Path:=MountSaveConcat(ord((pp+8)^)-ord('0'),fp);
|
||||
Result:=P_MOUNT;
|
||||
end;
|
||||
else
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
10:Case PQWORD(pp)^ of
|
||||
$6174616465766173: //savedata
|
||||
begin
|
||||
Case PWORD(pp+8)^ of
|
||||
$3031, //10
|
||||
$3131, //11
|
||||
$3231, //12
|
||||
$3331, //13
|
||||
$3431, //14
|
||||
$3531: //15
|
||||
begin
|
||||
if (fp^<>#0) then Inc(fp);
|
||||
Path:=MountSaveConcat(ord((pp+9)^)-ord('0')+10,fp);
|
||||
Result:=P_MOUNT;
|
||||
end;
|
||||
else
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
//Writeln((fp-pp),'*',fp,'*',pp);
|
||||
Result:=P_ERR;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function parse_filename(filename:PChar;var r:RawByteString):Integer;
|
||||
var
|
||||
Path:RawByteString;
|
||||
pp,fp:PChar;
|
||||
|
||||
begin
|
||||
r:='';
|
||||
//Writeln(filename);
|
||||
if (filename=nil) then Exit(EINVAL);
|
||||
|
||||
Path:=filename;
|
||||
DoFixRelative(Path);
|
||||
fp:=PChar(Path);
|
||||
pp:=PChar(Path);
|
||||
|
||||
While (fp^<>#0) do
|
||||
begin
|
||||
Case fp^ of
|
||||
'/':
|
||||
begin
|
||||
Case _parse_cast(pp,fp,r) of
|
||||
P_MOUNT:Exit(0); //mapped
|
||||
P_ERR :Exit(EACCES); //not mapped
|
||||
else;
|
||||
//next char
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Inc(fp);
|
||||
end;
|
||||
|
||||
Case _parse_cast(pp,fp,r) of
|
||||
P_MOUNT:Exit(0); //mapped
|
||||
else;
|
||||
Exit(EACCES); //not mapped
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
initialization
|
||||
rwlock_init(FSaveMounts_lock);
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user