unit kern_budget; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface type p_budget_resource=^t_budget_resource; t_budget_resource=packed record resid:Integer; attr :Integer; limit:QWORD; //cpuset used :QWORD; end; //budget resid const SCE_KERNEL_BUDGET_INVALID =0; SCE_KERNEL_BUDGET_MEMORY_DMEM =1; SCE_KERNEL_BUDGET_MEMORY_VMEM =2; SCE_KERNEL_BUDGET_MEMORY_MLOCK=3; SCE_KERNEL_BUDGET_CPU_SET =4; SCE_KERNEL_BUDGET_FD_FILE =5; SCE_KERNEL_BUDGET_FD_SOCKET =6; SCE_KERNEL_BUDGET_FD_EQUEUE =7; SCE_KERNEL_BUDGET_FD_PIPE =8; SCE_KERNEL_BUDGET_FD_DEVICE =9; SCE_KERNEL_BUDGET_THREADS =10; SCE_KERNEL_BUDGET_FD_IPCSOCKET=11; //budget proc_type PTYPE_BIG_APP = 0; //SCE_APPLICATION_TYPE_GAME PTYPE_MINI_APP = 1; //SCE_APPLICATION_TYPE_MINI PTYPE_SYSTEM = 2; //SCE_APPLICATION_TYPE_DAEMON PTYPE_NONGAME_MINI_APP = 3; function sys_budget_create(name:pchar;ptype:DWORD;new:Pointer;count:DWORD;prev:Pointer):Integer; function sys_budget_delete(key:Integer):Integer; function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer; function sys_budget_set(key:Integer):Integer; function sys_budget_get_ptype(pid:Integer):Integer; function sys_budget_get_ptype_of_budget(key:Integer):Integer; function sys_budget_getid():Integer; //internals type t_budget_info=packed record zero :QWORD; dmem_alloc:QWORD; malloc :QWORD; mlock :QWORD; end; const field_dmem_alloc=1; field_mlock =2; field_malloc =3; const FMEM_BASE =$4000000; //64MB Minimum reserved size of flex memory at system startup bigapp_size =$4000000; bigapp_max_fmem_size=$20000000; //512MB Maximum possible size of flex memory DUH_D1xxx:Boolean =False; //Development Mode in the DUH-D1xxx series var FMEM_LIMIT :QWORD=0; DMEM_LIMIT :QWORD=$180000000; // 6144MB game_fmem_size:QWORD=bigapp_size; ExtendedSize :QWORD=0; //148000000 5248MB //170000000 5888MB //124000000 4672MB BigAppMemory :QWORD=$170000000; // dmem_size + game_fmem_size g_self_loading :Integer=0; g_ext_game_fmem:Integer=0; //Enabling extended fmem size +256MB IGNORE_EXTENDED_DMEM_BASE:Integer=0; const M2MB_DEFAULT =0; //Default =0 (ATTRIBUTE2:0x00000) M2MB_DISABLE =1; //NotUsed =32768 (ATTRIBUTE2:0x08000) M2MB_READONLY=2; //Text_rodata=65536 (ATTRIBUTE2:0x10000) M2MB_ENABLE =3; //All_section=98304 (ATTRIBUTE2:0x18000) var g_mode_2mb :Integer=M2MB_DISABLE; g_mode_2mb_size:Integer=0; g_mode_2mb_rsrv:Integer=0; function vm_budget_limit (ptype,field:Integer):QWORD; function vm_budget_used (ptype,field:Integer):QWORD; function vm_budget_reserve(ptype,field:Integer;len:QWORD):Integer; procedure vm_budget_release(ptype,field:Integer;len:QWORD); procedure init_bigapp_limits; procedure set_bigapp_cred_limits; procedure set_bigapp_limits(size,is_2MB_align:QWORD); function dmem_process_relocated():Integer; function get_mlock_avail():QWORD; function get_mlock_total():QWORD; const //app_state as_start =1; as_stop =2; as_begin_game_app_mount =3; as___end_game_app_mount =4; as_begin_mini_app_mount =5; as___end_mini_app_mount =6; as__enable_ext_game_fmem=7; as_disable_ext_game_fmem=8; function kern_app_state_change(state:Integer):Integer; function sys_app_state_change (state:Integer):Integer; procedure reset_2mb_mode; function kern_reserve_2mb_page(size:QWORD;mode:Integer):Integer; function sys_reserve_2mb_page (size:QWORD;mode:Integer):Integer; implementation uses errno, sys_bootparam, kern_thr, kern_proc, kern_rwlock, systm, vmparam, elf64, subr_dynlib, kern_authinfo; var budget_limit :t_budget_info; budget_reserve:t_budget_info; budget_lock :Pointer; procedure vm_set_budget_limit(ptype,field:Integer;value:QWORD); begin case field of field_dmem_alloc:Writeln('vm_set_budget_limit(dmem_alloc,0x',HexStr(value,16),')'); field_mlock :Writeln('vm_set_budget_limit(mlock ,0x',HexStr(value,16),')'); field_malloc :Writeln('vm_set_budget_limit(malloc ,0x',HexStr(value,16),')'); else; end; rw_wlock(budget_lock); //TODO: ptype/budget_id ignored PQWORD(@budget_limit)[field]:=value; rw_wunlock(budget_lock); end; function vm_budget_limit(ptype,field:Integer):QWORD; begin rw_wlock(budget_lock); //TODO: ptype/budget_id ignored Result:=PQWORD(@budget_limit)[field]; rw_wunlock(budget_lock); end; function vm_budget_used(ptype,field:Integer):QWORD; begin rw_wlock(budget_lock); //TODO: ptype/budget_id ignored Result:=PQWORD(@budget_reserve)[field]; rw_wunlock(budget_lock); end; function vm_budget_reserve(ptype,field:Integer;len:QWORD):Integer; var rsv,limit:QWORD; begin if (ptype -1) and (len<>0) then begin rw_wlock(budget_lock); //TODO: ptype/budget_id ignored rsv:=PQWORD(@budget_reserve)[field]; size:=0; if (len <= rsv) then begin size:=rsv - len; end; PQWORD(@budget_reserve)[field]:=size; rw_wunlock(budget_lock); end; end; procedure init_bigapp_limits; var dmem_size :QWORD; limit_value:QWORD; m_256 :QWORD; begin if (p_neomode<>0) then begin BigAppMemory:=$170000000; //5888MB end else begin BigAppMemory:=$148000000; //5248MB end; dmem_size:=BigAppMemory - game_fmem_size; //[0..dmem_size),[game_fmem_size..BigAppMemory) //TODO: realloc dmem (DMEM_LIMIT->dmem_size) m_256:=QWORD(g_ext_game_fmem<>0) * $10000000; limit_value:=dmem_size; if (FMEM_LIMIT <= dmem_size) then begin limit_value:=FMEM_LIMIT; end; DMEM_LIMIT:=dmem_size; vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value); vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256)); end; procedure set_bigapp_cred_limits; var size :QWORD; limit_value:QWORD; m_256 :QWORD; ret :Boolean; begin ret:=is_sce_prog_attr_20_800000(@g_appinfo); if (ret) then begin size:=$a0000000; //2GB end else begin ret:=is_sce_prog_attr_20_400000(@g_appinfo); if ret then begin size:=$30000000; //768MB end else begin size:=QWORD(-1); end; end; m_256:=QWORD(g_ext_game_fmem<>0) * $10000000; limit_value:=size; if (DMEM_LIMIT < size) then begin limit_value:=DMEM_LIMIT; end; FMEM_LIMIT:=size; vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value); vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256)); end; procedure set_bigapp_limits(size,is_2MB_align:QWORD); var m_256 :QWORD; limit_value:QWORD; begin if (game_fmem_size<>size) then begin if (size < game_fmem_size) then begin //expand //TODO: realloc fmem (game_fmem_size->size) (switch_from_fmem) limit_value :=BigAppMemory - size; //TODO: realloc dmem (DMEM_LIMIT->limit_value) game_fmem_size:=size; DMEM_LIMIT :=limit_value; end else begin //shrink if (is_2MB_align<>0) and ((game_fmem_size and PAGE_2MB_MASK)<>0) then begin Writeln(stderr,'game_fmem_size is not multiple of 2MB: 0x',HexStr(game_fmem_size,8)); end; limit_value :=BigAppMemory - size; //TODO: realloc dmem (DMEM_LIMIT->limit_value) //TODO: realloc fmem (game_fmem_size->size) (switch_to_fmem) game_fmem_size:=size; DMEM_LIMIT :=limit_value; end; m_256:=QWORD(g_ext_game_fmem<>0) * $10000000; limit_value:=FMEM_LIMIT; if (DMEM_LIMIT < FMEM_LIMIT) then begin limit_value:=DMEM_LIMIT; end; vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value); vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256)); end; end; function expand_and_reserve_game_fmem(size:QWORD):QWORD; var dmem_size:QWORD; begin if (size <= QWORD(bigapp_max_fmem_size - game_fmem_size)) then begin dmem_size:=BigAppMemory - (game_fmem_size + size); //TODO: realloc dmem (DMEM_LIMIT->dmem_size) DMEM_LIMIT:=dmem_size; //TODO: realloc fmem (game_fmem_size->(game_fmem_size + size)) game_fmem_size:=(game_fmem_size + size); Exit(BigAppMemory - game_fmem_size); end; Writeln(stderr,'expand_and_reserve_game_fmem=',size); Assert(false,'expand_and_reserve_game_fmem'); end; function expand_budget_limit(size:QWORD):QWORD; var m_256 :QWORD; limit_value:QWORD; begin Result:=expand_and_reserve_game_fmem(size); m_256:=QWORD(g_ext_game_fmem<>0) * $10000000; limit_value:=FMEM_LIMIT; if (DMEM_LIMIT < FMEM_LIMIT) then begin limit_value:=DMEM_LIMIT; end; vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_value); vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256)); if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size)<>0) then begin Writeln(stderr,'wrong MLOCK budget accounting'); Assert(false,'wrong MLOCK budget accounting'); end; end; function allocate_extended_page_table_pool(ExtendedCpuPageTable:QWORD; ExtendedGpuPageTable:QWORD; param_3:QWORD):Integer; var GpuPages:QWORD; CpuPages:QWORD; GpuPagesSize:QWORD; size:QWORD; begin Result:=0; GpuPages:=(ExtendedGpuPageTable + $7fffff) shr 23; CpuPages:=(ExtendedCpuPageTable + $1fffff) shr 21; GpuPagesSize:=GpuPages * $4000; if ((GpuPagesSize or CpuPages)<> 0) then begin size:=0; if (param_3=0) then begin size:=(QWORD(ord(p_neomode=0)) * $800000) + GpuPagesSize + (CpuPages * $1000); if (QWORD(bigapp_max_fmem_size - game_fmem_size) < size) then begin Writeln('[KERNEL] WARNING: Failed to allocate extended page table pool. shortage = ' ,(game_fmem_size - bigapp_max_fmem_size) + $fffff + (size shr 20), 'MiB'); Exit(ENOMEM); end; param_3:=expand_budget_limit(size); end; //reserved physical pages ExtendedSize:=size; end; end; function dmem_process_relocated():Integer; label _no_mem_param, _next; var proc_param:TSceProcParam; mem_param:TSceKernelMemParam; mem_param_size:QWORD; size :QWORD; m_256 :QWORD; FMEM_SIZE:QWORD; dmem_size:QWORD; mmap_flags:Integer; ExtendedCpuPageTable:QWORD; ExtendedPageTable :QWORD; ExtendedGpuPageTable:QWORD; FlexibleMemorySize :QWORD; ExtendedMemory1:Boolean; ExtendedMemory2:Boolean; begin Result:=0; if (p_proc.p_budget_ptype=PTYPE_BIG_APP) then begin mmap_flags:=g_appinfo.mmap_flags and 1; end else begin mmap_flags:=0; end; proc_param:=Default(TSceProcParam); Result:=copy_proc_param(@proc_param); if (Result=ENOENT) then begin _no_mem_param: mem_param:=Default(TSceKernelMemParam); Result:=0; end else begin if (Result=0) then begin if (proc_param._sceKernelMemParam=nil) then goto _no_mem_param; mem_param_size:=fuword64(proc_param._sceKernelMemParam^.Size); if (mem_param_size=QWORD($ffffffffffffffff)) then begin Result:=EACCES; end else begin if (mem_param_size>sizeof(TSceKernelMemParam)) then begin mem_param_size:=sizeof(TSceKernelMemParam); end; mem_param:=Default(TSceKernelMemParam); Result:=copyin(proc_param._sceKernelMemParam,@mem_param,mem_param_size); if (Result=0) then goto _next; end; end; // Writeln('[KERNEL] ERROR: failed to load memory parameter: ',Result); end; _next: if (Byte((mmap_flags xor 1) or ord(g_self_loading=0))=0) then begin g_self_loading:=0; ExtendedMemory1:=true; if (p_proc.p_sdk_version < $5000000) then begin if (mem_param.sceKernelExtendedMemory1=nil) then begin ExtendedMemory1:=False; end else begin ExtendedMemory1:=fubyte(mem_param.sceKernelExtendedMemory1^)=1; end; end; m_256:=QWORD(g_ext_game_fmem<>0) * $10000000; //SCE_KERNEL_EXTENDED_DMEM_NEO_256 if (p_neomode<>0) and //only neomode ((not ExtendedMemory1) or (IGNORE_EXTENDED_DMEM_BASE<>0)) then begin //Subtract 256MB if the extended mode is disabled or ignored BigAppMemory:=BigAppMemory - $10000000 {+ ((ret or $10)=$19) * (-0x10000000)}; dmem_size:=BigAppMemory - game_fmem_size; //TODO: realloc dmem (DMEM_LIMIT->dmem_size) size:=dmem_size; if (FMEM_LIMIT <= dmem_size) then begin size:=FMEM_LIMIT; end; DMEM_LIMIT:=dmem_size; vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size); vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256)); end; ExtendedMemory2:=true; if (p_proc.p_sdk_version < $5000000) then begin if (mem_param.sceKernelExtendedMemory2<>nil) then begin ExtendedMemory2:=False; end else begin ExtendedMemory2:=fubyte(mem_param.sceKernelExtendedMemory2^)=1; end; end; //SCE_KERNEL_EXTENDED_DMEM_BASE_128 if (p_neomode=0) and //only base mode (IGNORE_EXTENDED_DMEM_BASE=0) then //extend mode not ignored begin if DUH_D1xxx then begin // if (ExtendedMemory2) then begin Writeln('[System] : SCE_KERNEL_EXTENDED_DMEM_BASE_128 was ignored'); end; // end else if (not ExtendedMemory2) then begin //Subtract 128MB if the extended mode is disabled BigAppMemory:=BigAppMemory -$8000000 {+ ((ret and $ffffffe7)=1) * (-$8000000)}; dmem_size:=BigAppMemory - game_fmem_size; //TODO: realloc dmem (DMEM_LIMIT->dmem_size) size:=dmem_size; if (FMEM_LIMIT <= dmem_size) then begin size:=FMEM_LIMIT; end; DMEM_LIMIT:=dmem_size; vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size); vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,(game_fmem_size + m_256)); end; end; if (mem_param.sceKernelExtendedCpuPageTable=nil) then begin ExtendedCpuPageTable:=QWORD(Int64(-1)); end else begin ExtendedCpuPageTable:=fuword64(mem_param.sceKernelExtendedCpuPageTable^); end; if (mem_param.sceKernelExtendedPageTable=nil) then begin ExtendedPageTable:=QWORD(Int64(-1)); end else begin ExtendedPageTable:=fuword64(mem_param.sceKernelExtendedPageTable^); end; if (int64(ExtendedCpuPageTable) < 0) and (int64(ExtendedPageTable) < 1) then begin ExtendedCpuPageTable:=0; end else if (ExtendedCpuPageTable > $1000000000) then begin ExtendedCpuPageTable:=0; Writeln(stderr,'[KERNEL] ERROR: The extended CPU page table pool must be smaller than 64GiB'); Result:=ENOMEM; end; if (mem_param.sceKernelExtendedGpuPageTable=nil) then begin ExtendedGpuPageTable:=QWORD(Int64(-1)); end else begin ExtendedGpuPageTable:=fuword64(mem_param.sceKernelExtendedGpuPageTable^); end; ExtendedGpuPageTable:=(not SarInt64(ExtendedGpuPageTable,63)) and ExtendedGpuPageTable; // MAX 64GB if (ExtendedGpuPageTable < $1000000001) then begin ExtendedSize:=0; FMEM_SIZE:=bigapp_max_fmem_size; if (Result=0) then begin Result:=allocate_extended_page_table_pool(ExtendedCpuPageTable,ExtendedGpuPageTable,0); FMEM_SIZE:=bigapp_max_fmem_size; if (Result=0) then begin if (mem_param.sceKernelFlexibleMemorySize=nil) then begin Result:=0; end else begin FlexibleMemorySize:=fuword64(mem_param.sceKernelFlexibleMemorySize^); Result:=0; FMEM_SIZE:=bigapp_max_fmem_size; if (FlexibleMemorySize<>QWORD($ffffffffffffffff)) then begin FMEM_SIZE:=FMEM_BASE + FlexibleMemorySize; if (bigapp_max_fmem_size < FMEM_SIZE) or (FMEM_SIZE < bigapp_size) or ((FMEM_SIZE and QWORD(not PAGE_MASK))<>FMEM_SIZE) then begin Writeln(stderr,'[KERNEL] ERROR: invalid FMEM size (0x',HexStr(FlexibleMemorySize,16),') is specified.'); Result:=EINVAL; FMEM_SIZE:=bigapp_max_fmem_size; end; end; end; end; end; end else begin Writeln('[KERNEL] ERROR: The extended GPU page table pool must be smaller than 64GiB'); Result:=ENOMEM; ExtendedSize:=0; FMEM_SIZE:=bigapp_max_fmem_size; end; if (FMEM_SIZE < game_fmem_size) then begin Writeln(stderr,'[KERNEL] ERROR: The executable file size (= 0x',HexStr(game_fmem_size,16), ') < specified FMEM size (=0x',HexStr(FMEM_SIZE,16),')'); if (Result=0) then begin Result:=Integer($a0020326); end; end else if (Result=0) then begin Result:=0; set_bigapp_limits(FMEM_SIZE,0); end; end else if (ExtendedSize=0) and (mmap_flags<>0) then begin if (mem_param.sceKernelExtendedPageTable=nil) then begin ExtendedPageTable:=QWORD(Int64(-1)); end else begin ExtendedPageTable:=fuword64(mem_param.sceKernelExtendedPageTable^); end; if (Int64(ExtendedPageTable) < 1) or (ExtendedPageTable=$100000000) then begin if (Int64(ExtendedPageTable) > 0) then begin allocate_extended_page_table_pool(ExtendedPageTable,0,0); end; end else begin Writeln(stderr,'[KERNEL] ERROR: failed to extend page table pool: ',Result); end; end; Writeln('DMEM_LIMIT =0x',HexStr(DMEM_LIMIT,16)); Writeln('FMEM_LIMIT =0x',HexStr(FMEM_LIMIT,16)); Writeln('BigAppMem =0x',HexStr(BigAppMemory,16)); Writeln('game_fmem_size =0x',HexStr(game_fmem_size,16)); // Writeln('vm_budget_dmem_alloc=0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_dmem_alloc),16)); Writeln('vm_budget_mlock =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_mlock ),16)); Writeln('vm_budget_malloc =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_malloc ),16)); end; function get_mlock_avail():QWORD; var used :QWORD; limit:QWORD; begin Result:=0; used :=vm_budget_used (p_proc.p_budget_ptype,field_mlock); limit:=vm_budget_limit(p_proc.p_budget_ptype,field_mlock); if (limit>used) then begin Result:=limit-used; end; end; function get_mlock_total():QWORD; begin Result:=vm_budget_limit(p_proc.p_budget_ptype,field_mlock) end; function sys_budget_create(name:pchar;ptype:DWORD;new:Pointer;count:DWORD;prev:Pointer):Integer; begin //name != null //ptype -> [0..3] (proc_type) //new -> p_budget_resource //count -> [0..11] (new/prev) //prev -> p_budget_resource Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; function sys_budget_delete(key:Integer):Integer; begin //key -> id_table Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer; begin //key -> [-2..-5] (budget limits [0..3]) else -> id_table //ptr -> p_budget_resource //psize -> in/out size Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; function sys_budget_set(key:Integer):Integer; begin //key -> id_table Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; function sys_budget_get_ptype(pid:Integer):Integer; var td:p_kthread; begin //sceKernelGetProcessType td:=curkthread; if (td=nil) then Exit(-1); if (pid<>-1) and (pid<>p_proc.p_pid) then begin Exit(ENOSYS); end; td^.td_retval[0]:=p_proc.p_budget_ptype; Result:=0; end; function sys_budget_get_ptype_of_budget(key:Integer):Integer; begin //key -> id_table Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; function sys_budget_getid():Integer; begin Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; // function kern_app_state_change(state:Integer):Integer; var used:QWORD; begin Result:=0; case state of as_start: begin g_self_loading:=1; //app_state_counter+1 end; as_stop: begin g_self_loading:=0; //app_state_counter-1 end; as_begin_game_app_mount: begin used:=vm_budget_used(PTYPE_BIG_APP,field_mlock); if (used<>0) then begin Writeln(stderr,'BUDGET_MEMORY_MLOCK of game is being used: ',used,' bytes'); Assert(false,'BUDGET_MEMORY_MLOCK'); end; end; as___end_game_app_mount: begin //game_mounts_exist reset_2mb_mode; vm_budget_release(PTYPE_BIG_APP,field_mlock,ExtendedSize); ExtendedSize:=0; used:=vm_budget_used(PTYPE_BIG_APP,field_mlock); if (used<>0) then begin Writeln(stderr,'BUDGET_MEMORY_MLOCK of game is being used: ',used,' bytes'); Assert(false,'BUDGET_MEMORY_MLOCK'); end; set_bigapp_limits(bigapp_size,0); end; as_begin_mini_app_mount:; //nothing as___end_mini_app_mount:; //nothing as__enable_ext_game_fmem: begin if (g_ext_game_fmem<>0) then begin Writeln(stderr,'ext_game_fmem is already enabled'); Assert (false ,'ext_game_fmem is already enabled'); end; g_ext_game_fmem:=1; end; as_disable_ext_game_fmem: begin g_ext_game_fmem:=0; end; else; end; end; //sceKernelNotifyAppStateChanged function sys_app_state_change(state:Integer):Integer; begin //sceSblACMgrIsSyscoreProcess Exit(EPERM); end; procedure reset_2mb_mode; var size:QWORD; begin if (Int64(g_mode_2mb_size) < 1) then begin g_mode_2mb_size:=0; g_mode_2mb_rsrv:=0; end else if (g_mode_2mb_size<>g_mode_2mb_rsrv) then begin Writeln(stderr,'2mpage budget'); Assert(false,'2mpage budget'); end else begin size:=g_mode_2mb_size; g_mode_2mb_rsrv:=0; g_mode_2mb_size:=0; vm_budget_release(PTYPE_BIG_APP,field_mlock,size); end; g_mode_2mb:=M2MB_DISABLE; end; function kern_reserve_2mb_page(size:QWORD;mode:Integer):Integer; var save_game_fmem_size:QWORD; size2:QWORD; mode2:Integer; begin Result:=0; save_game_fmem_size:=game_fmem_size; if not ((g_mode_2mb=M2MB_DISABLE) and (g_mode_2mb_size=0)) then begin Exit(EPERM); end; if (game_fmem_size<>bigapp_size) then begin Writeln(stderr,'[KERNEL] WARNING: The last bigapp termination handling was incomplete.'); Exit(EPERM); end; mode2:=M2MB_DISABLE; if (Int64(size) > PAGE_2MB_MASK) then begin mode2:=mode; end; if ((mode or 1)<>3) then begin mode2:=mode; end; if (mode2=M2MB_DEFAULT) then begin g_mode_2mb :=M2MB_DEFAULT; g_mode_2mb_size:=0; end else if (mode2=M2MB_DISABLE) then begin g_mode_2mb :=M2MB_DISABLE; g_mode_2mb_size:=-1; end else begin if (Int64(size) > $1bffffff) then begin Exit(EINVAL); end; if ((mode2 or 1)<>3) then begin Exit(EINVAL); end; if (Int64(size) > -1) then begin size2:=size; end else begin size2:=size + PAGE_2MB_MASK; end; size2:=size2 and QWORD(not PAGE_2MB_MASK); if (bigapp_max_fmem_size < (game_fmem_size + size2)) then begin size:=bigapp_max_fmem_size; end else begin size:=game_fmem_size + size2; end; set_bigapp_limits(size,0); if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size2)<>0) then begin set_bigapp_limits(save_game_fmem_size,0); Exit(ENOMEM); end; g_mode_2mb :=mode2; g_mode_2mb_size:=size2; g_mode_2mb_rsrv:=size2; end; end; function sys_reserve_2mb_page(size:QWORD;mode:Integer):Integer; begin //sceSblACMgrIsSyscoreProcess Exit(EPERM); end; end.