diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 692592e5ec..fa9e04c64d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -119,6 +119,14 @@ struct ARMv7Context u32 R_ADDR; u64 R_DATA; + struct perf_counter + { + u32 event; + u32 value; + }; + + std::array counters; + void write_gpr(u32 n, u32 value) { assert(n < 16); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index f58acfd0d3..6e1cec6fa8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -116,6 +116,7 @@ void ARMv7Thread::InitRegs() context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); + context.R_ADDR = 0; } void ARMv7Thread::InitStack() diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index f4705ab1d8..dbbce2e151 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -42,7 +42,7 @@ s32 sceKernelCreateThread( s32 cpuAffinityMask, vm::psv::ptr pOptParam) { - sceLibKernel.Error("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)", + sceLibKernel.Warning("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)", pName, entry, initPriority, stackSize, attr, cpuAffinityMask, pOptParam); ARMv7Thread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7)); @@ -61,7 +61,7 @@ s32 sceKernelCreateThread( s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pArgBlock) { - sceLibKernel.Error("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock); + sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock); std::shared_ptr t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); @@ -93,7 +93,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pAr s32 sceKernelExitThread(ARMv7Context& context, s32 exitStatus) { - sceLibKernel.Error("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + sceLibKernel.Warning("sceKernelExitThread(exitStatus=0x%x)", exitStatus); // exit status is stored in r0 context.thread.Stop(); @@ -103,7 +103,7 @@ s32 sceKernelExitThread(ARMv7Context& context, s32 exitStatus) s32 sceKernelDeleteThread(s32 threadId) { - sceLibKernel.Error("sceKernelDeleteThread(threadId=0x%x)", threadId); + sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId); std::shared_ptr t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); @@ -125,7 +125,7 @@ s32 sceKernelDeleteThread(s32 threadId) s32 sceKernelExitDeleteThread(ARMv7Context& context, s32 exitStatus) { - sceLibKernel.Error("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus); + sceLibKernel.Warning("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus); // exit status is stored in r0 context.thread.Stop(); @@ -261,7 +261,7 @@ s32 sceKernelDelayThreadCB(u32 usec) s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr pExitStatus, vm::psv::ptr pTimeout) { - sceLibKernel.Error("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout); + sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout); std::shared_ptr t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index b833a38c5f..d280e3dc24 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -16,7 +16,7 @@ namespace sce_libc_func { void __cxa_atexit(vm::psv::ptr func, vm::psv::ptr arg, vm::psv::ptr dso) { - sceLibc.Error("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso); + sceLibc.Warning("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso); LV2_LOCK(0); @@ -28,7 +28,7 @@ namespace sce_libc_func void __aeabi_atexit(vm::psv::ptr arg, vm::psv::ptr func, vm::psv::ptr dso) { - sceLibc.Error("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso); + sceLibc.Warning("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso); LV2_LOCK(0); @@ -40,7 +40,7 @@ namespace sce_libc_func void exit(ARMv7Context& context) { - sceLibc.Error("exit()"); + sceLibc.Warning("exit()"); LV2_LOCK(0); @@ -117,7 +117,7 @@ namespace sce_libc_func void printf(ARMv7Context& context, vm::psv::ptr fmt) // va_args... { - sceLibc.Error("printf(fmt=0x%x)", fmt); + sceLibc.Warning("printf(fmt=0x%x)", fmt); sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); @@ -126,7 +126,7 @@ namespace sce_libc_func void sprintf(ARMv7Context& context, vm::psv::ptr str, vm::psv::ptr fmt) // va_args... { - sceLibc.Error("sprintf(str=0x%x, fmt=0x%x)", str, fmt); + sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt); sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); @@ -139,28 +139,28 @@ namespace sce_libc_func void __cxa_set_dso_handle_main(vm::psv::ptr dso) { - sceLibc.Error("__cxa_set_dso_handle_main(dso=0x%x)", dso); + sceLibc.Warning("__cxa_set_dso_handle_main(dso=0x%x)", dso); g_dso = dso; } void memcpy(vm::psv::ptr dst, vm::psv::ptr src, u32 size) { - sceLibc.Error("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size); + sceLibc.Warning("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size); ::memcpy(dst.get_ptr(), src.get_ptr(), size); } void memset(vm::psv::ptr dst, s32 value, u32 size) { - sceLibc.Error("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size); + sceLibc.Warning("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size); ::memset(dst.get_ptr(), value, size); } void _Assert(vm::psv::ptr text, vm::psv::ptr func) { - sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func); + sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func); LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr()); Emu.Pause(); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp index f0f2674441..73260d9420 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp @@ -8,20 +8,17 @@ namespace sce_libstdcxx_func { void __aeabi_unwind_cpp_pr0() { - sceLibstdcxx.Todo(__FUNCTION__); - Emu.Pause(); + throw __FUNCTION__; } void __aeabi_unwind_cpp_pr1() { - sceLibstdcxx.Todo(__FUNCTION__); - Emu.Pause(); + throw __FUNCTION__; } void __aeabi_unwind_cpp_pr2() { - sceLibstdcxx.Todo(__FUNCTION__); - Emu.Pause(); + throw __FUNCTION__; } } diff --git a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp index d83e6d5f22..e7939506bc 100644 --- a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp +++ b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp @@ -2,48 +2,242 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/SysCalls/lv2/sys_time.h" + +#define RETURN_ERROR(code) { Emu.Pause(); scePerf.Error("%s() failed: %s", __FUNCTION__, #code); return code; } + extern psv_log_base scePerf; -s32 scePerfArmPmonReset(s32 threadId) +enum { - scePerf.Todo("scePerfArmPmonReset(threadId=0x%x)", threadId); + // Error Codes + SCE_PERF_ERROR_INVALID_ARGUMENT = 0x80580000, +}; + +enum : s32 +{ + // Thread IDs + SCE_PERF_ARM_PMON_THREAD_ID_ALL = -1, + SCE_PERF_ARM_PMON_THREAD_ID_SELF = 0, +}; + +enum : u32 +{ + // Counter Numbers + SCE_PERF_ARM_PMON_CYCLE_COUNTER = 31, + SCE_PERF_ARM_PMON_COUNTER_5 = 5, + SCE_PERF_ARM_PMON_COUNTER_4 = 4, + SCE_PERF_ARM_PMON_COUNTER_3 = 3, + SCE_PERF_ARM_PMON_COUNTER_2 = 2, + SCE_PERF_ARM_PMON_COUNTER_1 = 1, + SCE_PERF_ARM_PMON_COUNTER_0 = 0, + + // Counter Masks + SCE_PERF_ARM_PMON_COUNTER_MASK_5 = 0x20, + SCE_PERF_ARM_PMON_COUNTER_MASK_4 = 0x10, + SCE_PERF_ARM_PMON_COUNTER_MASK_3 = 0x08, + SCE_PERF_ARM_PMON_COUNTER_MASK_2 = 0x04, + SCE_PERF_ARM_PMON_COUNTER_MASK_1 = 0x02, + SCE_PERF_ARM_PMON_COUNTER_MASK_0 = 0x01, + SCE_PERF_ARM_PMON_COUNTER_MASK_ALL = 0x3f, +}; + +enum : u8 +{ + // Performance Counter Events + SCE_PERF_ARM_PMON_SOFT_INCREMENT = 0x00, + SCE_PERF_ARM_PMON_ICACHE_MISS = 0x01, + SCE_PERF_ARM_PMON_ITLB_MISS = 0x02, + SCE_PERF_ARM_PMON_DCACHE_MISS = 0x03, + SCE_PERF_ARM_PMON_DCACHE_ACCESS = 0x04, + SCE_PERF_ARM_PMON_DTLB_MISS = 0x05, + SCE_PERF_ARM_PMON_DATA_READ = 0x06, + SCE_PERF_ARM_PMON_DATA_WRITE = 0x07, + SCE_PERF_ARM_PMON_EXCEPTION_TAKEN = 0x09, + SCE_PERF_ARM_PMON_EXCEPTION_RETURN = 0x0A, + SCE_PERF_ARM_PMON_WRITE_CONTEXTID = 0x0B, + SCE_PERF_ARM_PMON_SOFT_CHANGEPC = 0x0C, + SCE_PERF_ARM_PMON_IMMEDIATE_BRANCH = 0x0D, + SCE_PERF_ARM_PMON_UNALIGNED = 0x0F, + SCE_PERF_ARM_PMON_BRANCH_MISPREDICT = 0x10, + SCE_PERF_ARM_PMON_PREDICT_BRANCH = 0x12, + SCE_PERF_ARM_PMON_COHERENT_LF_MISS = 0x50, + SCE_PERF_ARM_PMON_COHERENT_LF_HIT = 0x51, + SCE_PERF_ARM_PMON_ICACHE_STALL = 0x60, + SCE_PERF_ARM_PMON_DCACHE_STALL = 0x61, + SCE_PERF_ARM_PMON_MAINTLB_STALL = 0x62, + SCE_PERF_ARM_PMON_STREX_PASSED = 0x63, + SCE_PERF_ARM_PMON_STREX_FAILED = 0x64, + SCE_PERF_ARM_PMON_DATA_EVICTION = 0x65, + SCE_PERF_ARM_PMON_ISSUE_NO_DISPATCH = 0x66, + SCE_PERF_ARM_PMON_ISSUE_EMPTY = 0x67, + SCE_PERF_ARM_PMON_INST_RENAME = 0x68, + SCE_PERF_ARM_PMON_PREDICT_FUNC_RET = 0x6E, + SCE_PERF_ARM_PMON_MAIN_PIPE = 0x70, + SCE_PERF_ARM_PMON_SECOND_PIPE = 0x71, + SCE_PERF_ARM_PMON_LS_PIPE = 0x72, + SCE_PERF_ARM_PMON_FPU_RENAME = 0x73, + SCE_PERF_ARM_PMON_PLD_STALL = 0x80, + SCE_PERF_ARM_PMON_WRITE_STALL = 0x81, + SCE_PERF_ARM_PMON_INST_MAINTLB_STALL = 0x82, + SCE_PERF_ARM_PMON_DATA_MAINTLB_STALL = 0x83, + SCE_PERF_ARM_PMON_INST_UTLB_STALL = 0x84, + SCE_PERF_ARM_PMON_DATA_UTLB_STALL = 0x85, + SCE_PERF_ARM_PMON_DMB_STALL = 0x86, + SCE_PERF_ARM_PMON_INTEGER_CLOCK = 0x8A, + SCE_PERF_ARM_PMON_DATAENGINE_CLOCK = 0x8B, + SCE_PERF_ARM_PMON_ISB = 0x90, + SCE_PERF_ARM_PMON_DSB = 0x91, + SCE_PERF_ARM_PMON_DMB = 0x92, + SCE_PERF_ARM_PMON_EXT_INTERRUPT = 0x93, + SCE_PERF_ARM_PMON_PLE_LINE_REQ_COMPLETED = 0xA0, + SCE_PERF_ARM_PMON_PLE_CHANNEL_SKIPPED = 0xA1, + SCE_PERF_ARM_PMON_PLE_FIFO_FLUSH = 0xA2, + SCE_PERF_ARM_PMON_PLE_REQ_COMPLETED = 0xA3, + SCE_PERF_ARM_PMON_PLE_FIFO_OVERFLOW = 0xA4, + SCE_PERF_ARM_PMON_PLE_REQ_PROGRAMMED = 0xA5, +}; + +s32 scePerfArmPmonReset(ARMv7Context& context, s32 threadId) +{ + scePerf.Warning("scePerfArmPmonReset(threadId=0x%x)", threadId); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + context.counters = {}; return SCE_OK; } -s32 scePerfArmPmonSelectEvent(s32 threadId, u32 counter, u8 eventCode) +s32 scePerfArmPmonSelectEvent(ARMv7Context& context, s32 threadId, u32 counter, u8 eventCode) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonSelectEvent(threadId=0x%x, counter=0x%x, eventCode=0x%x)", threadId, counter, eventCode); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + if (counter >= 6) + { + RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT); + } + + u32 value = 0; // initial value + + switch (eventCode) + { + case SCE_PERF_ARM_PMON_SOFT_INCREMENT: break; + + case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT: + case SCE_PERF_ARM_PMON_DCACHE_MISS: + case SCE_PERF_ARM_PMON_UNALIGNED: + { + value = 1; // these events will probably never be implemented + break; + } + + case SCE_PERF_ARM_PMON_PREDICT_BRANCH: + case SCE_PERF_ARM_PMON_DCACHE_ACCESS: + { + value = 1000; // these events will probably never be implemented + break; + } + + default: throw "scePerfArmPmonSelectEvent(): unknown event requested"; + } + + context.counters[counter].event = eventCode; + context.counters[counter].value = value; + + return SCE_OK; } -s32 scePerfArmPmonStart(s32 threadId) +s32 scePerfArmPmonStart(ARMv7Context& context, s32 threadId) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonStart(threadId=0x%x)", threadId); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + return SCE_OK; } -s32 scePerfArmPmonStop(s32 threadId) +s32 scePerfArmPmonStop(ARMv7Context& context, s32 threadId) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonStop(threadId=0x%x)"); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + return SCE_OK; } -s32 scePerfArmPmonGetCounterValue(s32 threadId, u32 counter, vm::psv::ptr pValue) +s32 scePerfArmPmonGetCounterValue(ARMv7Context& context, s32 threadId, u32 counter, vm::psv::ptr pValue) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=0x%x)", threadId, counter, pValue); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + if (counter >= 6 && counter != SCE_PERF_ARM_PMON_CYCLE_COUNTER) + { + RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT); + } + + if (counter < 6) + { + *pValue = context.counters[counter].value; + } + else + { + throw "scePerfArmPmonGetCounterValue(): cycle counter requested"; + } + + return SCE_OK; } -s32 scePerfArmPmonSoftwareIncrement(u32 mask) +s32 scePerfArmPmonSoftwareIncrement(ARMv7Context& context, u32 mask) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonSoftwareIncrement(mask=0x%x)", mask); + + if (mask > SCE_PERF_ARM_PMON_COUNTER_MASK_ALL) + { + RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT); + } + + for (u32 i = 0; i < 6; i++, mask >>= 1) + { + if (mask & 1) + { + context.counters[i].value++; + } + } + + return SCE_OK; } u64 scePerfGetTimebaseValue() { - throw __FUNCTION__; + scePerf.Warning("scePerfGetTimebaseValue()"); + + return get_system_time(); } u32 scePerfGetTimebaseFrequency() { - throw __FUNCTION__; + scePerf.Warning("scePerfGetTimebaseFrequency()"); + + return 1; } s32 _sceRazorCpuInit(vm::psv::ptr pBufferBase, u32 bufferSize, u32 numPerfCounters, vm::psv::ptr> psceRazorVars) diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index c622308f3d..bf36001a51 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -93,6 +93,37 @@ namespace loader case MACHINE_MIPS: break; case MACHINE_ARM: { + struct psv_libc_param_t + { + u32 size; // 0x0000001c + u32 unk1; // 0x00000000 + + vm::psv::ptr sceLibcHeapSize; + vm::psv::ptr sceLibcHeapSizeDefault; + vm::psv::ptr sceLibcHeapExtendedAlloc; + vm::psv::ptr sceLibcHeapDelayedAlloc; + + u32 unk2; + }; + + struct psv_process_param_t + { + u32 size; // 0x00000030 + u32 unk1; // 'PSP2' + u32 unk2; // 0x00000005 + u32 unk3; + + vm::psv::ptr sceUserMainThreadName; + vm::psv::ptr sceUserMainThreadPriority; + vm::psv::ptr sceUserMainThreadStackSize; + vm::psv::ptr sceUserMainThreadAttribute; + vm::psv::ptr sceProcessName; + vm::psv::ptr sce_process_preload_disabled; + vm::psv::ptr sceUserMainThreadCpuAffinityMask; + + vm::psv::ptr __sce_libcparam; + }; + initialize_psv_modules(); auto armv7_thr_stop_data = vm::psv::ptr::make(Memory.PSV.RAM.AllocAlign(3 * 4)); @@ -104,10 +135,11 @@ namespace loader u32 fnid_addr = 0; u32 code_start = 0; u32 code_end = 0; - u32 vnid_addr = 0; std::unordered_map vnid_list; + auto proc_param = vm::psv::ptr::make(0); + for (auto& shdr : m_shdrs) { // get secton name @@ -130,24 +162,40 @@ namespace loader code_start = shdr.data_le.sh_addr; code_end = shdr.data_le.sh_size + code_start; } - else if (!strcmp(name.c_str(), ".sceModuleInfo.rodata")) + else if (!strcmp(name.c_str(), ".sceExport.rodata")) { - LOG_NOTICE(LOADER, ".sceModuleInfo.rodata analysis..."); + LOG_NOTICE(LOADER, ".sceExport.rodata analysis..."); - auto code = vm::psv::ptr::make(shdr.data_le.sh_addr); + auto enid = vm::psv::ptr::make(shdr.data_le.sh_addr); + auto edata = vm::psv::ptr::make(enid.addr() + shdr.data_le.sh_size / 2); - // very rough way to find the entry point - while (code[0] != 0xffffffffu) + for (u32 j = 0; j < shdr.data_le.sh_size / 8; j++) { - entry = code[0] + 0x81000000; - code++; - - if (code.addr() >= shdr.data_le.sh_addr + shdr.data_le.sh_size) + switch (const u32 nid = enid[j]) { - LOG_ERROR(LOADER, "Unable to find entry point in .sceModuleInfo.rodata"); - entry = 0; + case 0x935cd196: // set entry point + { + entry = edata[j]; break; } + + case 0x6c2224ba: // __sce_moduleinfo + { + // currently nothing, but it should theoretically be the root of analysis instead of section name comparison + break; + } + + case 0x70fba1e7: // __sce_process_param + { + proc_param.set(edata[j]); + break; + } + + default: + { + LOG_ERROR(LOADER, "Unknown export 0x%08x (addr=0x%08x)", nid, edata[j]); + } + } } } else if (!strcmp(name.c_str(), ".sceFNID.rodata")) @@ -320,10 +368,44 @@ namespace loader } } + LOG_NOTICE(LOADER, "__sce_process_param(addr=0x%x) analysis...", proc_param); + + if (proc_param->size != 0x30 || proc_param->unk1 != *(u32*)"PSP2" || proc_param->unk2 != 5) + { + LOG_ERROR(LOADER, "__sce_process_param: unexpected data found (size=0x%x, 0x%x, 0x%x, 0x%x)", proc_param->size, proc_param->unk1, proc_param->unk2, proc_param->unk3); + } + + LOG_NOTICE(LOADER, "*** &sceUserMainThreadName = 0x%x", proc_param->sceUserMainThreadName); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadPriority = 0x%x", proc_param->sceUserMainThreadPriority); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadStackSize = 0x%x", proc_param->sceUserMainThreadStackSize); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadAttribute = 0x%x", proc_param->sceUserMainThreadAttribute); + LOG_NOTICE(LOADER, "*** &sceProcessName = 0x%x", proc_param->sceProcessName); + LOG_NOTICE(LOADER, "*** &sce_process_preload_disabled = 0x%x", proc_param->sce_process_preload_disabled); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadCpuAffinityMask = 0x%x", proc_param->sceUserMainThreadCpuAffinityMask); + + auto libc_param = proc_param->__sce_libcparam; + + LOG_NOTICE(LOADER, "__sce_libcparam(addr=0x%x) analysis...", libc_param); + + if (libc_param->size != 0x1c || libc_param->unk1) + { + LOG_ERROR(LOADER, "__sce_libcparam: unexpected data found (size=0x%x, 0x%x, 0x%x)", libc_param->size, libc_param->unk1, libc_param->unk2); + } + + LOG_NOTICE(LOADER, "*** &sceLibcHeapSize = 0x%x", libc_param->sceLibcHeapSize); + LOG_NOTICE(LOADER, "*** &sceLibcHeapSizeDefault = 0x%x", libc_param->sceLibcHeapSizeDefault); + LOG_NOTICE(LOADER, "*** &sceLibcHeapExtendedAlloc = 0x%x", libc_param->sceLibcHeapExtendedAlloc); + LOG_NOTICE(LOADER, "*** &sceLibcHeapDelayedAlloc = 0x%x", libc_param->sceLibcHeapDelayedAlloc); + armv7_init_tls(); armv7_decoder_initialize(code_start, code_end); - armv7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath(), "-emu" }).run(); + const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread"; + const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0; + const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0; + + /* TODO: Thumb/ARM encoding selection */ + armv7_thread(entry & ~1, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run(); break; } case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break;