red-prig / fpps4-game-compatibility

Game compatibility
169 stars 12 forks source link

Persona 3 Reload - CUSA37521 #1964

Open nagitookomaeda opened 2 months ago

nagitookomaeda commented 2 months ago

Game Name

Persona 3 Reload

Game code

CUSA37521

Game version

01.02

Used emulator's version

ad0b024

Current status

Nothing

Error

[main:12936] nop nid:libkernel:A8249FA8320B967B:sceKernelMemoryPoolExpand

Description

Nothing

Used hacks

No response

Screenshots

image image

Log File

No response

mrsteyk commented 1 month ago

With those simple AND HACKY WinAPI dependant implementations you can get to Aio funcs. (I do not write in fp)

function ps4_sceKernelMemoryPoolExpand(searchStart:Pointer;searchEnd:Pointer;len:size_t;alignment:size_t;physAddrOut:PQWORD):Integer; SysV_ABI_CDecl;
begin
 //Result:=EINVAL; // any non zero will abort
 // a1/start is penultimate of sceKernelAvailableDirectMemorySize (physAddrOut)
 // a2/end is sceKernelGetDirectMemorySize (DMEM size)
 // a3/len is sceKernelGetDirectMemorySize (DMEM size) - 0x10000LL
 // a4/align is constant zero, alignment based on public GH repos?
 // a5/physAddrOut is unused???
 WriteLn('ps4_sceKernelMemoryPoolExpand ', QWORD(searchStart), ' ', QWORD(searchEnd), ' ', len, ' ', alignment, ' ', QWORD(physAddrOut));
 Result:=0;
end;

function ps4_sceKernelMemoryPoolReserve(addr:Pointer;size:size_t;memory_type:size_t;flags:size_t;addr_out:PQWORD):Integer; SysV_ABI_CDecl;
begin
 WriteLn('ps4_sceKernelMemoryPoolReserve ', QWORD(addr), ' ', size, ' ', str_mem_type(memory_type), ' ', flags, ' ', QWORD(addr_out));
 addr_out^:=QWORD(VirtualAlloc(LPVOID(addr), size, MEM_RESERVE, PAGE_READWRITE));
 Result:=Integer(addr_out^ = 0);
end;
function ps4_sceKernelMemoryPoolCommit(addr:Pointer;len:size_t;memory_type:Integer;prot:Integer;flags:Integer):Integer; SysV_ABI_CDecl;
var
 a: Pointer;
begin
 Result:=EINVAL;
 a:=Pointer(0);
 WriteLn('ps4_sceKernelMemoryPoolCommit ', QWORD(addr), ' ', len, ' ', str_mem_type(memory_type), ' ', prot, ' ', flags);
 if memory_type <> 3 then
 begin
  a:=Pointer(VirtualAlloc(LPVOID(addr), len, MEM_COMMIT, PAGE_READWRITE));
  Result:=Integer(QWORD(a) = 0);
  WriteLn('ps4_sceKernelMemoryPoolCommit  ', QWORD(a), ' ', Result);
  Assert(addr = a);

  _set_errno(Result);
  Result:=px2sce(Result);
 end;
end;
[main:25524] nop nid:libkernel:BD853C3FD4DDD99A:sceKernelAioInitializeImpl

GoldHEN(?) implements async io with already existing sync functions.

gandalfthewhite19890404 commented 1 month ago

With those simple WinAPI dependant implementations you can get to Aio funcs. (I do not write in fp)

function ps4_sceKernelMemoryPoolExpand(searchStart:Pointer;searchEnd:Pointer;len:size_t;alignment:size_t;physAddrOut:PQWORD):Integer; SysV_ABI_CDecl;
begin
 //Result:=EINVAL; // any non zero will abort
 // a1/start is penultimate of sceKernelAvailableDirectMemorySize (physAddrOut)
 // a2/end is sceKernelGetDirectMemorySize (DMEM size)
 // a3/len is sceKernelGetDirectMemorySize (DMEM size) - 0x10000LL
 // a4/align is constant zero, alignment based on public GH repos?
 // a5/physAddrOut is unused???
 WriteLn('ps4_sceKernelMemoryPoolExpand ', QWORD(searchStart), ' ', QWORD(searchEnd), ' ', len, ' ', alignment, ' ', QWORD(physAddrOut));
 Result:=0;
end;

function ps4_sceKernelMemoryPoolReserve(addr:Pointer;size:size_t;memory_type:size_t;flags:size_t;addr_out:PQWORD):Integer; SysV_ABI_CDecl;
begin
 WriteLn('ps4_sceKernelMemoryPoolReserve ', QWORD(addr), ' ', size, ' ', str_mem_type(memory_type), ' ', flags, ' ', QWORD(addr_out));
 addr_out^:=QWORD(VirtualAlloc(LPVOID(addr), size, MEM_RESERVE, PAGE_READWRITE));
 Result:=Integer(addr_out^ = 0);
end;
function ps4_sceKernelMemoryPoolCommit(addr:Pointer;len:size_t;memory_type:Integer;prot:Integer;flags:Integer):Integer; SysV_ABI_CDecl;
var
 a: Pointer;
begin
 Result:=EINVAL;
 a:=Pointer(0);
 WriteLn('ps4_sceKernelMemoryPoolCommit ', QWORD(addr), ' ', len, ' ', str_mem_type(memory_type), ' ', prot, ' ', flags);
 if memory_type <> 3 then
 begin
  a:=Pointer(VirtualAlloc(LPVOID(addr), len, MEM_COMMIT, PAGE_READWRITE));
  Result:=Integer(QWORD(a) = 0);
  WriteLn('ps4_sceKernelMemoryPoolCommit  ', QWORD(a), ' ', Result);
  Assert(addr = a);

  _set_errno(Result);
  Result:=px2sce(Result);
 end;
end;
[main:25524] nop nid:libkernel:BD853C3FD4DDD99A:sceKernelAioInitializeImpl

GoldHEN(?) implements async io with already existing sync functions.

Where you got it? Do not mix source code from other branches.

mrsteyk commented 1 month ago

Where you got it? Do not mix source code from other branches.

I wrote that hacky code myself (and missed word hacky in original message). I couldn't figure out how to use custom _mmap thing, so I just used WinAPI directly, thankfully Windows doesn't map stuff there.

Before, for reserve I had this:

Result:=_mmap(addr, size, PROT_NONE, flags or MAP_VOID, -1, 0, addr_out);

Commit:

Result:=_mmap(addr, len, prot, flags or MAP_ANON, -1, 0, a);

But it was crashing.

On Linux what I saw for reserve in other apps (not UE4) is MAP_ANONYMOUS|MAP_PRIVATE with PROT_NONE, and commit was mprotect to RW, decommit was mprotect with madvise to PROT_NONE and MADV_DONTNEED, idk how it works in those managers.

It's also almost impossible to find any docs for Orbis from my experience. I can only guess that UE4 wants to decommit DMEM for 4 GPA/Arena ranges.

red-prig commented 1 month ago

The implementation of MemoryPool is quite complex and I will not add it to the trunk development branch; later it will be implemented at the system call level of the kern branch