From a254507be1fe7fb3cf0f1274e35eeb545f65618f Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Wed, 10 Dec 2014 10:12:13 +0530 Subject: [PATCH 01/94] SPURS: Implement taskset attribute functions --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 124 ++++++++++++++++++++--- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 23 +++++ 2 files changed, 134 insertions(+), 13 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 4248c35d74..0aff338d50 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2296,15 +2296,49 @@ s64 cellSpursJobChainGetSpursAddress() #endif } -s64 cellSpursCreateTasksetWithAttribute() +s64 spursCreateTaskset(vm::ptr spurs, vm::ptr taskset, u64 args, vm::ptr priority, + u32 max_contention, u32 enable_clear_ls, u32 size, u8 unknown /*TODO: Figure this out*/) +{ + if (!spurs || !taskset) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CELL_SPURS_ALIGN || taskset.addr() % CELL_SPURS_TASKSET_ALIGN) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + memset((void *)taskset.addr(), 0, size); + + // TODO: Implement the rest of this + return CELL_OK; +} + +s64 cellSpursCreateTasksetWithAttribute(vm::ptr spurs, vm::ptr taskset, vm::ptr attr) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14BEC, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + + if (!attr) + { + CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (attr.addr() % 8) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (attr->revision != 1) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + return spursCreateTaskset(spurs, taskset, attr->args, vm::ptr::make(attr.addr() + offsetof(CellSpursTasksetAttribute, priority)), + attr->max_contention, attr->enable_clear_ls, attr->taskset_size, 0 /*TODO: Figure this out*/); } s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr taskset, u64 args, vm::ptr priority, u32 maxContention) @@ -2314,12 +2348,16 @@ s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr t #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x14CB8, libsre_rtoc); -#else +#endif + +#if 0 SPURSManagerTasksetAttribute *tattr = new SPURSManagerTasksetAttribute(args, priority, maxContention); taskset->taskset = new SPURSManagerTaskset(taskset.addr(), tattr); return CELL_OK; #endif + + return spursCreateTaskset(spurs, taskset, args, priority, maxContention, 0, CELL_SPURS_TASKSET_SIZE, 0); } s64 cellSpursJoinTaskset(vm::ptr taskset) @@ -2390,35 +2428,70 @@ s64 cellSpursCreateTaskWithAttribute() #endif } -s64 cellSpursTasksetAttributeSetName() +s64 cellSpursTasksetAttributeSetName(vm::ptr attr, vm::ptr name) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14210, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!attr || !name) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (attr.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + attr->name = name.addr(); return CELL_OK; #endif } -s64 cellSpursTasksetAttributeSetTasksetSize() +s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr attr, size_t size) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14254, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!attr) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (attr.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (size != CELL_SPURS_TASKSET_SIZE && size != CELL_SPURS_TASKSET2_SIZE) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + attr->taskset_size = size; return CELL_OK; #endif } -s64 cellSpursTasksetAttributeEnableClearLS() +s64 cellSpursTasksetAttributeEnableClearLS(vm::ptr attr, s32 enable) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x142AC, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!attr) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (attr.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + attr->enable_clear_ls = enable ? 1 : 0; return CELL_OK; #endif } @@ -2430,6 +2503,7 @@ s64 _cellSpursTasksetAttribute2Initialize(vm::ptr at #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1474C, libsre_rtoc); #else + memset(attribute.get_ptr(), 0, CELL_SPURS_TASKSET_ATTRIBUTE2_SIZE); attribute->revision = revision; attribute->name_addr = NULL; attribute->argTaskset = 0; @@ -2694,13 +2768,37 @@ s64 cellSpursGetTasksetInfo() #endif } -s64 _cellSpursTasksetAttributeInitialize() +s64 _cellSpursTasksetAttributeInitialize(vm::ptr attribute, u32 revision, u32 sdk_version, u64 args, vm::ptr priority, u32 max_contention) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x142FC, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!attribute) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (attribute.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + for (u32 i = 0; i < 8; i++) + { + if (priority[i] > 0xF) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + } + + memset(attribute.get_ptr(), 0, CELL_SPURS_TASKSET_ATTRIBUTE_SIZE); + attribute->revision = revision; + attribute->sdk_version = sdk_version; + attribute->args = args; + memcpy(attribute->priority, priority.get_ptr(), 8); + attribute->taskset_size = CELL_SPURS_TASKSET_SIZE; + attribute->max_contention = max_contention; return CELL_OK; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 4e72b50826..0248311f70 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -130,6 +130,17 @@ enum TaskConstants CELL_SPURS_TASK_TOP = 0x3000, CELL_SPURS_TASK_BOTTOM = 0x40000, CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, + CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASK_ATTRIBUTE_SIZE = 256, + CELL_SPURS_TASKSET_SIZE = 6400, + CELL_SPURS_TASKSET_ALIGN = 128, + CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN = 8, + CELL_SPURS_TASKSET_ATTRIBUTE_SIZE = 512, + CELL_SPURS_TASKSET2_SIZE = 10496, + CELL_SPURS_TASKSET2_ALIGN = 128, + CELL_SPURS_TASKSET_ATTRIBUTE2_ALIGN = 8, + CELL_SPURS_TASKSET_ATTRIBUTE2_SIZE = 512, }; class SPURSManager; @@ -531,6 +542,18 @@ struct CellSpursTaskset2 be_t skip[10496]; }; +struct CellSpursTasksetAttribute +{ + be_t revision; + be_t sdk_version; + be_t args; + u8 priority[8]; + be_t max_contention; + be_t name; + be_t taskset_size; + be_t enable_clear_ls; +}; + struct CellSpursTasksetAttribute2 { be_t revision; From 5dd15b3c47bb9acc47e2e351fec0aaeeae78afb4 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 13 Dec 2014 01:42:09 +0530 Subject: [PATCH 02/94] SPURS: Implement create taskset --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 142 ++++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 106 ++++++++++++----- 2 files changed, 178 insertions(+), 70 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 0aff338d50..aebf52dbf8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2296,22 +2296,50 @@ s64 cellSpursJobChainGetSpursAddress() #endif } -s64 spursCreateTaskset(vm::ptr spurs, vm::ptr taskset, u64 args, vm::ptr priority, - u32 max_contention, u32 enable_clear_ls, u32 size, u8 unknown /*TODO: Figure this out*/) +s64 spursCreateTaskset(vm::ptr spurs, vm::ptr taskset, u64 args, vm::ptr priority, + u32 max_contention, vm::ptr name, u32 size, s32 enable_clear_ls) { if (!spurs || !taskset) { return CELL_SPURS_TASK_ERROR_NULL_POINTER; } - if (spurs.addr() % CELL_SPURS_ALIGN || taskset.addr() % CELL_SPURS_TASKSET_ALIGN) + if (spurs.addr() % CellSpurs::align || taskset.addr() % CellSpursTaskset::align) { return CELL_SPURS_TASK_ERROR_ALIGN; } memset((void *)taskset.addr(), 0, size); - // TODO: Implement the rest of this + taskset->m.spurs = spurs; + taskset->m.args = args; + taskset->m.enable_clear_ls = enable_clear_ls > 0 ? 1 : 0; + taskset->m.size = size; + + auto wkl_attr = vm::ptr::make((u32)Memory.Alloc(CellSpursWorkloadAttribute::size, CellSpursWorkloadAttribute::align)); + _cellSpursWorkloadAttributeInitialize(wkl_attr, 1 /*revision*/, 0x33 /*sdk_version*/, vm::ptr::make(16) /*pm*/, 0x1E40 /*pm_size*/, + taskset.addr(), priority, 8 /*min_contention*/, max_contention); + // TODO: Check return code + + auto cls = vm::ptr::make((u32)Memory.Alloc(1, 1)); + *((char *)cls.get_ptr()) = 0; + cellSpursWorkloadAttributeSetName(wkl_attr, cls, name); + // TODO: Check return code + + // TODO: cellSpursWorkloadAttributeSetShutdownCompletionEventHook(wkl_attr, hook, taskset); + // TODO: Check return code + + auto wid = vm::ptr::make((u32)Memory.Alloc(4, 4)); + cellSpursAddWorkloadWithAttribute(spurs, wid, vm::ptr::make(wkl_attr.addr())); + // TODO: Check return code + + taskset->m.x72 = 0x80; + taskset->m.wid.FromBE(*wid); + // TODO: cellSpursSetExceptionEventHandler(spurs, wid, hook, taskset); + // TODO: Check return code + + Memory.Free(wkl_attr.addr()); + Memory.Free(wid.addr()); return CELL_OK; } @@ -2327,21 +2355,28 @@ s64 cellSpursCreateTasksetWithAttribute(vm::ptr spurs, vm::ptrrevision != 1) + if (attr->m.revision != CELL_SPURS_TASKSET_ATTRIBUTE_REVISION) { return CELL_SPURS_TASK_ERROR_INVAL; } - return spursCreateTaskset(spurs, taskset, attr->args, vm::ptr::make(attr.addr() + offsetof(CellSpursTasksetAttribute, priority)), - attr->max_contention, attr->enable_clear_ls, attr->taskset_size, 0 /*TODO: Figure this out*/); + auto rc = spursCreateTaskset(spurs, taskset, attr->m.args, vm::ptr::make(attr.addr() + offsetof(CellSpursTasksetAttribute, m.priority)), + attr->m.max_contention, vm::ptr::make(attr->m.name.addr()), attr->m.taskset_size, attr->m.enable_clear_ls); + + if (attr->m.taskset_size >= CellSpursTaskset2::size) + { + // TODO: Implement this + } + + return rc; } -s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr taskset, u64 args, vm::ptr priority, u32 maxContention) +s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr taskset, u64 args, vm::ptr priority, u32 maxContention) { cellSpurs->Warning("cellSpursCreateTaskset(spurs_addr=0x%x, taskset_addr=0x%x, args=0x%llx, priority_addr=0x%x, maxContention=%d)", spurs.addr(), taskset.addr(), args, priority.addr(), maxContention); @@ -2357,7 +2392,7 @@ s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr t return CELL_OK; #endif - return spursCreateTaskset(spurs, taskset, args, priority, maxContention, 0, CELL_SPURS_TASKSET_SIZE, 0); + return spursCreateTaskset(spurs, taskset, args, priority, maxContention, vm::ptr::make(0), CellSpursTaskset::size, 0); } s64 cellSpursJoinTaskset(vm::ptr taskset) @@ -2439,17 +2474,17 @@ s64 cellSpursTasksetAttributeSetName(vm::ptr attr, vm return CELL_SPURS_TASK_ERROR_NULL_POINTER; } - if (attr.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + if (attr.addr() % CellSpursTasksetAttribute::align) { return CELL_SPURS_TASK_ERROR_ALIGN; } - attr->name = name.addr(); + attr->m.name = name; return CELL_OK; #endif } -s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr attr, size_t size) +s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr attr, u32 size) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); @@ -2460,17 +2495,17 @@ s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr a return CELL_SPURS_TASK_ERROR_NULL_POINTER; } - if (attr.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + if (attr.addr() % CellSpursTasksetAttribute::align) { return CELL_SPURS_TASK_ERROR_ALIGN; } - if (size != CELL_SPURS_TASKSET_SIZE && size != CELL_SPURS_TASKSET2_SIZE) + if (size != CellSpursTaskset::size && size != CellSpursTaskset2::size) { return CELL_SPURS_TASK_ERROR_INVAL; } - attr->taskset_size = size; + attr->m.taskset_size = size; return CELL_OK; #endif } @@ -2486,12 +2521,12 @@ s64 cellSpursTasksetAttributeEnableClearLS(vm::ptr at return CELL_SPURS_TASK_ERROR_NULL_POINTER; } - if (attr.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + if (attr.addr() % CellSpursTasksetAttribute::align) { return CELL_SPURS_TASK_ERROR_ALIGN; } - attr->enable_clear_ls = enable ? 1 : 0; + attr->m.enable_clear_ls = enable ? 1 : 0; return CELL_OK; #endif } @@ -2503,20 +2538,19 @@ s64 _cellSpursTasksetAttribute2Initialize(vm::ptr at #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1474C, libsre_rtoc); #else - memset(attribute.get_ptr(), 0, CELL_SPURS_TASKSET_ATTRIBUTE2_SIZE); - attribute->revision = revision; - attribute->name_addr = NULL; - attribute->argTaskset = 0; + memset(attribute.get_ptr(), 0, CellSpursTasksetAttribute2::size); + attribute->m.revision = revision; + attribute->m.name.set(0); + attribute->m.args = 0; for (s32 i = 0; i < 8; i++) { - attribute->priority[i] = 1; + attribute->m.priority[i] = 1; } - attribute->maxContention = 8; - attribute->enableClearLs = 0; - attribute->CellSpursTaskNameBuffer_addr = 0; - + attribute->m.max_contention = 8; + attribute->m.enable_clear_ls = 0; + attribute->m.task_name_buffer.set(0); return CELL_OK; #endif } @@ -2647,13 +2681,43 @@ s64 cellSpursTaskGetContextSaveAreaSize() #endif } -s64 cellSpursCreateTaskset2() +s64 cellSpursCreateTaskset2(vm::ptr spurs, vm::ptr taskset, vm::ptr attr) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x15108, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + auto free_attr = false; + if (!attr) + { + attr.set(Memory.Alloc(CellSpursTasksetAttribute2::size, CellSpursTasksetAttribute2::align)); + free_attr = true; + _cellSpursTasksetAttribute2Initialize(attr, 0); + } + + auto rc = spursCreateTaskset(spurs, vm::ptr::make(taskset.addr()), attr->m.args, + vm::ptr::make(attr.addr() + offsetof(CellSpursTasksetAttribute, m.priority)), + attr->m.max_contention, vm::ptr::make(attr->m.name.addr()), CellSpursTaskset2::size, (u8)attr->m.enable_clear_ls); + if (rc != CELL_OK) + { + if (free_attr) + { + Memory.Free(attr.addr()); + } + return rc; + } + + if (attr->m.task_name_buffer.addr() % CellSpursTaskNameBuffer::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + // TODO: Implement rest of the function + + if (free_attr) + { + Memory.Free(attr.addr()); + } return CELL_OK; #endif } @@ -2735,7 +2799,7 @@ s64 cellSpursTasksetUnsetExceptionEventHandler() #endif } -s64 cellSpursLookUpTasksetAddress() +s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); @@ -2746,7 +2810,7 @@ s64 cellSpursLookUpTasksetAddress() #endif } -s64 cellSpursTasksetGetSpursAddress() +s64 cellSpursTasksetGetSpursAddress(vm::ptr taskset, vm::ptr spurs) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); @@ -2779,7 +2843,7 @@ s64 _cellSpursTasksetAttributeInitialize(vm::ptr attr return CELL_SPURS_TASK_ERROR_NULL_POINTER; } - if (attribute.addr() % CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN) + if (attribute.addr() % CellSpursTasksetAttribute::align) { return CELL_SPURS_TASK_ERROR_ALIGN; } @@ -2792,13 +2856,13 @@ s64 _cellSpursTasksetAttributeInitialize(vm::ptr attr } } - memset(attribute.get_ptr(), 0, CELL_SPURS_TASKSET_ATTRIBUTE_SIZE); - attribute->revision = revision; - attribute->sdk_version = sdk_version; - attribute->args = args; - memcpy(attribute->priority, priority.get_ptr(), 8); - attribute->taskset_size = CELL_SPURS_TASKSET_SIZE; - attribute->max_contention = max_contention; + memset(attribute.get_ptr(), 0, CellSpursTasksetAttribute::size); + attribute->m.revision = revision; + attribute->m.sdk_version = sdk_version; + attribute->m.args = args; + memcpy(attribute->m.priority, priority.get_ptr(), 8); + attribute->m.taskset_size = CellSpursTaskset::size; + attribute->m.max_contention = max_contention; return CELL_OK; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 0248311f70..adb1a60799 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -131,16 +131,7 @@ enum TaskConstants CELL_SPURS_TASK_BOTTOM = 0x40000, CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, - CELL_SPURS_TASK_ATTRIBUTE_SIZE = 256, - CELL_SPURS_TASKSET_SIZE = 6400, - CELL_SPURS_TASKSET_ALIGN = 128, CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, - CELL_SPURS_TASKSET_ATTRIBUTE_ALIGN = 8, - CELL_SPURS_TASKSET_ATTRIBUTE_SIZE = 512, - CELL_SPURS_TASKSET2_SIZE = 10496, - CELL_SPURS_TASKSET2_ALIGN = 128, - CELL_SPURS_TASKSET_ATTRIBUTE2_ALIGN = 8, - CELL_SPURS_TASKSET_ATTRIBUTE2_SIZE = 512, }; class SPURSManager; @@ -428,7 +419,31 @@ struct CellSpursEventFlag struct CellSpursTaskset { - SPURSManagerTaskset *taskset; + static const u32 align = 128; + static const u32 size = 6400; + + union + { + // Raw data + u8 _u8[size]; + + // Real data + struct + { + u8 unk1[0x64]; // 0x00 + vm::bptr spurs; // 0x64 + be_t args; // 0x68 + u8 enable_clear_ls; // 0x70 + u8 x71; // 0x71 + u8 x72; // 0x72 + u8 x73; // 0x73 + be_t wid; // 0x74 + u8 unk3[0x1818]; // 0x78 + be_t size; // 0x1890 + } m; + + SPURSManagerTaskset *taskset; + }; }; struct CellSpursInfo @@ -524,6 +539,13 @@ struct CellSpursTracePacket //typedef void (*CellSpursTasksetExceptionEventHandler)(vm::ptr spurs, vm::ptr taskset, // u32 idTask, vm::ptr info, vm::ptr arg); +struct CellSpursTaskNameBuffer +{ + static const u32 align = 16; + + char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH]; +}; + struct CellSpursTasksetInfo { //CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK]; @@ -539,37 +561,59 @@ struct CellSpursTasksetInfo struct CellSpursTaskset2 { + static const u32 align = 128; + static const u32 size = 10496; + be_t skip[10496]; }; struct CellSpursTasksetAttribute { - be_t revision; - be_t sdk_version; - be_t args; - u8 priority[8]; - be_t max_contention; - be_t name; - be_t taskset_size; - be_t enable_clear_ls; + static const u32 align = 8; + static const u32 size = 512; + + union + { + // Raw data + u8 _u8[size]; + + // Real data + struct + { + be_t revision; // 0x00 + be_t sdk_version; // 0x04 + be_t args; // 0x08 + u8 priority[8]; // 0x10 + be_t max_contention; // 0x18 + vm::bptr name; // 0x1C + be_t taskset_size; // 0x20 + be_t enable_clear_ls; // 0x24 + } m; + }; }; struct CellSpursTasksetAttribute2 { - be_t revision; - be_t name_addr; - be_t argTaskset; - u8 priority[8]; - be_t maxContention; - be_t enableClearLs; - be_t CellSpursTaskNameBuffer_addr; //??? *taskNameBuffer - //be_t __reserved__[]; -}; + static const u32 align = 8; + static const u32 size = 512; -// cellSpurs task structures. -struct CellSpursTaskNameBuffer -{ - char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH]; + union + { + // Raw data + u8 _u8[size]; + + // Real data + struct + { + be_t revision; // 0x00 + vm::bptr name; // 0x04 + be_t args; // 0x08 + u8 priority[8]; // 0x10 + be_t max_contention; // 0x18 + be_t enable_clear_ls; // 0x1C + vm::bptr task_name_buffer; // 0x20 + } m; + }; }; struct CellSpursTraceTaskData From 40f5f73658a2e4ad388884feacfdf9f963aed359 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sun, 14 Dec 2014 00:22:31 +0530 Subject: [PATCH 03/94] SPURS: Implement some taskset functions --- rpcs3/Emu/Memory/vm_ptr.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 91 ++++++++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 81 ++++++++++++++++++--- rpcs3/emucore.vcxproj | 5 ++ 4 files changed, 156 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 838caf930c..6f0c65ed0d 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -253,7 +253,7 @@ namespace vm void* get_ptr() const { - return vm::get_ptr(m_addr); + return vm::get_ptr((u32)m_addr); } explicit operator void*() const @@ -313,7 +313,7 @@ namespace vm const void* get_ptr() const { - return vm::get_ptr(m_addr); + return vm::get_ptr((u32)m_addr); } explicit operator const void*() const diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index aebf52dbf8..831748949b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2309,7 +2309,7 @@ s64 spursCreateTaskset(vm::ptr spurs, vm::ptr tasks return CELL_SPURS_TASK_ERROR_ALIGN; } - memset((void *)taskset.addr(), 0, size); + memset(taskset.get_ptr(), 0, size); taskset->m.spurs = spurs; taskset->m.args = args; @@ -2406,13 +2406,28 @@ s64 cellSpursJoinTaskset(vm::ptr taskset) #endif } -s64 cellSpursGetTasksetId(vm::ptr taskset, vm::ptr workloadId) +s64 cellSpursGetTasksetId(vm::ptr taskset, vm::ptr wid) { #ifdef PRX_DEBUG cellSpurs->Warning("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.addr(), workloadId.addr()); return GetCurrentPPUThread().FastCall2(libsre + 0x14EA0, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!taskset || !wid) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (taskset.addr() % CellSpursTaskset::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + *wid = taskset->m.wid.ToBE(); return CELL_OK; #endif } @@ -2777,29 +2792,66 @@ s64 cellSpursCreateTask2WithBinInfo() #endif } -s64 cellSpursTasksetSetExceptionEventHandler() +s64 cellSpursTasksetSetExceptionEventHandler(vm::ptr taskset, vm::ptr handler, vm::ptr arg) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x13124, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!taskset || !handler) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (taskset.addr() % CellSpursTaskset::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + if (taskset->m.exception_handler != 0) + { + return CELL_SPURS_TASK_ERROR_BUSY; + } + + taskset->m.exception_handler = handler; + taskset->m.exception_handler_arg = arg; return CELL_OK; #endif } -s64 cellSpursTasksetUnsetExceptionEventHandler() +s64 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr taskset) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x13194, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!taskset) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (taskset.addr() % CellSpursTaskset::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + taskset->m.exception_handler.set(0); + taskset->m.exception_handler_arg.set(0); return CELL_OK; #endif } -s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id) +s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); @@ -2810,13 +2862,28 @@ s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, vm::ptr spurs) +s64 cellSpursTasksetGetSpursAddress(vm::ptr taskset, vm::ptr spurs) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14408, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!taskset || !spurs) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (taskset.addr() % CellSpursTaskset::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + *spurs = (u32)taskset->m.spurs.addr().ToBE(); return CELL_OK; #endif } @@ -3092,6 +3159,8 @@ void cellSpurs_init(Module *pxThis) REG_FUNC(cellSpurs, cellSpursEnableExceptionEventHandler); REG_FUNC(cellSpurs, cellSpursSetGlobalExceptionEventHandler); REG_FUNC(cellSpurs, cellSpursUnsetGlobalExceptionEventHandler); + REG_FUNC(cellSpurs, cellSpursSetExceptionEventHandler); + REG_FUNC(cellSpurs, cellSpursUnsetExceptionEventHandler); // Event flag REG_FUNC(cellSpurs, _cellSpursEventFlagInitialize); @@ -3137,8 +3206,6 @@ void cellSpurs_init(Module *pxThis) REG_FUNC(cellSpurs, cellSpursCreateTask2WithBinInfo); REG_FUNC(cellSpurs, cellSpursLookUpTasksetAddress); REG_FUNC(cellSpurs, cellSpursTasksetGetSpursAddress); - REG_FUNC(cellSpurs, cellSpursSetExceptionEventHandler); - REG_FUNC(cellSpurs, cellSpursUnsetExceptionEventHandler); REG_FUNC(cellSpurs, cellSpursGetTasksetInfo); REG_FUNC(cellSpurs, cellSpursTasksetSetExceptionEventHandler); REG_FUNC(cellSpurs, cellSpursTasksetUnsetExceptionEventHandler); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index adb1a60799..fc8871ecd6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -427,19 +427,38 @@ struct CellSpursTaskset // Raw data u8 _u8[size]; + struct TaskInfo + { + be_t args[4]; + vm::bptr elf; + vm::bptr context_save_storage; + be_t ls_pattern[4]; + }; + // Real data struct { - u8 unk1[0x64]; // 0x00 - vm::bptr spurs; // 0x64 - be_t args; // 0x68 - u8 enable_clear_ls; // 0x70 - u8 x71; // 0x71 - u8 x72; // 0x72 - u8 x73; // 0x73 - be_t wid; // 0x74 - u8 unk3[0x1818]; // 0x78 - be_t size; // 0x1890 + be_t running_set[4]; // 0x00 + be_t ready_set[4]; // 0x10 + be_t unk_set[4]; // 0x20 - TODO: Find out what this is + be_t enabled_set[4]; // 0x30 + be_t signal_received_set[4]; // 0x40 + be_t waiting_set[4]; // 0x50 + vm::bptr spurs; // 0x60 + be_t args; // 0x68 + u8 enable_clear_ls; // 0x70 + u8 x71; // 0x71 + u8 x72; // 0x72 + u8 last_scheduled_task; // 0x73 + be_t wid; // 0x74 + u8 unk1[8]; // 0x78 + TaskInfo task_info[128]; // 0x80 + vm::bptr exception_handler; // 0x1880 + vm::bptr exception_handler_arg; // 0x1888 + be_t size; // 0x1890 + u32 unk2; // 0x1894 + u32 event_flag_id1; // 0x1898 + u32 event_flag_id2; // 0x189C } m; SPURSManagerTaskset *taskset; @@ -564,7 +583,47 @@ struct CellSpursTaskset2 static const u32 align = 128; static const u32 size = 10496; - be_t skip[10496]; + union + { + // Raw data + u8 _u8[size]; + + struct TaskInfo + { + be_t args[4]; + vm::bptr elf_address; + vm::bptr context_save_storage; + be_t ls_pattern[4]; + }; + + // Real data + struct + { + be_t running_set[4]; // 0x00 + be_t ready_set[4]; // 0x10 + be_t unk_set[4]; // 0x20 - TODO: Find out what this is + be_t enabled_set[4]; // 0x30 + be_t signal_received_set[4]; // 0x40 + be_t waiting_set[4]; // 0x50 + vm::bptr spurs; // 0x60 + be_t args; // 0x68 + u8 enable_clear_ls; // 0x70 + u8 x71; // 0x71 + u8 x72; // 0x72 + u8 last_scheduled_task; // 0x73 + be_t wid; // 0x74 + u8 unk1[8]; // 0x78 + TaskInfo task_info[128]; // 0x80 + vm::bptr exception_handler; // 0x1880 + vm::bptr exception_handler_arg; // 0x1888 + be_t size; // 0x1890 + u32 unk2; // 0x1894 + u32 event_flag_id1; // 0x1898 + u32 event_flag_id2; // 0x189C + u8 unk3[0x88]; // 0x1900 + u128 task_exit_code[128]; // 0x1988 + } m; + }; }; struct CellSpursTasksetAttribute diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index b0990ba2f6..8e2629cea3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -662,6 +662,7 @@ _UNICODE;UNICODE;%(PreprocessorDefinitions) stdafx.h Async + true true @@ -676,6 +677,7 @@ _UNICODE;UNICODE;LLVM_AVAILABLE;%(PreprocessorDefinitions) stdafx.h Async + true true @@ -694,6 +696,7 @@ _UNICODE;UNICODE;MSVC_CRT_MEMLEAK_DETECTION;%(PreprocessorDefinitions) stdafx.h Async + true true @@ -741,6 +744,7 @@ Use stdafx.h Async + true true @@ -759,6 +763,7 @@ stdafx.h Async LLVM_AVAILABLE;%(PreprocessorDefinitions) + true true From 53e0979f2910879090dbae21345625bafea08b97 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sun, 14 Dec 2014 03:19:06 +0530 Subject: [PATCH 04/94] SPURS: Implement cellSpursCreateTask --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 122 ++++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 62 +++++++----- 2 files changed, 153 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 831748949b..2810152043 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2427,7 +2427,7 @@ s64 cellSpursGetTasksetId(vm::ptr taskset, vm::ptr wid) return CELL_SPURS_TASK_ERROR_INVAL; } - *wid = taskset->m.wid.ToBE(); + *wid = taskset->m.wid; return CELL_OK; #endif } @@ -2443,6 +2443,121 @@ s64 cellSpursShutdownTaskset(vm::ptr taskset) #endif } +u32 _cellSpursGetSdkVersion() +{ + static u32 sdk_version = -2; + + if (sdk_version == -2) + { + auto version = vm::ptr::make((u32)Memory.Alloc(sizeof(u32), sizeof(u32))); + sys_process_get_sdk_version(sys_process_getpid(), version); + sdk_version = *version; + Memory.Free(version.addr()); + } + + return sdk_version; +} + +s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm::ptr elf_addr, vm::ptr context_addr, u32 context_size, vm::ptr ls_pattern, vm::ptr arg) +{ + if (!taskset || !elf_addr) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (elf_addr.addr() % 16) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + auto sdk_version = _cellSpursGetSdkVersion(); + if (sdk_version < 0x27FFFF) + { + if (context_addr.addr() % 16) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + } + else + { + if (context_addr.addr() % 128) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + } + + u32 alloc_ls_blocks = 0; + if (context_addr.addr() != 0) + { + if (context_size < CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + alloc_ls_blocks = context_size > 0x3D400 ? 0x7A : ((context_size - 0x400) >> 11); + if (ls_pattern.addr() != 0) + { + u32 ls_blocks = 0; + for (u32 i = 0; i < 2; i++) + { + for (u32 j = 0; j < 64; j++) + { + if (ls_pattern->u64[0] & ((u64)1 << j)) + { + ls_blocks++; + } + } + } + + if (ls_blocks > alloc_ls_blocks) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + if (ls_pattern->u32[0] & 0xFC000000) + { + // Prevent save/restore to SPURS management area + return CELL_SPURS_TASK_ERROR_INVAL; + } + } + } + else + { + alloc_ls_blocks = 0; + } + + // TODO: Verify the ELF header is proper and all its load segments are at address >= 0x3000 + + // TODO: Make the following block execute atomically + u32 tmp_task_id; + for (tmp_task_id = 0; tmp_task_id < CELL_SPURS_MAX_TASK; tmp_task_id++) + { + u32 l = tmp_task_id >> 5; + u32 b = tmp_task_id & 0x1F; + if ((taskset->m.enabled_set[l] & (0x80000000 >> b)) == 0) + { + taskset->m.enabled_set[l] |= 0x80000000 >> b; + break; + } + } + + if (tmp_task_id >= CELL_SPURS_MAX_TASK) + { + CELL_SPURS_TASK_ERROR_AGAIN; + } + + taskset->m.task_info[tmp_task_id].elf_addr.set(elf_addr.addr()); + taskset->m.task_info[tmp_task_id].context_save_storage.set((context_addr.addr() & 0xFFFFFFF8) | alloc_ls_blocks); + for (u32 i = 0; i < 2; i++) + { + taskset->m.task_info[tmp_task_id].args.u64[i] = arg != 0 ? arg->u64[i] : 0; + taskset->m.task_info[tmp_task_id].ls_pattern.u64[i] = ls_pattern != 0 ? ls_pattern->u64[i] : 0; + } + + *task_id = tmp_task_id; + return CELL_OK; +} + s64 cellSpursCreateTask(vm::ptr taskset, vm::ptr taskID, u32 elf_addr, u32 context_addr, u32 context_size, vm::ptr lsPattern, vm::ptr argument) { @@ -2451,8 +2566,7 @@ s64 cellSpursCreateTask(vm::ptr taskset, vm::ptr taskID, taskset.addr(), taskID.addr(), elf_addr, context_addr, context_size, lsPattern.addr(), argument.addr()); return GetCurrentPPUThread().FastCall2(libsre + 0x12414, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; + return spursCreateTask(taskset, taskID, vm::ptr::make(elf_addr), vm::ptr::make(context_addr), context_size, lsPattern, argument); #endif } @@ -2883,7 +2997,7 @@ s64 cellSpursTasksetGetSpursAddress(vm::ptr taskset, vm: return CELL_SPURS_TASK_ERROR_INVAL; } - *spurs = (u32)taskset->m.spurs.addr().ToBE(); + *spurs = (u32)taskset->m.spurs.addr(); return CELL_OK; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index fc8871ecd6..4a8ba993af 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -132,6 +132,7 @@ enum TaskConstants CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, }; class SPURSManager; @@ -417,6 +418,18 @@ struct CellSpursEventFlag SPURSManagerEventFlag *eventFlag; }; +union CellSpursTaskArgument +{ + be_t u32[4]; + be_t u64[2]; +}; + +union CellSpursTaskLsPattern +{ + be_t u32[4]; + be_t u64[2]; +}; + struct CellSpursTaskset { static const u32 align = 128; @@ -429,14 +442,16 @@ struct CellSpursTaskset struct TaskInfo { - be_t args[4]; - vm::bptr elf; - vm::bptr context_save_storage; - be_t ls_pattern[4]; + CellSpursTaskArgument args; + vm::bptr elf_addr; + vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; }; + static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); + // Real data - struct + struct _CellSpursTaskset { be_t running_set[4]; // 0x00 be_t ready_set[4]; // 0x10 @@ -459,8 +474,11 @@ struct CellSpursTaskset u32 unk2; // 0x1894 u32 event_flag_id1; // 0x1898 u32 event_flag_id2; // 0x189C + u8 unk3[0x60]; // 0x18A0 } m; + static_assert(sizeof(_CellSpursTaskset) == size, "Wrong _CellSpursTaskset size"); + SPURSManagerTaskset *taskset; }; }; @@ -590,14 +608,16 @@ struct CellSpursTaskset2 struct TaskInfo { - be_t args[4]; - vm::bptr elf_address; - vm::bptr context_save_storage; - be_t ls_pattern[4]; + CellSpursTaskArgument args; + vm::bptr elf_addr; + vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; }; + static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); + // Real data - struct + struct _CellSpursTaskset2 { be_t running_set[4]; // 0x00 be_t ready_set[4]; // 0x10 @@ -620,9 +640,12 @@ struct CellSpursTaskset2 u32 unk2; // 0x1894 u32 event_flag_id1; // 0x1898 u32 event_flag_id2; // 0x189C - u8 unk3[0x88]; // 0x1900 - u128 task_exit_code[128]; // 0x1988 + u8 unk3[0xE8]; // 0x18A0 + u64 task_exit_code[256]; // 0x1988 + u8 unk4[0x778]; // 0x2188 } m; + + static_assert(sizeof(_CellSpursTaskset2) == size, "Wrong _CellSpursTaskset2 size"); }; }; @@ -681,21 +704,6 @@ struct CellSpursTraceTaskData be_t task; }; -typedef be_t be_u32; -typedef be_t be_u64; - -struct CellSpursTaskArgument -{ - be_u32 u32[4]; - be_u64 u64[2]; -}; - -struct CellSpursTaskLsPattern -{ - be_u32 u32[4]; - be_u64 u64[2]; -}; - struct CellSpursTaskAttribute2 { be_t revision; From 68cc9b205920c3579d5d89897caa022f506d44bc Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sun, 14 Dec 2014 12:07:46 +0530 Subject: [PATCH 05/94] SPURS: Enable logging of taskset calls --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 91 ++++++++++++++++-------- 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 2810152043..8163443e42 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2345,8 +2345,9 @@ s64 spursCreateTaskset(vm::ptr spurs, vm::ptr tasks s64 cellSpursCreateTasksetWithAttribute(vm::ptr spurs, vm::ptr taskset, vm::ptr attr) { + cellSpurs->Warning("%s(spurs=0x%x, taskset=0x%x, attr=0x%x)", __FUNCTION__, spurs.addr(), taskset.addr(), attr.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14BEC, libsre_rtoc); #endif @@ -2397,8 +2398,9 @@ s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr t s64 cellSpursJoinTaskset(vm::ptr taskset) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursJoinTaskset(taskset_addr=0x%x)", taskset.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x152F8, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2408,8 +2410,9 @@ s64 cellSpursJoinTaskset(vm::ptr taskset) s64 cellSpursGetTasksetId(vm::ptr taskset, vm::ptr wid) { + cellSpurs->Warning("cellSpursGetTasksetId(taskset_addr=0x%x, wid=0x%x)", taskset.addr(), wid.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.addr(), workloadId.addr()); return GetCurrentPPUThread().FastCall2(libsre + 0x14EA0, libsre_rtoc); #else if (!taskset || !wid) @@ -2434,8 +2437,9 @@ s64 cellSpursGetTasksetId(vm::ptr taskset, vm::ptr wid) s64 cellSpursShutdownTaskset(vm::ptr taskset) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursShutdownTaskset(taskset_addr=0x%x)", taskset.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x14868, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2561,9 +2565,10 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: s64 cellSpursCreateTask(vm::ptr taskset, vm::ptr taskID, u32 elf_addr, u32 context_addr, u32 context_size, vm::ptr lsPattern, vm::ptr argument) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursCreateTask(taskset_addr=0x%x, taskID_addr=0x%x, elf_addr_addr=0x%x, context_addr_addr=0x%x, context_size=%d, lsPattern_addr=0x%x, argument_addr=0x%x)", taskset.addr(), taskID.addr(), elf_addr, context_addr, context_size, lsPattern.addr(), argument.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x12414, libsre_rtoc); #else return spursCreateTask(taskset, taskID, vm::ptr::make(elf_addr), vm::ptr::make(context_addr), context_size, lsPattern, argument); @@ -2583,8 +2588,9 @@ s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID) s64 cellSpursCreateTaskWithAttribute() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x12204, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2594,8 +2600,9 @@ s64 cellSpursCreateTaskWithAttribute() s64 cellSpursTasksetAttributeSetName(vm::ptr attr, vm::ptr name) { + cellSpurs->Warning("%s(attr=0x%x, name=0x%x)", __FUNCTION__, attr.addr(), name.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14210, libsre_rtoc); #else if (!attr || !name) @@ -2615,8 +2622,9 @@ s64 cellSpursTasksetAttributeSetName(vm::ptr attr, vm s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr attr, u32 size) { + cellSpurs->Warning("%s(attr=0x%x, size=0x%x)", __FUNCTION__, attr.addr(), size); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14254, libsre_rtoc); #else if (!attr) @@ -2641,8 +2649,9 @@ s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr a s64 cellSpursTasksetAttributeEnableClearLS(vm::ptr attr, s32 enable) { + cellSpurs->Warning("%s(attr=0x%x, enable=%d)", __FUNCTION__, attr.addr(), enable); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x142AC, libsre_rtoc); #else if (!attr) @@ -2686,8 +2695,9 @@ s64 _cellSpursTasksetAttribute2Initialize(vm::ptr at s64 cellSpursTaskExitCodeGet() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1397C, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2697,8 +2707,9 @@ s64 cellSpursTaskExitCodeGet() s64 cellSpursTaskExitCodeInitialize() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1352C, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2708,8 +2719,9 @@ s64 cellSpursTaskExitCodeInitialize() s64 cellSpursTaskExitCodeTryGet() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x13974, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2719,8 +2731,9 @@ s64 cellSpursTaskExitCodeTryGet() s64 cellSpursTaskGetLoadableSegmentPattern() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x13ED4, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2730,8 +2743,9 @@ s64 cellSpursTaskGetLoadableSegmentPattern() s64 cellSpursTaskGetReadOnlyAreaPattern() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x13CFC, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2741,8 +2755,9 @@ s64 cellSpursTaskGetReadOnlyAreaPattern() s64 cellSpursTaskGenerateLsPattern() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x13B78, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2752,8 +2767,9 @@ s64 cellSpursTaskGenerateLsPattern() s64 _cellSpursTaskAttributeInitialize() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x10C30, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2763,8 +2779,9 @@ s64 _cellSpursTaskAttributeInitialize() s64 cellSpursTaskAttributeSetExitCodeContainer() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x10A98, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2801,8 +2818,9 @@ s64 _cellSpursTaskAttribute2Initialize(vm::ptr attribut s64 cellSpursTaskGetContextSaveAreaSize() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1409C, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2812,8 +2830,9 @@ s64 cellSpursTaskGetContextSaveAreaSize() s64 cellSpursCreateTaskset2(vm::ptr spurs, vm::ptr taskset, vm::ptr attr) { + cellSpurs->Warning("%s(spurs=0x%x, taskset=0x%x, attr=0x%x)", __FUNCTION__, spurs.addr(), taskset.addr(), attr.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x15108, libsre_rtoc); #else auto free_attr = false; @@ -2853,8 +2872,9 @@ s64 cellSpursCreateTaskset2(vm::ptr spurs, vm::ptr s64 cellSpursCreateTask2() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x11E54, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2864,8 +2884,9 @@ s64 cellSpursCreateTask2() s64 cellSpursJoinTask2() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x11378, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2875,8 +2896,9 @@ s64 cellSpursJoinTask2() s64 cellSpursTryJoinTask2() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x11748, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2886,8 +2908,9 @@ s64 cellSpursTryJoinTask2() s64 cellSpursDestroyTaskset2() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x14EE8, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2897,8 +2920,9 @@ s64 cellSpursDestroyTaskset2() s64 cellSpursCreateTask2WithBinInfo() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x120E0, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2908,8 +2932,9 @@ s64 cellSpursCreateTask2WithBinInfo() s64 cellSpursTasksetSetExceptionEventHandler(vm::ptr taskset, vm::ptr handler, vm::ptr arg) { + cellSpurs->Warning("%s(taskset=0x5x, handler=0x%x, arg=0x%x)", __FUNCTION__, taskset.addr(), handler.addr(), arg.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x13124, libsre_rtoc); #else if (!taskset || !handler) @@ -2940,8 +2965,9 @@ s64 cellSpursTasksetSetExceptionEventHandler(vm::ptr taskset, s64 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr taskset) { + cellSpurs->Warning("%s(taskset=0x%x)", __FUNCTION__, taskset.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x13194, libsre_rtoc); #else if (!taskset) @@ -2967,8 +2993,9 @@ s64 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr taskset s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id) { + cellSpurs->Warning("%s(spurs=0x%x, taskset=0x%x, id=0x%x)", __FUNCTION__, spurs.addr(), taskset.addr(), id); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x133AC, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -2978,8 +3005,9 @@ s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset s64 cellSpursTasksetGetSpursAddress(vm::ptr taskset, vm::ptr spurs) { + cellSpurs->Warning("%s(taskset=0x%x, spurs=0x%x)", __FUNCTION__, taskset.addr(), spurs.addr()); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x14408, libsre_rtoc); #else if (!taskset || !spurs) @@ -3004,8 +3032,9 @@ s64 cellSpursTasksetGetSpursAddress(vm::ptr taskset, vm: s64 cellSpursGetTasksetInfo() { -#ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1445C, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -3015,8 +3044,10 @@ s64 cellSpursGetTasksetInfo() s64 _cellSpursTasksetAttributeInitialize(vm::ptr attribute, u32 revision, u32 sdk_version, u64 args, vm::ptr priority, u32 max_contention) { + cellSpurs->Warning("%s(attribute=0x%x, revision=%u, skd_version=%u, args=0x%llx, priority=0x%x, max_contention=%u)", + __FUNCTION__, attribute.addr(), revision, sdk_version, args, priority.addr(), max_contention); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0x142FC, libsre_rtoc); #else if (!attribute) From 5a6016003542d7064ac716f7f7f7c71d0d1b59e7 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Tue, 16 Dec 2014 09:12:50 +0530 Subject: [PATCH 06/94] SPURS: Added comments on CellSpurs fields --- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 126 ++++++++++++------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 4a8ba993af..849a597223 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -224,7 +224,7 @@ struct CellSpurs struct _sub_str1 { - u8 unk0[0x20]; + u8 unk0[0x20]; // 0x00 - SPU exceptionh handler 0x08 - SPU exception handler args be_t sem; // 0x20 u8 unk1[0x8]; vm::bptr hook; // 0x30 @@ -234,14 +234,14 @@ struct CellSpurs static_assert(sizeof(_sub_str1) == 0x80, "Wrong _sub_str1 size"); - struct _sub_str2 + struct _sub_str2 // Event port multiplexer { - be_t unk0; - be_t unk1; - be_t unk2; - be_t unk3; + be_t unk0; // 0x00 Outstanding requests + be_t unk1; // 0x04 + be_t unk2; // 0x08 + be_t unk3; // 0x0C be_t port; // 0x10 - u8 unk_[0x68]; + u8 unk_[0x68]; // 0x18 - The first u64 seems to be the start of a linked list. The linked list struct seems to be {u64 next; u64 data; u64 handler} }; static_assert(sizeof(_sub_str2) == 0x80, "Wrong _sub_str2 size"); @@ -275,43 +275,43 @@ struct CellSpurs struct { atomic_t wklReadyCount[0x20]; // 0x0 (index = wid) - u8 wklA[0x10]; // 0x20 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - u8 wklB[0x10]; // 0x30 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - u8 wklMinCnt[0x10]; // 0x40 (seems only for first 0..15 wids) - atomic_t wklMaxCnt[0x10]; // 0x50 (packed 4-bit data, index = wid % 16, internal index = wid / 16) + u8 wklA[0x10]; // 0x20 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Current contention + u8 wklB[0x10]; // 0x30 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Pending + u8 wklMinCnt[0x10]; // 0x40 (seems only for first 0..15 wids) - Min contention + atomic_t wklMaxCnt[0x10]; // 0x50 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Max contention CellSpursWorkloadFlag wklFlag; // 0x60 - atomic_t wklSet1; // 0x70 (bitset for 0..15 wids) - atomic_t x72; // 0x72 - u8 x73; // 0x73 - u8 flags1; // 0x74 - u8 x75; // 0x75 - u8 nSpus; // 0x76 + atomic_t wklSet1; // 0x70 (bitset for 0..15 wids) - Workload signal + atomic_t x72; // 0x72 - message + u8 x73; // 0x73 - idling + u8 flags1; // 0x74 - Bit0(MSB)=exit_if_no_work, Bit1=32_workloads + u8 x75; // 0x75 - trace control + u8 nSpus; // 0x76 - Number of SPUs atomic_t flagRecv; // 0x77 - atomic_t wklSet2; // 0x78 (bitset for 16..32 wids) + atomic_t wklSet2; // 0x78 (bitset for 16..32 wids) - Workload signal u8 x7A[6]; // 0x7A - atomic_t wklStat1[0x10]; // 0x80 - u8 wklD1[0x10]; // 0x90 - u8 wklE1[0x10]; // 0xA0 - atomic_t wklMskA; // 0xB0 - atomic_t wklMskB; // 0xB4 - u8 xB8[5]; // 0xB8 - atomic_t xBD; // 0xBD - u8 xBE[2]; // 0xBE - u8 xC0[8]; // 0xC0 - u8 xC8; // 0xC8 - u8 spuPort; // 0xC9 + atomic_t wklStat1[0x10]; // 0x80 - Workload state (16*u8) - State enum {non_exitent, preparing, runnable, shutting_down, removable, invalid} + u8 wklD1[0x10]; // 0x90 - Workload status (16*u8) + u8 wklE1[0x10]; // 0xA0 - Workload event (16*u8) + atomic_t wklMskA; // 0xB0 - Available workloads (32*u1) + atomic_t wklMskB; // 0xB4 - Available module id + u8 xB8[5]; // 0xB8 - 0xBC - exit barrier + atomic_t xBD; // 0xBD - update workload + u8 xBE[2]; // 0xBE - 0xBF - message - terminate + u8 xC0[8]; // 0xC0 - System workload + u8 xC8; // 0xC8 - System service - on spu + u8 spuPort; // 0xC9 - SPU port for system service u8 xCA; // 0xCA u8 xCB; // 0xCB u8 xCC; // 0xCC u8 xCD; // 0xCD - u8 xCE; // 0xCE + u8 xCE; // 0xCE - message - update trace u8 xCF; // 0xCF - atomic_t wklStat2[0x10]; // 0xD0 - u8 wklD2[0x10]; // 0xE0 - u8 wklE2[0x10]; // 0xF0 + atomic_t wklStat2[0x10]; // 0xD0 - Workload state (16*u8) + u8 wklD2[0x10]; // 0xE0 - Workload status (16*u8) + u8 wklE2[0x10]; // 0xF0 - Workload event (16*u8) _sub_str1 wklF1[0x10]; // 0x100 - be_t unk22; // 0x900 - u8 unknown7[0x980 - 0x908]; + be_t unk22; // 0x900 - SPURS trace buffer + u8 unknown7[0x980 - 0x908]; // 0x908 - Per SPU trace info ??? (8*u32) 0x950 - SPURS trace mode (u32) be_t semPrv; // 0x980 be_t unk11; // 0x988 be_t unk12; // 0x98C @@ -321,14 +321,14 @@ struct CellSpurs _sub_str3 wklSysG; // 0xD00 be_t ppu0; // 0xD20 be_t ppu1; // 0xD28 - be_t spuTG; // 0xD30 + be_t spuTG; // 0xD30 - SPU thread group be_t spus[8]; // 0xD34 u8 unknown3[0xD5C - 0xD54]; - be_t queue; // 0xD5C - be_t port; // 0xD60 - atomic_t xD64; // 0xD64 - atomic_t xD65; // 0xD65 - atomic_t xD66; // 0xD66 + be_t queue; // 0xD5C - Event queue + be_t port; // 0xD60 - Event port + atomic_t xD64; // 0xD64 - SPURS handler dirty + atomic_t xD65; // 0xD65 - SPURS handler waiting + atomic_t xD66; // 0xD66 - SPURS handler exiting atomic_t enableEH; // 0xD68 be_t exception; // 0xD6C sys_spu_image spuImg; // 0xD70 @@ -340,13 +340,13 @@ struct CellSpurs be_t unk5; // 0xD9C be_t revision; // 0xDA0 be_t sdkVersion; // 0xDA4 - atomic_t spups; // 0xDA8 + atomic_t spups; // 0xDA8 - SPU port bits sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 u8 unknown9[0xE00 - 0xDD0]; _sub_str4 wklH1[0x10]; // 0xE00 _sub_str2 sub3; // 0xF00 - u8 unknown6[0x1000 - 0xF80]; + u8 unknown6[0x1000 - 0xF80]; // 0xF80 - Gloabl SPU exception handler 0xF88 - Gloabl SPU exception handlers args _sub_str3 wklG2[0x10]; // 0x1000 _sub_str1 wklF2[0x10]; // 0x1200 _sub_str4 wklH2[0x10]; // 0x1A00 @@ -435,21 +435,21 @@ struct CellSpursTaskset static const u32 align = 128; static const u32 size = 6400; + struct TaskInfo + { + CellSpursTaskArgument args; + vm::bptr elf_addr; + vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; + }; + + static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); + union { // Raw data u8 _u8[size]; - struct TaskInfo - { - CellSpursTaskArgument args; - vm::bptr elf_addr; - vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) - CellSpursTaskLsPattern ls_pattern; - }; - - static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); - // Real data struct _CellSpursTaskset { @@ -601,21 +601,21 @@ struct CellSpursTaskset2 static const u32 align = 128; static const u32 size = 10496; + struct TaskInfo + { + CellSpursTaskArgument args; + vm::bptr elf_addr; + vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; + }; + + static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); + union { // Raw data u8 _u8[size]; - struct TaskInfo - { - CellSpursTaskArgument args; - vm::bptr elf_addr; - vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) - CellSpursTaskLsPattern ls_pattern; - }; - - static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); - // Real data struct _CellSpursTaskset2 { From 698f4fd4506dd0c8429d82026c82b0761c7b1706 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sun, 21 Dec 2014 01:37:29 +0530 Subject: [PATCH 07/94] SPURS: Improve the readability of the SPURS2 kernel at the cost of some performance --- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/Memory/vm_ptr.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 332 ++++++++++++----------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 91 +++++-- 4 files changed, 242 insertions(+), 185 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index aaffd7d00d..e7c28ed8ff 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -608,7 +608,7 @@ public: for (auto &arg : values) { u32 arg_size = align(u32(arg.size() + 1), stack_align); - u32 arg_addr = Memory.MainMem.AllocAlign(arg_size, stack_align); + u32 arg_addr = (u32)Memory.MainMem.AllocAlign(arg_size, stack_align); std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 6f0c65ed0d..0970ad7996 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -112,7 +112,7 @@ namespace vm __forceinline T* const operator -> () const { - return vm::get_ptr(m_addr); + return vm::get_ptr((u32)m_addr); } _ptr_base operator++ (int) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 8163443e42..483c3d56c6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -37,7 +37,7 @@ s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptrm.wklSysG.pm.set(be_t::make(vm::read32(libsre_rtoc - 0x7EA4))); spurs->m.wklSysG.size = 0x2200; #else - spurs->m.wklSysG.pm.set(be_t::make(0x100)); // wrong 64-bit address + spurs->m.wklInfoSysSrv.pm.set(be_t::make(0x100)); // wrong 64-bit address #endif - spurs->m.wklSysG.data = 0; - spurs->m.wklSysG.copy.write_relaxed(0xff); + spurs->m.wklInfoSysSrv.data = 0; + spurs->m.wklInfoSysSrv.copy.write_relaxed(0xff); u32 sem; for (u32 i = 0; i < 0x10; i++) { @@ -146,7 +146,7 @@ s64 spursInit( assert(!"spu_image_import() failed"); } #else - spurs->m.spuImg.addr = Memory.Alloc(0x40000, 4096); + spurs->m.spuImg.addr = (u32)Memory.Alloc(0x40000, 4096); #endif s32 tgt = SYS_SPU_THREAD_GROUP_TYPE_NORMAL; @@ -208,12 +208,12 @@ s64 spursInit( u64 vRES = 0x20ull << 32; u128 vSET = {}; - if (spurs->m.x72.read_relaxed() & (1 << num)) + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << num)) { SPU.WriteLS8(0x1eb, 0); // var4 if (arg1 == 0 || var1 == 0x20) { - spurs->m.x72._and_not(1 << num); + spurs->m.sysSrvMessage._and_not(1 << num); } } else @@ -224,9 +224,9 @@ s64 spursInit( u128 savedD = SPU.ReadLS128(0x1B0); u128 vRC = u128::add8(u128::minu8(wklReadyCount0, u128::from8p(8)), u128::minu8(wklReadyCount1, u128::from8p(8))); u32 wklFlag = spurs->m.wklFlag.flag.read_relaxed(); - u32 flagRecv = spurs->m.flagRecv.read_relaxed(); + u32 flagRecv = spurs->m.wklFlagReceiver.read_relaxed(); u128 vFM = u128::fromV(g_imm_table.fsmb_table[(wklFlag == 0) && (flagRecv < 16) ? 0x8000 >> flagRecv : 0]); - u128 wklSet1 = u128::fromV(g_imm_table.fsmb_table[spurs->m.wklSet1.read_relaxed()]); + u128 wklSet1 = u128::fromV(g_imm_table.fsmb_table[spurs->m.wklSignal1.read_relaxed()]); u128 vFMS1 = vFM | wklSet1; u128 vFMV1 = u128::fromV(g_imm_table.fsmb_table[(var1 < 16) ? 0x8000 >> var1 : 0]); u32 var5 = SPU.ReadLS32(0x1ec); @@ -270,7 +270,7 @@ s64 spursInit( if (!arg1 || var1 == vNUM) { - spurs->m.wklSet1._and_not(be_t::make((u16)(vNUM < 16 ? 0x8000 >> vNUM : 0))); + spurs->m.wklSignal1._and_not(be_t::make((u16)(vNUM < 16 ? 0x8000 >> vNUM : 0))); if (vNUM == flagRecv && wklFlag == 0) { spurs->m.wklFlag.flag.write_relaxed(be_t::make(-1)); @@ -305,126 +305,145 @@ s64 spursInit( { LV2_LOCK(0); // TODO: lock-free implementation if possible - const u32 arg1 = SPU.GPR[3]._u32[3]; - u32 var0 = SPU.ReadLS32(0x1d8); - u32 var1 = SPU.ReadLS32(0x1dc); - u128 wklA = vm::read128(spurs.addr() + 0x20); - u128 wklB = vm::read128(spurs.addr() + 0x30); - u128 savedA = SPU.ReadLS128(0x180); - u128 savedB = SPU.ReadLS128(0x190); - u128 vAA = u128::sub8(wklA, savedA); - u128 vBB = u128::sub8(wklB, savedB); - u128 vM1 = {}; if (var1 <= 31) vM1.u8r[var1 & 0xf] = (var1 <= 15) ? 0xf : 0xf0; - u128 vAABB = (arg1 == 0) ? vAA : u128::add8(vAA, u128::andnot(vM1, vBB)); + auto mgmt = vm::get_ptr(SPU.ls_offset); - u32 vNUM = 0x20; - u64 vRES = 0x20ull << 32; - u128 vSET = {}; + // The first and only argument to this function is a boolean that is set to false if the function + // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. + // If the first argument is true then the shared data is not updated with the result. + const auto isPoll = SPU.GPR[3]._u32[3]; - if (spurs->m.x72.read_relaxed() & (1 << num)) + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD2]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - SPU.WriteLS8(0x1eb, 0); // var4 - if (arg1 == 0 || var1 == 0x20) + contention[i] = mgmt->spurs->m.wklCurrentContention[i & 0x0F] - mgmt->wklLocContention[i & 0x0F]; + contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; + + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) { - spurs->m.x72._and_not(1 << num); + pendingContention[i] = mgmt->spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; + pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; + if (i != mgmt->wklCurrentId) + { + contention[i] += pendingContention[i]; + } + } + } + + u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + u32 pollStatus = 0; + + // The system service workload has the highest priority. Select the system service workload if + // the system service message bit for this SPU is set. + if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) + { + // Not sure what this does. Possibly Mark the SPU as in use. + mgmt->x1EB = 0; + if (!isPoll || mgmt->wklCurrentId == 0x20) + { + // Clear the message bit + mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); } } else { - u128 wklReadyCount0 = vm::read128(spurs.addr() + 0x0); - u128 wklReadyCount1 = vm::read128(spurs.addr() + 0x10); - u128 savedC = SPU.ReadLS128(0x1A0); - u128 wklMaxCnt = vm::read128(spurs.addr() + 0x50); - u32 wklFlag = spurs->m.wklFlag.flag.read_relaxed(); - u32 flagRecv = spurs->m.flagRecv.read_relaxed(); - u128 wklSet1 = u128::fromV(g_imm_table.fsmb_table[spurs->m.wklSet1.read_relaxed()]); - u128 wklSet2 = u128::fromV(g_imm_table.fsmb_table[spurs->m.wklSet2.read_relaxed()]); - u128 vABL = vAABB & u128::from8p(0x0f); - u128 vABH = u128::fromV(_mm_srli_epi32((vAABB & u128::from8p(0xf0)).vi, 4)); - u32 var5 = SPU.ReadLS32(0x1ec); - u128 v5L = u128::fromV(g_imm_table.fsmb_table[var5 >> 16]); - u128 v5H = u128::fromV(g_imm_table.fsmb_table[(u16)var5]); - u128 vFML = u128::fromV(g_imm_table.fsmb_table[(wklFlag == 0) && (flagRecv < 16) ? 0x8000 >> flagRecv : 0]); - u128 vFMH = u128::fromV(g_imm_table.fsmb_table[(u16)((wklFlag == 0) && (flagRecv < 32) ? 0x80000000 >> flagRecv : 0)]); - u128 vCL = u128::fromV(_mm_slli_epi32((savedC & u128::from8p(0x0f)).vi, 4)); - u128 vCH = savedC & u128::from8p(0xf0); - u128 vABRL = u128::gtu8(wklReadyCount0, vABL); - u128 vABRH = u128::gtu8(wklReadyCount1, vABH); - u128 vCCL = v5L & u128::gtu8(vCL, {}) & u128::gtu8(wklMaxCnt & u128::from8p(0x0f), vABL) & (wklSet1 | vFML | vABRL); - u128 vCCH = v5H & u128::gtu8(vCH, {}) & u128::gtu8(u128::fromV(_mm_srli_epi32((wklMaxCnt & u128::from8p(0xf0)).vi, 4)), vABH) & (wklSet2 | vFMH | vABRH); - u128 v1H = {}; if (var1 <= 31 && var1 > 15) v1H.u8r[var1 & 0xf] = 4; - u128 v1L = {}; if (var1 <= 15) v1L.u8r[var1] = 4; - u128 vCH1 = (v1H | vCH & u128::from8p(0xFB)) & vCCH; - u128 vCL1 = (v1L | vCL & u128::from8p(0xFB)) & vCCL; - u128 vSTATL = vABRL & u128::from8p(1) | wklSet1 & u128::from8p(2) | vFML & u128::from8p(4); - u128 vSTATH = vABRH & u128::from8p(1) | wklSet2 & u128::from8p(2) | vFMH & u128::from8p(4); + // Caclulate the scheduling weight for each worjload + u8 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) + { + auto j = i & 0x0F; + u8 x1ECx1EE = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->x1EC & (0x8000 >> j) : mgmt->x1EE & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; + u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - s32 max = -1; - for (u32 i = 0; i < 0x10; i++) - { - const s32 value = vCL1.u8r[i]; - if (value > max && (vCCL.u8r[i] & 1)) + // For a worload to be considered for scheduling: + // 1. Its priority must be greater than 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The bit in 0x1EC/0x1EE for the wokload must be set + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // Condition #4 may be overriden using a workload signal or using the workload flag + if (x1ECx1EE && priority > 0 && maxContention > contention[i]) { - vNUM = i; - max = value; - } - } - for (u32 i = 16; i < 0x20; i++) - { - const s32 value = vCH1.u8r[i]; - if (value > max && (vCCH.u8r[i] & 1)) - { - vNUM = i; - max = value; + if (wklFlag || wklSignal || mgmt->spurs->m.wklReadyCount[i].read_relaxed() > contention[i]) + { + // The scheduling weight of the workload is equal to the priority of the workload for the SPU. + // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. + u8 weight = priority << 4; + if (mgmt->wklCurrentId == i) + { + weight |= 0x04; + } + + // In case of a tie the lower numbered workload is chosen + if (weight > maxWeight) + { + wklSelectedId = i; + maxWeight = weight; + pollStatus = mgmt->spurs->m.wklReadyCount[i].read_relaxed() > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } } } - if (vNUM < 0x10) - { - vRES = ((u64)vNUM << 32) | vSTATL.u8r[vNUM]; - vSET.u8r[vNUM] = 0x01; - } - else if (vNUM < 0x20) - { - vRES = ((u64)vNUM << 32) | vSTATH.u8r[vNUM & 0xf]; - vSET.u8r[vNUM] = 0x10; - } + // Not sure what this does. Possibly mark the SPU as idle/in use. + mgmt->x1EB = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - SPU.WriteLS8(0x1eb, vNUM == 0x20); - - if (!arg1 || var1 == vNUM) + if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { - spurs->m.wklSet1._and_not(be_t::make((u16)(vNUM < 16 ? 0x8000 >> vNUM : 0))); - spurs->m.wklSet2._and_not(be_t::make((u16)(0x80000000 >> vNUM))); - if (vNUM == flagRecv && wklFlag == 0) + // Clear workload signal for the selected workload + mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); + mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) { - spurs->m.wklFlag.flag.write_relaxed(be_t::make(-1)); + mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); } } } - if (arg1 == 0) + if (!isPoll) { - vm::write128(spurs.addr() + 0x20, u128::add8(vAA, vSET)); // update wklA + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + contention[wklSelectedId]++; + } - SPU.WriteLS128(0x180, vSET); // update savedA - SPU.WriteLS32(0x1dc, vNUM); // update var1 + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) + { + mgmt->spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); + mgmt->wklLocContention[i] = 0; + mgmt->wklLocPendingContention[i] = 0; + } + + mgmt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + mgmt->wklCurrentId = wklSelectedId; + } + else if (wklSelectedId != mgmt->wklCurrentId) + { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) + { + mgmt->spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); + mgmt->wklLocPendingContention[i] = 0; + } + + mgmt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; } - if (arg1 == 1 && vNUM != var1) - { - vm::write128(spurs.addr() + 0x30, u128::add8(vBB, vSET)); // update wklB - - SPU.WriteLS128(0x190, vSET); // update savedB - } - else - { - vm::write128(spurs.addr() + 0x30, vBB); // update wklB - - SPU.WriteLS128(0x190, {}); // update savedB - } - - return vRES; + u64 result = (u64)wklSelectedId << 32; + result |= pollStatus; + return result; }; //SPU.m_code3_func = [spurs, num](SPUThread& SPU) -> u64 // test //{ @@ -434,10 +453,13 @@ s64 spursInit( // return vRES; //}; - SPU.WriteLS128(0x1c0, u128::from32r(0, spurs.addr(), num, 0x1f)); + SpursKernelMgmtData * mgmt = vm::get_ptr(SPU.ls_offset); + mgmt->spurs = spurs; + mgmt->spuNum = num; + mgmt->dmaTagId = 0x1F; - u32 wid = 0x20; - u32 stat = 0; + u32 wid = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + u32 pollStatus = 0; while (true) { if (Emu.IsStopped()) @@ -447,14 +469,14 @@ s64 spursInit( } // get current workload info: - auto& wkl = wid <= 15 ? spurs->m.wklG1[wid] : (wid <= 31 && isSecond ? spurs->m.wklG2[wid & 0xf] : spurs->m.wklSysG); + auto& wkl = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isSecond ? spurs->m.wklInfo2[wid & 0xf] : spurs->m.wklInfoSysSrv); - if (SPU.ReadLS64(0x1d0) != wkl.pm.addr()) + if (mgmt->wklCurrentAddr != wkl.pm) { // load executable code: memcpy(vm::get_ptr(SPU.ls_offset + 0xa00), wkl.pm.get_ptr(), wkl.size); - SPU.WriteLS64(0x1d0, wkl.pm.addr()); - SPU.WriteLS32(0x1d8, wkl.copy.read_relaxed()); + mgmt->wklCurrentAddr = wkl.pm; + mgmt->x1D8 = wkl.copy.read_relaxed(); } if (!isSecond) SPU.WriteLS16(0x1e8, 0); @@ -463,7 +485,7 @@ s64 spursInit( SPU.GPR[1]._u32[3] = 0x3FFB0; SPU.GPR[3]._u32[3] = 0x100; SPU.GPR[4]._u64[1] = wkl.data; - SPU.GPR[5]._u32[3] = stat; + SPU.GPR[5]._u32[3] = pollStatus; SPU.FastCall(0xa00); // check status: @@ -481,7 +503,7 @@ s64 spursInit( SPU.GPR[3].clear(); assert(SPU.m_code3_func); u64 res = SPU.m_code3_func(SPU); - stat = (u32)(res); + pollStatus = (u32)(res); wid = (u32)(res >> 32); } @@ -507,8 +529,8 @@ s64 spursInit( assert(!"lwcond_create() failed"); } - spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK ? SF1_EXIT_IF_NO_WORK : 0) | (isSecond ? SF1_IS_SECOND : 0); - spurs->m.flagRecv.write_relaxed(0xff); + spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK ? SF1_EXIT_IF_NO_WORK : 0) | (isSecond ? SF1_32_WORKLOADS : 0); + spurs->m.wklFlagReceiver.write_relaxed(0xff); spurs->m.wklFlag.flag.write_relaxed(be_t::make(-1)); spurs->_u8[0xD64] = 0; spurs->_u8[0xD65] = 0; @@ -516,7 +538,7 @@ s64 spursInit( spurs->m.ppuPriority = ppuPriority; u32 queue; - if (s32 res = spursCreateLv2EventQueue(spurs, queue, vm::ptr::make(spurs.addr() + 0xc9), 0x2a, *(u64*)"_spuPrv")) + if (s32 res = (s32)spursCreateLv2EventQueue(spurs, queue, vm::ptr::make(spurs.addr() + 0xc9), 0x2a, *(u64*)"_spuPrv")) { assert(!"spursCreateLv2EventQueue() failed"); } @@ -575,14 +597,14 @@ s64 spursInit( for (u32 i = 0; i < 16; i++) { if (spurs->m.wklStat1[i].read_relaxed() == 2 && - spurs->m.wklG1[i].priority.ToBE() != 0 && - spurs->m.wklMaxCnt[i].read_relaxed() & 0xf + spurs->m.wklInfo1[i].priority.ToBE() != 0 && + spurs->m.wklMaxContention[i].read_relaxed() & 0xf ) { if (spurs->m.wklReadyCount[i].read_relaxed() || - spurs->m.wklSet1.read_relaxed() & (0x8000u >> i) || + spurs->m.wklSignal1.read_relaxed() & (0x8000u >> i) || (spurs->m.wklFlag.flag.read_relaxed() == 0 && - spurs->m.flagRecv.read_relaxed() == (u8)i + spurs->m.wklFlagReceiver.read_relaxed() == (u8)i )) { do_break = true; @@ -590,17 +612,17 @@ s64 spursInit( } } } - if (spurs->m.flags1 & SF1_IS_SECOND) for (u32 i = 0; i < 16; i++) + if (spurs->m.flags1 & SF1_32_WORKLOADS) for (u32 i = 0; i < 16; i++) { if (spurs->m.wklStat2[i].read_relaxed() == 2 && - spurs->m.wklG2[i].priority.ToBE() != 0 && - spurs->m.wklMaxCnt[i].read_relaxed() & 0xf0 + spurs->m.wklInfo2[i].priority.ToBE() != 0 && + spurs->m.wklMaxContention[i].read_relaxed() & 0xf0 ) { if (spurs->m.wklReadyCount[i + 0x10].read_relaxed() || - spurs->m.wklSet2.read_relaxed() & (0x8000u >> i) || + spurs->m.wklSignal2.read_relaxed() & (0x8000u >> i) || (spurs->m.wklFlag.flag.read_relaxed() == 0 && - spurs->m.flagRecv.read_relaxed() == (u8)i + 0x10 + spurs->m.wklFlagReceiver.read_relaxed() == (u8)i + 0x10 )) { do_break = true; @@ -1339,7 +1361,7 @@ s32 spursAddWorkload( } u32 wnum; - const u32 wmax = spurs->m.flags1 & SF1_IS_SECOND ? 0x20u : 0x10u; // TODO: check if can be changed + const u32 wmax = spurs->m.flags1 & SF1_32_WORKLOADS ? 0x20u : 0x10u; // TODO: check if can be changed spurs->m.wklMskA.atomic_op([spurs, wmax, &wnum](be_t& value) { wnum = cntlz32(~(u32)value); // found empty position @@ -1358,15 +1380,15 @@ s32 spursAddWorkload( u32 index = wnum & 0xf; if (wnum <= 15) { - assert((spurs->m.wklA[wnum] & 0xf) == 0); - assert((spurs->m.wklB[wnum] & 0xf) == 0); + assert((spurs->m.wklCurrentContention[wnum] & 0xf) == 0); + assert((spurs->m.wklPendingContention[wnum] & 0xf) == 0); spurs->m.wklStat1[wnum].write_relaxed(1); spurs->m.wklD1[wnum] = 0; spurs->m.wklE1[wnum] = 0; - spurs->m.wklG1[wnum].pm = pm; - spurs->m.wklG1[wnum].data = data; - spurs->m.wklG1[wnum].size = size; - spurs->m.wklG1[wnum].priority = *(be_t*)priorityTable; + spurs->m.wklInfo1[wnum].pm = pm; + spurs->m.wklInfo1[wnum].data = data; + spurs->m.wklInfo1[wnum].size = size; + spurs->m.wklInfo1[wnum].priority = *(be_t*)priorityTable; spurs->m.wklH1[wnum].nameClass = nameClass; spurs->m.wklH1[wnum].nameInstance = nameInstance; memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id @@ -1377,23 +1399,23 @@ s32 spursAddWorkload( spurs->m.wklF1[wnum].hookArg = hookArg; spurs->m.wklE1[wnum] |= 2; } - if ((spurs->m.flags1 & SF1_IS_SECOND) == 0) + if ((spurs->m.flags1 & SF1_32_WORKLOADS) == 0) { spurs->m.wklReadyCount[wnum + 16].write_relaxed(0); - spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : minContention; + spurs->m.wklMinContention[wnum] = minContention > 8 ? 8 : minContention; } } else { - assert((spurs->m.wklA[index] & 0xf0) == 0); - assert((spurs->m.wklB[index] & 0xf0) == 0); + assert((spurs->m.wklCurrentContention[index] & 0xf0) == 0); + assert((spurs->m.wklPendingContention[index] & 0xf0) == 0); spurs->m.wklStat2[index].write_relaxed(1); spurs->m.wklD2[index] = 0; spurs->m.wklE2[index] = 0; - spurs->m.wklG2[index].pm = pm; - spurs->m.wklG2[index].data = data; - spurs->m.wklG2[index].size = size; - spurs->m.wklG2[index].priority = *(be_t*)priorityTable; + spurs->m.wklInfo2[index].pm = pm; + spurs->m.wklInfo2[index].data = data; + spurs->m.wklInfo2[index].size = size; + spurs->m.wklInfo2[index].priority = *(be_t*)priorityTable; spurs->m.wklH2[index].nameClass = nameClass; spurs->m.wklH2[index].nameInstance = nameInstance; memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id @@ -1409,27 +1431,27 @@ s32 spursAddWorkload( if (wnum <= 15) { - spurs->m.wklMaxCnt[wnum].atomic_op([maxContention](u8& v) + spurs->m.wklMaxContention[wnum].atomic_op([maxContention](u8& v) { v &= ~0xf; v |= (maxContention > 8 ? 8 : maxContention); }); - spurs->m.wklSet1._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag1 + spurs->m.wklSignal1._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag1 } else { - spurs->m.wklMaxCnt[index].atomic_op([maxContention](u8& v) + spurs->m.wklMaxContention[index].atomic_op([maxContention](u8& v) { v &= ~0xf0; v |= (maxContention > 8 ? 8 : maxContention) << 4; }); - spurs->m.wklSet2._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag2 + spurs->m.wklSignal2._and_not({ be_t::make(0x8000 >> index) }); // clear bit in wklFlag2 } - spurs->m.flagRecv.compare_and_swap(wnum, 0xff); + spurs->m.wklFlagReceiver.compare_and_swap(wnum, 0xff); u32 res_wkl; - CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf]; + CellSpurs::WorkloadInfo& wkl = wnum <= 15 ? spurs->m.wklInfo1[wnum] : spurs->m.wklInfo2[wnum & 0xf]; spurs->m.wklMskB.atomic_op_sync([spurs, &wkl, wnum, &res_wkl](be_t& v) { const u32 mask = v.ToLE() & ~(0x80000000u >> wnum); @@ -1439,7 +1461,7 @@ s32 spursAddWorkload( { if (mask & m) { - CellSpurs::_sub_str3& current = i <= 15 ? spurs->m.wklG1[i] : spurs->m.wklG2[i & 0xf]; + CellSpurs::WorkloadInfo& current = i <= 15 ? spurs->m.wklInfo1[i] : spurs->m.wklInfo2[i & 0xf]; if (current.pm.addr() == wkl.pm.addr()) { // if a workload with identical policy module found @@ -1461,7 +1483,7 @@ s32 spursAddWorkload( spurs->wklStat(wnum).exchange(2); spurs->m.xBD.exchange(0xff); - spurs->m.x72.exchange(0xff); + spurs->m.sysSrvMessage.exchange(0xff); return CELL_OK; } @@ -1671,7 +1693,7 @@ s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set { return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; } - if (wid >= (spurs->m.flags1 & SF1_IS_SECOND ? 0x20u : 0x10u)) + if (wid >= (spurs->m.flags1 & SF1_32_WORKLOADS ? 0x20u : 0x10u)) { return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; } @@ -1687,14 +1709,14 @@ s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set { if (is_set) { - if (spurs->m.flagRecv.read_relaxed() != 0xff) + if (spurs->m.wklFlagReceiver.read_relaxed() != 0xff) { return CELL_SPURS_POLICY_MODULE_ERROR_BUSY; } } else { - if (spurs->m.flagRecv.read_relaxed() != wid) + if (spurs->m.wklFlagReceiver.read_relaxed() != wid) { return CELL_SPURS_POLICY_MODULE_ERROR_PERM; } @@ -1706,7 +1728,7 @@ s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set return res; } - spurs->m.flagRecv.atomic_op([wid, is_set](u8& FR) + spurs->m.wklFlagReceiver.atomic_op([wid, is_set](u8& FR) { if (is_set) { @@ -1783,7 +1805,7 @@ s64 cellSpursReadyCountStore(vm::ptr spurs, u32 wid, u32 value) { return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; } - if (wid >= (spurs->m.flags1 & SF1_IS_SECOND ? 0x20u : 0x10u) || value > 0xff) + if (wid >= (spurs->m.flags1 & SF1_32_WORKLOADS ? 0x20u : 0x10u) || value > 0xff) { return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 849a597223..61fcc42648 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -94,6 +94,7 @@ enum SPURSKernelInterfaces CELL_SPURS_MAX_SPU = 8, CELL_SPURS_MAX_WORKLOAD = 16, CELL_SPURS_MAX_WORKLOAD2 = 32, + CELL_SPURS_SYS_SERVICE_WORKLOAD_ID = 32, CELL_SPURS_MAX_PRIORITY = 16, CELL_SPURS_NAME_MAX_LENGTH = 15, CELL_SPURS_SIZE = 4096, @@ -162,8 +163,8 @@ enum SpursAttrFlags : u32 enum SpursFlags1 : u8 { SF1_NONE = 0x0, - - SF1_IS_SECOND = 0x40, + + SF1_32_WORKLOADS = 0x40, SF1_EXIT_IF_NO_WORK = 0x80, }; @@ -214,6 +215,12 @@ struct CellSpursWorkloadFlag typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); +enum CellSpursModulePollStatus { + CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1, + CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2, + CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4 +}; + // Core CellSpurs structures struct CellSpurs { @@ -246,7 +253,7 @@ struct CellSpurs static_assert(sizeof(_sub_str2) == 0x80, "Wrong _sub_str2 size"); - struct _sub_str3 + struct WorkloadInfo { vm::bptr pm; // policy module be_t data; // spu argument @@ -255,7 +262,7 @@ struct CellSpurs be_t priority; }; - static_assert(sizeof(_sub_str3) == 0x20, "Wrong _sub_str3 size"); + static_assert(sizeof(WorkloadInfo) == 0x20, "Wrong WorkloadInfo size"); struct _sub_str4 { @@ -274,29 +281,33 @@ struct CellSpurs // real data struct { - atomic_t wklReadyCount[0x20]; // 0x0 (index = wid) - u8 wklA[0x10]; // 0x20 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Current contention - u8 wklB[0x10]; // 0x30 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Pending - u8 wklMinCnt[0x10]; // 0x40 (seems only for first 0..15 wids) - Min contention - atomic_t wklMaxCnt[0x10]; // 0x50 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Max contention - CellSpursWorkloadFlag wklFlag; // 0x60 - atomic_t wklSet1; // 0x70 (bitset for 0..15 wids) - Workload signal - atomic_t x72; // 0x72 - message - u8 x73; // 0x73 - idling - u8 flags1; // 0x74 - Bit0(MSB)=exit_if_no_work, Bit1=32_workloads - u8 x75; // 0x75 - trace control - u8 nSpus; // 0x76 - Number of SPUs - atomic_t flagRecv; // 0x77 - atomic_t wklSet2; // 0x78 (bitset for 16..32 wids) - Workload signal - u8 x7A[6]; // 0x7A + // The first 0x80 bytes of the CellSpurs structure is shared by all instances of the SPURS kernel in a SPURS instance and the PPU. + // The SPURS kernel copies this from main memory to the LS (address 0x100) then runs its scheduling algorithm using this as one + // of the inputs. After selecting a new workload, the SPURS kernel updates this and writes it back to main memory. + // The read-modify-write is performed atomically by the SPURS kernel. + atomic_t wklReadyCount[0x10]; // 0x00 (index = wid) - Number of SPUs requested by each workload + u8 wklCurrentContention[0x10]; // 0x20 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Number of SPUs used by each workload + u8 wklPendingContention[0x10]; // 0x30 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Number of SPUs that are pending to context switch to the workload + u8 wklMinContention[0x10]; // 0x40 (seems only for first 0..15 wids) - Min SPUs required for each workload + atomic_t wklMaxContention[0x10]; // 0x50 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Max SPUs that may be allocated to each workload + CellSpursWorkloadFlag wklFlag; // 0x60 + atomic_t wklSignal1; // 0x70 (bitset for 0..15 wids) + atomic_t sysSrvMessage; // 0x72 + u8 sysSrvIdling; // 0x73 + u8 flags1; // 0x74 Type is SpursFlags1 + u8 sysSrvTraceControl; // 0x75 + u8 nSpus; // 0x76 + atomic_t wklFlagReceiver; // 0x77 + atomic_t wklSignal2; // 0x78 (bitset for 16..32 wids) + u8 x7A[6]; // 0x7A atomic_t wklStat1[0x10]; // 0x80 - Workload state (16*u8) - State enum {non_exitent, preparing, runnable, shutting_down, removable, invalid} u8 wklD1[0x10]; // 0x90 - Workload status (16*u8) u8 wklE1[0x10]; // 0xA0 - Workload event (16*u8) - atomic_t wklMskA; // 0xB0 - Available workloads (32*u1) - atomic_t wklMskB; // 0xB4 - Available module id - u8 xB8[5]; // 0xB8 - 0xBC - exit barrier - atomic_t xBD; // 0xBD - update workload - u8 xBE[2]; // 0xBE - 0xBF - message - terminate + atomic_t wklMskA; // 0xB0 - System service - Available workloads (32*u1) + atomic_t wklMskB; // 0xB4 - System service - Available module id + u8 xB8[5]; // 0xB8 - 0xBC - Syetem service exit barrier + atomic_t xBD; // 0xBD - System service message - update workload + u8 xBE[2]; // 0xBE - 0xBF - System service message - terminate u8 xC0[8]; // 0xC0 - System workload u8 xC8; // 0xC8 - System service - on spu u8 spuPort; // 0xC9 - SPU port for system service @@ -304,7 +315,7 @@ struct CellSpurs u8 xCB; // 0xCB u8 xCC; // 0xCC u8 xCD; // 0xCD - u8 xCE; // 0xCE - message - update trace + u8 xCE; // 0xCE - System service message - update trace u8 xCF; // 0xCF atomic_t wklStat2[0x10]; // 0xD0 - Workload state (16*u8) u8 wklD2[0x10]; // 0xE0 - Workload status (16*u8) @@ -317,8 +328,8 @@ struct CellSpurs be_t unk12; // 0x98C be_t unk13; // 0x990 u8 unknown4[0xB00 - 0x998]; - _sub_str3 wklG1[0x10]; // 0xB00 - _sub_str3 wklSysG; // 0xD00 + WorkloadInfo wklInfo1[0x10]; // 0xB00 + WorkloadInfo wklInfoSysSrv; // 0xD00 be_t ppu0; // 0xD20 be_t ppu1; // 0xD28 be_t spuTG; // 0xD30 - SPU thread group @@ -347,7 +358,7 @@ struct CellSpurs _sub_str4 wklH1[0x10]; // 0xE00 _sub_str2 sub3; // 0xF00 u8 unknown6[0x1000 - 0xF80]; // 0xF80 - Gloabl SPU exception handler 0xF88 - Gloabl SPU exception handlers args - _sub_str3 wklG2[0x10]; // 0x1000 + WorkloadInfo wklInfo2[0x10]; // 0x1000 _sub_str1 wklF2[0x10]; // 0x1200 _sub_str4 wklH2[0x10]; // 0x1A00 } m; @@ -741,5 +752,29 @@ struct CellSpursTaskBinInfo CellSpursTaskLsPattern lsPattern; }; +// The SPURS kernel data store. This resides at 0x00 of the LS. +struct SpursKernelMgmtData { + u8 unk0[0x100]; // 0x00 + u8 tempArea[0x80]; // 0x100 + u8 wklLocContention[0x10]; // 0x180 + u8 wklLocPendingContention[0x10]; // 0x190 + u8 priority[0x10]; // 0x1A0 + u8 x1B0[0x10]; // 0x1B0 + vm::bptr spurs; // 0x1C0 + be_t spuNum; // 0x1C8 + be_t dmaTagId; // 0x1CC + vm::bptr wklCurrentAddr; // 0x1D0 + be_t x1D8; // 0x1D8 + u32 wklCurrentId; // 0x1DC + be_t yieldToKernelAddr; // 0x1E0 + be_t selectWorkloadAddr; // 0x1E4 + u8 x1E8; // 0x1E8 + u8 x1E9; // 0x1E9 + u8 x1EA; // 0x1EA + u8 x1EB; // 0x1EB - This might be spuIdling + be_t x1EC; // 0x1EC - This might be wklEnable1 + be_t x1EE; // 0x1EE - This might be wklEnable2 +}; + s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); s64 spursWakeUp(vm::ptr spurs); From 52b342464be7c067d62473730703345923f3148f Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Mon, 22 Dec 2014 01:07:53 +0530 Subject: [PATCH 08/94] SPURS: Improve readability of SPURS1 kernel at the cost of some perormance --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 311 ++++++++++++++--------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 41 +-- 2 files changed, 210 insertions(+), 142 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 483c3d56c6..557ff274ac 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -109,13 +109,13 @@ s64 spursInit( // default or system workload: #ifdef PRX_DEBUG - spurs->m.wklSysG.pm.set(be_t::make(vm::read32(libsre_rtoc - 0x7EA4))); - spurs->m.wklSysG.size = 0x2200; + spurs->m.wklInfoSysSrv.addr.set(be_t::make(vm::read32(libsre_rtoc - 0x7EA4))); + spurs->m.wklInfoSysSrv.size = 0x2200; #else - spurs->m.wklInfoSysSrv.pm.set(be_t::make(0x100)); // wrong 64-bit address + spurs->m.wklInfoSysSrv.addr.set(be_t::make(0x100)); // wrong 64-bit address #endif - spurs->m.wklInfoSysSrv.data = 0; - spurs->m.wklInfoSysSrv.copy.write_relaxed(0xff); + spurs->m.wklInfoSysSrv.arg = 0; + spurs->m.wklInfoSysSrv.uniqueId.write_relaxed(0xff); u32 sem; for (u32 i = 0; i < 0x10; i++) { @@ -192,114 +192,164 @@ s64 spursInit( { LV2_LOCK(0); // TODO: lock-free implementation if possible - const u32 arg1 = SPU.GPR[3]._u32[3]; - u32 var0 = SPU.ReadLS32(0x1d8); - u32 var1 = SPU.ReadLS32(0x1dc); - u128 wklA = vm::read128(spurs.addr() + 0x20); - u128 wklB = vm::read128(spurs.addr() + 0x30); - u128 savedA = SPU.ReadLS128(0x180); - u128 savedB = SPU.ReadLS128(0x190); - u128 vAA = u128::sub8(wklA, savedA); - u128 vBB = u128::sub8(wklB, savedB); - u128 vM1 = {}; if (var1 <= 15) vM1.u8r[var1] = 0xff; - u128 vAABB = (arg1 == 0) ? vAA : u128::add8(vAA, u128::andnot(vM1, vBB)); - - u32 vNUM = 0x20; - u64 vRES = 0x20ull << 32; - u128 vSET = {}; + auto mgmt = vm::get_ptr(SPU.ls_offset); - if (spurs->m.sysSrvMessage.read_relaxed() & (1 << num)) + // The first and only argument to this function is a boolean that is set to false if the function + // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. + // If the first argument is true then the shared data is not updated with the result. + const auto isPoll = SPU.GPR[3]._u32[3]; + + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - SPU.WriteLS8(0x1eb, 0); // var4 - if (arg1 == 0 || var1 == 0x20) - { - spurs->m.sysSrvMessage._and_not(1 << num); - } - } - else - { - u128 wklReadyCount0 = vm::read128(spurs.addr() + 0x0); - u128 wklReadyCount1 = vm::read128(spurs.addr() + 0x10); - u128 savedC = SPU.ReadLS128(0x1A0); - u128 savedD = SPU.ReadLS128(0x1B0); - u128 vRC = u128::add8(u128::minu8(wklReadyCount0, u128::from8p(8)), u128::minu8(wklReadyCount1, u128::from8p(8))); - u32 wklFlag = spurs->m.wklFlag.flag.read_relaxed(); - u32 flagRecv = spurs->m.wklFlagReceiver.read_relaxed(); - u128 vFM = u128::fromV(g_imm_table.fsmb_table[(wklFlag == 0) && (flagRecv < 16) ? 0x8000 >> flagRecv : 0]); - u128 wklSet1 = u128::fromV(g_imm_table.fsmb_table[spurs->m.wklSignal1.read_relaxed()]); - u128 vFMS1 = vFM | wklSet1; - u128 vFMV1 = u128::fromV(g_imm_table.fsmb_table[(var1 < 16) ? 0x8000 >> var1 : 0]); - u32 var5 = SPU.ReadLS32(0x1ec); - u128 wklMinCnt = vm::read128(spurs.addr() + 0x40); - u128 wklMaxCnt = vm::read128(spurs.addr() + 0x50); - u128 vCC = u128::andnot(vFMS1, u128::eq8(wklReadyCount0, {}) | u128::leu8(vRC, vAABB)) | - u128::leu8(wklMaxCnt, vAABB) | - u128::eq8(savedC, {}) | - u128::fromV(g_imm_table.fsmb_table[(~var5) >> 16]); - u128 vCCH1 = u128::andnot(vCC, - u128::from8p(0x80) & (vFMS1 | u128::gtu8(wklReadyCount0, vAABB)) | - u128::from8p(0x7f) & savedC); - u128 vCCL1 = u128::andnot(vCC, - u128::from8p(0x80) & vFMV1 | - u128::from8p(0x40) & u128::gtu8(vAABB, {}) & u128::gtu8(wklMinCnt, vAABB) | - u128::from8p(0x3c) & u128::fromV(_mm_slli_epi32(u128::sub8(u128::from8p(8), vAABB).vi, 2)) | - u128::from8p(0x02) & u128::eq8(savedD, u128::from8p((u8)var0)) | - u128::from8p(0x01)); - u128 vSTAT = - u128::from8p(0x01) & u128::gtu8(wklReadyCount0, vAABB) | - u128::from8p(0x02) & wklSet1 | - u128::from8p(0x04) & vFM; + contention[i] = mgmt->spurs->m.wklCurrentContention[i] - mgmt->wklLocContention[i]; - for (s32 i = 0, max = -1; i < 0x10; i++) + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) { - const s32 value = ((s32)vCCH1.u8r[i] << 8) | ((s32)vCCL1.u8r[i]); - if (value > max && (vCC.u8r[i] & 1) == 0) + pendingContention[i] = mgmt->spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; + if (i != mgmt->wklCurrentId) { - vNUM = i; - max = value; - } - } - - if (vNUM < 0x10) - { - vRES = ((u64)vNUM << 32) | vSTAT.u8r[vNUM]; - vSET.u8r[vNUM] = 0x01; - } - - SPU.WriteLS8(0x1eb, vNUM == 0x20); - - if (!arg1 || var1 == vNUM) - { - spurs->m.wklSignal1._and_not(be_t::make((u16)(vNUM < 16 ? 0x8000 >> vNUM : 0))); - if (vNUM == flagRecv && wklFlag == 0) - { - spurs->m.wklFlag.flag.write_relaxed(be_t::make(-1)); + contention[i] += pendingContention[i]; } } } - if (arg1 == 0) + u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + u32 pollStatus = 0; + + // The system service workload has the highest priority. Select the system service workload if + // the system service message bit for this SPU is set. + if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - vm::write128(spurs.addr() + 0x20, u128::add8(vAA, vSET)); // update wklA - - SPU.WriteLS128(0x180, vSET); // update savedA - SPU.WriteLS32(0x1dc, vNUM); // update var1 - } - - if (arg1 == 1 && vNUM != var1) - { - vm::write128(spurs.addr() + 0x30, u128::add8(vBB, vSET)); // update wklB - - SPU.WriteLS128(0x190, vSET); // update savedB + // Not sure what this does. Possibly Mark the SPU as in use. + mgmt->x1EB = 0; + if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + // Clear the message bit + mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + } } else { - vm::write128(spurs.addr() + 0x30, vBB); // update wklB + // Caclulate the scheduling weight for each workload + u16 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + u8 x1EC = mgmt->x1EC & (0x8000 >> i); + u8 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); + u8 idleSpuCount = mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); + u8 requestCount = readyCount + idleSpuCount; - SPU.WriteLS128(0x190, {}); // update savedB + // For a workload to be considered for scheduling: + // 1. Its priority must not be 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The bit in 0x1EC for the wokload must be set + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload flag receiver + if (x1EC && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) + { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) + { + // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: + // 1. Wokload signal set or workload flag or ready count > contention + // 2. Priority of the workload on the SPU + // 3. Is the workload the last selected workload + // 4. Minimum contention of the workload + // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) + // 6. Is the workload executable same as the currently loaded executable + // 7. The workload id (lesser the number, more the weight) + u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; + weight |= (u16)(mgmt->priority[i] & 0x7F) << 16; + weight |= i == mgmt->wklCurrentId ? 0x80 : 0x00; + weight |= (contention[i] > 0 && mgmt->spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00; + weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; + weight |= mgmt->wklUniqueId[i] == mgmt->wklCurrentId ? 0x02 : 0x00; + weight |= 0x01; + + // In case of a tie the lower numbered workload is chosen + if (weight > maxWeight) + { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + mgmt->x1EB = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == mgmt->wklCurrentId) + { + // Clear workload signal for the selected workload + mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); + mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) + { + mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + } + } } - return vRES; + if (!isPoll) + { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + contention[wklSelectedId]++; + } + + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + mgmt->spurs->m.wklCurrentContention[i] = contention[i]; + mgmt->wklLocContention[i] = 0; + mgmt->wklLocPendingContention[i] = 0; + } + + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + mgmt->wklLocContention[wklSelectedId] = 1; + } + + mgmt->wklCurrentId = wklSelectedId; + } + else if (wklSelectedId != mgmt->wklCurrentId) + { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + pendingContention[wklSelectedId]++; + } + + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) + { + mgmt->spurs->m.wklPendingContention[i] = pendingContention[i]; + mgmt->wklLocPendingContention[i] = 0; + } + + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + mgmt->wklLocPendingContention[wklSelectedId] = 1; + } + } + + u64 result = (u64)wklSelectedId << 32; + result |= pollStatus; + return result; }; else SPU.m_code3_func = [spurs, num](SPUThread& SPU) -> u64 // second kernel { @@ -324,7 +374,7 @@ s64 spursInit( // to prevent unnecessary jumps to the kernel if (isPoll) { - pendingContention[i] = mgmt->spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; + pendingContention[i] = mgmt->spurs->m.wklPendingContention[i & 0x0F] - mgmt->wklLocPendingContention[i & 0x0F]; pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; if (i != mgmt->wklCurrentId) { @@ -342,7 +392,7 @@ s64 spursInit( { // Not sure what this does. Possibly Mark the SPU as in use. mgmt->x1EB = 0; - if (!isPoll || mgmt->wklCurrentId == 0x20) + if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { // Clear the message bit mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); @@ -350,7 +400,7 @@ s64 spursInit( } else { - // Caclulate the scheduling weight for each worjload + // Caclulate the scheduling weight for each workload u8 maxWeight = 0; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { @@ -360,31 +410,33 @@ s64 spursInit( u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklReadyCount1[j].read_relaxed() : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); - // For a worload to be considered for scheduling: + // For a workload to be considered for scheduling: // 1. Its priority must be greater than 0 // 2. The number of SPUs used by it must be less than the max contention for that workload // 3. The bit in 0x1EC/0x1EE for the wokload must be set // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // Condition #4 may be overriden using a workload signal or using the workload flag + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload receiver if (x1ECx1EE && priority > 0 && maxContention > contention[i]) { - if (wklFlag || wklSignal || mgmt->spurs->m.wklReadyCount[i].read_relaxed() > contention[i]) + if (wklFlag || wklSignal || readyCount > contention[i]) { // The scheduling weight of the workload is equal to the priority of the workload for the SPU. // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. + // In case of a tie the lower numbered workload is chosen. u8 weight = priority << 4; if (mgmt->wklCurrentId == i) { weight |= 0x04; } - // In case of a tie the lower numbered workload is chosen if (weight > maxWeight) { wklSelectedId = i; maxWeight = weight; - pollStatus = mgmt->spurs->m.wklReadyCount[i].read_relaxed() > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; } @@ -432,6 +484,11 @@ s64 spursInit( { // Not called by kernel but a context switch is required // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) + { + pendingContention[wklSelectedId]++; + } + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { mgmt->spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); @@ -471,12 +528,12 @@ s64 spursInit( // get current workload info: auto& wkl = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isSecond ? spurs->m.wklInfo2[wid & 0xf] : spurs->m.wklInfoSysSrv); - if (mgmt->wklCurrentAddr != wkl.pm) + if (mgmt->wklCurrentAddr != wkl.addr) { // load executable code: - memcpy(vm::get_ptr(SPU.ls_offset + 0xa00), wkl.pm.get_ptr(), wkl.size); - mgmt->wklCurrentAddr = wkl.pm; - mgmt->x1D8 = wkl.copy.read_relaxed(); + memcpy(vm::get_ptr(SPU.ls_offset + 0xa00), wkl.addr.get_ptr(), wkl.size); + mgmt->wklCurrentAddr = wkl.addr; + mgmt->wklCurrentUniqueId = wkl.uniqueId.read_relaxed(); } if (!isSecond) SPU.WriteLS16(0x1e8, 0); @@ -484,7 +541,7 @@ s64 spursInit( // run workload: SPU.GPR[1]._u32[3] = 0x3FFB0; SPU.GPR[3]._u32[3] = 0x100; - SPU.GPR[4]._u64[1] = wkl.data; + SPU.GPR[4]._u64[1] = wkl.arg; SPU.GPR[5]._u32[3] = pollStatus; SPU.FastCall(0xa00); @@ -601,7 +658,7 @@ s64 spursInit( spurs->m.wklMaxContention[i].read_relaxed() & 0xf ) { - if (spurs->m.wklReadyCount[i].read_relaxed() || + if (spurs->m.wklReadyCount1[i].read_relaxed() || spurs->m.wklSignal1.read_relaxed() & (0x8000u >> i) || (spurs->m.wklFlag.flag.read_relaxed() == 0 && spurs->m.wklFlagReceiver.read_relaxed() == (u8)i @@ -619,7 +676,7 @@ s64 spursInit( spurs->m.wklMaxContention[i].read_relaxed() & 0xf0 ) { - if (spurs->m.wklReadyCount[i + 0x10].read_relaxed() || + if (spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() || spurs->m.wklSignal2.read_relaxed() & (0x8000u >> i) || (spurs->m.wklFlag.flag.read_relaxed() == 0 && spurs->m.wklFlagReceiver.read_relaxed() == (u8)i + 0x10 @@ -1385,8 +1442,8 @@ s32 spursAddWorkload( spurs->m.wklStat1[wnum].write_relaxed(1); spurs->m.wklD1[wnum] = 0; spurs->m.wklE1[wnum] = 0; - spurs->m.wklInfo1[wnum].pm = pm; - spurs->m.wklInfo1[wnum].data = data; + spurs->m.wklInfo1[wnum].addr = pm; + spurs->m.wklInfo1[wnum].arg = data; spurs->m.wklInfo1[wnum].size = size; spurs->m.wklInfo1[wnum].priority = *(be_t*)priorityTable; spurs->m.wklH1[wnum].nameClass = nameClass; @@ -1401,9 +1458,10 @@ s32 spursAddWorkload( } if ((spurs->m.flags1 & SF1_32_WORKLOADS) == 0) { - spurs->m.wklReadyCount[wnum + 16].write_relaxed(0); + spurs->m.wklIdleSpuCountOrReadyCount2[wnum].write_relaxed(0); spurs->m.wklMinContention[wnum] = minContention > 8 ? 8 : minContention; } + spurs->m.wklReadyCount1[wnum].write_relaxed(0); } else { @@ -1412,8 +1470,8 @@ s32 spursAddWorkload( spurs->m.wklStat2[index].write_relaxed(1); spurs->m.wklD2[index] = 0; spurs->m.wklE2[index] = 0; - spurs->m.wklInfo2[index].pm = pm; - spurs->m.wklInfo2[index].data = data; + spurs->m.wklInfo2[index].addr = pm; + spurs->m.wklInfo2[index].arg = data; spurs->m.wklInfo2[index].size = size; spurs->m.wklInfo2[index].priority = *(be_t*)priorityTable; spurs->m.wklH2[index].nameClass = nameClass; @@ -1426,8 +1484,8 @@ s32 spursAddWorkload( spurs->m.wklF2[index].hookArg = hookArg; spurs->m.wklE2[index] |= 2; } + spurs->m.wklIdleSpuCountOrReadyCount2[wnum].write_relaxed(0); } - spurs->m.wklReadyCount[wnum].write_relaxed(0); if (wnum <= 15) { @@ -1462,21 +1520,21 @@ s32 spursAddWorkload( if (mask & m) { CellSpurs::WorkloadInfo& current = i <= 15 ? spurs->m.wklInfo1[i] : spurs->m.wklInfo2[i & 0xf]; - if (current.pm.addr() == wkl.pm.addr()) + if (current.addr.addr() == wkl.addr.addr()) { // if a workload with identical policy module found - res_wkl = current.copy.read_relaxed(); + res_wkl = current.uniqueId.read_relaxed(); break; } else { - k |= 0x80000000 >> current.copy.read_relaxed(); + k |= 0x80000000 >> current.uniqueId.read_relaxed(); res_wkl = cntlz32(~k); } } } - wkl.copy.exchange((u8)res_wkl); + wkl.uniqueId.exchange((u8)res_wkl); v = mask | (0x80000000u >> wnum); }); assert(res_wkl <= 31); @@ -1818,7 +1876,14 @@ s64 cellSpursReadyCountStore(vm::ptr spurs, u32 wid, u32 value) return CELL_SPURS_POLICY_MODULE_ERROR_STAT; } - spurs->m.wklReadyCount[wid].exchange((u8)value); + if (wid < CELL_SPURS_MAX_WORKLOAD) + { + spurs->m.wklReadyCount1[wid].exchange((u8)value); + } + else + { + spurs->m.wklIdleSpuCountOrReadyCount2[wid].exchange((u8)value); + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 61fcc42648..379679207f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -255,10 +255,10 @@ struct CellSpurs struct WorkloadInfo { - vm::bptr pm; // policy module - be_t data; // spu argument + vm::bptr addr; // Address of the executable + be_t arg; // spu argument be_t size; - atomic_t copy; + atomic_t uniqueId; // The unique id is the same for all workloads with the same addr be_t priority; }; @@ -285,21 +285,22 @@ struct CellSpurs // The SPURS kernel copies this from main memory to the LS (address 0x100) then runs its scheduling algorithm using this as one // of the inputs. After selecting a new workload, the SPURS kernel updates this and writes it back to main memory. // The read-modify-write is performed atomically by the SPURS kernel. - atomic_t wklReadyCount[0x10]; // 0x00 (index = wid) - Number of SPUs requested by each workload - u8 wklCurrentContention[0x10]; // 0x20 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Number of SPUs used by each workload - u8 wklPendingContention[0x10]; // 0x30 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Number of SPUs that are pending to context switch to the workload - u8 wklMinContention[0x10]; // 0x40 (seems only for first 0..15 wids) - Min SPUs required for each workload - atomic_t wklMaxContention[0x10]; // 0x50 (packed 4-bit data, index = wid % 16, internal index = wid / 16) - Max SPUs that may be allocated to each workload - CellSpursWorkloadFlag wklFlag; // 0x60 - atomic_t wklSignal1; // 0x70 (bitset for 0..15 wids) - atomic_t sysSrvMessage; // 0x72 - u8 sysSrvIdling; // 0x73 - u8 flags1; // 0x74 Type is SpursFlags1 - u8 sysSrvTraceControl; // 0x75 - u8 nSpus; // 0x76 - atomic_t wklFlagReceiver; // 0x77 - atomic_t wklSignal2; // 0x78 (bitset for 16..32 wids) - u8 x7A[6]; // 0x7A + atomic_t wklReadyCount1[0x10]; // 0x00 Number of SPUs requested by each workload (0..15 wids). + atomic_t wklIdleSpuCountOrReadyCount2[0x10]; // 0x10 SPURS1: Number of idle SPUs requested by each workload (0..15 wids). SPURS2: Number of SPUs requested by each workload (16..31 wids). + u8 wklCurrentContention[0x10]; // 0x20 Number of SPUs used by each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + u8 wklPendingContention[0x10]; // 0x30 Number of SPUs that are pending to context switch to the workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + u8 wklMinContention[0x10]; // 0x40 Min SPUs required for each workload. SPURS1: index = wid. SPURS2: Unused. + atomic_t wklMaxContention[0x10]; // 0x50 Max SPUs that may be allocated to each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. + CellSpursWorkloadFlag wklFlag; // 0x60 + atomic_t wklSignal1; // 0x70 (bitset for 0..15 wids) + atomic_t sysSrvMessage; // 0x72 + u8 sysSrvIdling; // 0x73 + u8 flags1; // 0x74 Type is SpursFlags1 + u8 sysSrvTraceControl; // 0x75 + u8 nSpus; // 0x76 + atomic_t wklFlagReceiver; // 0x77 + atomic_t wklSignal2; // 0x78 (bitset for 16..32 wids) + u8 x7A[6]; // 0x7A atomic_t wklStat1[0x10]; // 0x80 - Workload state (16*u8) - State enum {non_exitent, preparing, runnable, shutting_down, removable, invalid} u8 wklD1[0x10]; // 0x90 - Workload status (16*u8) u8 wklE1[0x10]; // 0xA0 - Workload event (16*u8) @@ -764,7 +765,7 @@ struct SpursKernelMgmtData { be_t spuNum; // 0x1C8 be_t dmaTagId; // 0x1CC vm::bptr wklCurrentAddr; // 0x1D0 - be_t x1D8; // 0x1D8 + be_t wklCurrentUniqueId; // 0x1D8 u32 wklCurrentId; // 0x1DC be_t yieldToKernelAddr; // 0x1E0 be_t selectWorkloadAddr; // 0x1E4 @@ -774,6 +775,8 @@ struct SpursKernelMgmtData { u8 x1EB; // 0x1EB - This might be spuIdling be_t x1EC; // 0x1EC - This might be wklEnable1 be_t x1EE; // 0x1EE - This might be wklEnable2 + u8 x1F0[0x220 - 0x1F0]; // 0x1F0 + u8 wklUniqueId[0x10]; // 0x220 }; s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); From 66641160422e704616065c717f815c60cb647499 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Thu, 1 Jan 2015 01:51:22 +0530 Subject: [PATCH 09/94] SPURS: System service workload - initial commit --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 251 ++++++++++++++++++++--- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 189 ++++++++++------- rpcs3/cellSpursSpu.cpp | 220 ++++++++++++++++++++ rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 5 files changed, 561 insertions(+), 103 deletions(-) create mode 100644 rpcs3/cellSpursSpu.cpp diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 557ff274ac..bdf0d97101 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -101,7 +101,7 @@ s64 spursInit( } spurs->m.xCC = 0; spurs->m.xCD = 0; - spurs->m.xCE = 0; + spurs->m.sysSrvMsgUpdateTrace = 0; for (u32 i = 0; i < 8; i++) { spurs->m.xC0[i] = -1; @@ -225,8 +225,7 @@ s64 spursInit( // the system service message bit for this SPU is set. if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - // Not sure what this does. Possibly Mark the SPU as in use. - mgmt->x1EB = 0; + mgmt->spuIdling = 0; if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { // Clear the message bit @@ -239,7 +238,7 @@ s64 spursInit( u16 maxWeight = 0; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u8 x1EC = mgmt->x1EC & (0x8000 >> i); + u8 runnable = mgmt->wklRunnable1 & (0x8000 >> i); u8 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); @@ -249,11 +248,11 @@ s64 spursInit( // For a workload to be considered for scheduling: // 1. Its priority must not be 0 // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The bit in 0x1EC for the wokload must be set + // 3. The workload should be in runnable state // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) // OR the workload must be signalled // OR the workload flag is 0 and the workload is configured as the wokload flag receiver - if (x1EC && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) + if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) { if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { @@ -287,7 +286,7 @@ s64 spursInit( } // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->x1EB = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { @@ -391,7 +390,7 @@ s64 spursInit( if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { // Not sure what this does. Possibly Mark the SPU as in use. - mgmt->x1EB = 0; + mgmt->spuIdling = 0; if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { // Clear the message bit @@ -405,7 +404,7 @@ s64 spursInit( for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { auto j = i & 0x0F; - u8 x1ECx1EE = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->x1EC & (0x8000 >> j) : mgmt->x1EE & (0x8000 >> j); + u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); @@ -415,11 +414,11 @@ s64 spursInit( // For a workload to be considered for scheduling: // 1. Its priority must be greater than 0 // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The bit in 0x1EC/0x1EE for the wokload must be set + // 3. The workload should be in runnable state // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) // OR the workload must be signalled // OR the workload flag is 0 and the workload is configured as the wokload receiver - if (x1ECx1EE && priority > 0 && maxContention > contention[i]) + if (runnable && priority > 0 && maxContention > contention[i]) { if (wklFlag || wklSignal || readyCount > contention[i]) { @@ -445,7 +444,7 @@ s64 spursInit( } // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->x1EB = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { @@ -653,7 +652,7 @@ s64 spursInit( bool do_break = false; for (u32 i = 0; i < 16; i++) { - if (spurs->m.wklStat1[i].read_relaxed() == 2 && + if (spurs->m.wklState1[i].read_relaxed() == 2 && spurs->m.wklInfo1[i].priority.ToBE() != 0 && spurs->m.wklMaxContention[i].read_relaxed() & 0xf ) @@ -671,7 +670,7 @@ s64 spursInit( } if (spurs->m.flags1 & SF1_32_WORKLOADS) for (u32 i = 0; i < 16; i++) { - if (spurs->m.wklStat2[i].read_relaxed() == 2 && + if (spurs->m.wklState2[i].read_relaxed() == 2 && spurs->m.wklInfo2[i].priority.ToBE() != 0 && spurs->m.wklMaxContention[i].read_relaxed() & 0xf0 ) @@ -756,7 +755,7 @@ s64 spursInit( } } - spurs->m.unk22 = 0; + spurs->m.traceBuffer = 0; // can also use cellLibprof if available (omitted) // some unknown subroutine @@ -1439,13 +1438,16 @@ s32 spursAddWorkload( { assert((spurs->m.wklCurrentContention[wnum] & 0xf) == 0); assert((spurs->m.wklPendingContention[wnum] & 0xf) == 0); - spurs->m.wklStat1[wnum].write_relaxed(1); - spurs->m.wklD1[wnum] = 0; - spurs->m.wklE1[wnum] = 0; + spurs->m.wklState1[wnum].write_relaxed(1); + spurs->m.wklStatus1[wnum] = 0; + spurs->m.wklEvent1[wnum] = 0; spurs->m.wklInfo1[wnum].addr = pm; spurs->m.wklInfo1[wnum].arg = data; spurs->m.wklInfo1[wnum].size = size; - spurs->m.wklInfo1[wnum].priority = *(be_t*)priorityTable; + for (u32 i = 0; i < 8; i++) + { + spurs->m.wklInfo1[wnum].priority[i] = priorityTable[i]; + } spurs->m.wklH1[wnum].nameClass = nameClass; spurs->m.wklH1[wnum].nameInstance = nameInstance; memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id @@ -1454,7 +1456,7 @@ s32 spursAddWorkload( { spurs->m.wklF1[wnum].hook = hook; spurs->m.wklF1[wnum].hookArg = hookArg; - spurs->m.wklE1[wnum] |= 2; + spurs->m.wklEvent1[wnum] |= 2; } if ((spurs->m.flags1 & SF1_32_WORKLOADS) == 0) { @@ -1467,13 +1469,16 @@ s32 spursAddWorkload( { assert((spurs->m.wklCurrentContention[index] & 0xf0) == 0); assert((spurs->m.wklPendingContention[index] & 0xf0) == 0); - spurs->m.wklStat2[index].write_relaxed(1); - spurs->m.wklD2[index] = 0; - spurs->m.wklE2[index] = 0; + spurs->m.wklState2[index].write_relaxed(1); + spurs->m.wklStatus2[index] = 0; + spurs->m.wklEvent2[index] = 0; spurs->m.wklInfo2[index].addr = pm; spurs->m.wklInfo2[index].arg = data; spurs->m.wklInfo2[index].size = size; - spurs->m.wklInfo2[index].priority = *(be_t*)priorityTable; + for (u32 i = 0; i < 8; i++) + { + spurs->m.wklInfo2[index].priority[i] = priorityTable[i]; + } spurs->m.wklH2[index].nameClass = nameClass; spurs->m.wklH2[index].nameInstance = nameInstance; memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id @@ -1482,7 +1487,7 @@ s32 spursAddWorkload( { spurs->m.wklF2[index].hook = hook; spurs->m.wklF2[index].hookArg = hookArg; - spurs->m.wklE2[index] |= 2; + spurs->m.wklEvent2[index] |= 2; } spurs->m.wklIdleSpuCountOrReadyCount2[wnum].write_relaxed(0); } @@ -1539,8 +1544,8 @@ s32 spursAddWorkload( }); assert(res_wkl <= 31); - spurs->wklStat(wnum).exchange(2); - spurs->m.xBD.exchange(0xff); + spurs->wklState(wnum).exchange(2); + spurs->m.sysSrvMsgUpdateWorkload.exchange(0xff); spurs->m.sysSrvMessage.exchange(0xff); return CELL_OK; } @@ -1871,7 +1876,7 @@ s64 cellSpursReadyCountStore(vm::ptr spurs, u32 wid, u32 value) { return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; } - if (spurs->m.exception.ToBE() || spurs->wklStat(wid).read_relaxed() != 2) + if (spurs->m.exception.ToBE() || spurs->wklState(wid).read_relaxed() != 2) { return CELL_SPURS_POLICY_MODULE_ERROR_STAT; } @@ -3364,6 +3369,190 @@ s64 cellSpursSemaphoreGetTasksetAddress() #endif } +bool spursIsLibProfLoaded() +{ + return false; +} + +void spursTraceStatusUpdate(vm::ptr spurs) +{ + LV2_LOCK(0); + + if (spurs->m.xCC != 0) + { + spurs->m.xCD = 1; + spurs->m.sysSrvMsgUpdateTrace = (1 << spurs->m.nSpus) - 1; + spurs->m.sysSrvMessage.write_relaxed(0xFF); + sys_semaphore_wait(spurs->m.semPrv, 0); + } +} + +s64 spursTraceInitialize(vm::ptr spurs, vm::ptr buffer, u32 size, u32 mode, u32 updateStatus) +{ + if (!spurs || !buffer) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align || buffer.addr() % CellSpursTraceInfo::align) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + if (size < CellSpursTraceInfo::size || mode & ~(CELL_SPURS_TRACE_MODE_FLAG_MASK)) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + + if (spurs->m.traceBuffer != 0) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + spurs->m.traceDataSize = size - CellSpursTraceInfo::size; + for (u32 i = 0; i < 8; i++) + { + buffer->spu_thread[i] = spurs->m.spus[i]; + buffer->count[i] = 0; + } + + buffer->spu_thread_grp = spurs->m.spuTG; + buffer->nspu = spurs->m.nSpus; + spurs->m.traceBuffer = buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0); + spurs->m.traceMode = mode; + + u32 spuTraceDataCount = (spurs->m.traceDataSize / CellSpursTracePacket::size) / spurs->m.nSpus; + for (u32 i = 0, j = 8; i < 6; i++) + { + spurs->m.x908[i] = j; + j += spuTraceDataCount; + } + + spurs->m.sysSrvTraceControl = 0; + if (updateStatus) + { + spursTraceStatusUpdate(spurs); + } + + return CELL_OK; +} + +s64 cellSpursTraceInitialize(vm::ptr spurs, vm::ptr buffer, u32 size, u32 mode) +{ + if (spursIsLibProfLoaded()) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + return spursTraceInitialize(spurs, buffer, size, mode, 1); +} + +s64 spursTraceStart(vm::ptr spurs, u32 updateStatus) +{ + if (!spurs) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + if (!spurs->m.traceBuffer) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + spurs->m.sysSrvTraceControl = 1; + if (updateStatus) + { + spursTraceStatusUpdate(spurs); + } + + return CELL_OK; +} + +s64 cellSpursTraceStart(vm::ptr spurs) +{ + if (!spurs) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + return spursTraceStart(spurs, spurs->m.traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP); +} + +s64 spursTraceStop(vm::ptr spurs, u32 updateStatus) +{ + if (!spurs) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + if (!spurs->m.traceBuffer) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + spurs->m.sysSrvTraceControl = 2; + if (updateStatus) + { + spursTraceStatusUpdate(spurs); + } + + return CELL_OK; +} + +s64 cellSpursTraceStop(vm::ptr spurs) +{ + if (!spurs) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + return spursTraceStop(spurs, spurs->m.traceMode & CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP); +} + +s64 cellSpursTraceFinalize(vm::ptr spurs) +{ + if (!spurs) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + if (!spurs->m.traceBuffer) + { + return CELL_SPURS_CORE_ERROR_STAT; + } + + spurs->m.sysSrvTraceControl = 0; + spurs->m.traceMode = 0; + spurs->m.traceBuffer = 0; + spursTraceStatusUpdate(spurs); + return CELL_OK; +} + void cellSpurs_init(Module *pxThis) { cellSpurs = pxThis; @@ -3521,5 +3710,11 @@ void cellSpurs_init(Module *pxThis) REG_FUNC(cellSpurs, _cellSpursSemaphoreInitialize); REG_FUNC(cellSpurs, cellSpursSemaphoreGetTasksetAddress); + // Trace + REG_FUNC(cellSpurs, cellSpursTraceInitialize); + REG_FUNC(cellSpurs, cellSpursTraceStart); + REG_FUNC(cellSpurs, cellSpursTraceStop); + REG_FUNC(cellSpurs, cellSpursTraceFinalize); + // TODO: some trace funcs } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 379679207f..1307de72e9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -114,34 +114,6 @@ enum RangeofEventQueuePortNumbers CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63, }; -enum SPURSTraceTypes -{ - CELL_SPURS_TRACE_TAG_LOAD = 0x2a, - CELL_SPURS_TRACE_TAG_MAP = 0x2b, - CELL_SPURS_TRACE_TAG_START = 0x2c, - CELL_SPURS_TRACE_TAG_STOP = 0x2d, - CELL_SPURS_TRACE_TAG_USER = 0x2e, - CELL_SPURS_TRACE_TAG_GUID = 0x2f, -}; - -// SPURS task defines. -enum TaskConstants -{ - CELL_SPURS_MAX_TASK = 128, - CELL_SPURS_TASK_TOP = 0x3000, - CELL_SPURS_TASK_BOTTOM = 0x40000, - CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, - CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, - CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, - CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, -}; - -class SPURSManager; -class SPURSManagerEventFlag; -class SPURSManagerTaskset; - -struct CellSpurs; - enum SpursAttrFlags : u32 { SAF_NONE = 0x0, @@ -168,6 +140,68 @@ enum SpursFlags1 : u8 SF1_EXIT_IF_NO_WORK = 0x80, }; +enum SpursWorkloadConstants +{ + // Workload states + SPURS_WKL_STATE_NON_EXISTENT = 0, + SPURS_WKL_STATE_PREPARING = 1, + SPURS_WKL_STATE_RUNNABLE = 2, + SPURS_WKL_STATE_SHUTTING_DOWN = 3, + SPURS_WKL_STATE_REMOVABLE = 4, + SPURS_WKL_STATE_INVALID = 5, +}; + +enum CellSpursModulePollStatus +{ + CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1, + CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2, + CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4 +}; + +enum SpursTraceConstants +{ + // Trace tag types + CELL_SPURS_TRACE_TAG_KERNEL = 0x20, + CELL_SPURS_TRACE_TAG_SERVICE = 0x21, + CELL_SPURS_TRACE_TAG_TASK = 0x22, + CELL_SPURS_TRACE_TAG_JOB = 0x23, + CELL_SPURS_TRACE_TAG_OVIS = 0x24, + CELL_SPURS_TRACE_TAG_LOAD = 0x2a, + CELL_SPURS_TRACE_TAG_MAP = 0x2b, + CELL_SPURS_TRACE_TAG_START = 0x2c, + CELL_SPURS_TRACE_TAG_STOP = 0x2d, + CELL_SPURS_TRACE_TAG_USER = 0x2e, + CELL_SPURS_TRACE_TAG_GUID = 0x2f, + + // Service incident + CELL_SPURS_TRACE_SERVICE_INIT = 0x01, + CELL_SPURS_TRACE_SERVICE_WAIT = 0x02, + CELL_SPURS_TRACE_SERVICE_EXIT = 0x03, + + // Trace mode flags + CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER = 0x1, + CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP = 0x2, + CELL_SPURS_TRACE_MODE_FLAG_MASK = 0x3, +}; + +// SPURS task constants +enum SpursTaskConstants +{ + CELL_SPURS_MAX_TASK = 128, + CELL_SPURS_TASK_TOP = 0x3000, + CELL_SPURS_TASK_BOTTOM = 0x40000, + CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, + CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, + CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, +}; + +class SPURSManager; +class SPURSManagerEventFlag; +class SPURSManagerTaskset; + +struct CellSpurs; + struct CellSpursAttribute { static const uint align = 8; @@ -215,12 +249,6 @@ struct CellSpursWorkloadFlag typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); -enum CellSpursModulePollStatus { - CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT = 1, - CELL_SPURS_MODULE_POLL_STATUS_SIGNAL = 2, - CELL_SPURS_MODULE_POLL_STATUS_FLAG = 4 -}; - // Core CellSpurs structures struct CellSpurs { @@ -259,7 +287,7 @@ struct CellSpurs be_t arg; // spu argument be_t size; atomic_t uniqueId; // The unique id is the same for all workloads with the same addr - be_t priority; + be_t priority[8]; }; static_assert(sizeof(WorkloadInfo) == 0x20, "Wrong WorkloadInfo size"); @@ -294,36 +322,41 @@ struct CellSpurs CellSpursWorkloadFlag wklFlag; // 0x60 atomic_t wklSignal1; // 0x70 (bitset for 0..15 wids) atomic_t sysSrvMessage; // 0x72 - u8 sysSrvIdling; // 0x73 + u8 spuIdling; // 0x73 u8 flags1; // 0x74 Type is SpursFlags1 u8 sysSrvTraceControl; // 0x75 u8 nSpus; // 0x76 atomic_t wklFlagReceiver; // 0x77 atomic_t wklSignal2; // 0x78 (bitset for 16..32 wids) u8 x7A[6]; // 0x7A - atomic_t wklStat1[0x10]; // 0x80 - Workload state (16*u8) - State enum {non_exitent, preparing, runnable, shutting_down, removable, invalid} - u8 wklD1[0x10]; // 0x90 - Workload status (16*u8) - u8 wklE1[0x10]; // 0xA0 - Workload event (16*u8) + atomic_t wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* + u8 wklStatus1[0x10]; // 0x90 + u8 wklEvent1[0x10]; // 0xA0 atomic_t wklMskA; // 0xB0 - System service - Available workloads (32*u1) atomic_t wklMskB; // 0xB4 - System service - Available module id u8 xB8[5]; // 0xB8 - 0xBC - Syetem service exit barrier - atomic_t xBD; // 0xBD - System service message - update workload - u8 xBE[2]; // 0xBE - 0xBF - System service message - terminate + atomic_t sysSrvMsgUpdateWorkload; // 0xBD + u8 xBE[2]; // 0xBE + u8 sysSrvMsgTerminate; // 0xBF u8 xC0[8]; // 0xC0 - System workload - u8 xC8; // 0xC8 - System service - on spu + u8 sysSrvOnSpu; // 0xC8 u8 spuPort; // 0xC9 - SPU port for system service u8 xCA; // 0xCA u8 xCB; // 0xCB u8 xCC; // 0xCC u8 xCD; // 0xCD - u8 xCE; // 0xCE - System service message - update trace + u8 sysSrvMsgUpdateTrace; // 0xCE u8 xCF; // 0xCF - atomic_t wklStat2[0x10]; // 0xD0 - Workload state (16*u8) - u8 wklD2[0x10]; // 0xE0 - Workload status (16*u8) - u8 wklE2[0x10]; // 0xF0 - Workload event (16*u8) + atomic_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* + u8 wklStatus2[0x10]; // 0xE0 + u8 wklEvent2[0x10]; // 0xF0 _sub_str1 wklF1[0x10]; // 0x100 - be_t unk22; // 0x900 - SPURS trace buffer - u8 unknown7[0x980 - 0x908]; // 0x908 - Per SPU trace info ??? (8*u32) 0x950 - SPURS trace mode (u32) + be_t traceBuffer; // 0x900 + be_t x908[6]; // 0x908 - Indices to traceData (a guess) + u8 unknown7[0x948 - 0x920]; // 0x920 + be_t traceDataSize; // 0x948 + be_t traceMode; // 0x950 + u8 unknown8[0x980 - 0x954]; // 0x954 be_t semPrv; // 0x980 be_t unk11; // 0x988 be_t unk12; // 0x98C @@ -371,15 +404,15 @@ struct CellSpurs } c; }; - __forceinline atomic_t& wklStat(const u32 wid) + __forceinline atomic_t& wklState(const u32 wid) { if (wid & 0x10) { - return m.wklStat2[wid & 0xf]; + return m.wklState2[wid & 0xf]; } else { - return m.wklStat1[wid & 0xf]; + return m.wklState1[wid & 0xf]; } } @@ -526,25 +559,21 @@ struct CellSpursExceptionInfo struct CellSpursTraceInfo { - be_t spu_thread[8]; - be_t count[8]; - be_t spu_thread_grp; - be_t nspu; - //u8 padding[]; -}; + static const u32 size = 0x80; + static const u32 align = 16; -struct CellTraceHeader -{ - u8 tag; - u8 length; - u8 cpu; - u8 thread; - be_t time; + be_t spu_thread[8]; // 0x00 + be_t count[8]; // 0x20 + be_t spu_thread_grp; // 0x40 + be_t nspu; // 0x44 + //u8 padding[]; }; struct CellSpursTracePacket { - struct header_struct + static const u32 size = 16; + + struct { u8 tag; u8 length; @@ -553,23 +582,29 @@ struct CellSpursTracePacket be_t time; } header; - struct data_struct + union { - struct load_struct + struct + { + be_t incident; + be_t reserved; + } service; + + struct { be_t ea; be_t ls; be_t size; } load; - struct map_struct + struct { be_t offset; be_t ls; be_t size; } map; - struct start_struct + struct { s8 module[4]; be_t level; @@ -578,6 +613,7 @@ struct CellSpursTracePacket be_t user; be_t guid; + be_t stop; } data; }; @@ -771,12 +807,15 @@ struct SpursKernelMgmtData { be_t selectWorkloadAddr; // 0x1E4 u8 x1E8; // 0x1E8 u8 x1E9; // 0x1E9 - u8 x1EA; // 0x1EA - u8 x1EB; // 0x1EB - This might be spuIdling - be_t x1EC; // 0x1EC - This might be wklEnable1 - be_t x1EE; // 0x1EE - This might be wklEnable2 - u8 x1F0[0x220 - 0x1F0]; // 0x1F0 - u8 wklUniqueId[0x10]; // 0x220 + u8 sysSrvInitialised; // 0x1EA + u8 spuIdling; // 0x1EB + be_t wklRunnable1; // 0x1EC + be_t wklRunnable2; // 0x1EE + u8 x1F0[0x210 - 0x1F0]; // 0x1F0 + be_t traceBuffer; // 0x210 + be_t traceMsgCount; // 0x218 + be_t traceMaxCount; // 0x21C + u8 wklUniqueId[0x10]; // 0x220 }; s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); diff --git a/rpcs3/cellSpursSpu.cpp b/rpcs3/cellSpursSpu.cpp new file mode 100644 index 0000000000..6aad7f7430 --- /dev/null +++ b/rpcs3/cellSpursSpu.cpp @@ -0,0 +1,220 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/System.h" +#include "Emu/Cell/SPUThread.h" +#include "Emu/SysCalls/Modules/cellSpurs.h" + +/// Output trace information +void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag) { + // TODO: Implement this +} + +/// Check for execution right requests +unsigned cellSpursModulePollStatus(CellSpursModulePollStatus * status) { + // TODO: Implement this + return 0; +} + +void spursSysServiceCleanup(SPUThread & spu, SpursKernelMgmtData * mgmt) { + // TODO: Implement this +} + +void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) { + // TODO: Implement this +} + +void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownMask) { + u32 wklNotifyMask = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if (wklShutdownMask & (0x80000000 >> i)) { + mgmt->spurs->m.wklEvent1[i] |= 0x01; + if (mgmt->spurs->m.wklEvent1[i] & 0x02 || mgmt->spurs->m.wklEvent1[i] & 0x10) { + wklNotifyMask |= 0x80000000 >> i; + } + } + } + + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if (wklShutdownMask & (0x8000 >> i)) { + mgmt->spurs->m.wklEvent2[i] |= 0x01; + if (mgmt->spurs->m.wklEvent2[i] & 0x02 || mgmt->spurs->m.wklEvent2[i] & 0x10) { + wklNotifyMask |= 0x8000 >> i; + } + } + } + + if (wklNotifyMask) { + // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 0, wklNotifyMask); + } +} + +/// Update workload information in the LS from main memory +void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) { + u32 wklShutdownMask = 0; + mgmt->wklRunnable1 = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + mgmt->priority[i] = mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum]; + mgmt->wklUniqueId[i] = mgmt->spurs->m.wklInfo1[i].uniqueId.read_relaxed(); + + auto wklStatus = mgmt->spurs->m.wklStatus1[i]; + if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + mgmt->spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum; + mgmt->wklRunnable1 |= 0x8000 >> i; + } else { + mgmt->spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum); + } + + if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && ((mgmt->spurs->m.wklStatus1[i] & (1 << mgmt->spuNum)) == 0)) { + mgmt->spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownMask |= 0x80000000 >> i; + } + } + } + + if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { + mgmt->wklRunnable2 = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if (mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) { + mgmt->priority[i] |= (0x10 - mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) << 4; + } + + auto wklStatus = mgmt->spurs->m.wklStatus2[i]; + if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + mgmt->spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum; + mgmt->wklRunnable2 |= 0x8000 >> i; + } else { + mgmt->spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum); + } + + if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && ((mgmt->spurs->m.wklStatus2[i] & (1 << mgmt->spuNum)) == 0)) { + mgmt->spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownMask |= 0x8000 >> i; + } + } + } + } + + if (wklShutdownMask) { + spursSysServiceUpdateEvent(spu, mgmt, wklShutdownMask); + } +} + +/// Process any messages +void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { + if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { + mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); + spursSysServiceUpdateWorkload(spu, mgmt); + } + + if (mgmt->spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { + spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0); + } + + if (mgmt->spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { + mgmt->spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); + // TODO: Rest of the terminate processing + } +} + +void spursSysServiceExitIfRequired() { + // TODO: Implement this +} + +/// Main function for the system service workload +void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { + auto mgmt = vm::get_ptr(spu.ls_offset); + + if (mgmt->spurs.addr() % CellSpurs::align) { + // TODO: Halt + } + + // Initialise the system service if this is the first time its being started on this SPU + if (mgmt->sysSrvInitialised != 0) { + mgmt->sysSrvInitialised = 1; + + if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { + // TODO: Halt + } + + mgmt->spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; + mgmt->traceBuffer = 0; + mgmt->traceMsgCount = -1; + + spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0); + spursSysServiceCleanup(spu, mgmt); + + // Trace - SERVICE: INIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + } + + // Trace - START: Module='SYS ' + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_START; + memcpy(pkt.data.start.module, "SYS ", 4); + pkt.data.start.level = 1; // Policy module + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + while (true) { + spursSysServiceProcessMessages(spu, mgmt); + + if (cellSpursModulePollStatus(nullptr)) { + // Trace - SERVICE: EXIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + // Trace - STOP: GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = 0; // TODO: Put GUID of the sys service workload here + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + break; + } + + if (mgmt->spuIdling == 0) { + continue; + } + + // Trace - SERVICE: WAIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + spursSysServiceExitIfRequired(); + } +} + +/// Entry point of the system service workload +void spursSysServiceWorkloadEntry(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); + auto arg = spu.GPR[4]._u64[1]; + auto pollStatus = spu.GPR[5]._u32[3]; + + spu.GPR[1]._u32[3] = 0x3FFD0; + *(vm::ptr::make(spu.GPR[1]._u32[3])) = 0x3FFF0; + memset(vm::get_ptr(spu.ls_offset + 0x3FFE0), 0, 32); + + LV2_LOCK(0); + + if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + spursSysServiceWorkloadMain(spu, pollStatus); + } else { + // TODO: If we reach here it means the current workload was preempted to start the + // system service workload. Need to implement this. + } + + // TODO: Ensure that this function always returns to the SPURS kernel + return; +} diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 8e2629cea3..3599cd2cd3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -54,6 +54,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 9335c19690..a1e6732cc9 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -653,6 +653,9 @@ Emu\CPU\ARMv7\Modules + + Emu\SysCalls\Modules + From 4a83d43a8f317c0a5f75ddced3b78f20db84d7e8 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Fri, 2 Jan 2015 01:33:36 +0530 Subject: [PATCH 10/94] SPURS: System service workload --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 10 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 12 +- rpcs3/cellSpursSpu.cpp | 162 ++++++++++++++++++++--- 3 files changed, 159 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index bdf0d97101..4cac04ffad 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -104,7 +104,7 @@ s64 spursInit( spurs->m.sysSrvMsgUpdateTrace = 0; for (u32 i = 0; i < 8; i++) { - spurs->m.xC0[i] = -1; + spurs->m.sysSrvWorkload[i] = -1; } // default or system workload: @@ -755,7 +755,7 @@ s64 spursInit( } } - spurs->m.traceBuffer = 0; + spurs->m.traceBuffer.set(0); // can also use cellLibprof if available (omitted) // some unknown subroutine @@ -3418,13 +3418,13 @@ s64 spursTraceInitialize(vm::ptr spurs, vm::ptr b buffer->spu_thread_grp = spurs->m.spuTG; buffer->nspu = spurs->m.nSpus; - spurs->m.traceBuffer = buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0); + spurs->m.traceBuffer.set(buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0)); spurs->m.traceMode = mode; u32 spuTraceDataCount = (spurs->m.traceDataSize / CellSpursTracePacket::size) / spurs->m.nSpus; for (u32 i = 0, j = 8; i < 6; i++) { - spurs->m.x908[i] = j; + spurs->m.traceStartIndex[i] = j; j += spuTraceDataCount; } @@ -3548,7 +3548,7 @@ s64 cellSpursTraceFinalize(vm::ptr spurs) spurs->m.sysSrvTraceControl = 0; spurs->m.traceMode = 0; - spurs->m.traceBuffer = 0; + spurs->m.traceBuffer.set(0); spursTraceStatusUpdate(spurs); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 1307de72e9..3d817e4a4d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -249,6 +249,8 @@ struct CellSpursWorkloadFlag typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); +struct CellSpursTraceInfo; + // Core CellSpurs structures struct CellSpurs { @@ -336,9 +338,9 @@ struct CellSpurs atomic_t wklMskB; // 0xB4 - System service - Available module id u8 xB8[5]; // 0xB8 - 0xBC - Syetem service exit barrier atomic_t sysSrvMsgUpdateWorkload; // 0xBD - u8 xBE[2]; // 0xBE + u8 xBE; // 0xBE u8 sysSrvMsgTerminate; // 0xBF - u8 xC0[8]; // 0xC0 - System workload + u8 sysSrvWorkload[8]; // 0xC0 u8 sysSrvOnSpu; // 0xC8 u8 spuPort; // 0xC9 - SPU port for system service u8 xCA; // 0xCA @@ -351,8 +353,8 @@ struct CellSpurs u8 wklStatus2[0x10]; // 0xE0 u8 wklEvent2[0x10]; // 0xF0 _sub_str1 wklF1[0x10]; // 0x100 - be_t traceBuffer; // 0x900 - be_t x908[6]; // 0x908 - Indices to traceData (a guess) + vm::bptr traceBuffer; // 0x900 + be_t traceStartIndex[6]; // 0x908 u8 unknown7[0x948 - 0x920]; // 0x920 be_t traceDataSize; // 0x948 be_t traceMode; // 0x950 @@ -810,7 +812,7 @@ struct SpursKernelMgmtData { u8 sysSrvInitialised; // 0x1EA u8 spuIdling; // 0x1EB be_t wklRunnable1; // 0x1EC - be_t wklRunnable2; // 0x1EE + be_t wklRunnable2; // 0x1EE u8 x1F0[0x210 - 0x1F0]; // 0x1F0 be_t traceBuffer; // 0x210 be_t traceMsgCount; // 0x218 diff --git a/rpcs3/cellSpursSpu.cpp b/rpcs3/cellSpursSpu.cpp index 6aad7f7430..33c75e8a44 100644 --- a/rpcs3/cellSpursSpu.cpp +++ b/rpcs3/cellSpursSpu.cpp @@ -15,14 +15,80 @@ unsigned cellSpursModulePollStatus(CellSpursModulePollStatus * status) { return 0; } -void spursSysServiceCleanup(SPUThread & spu, SpursKernelMgmtData * mgmt) { - // TODO: Implement this +/// Restore scheduling paraneters to the right values after a workload has been preempted by the system service workload +void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt) { + if (mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] != -1) { + auto wklId = mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum]; + mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] = -1; + + spursSysServiceUpdateWorkload(spu, mgmt); + if (wklId >= CELL_SPURS_MAX_WORKLOAD) { + mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; + mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); + } else { + mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; + mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); + } + + auto wklIdSaved = mgmt->wklCurrentId; + mgmt->wklCurrentId = wklId; + + // Trace - STOP: GUID + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = 0; // TODO: Put GUID of the sys service workload here + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + mgmt->wklCurrentId = wklIdSaved; + } } +/// Updatre the trace count for this SPU in CellSpurs +void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt) { + if (mgmt->traceBuffer) { + mgmt->spurs->m.traceBuffer->count[mgmt->spuNum] = mgmt->traceMsgCount; + } +} + +/// Update trace control in SPU from CellSpurs void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) { - // TODO: Implement this + auto sysSrvMsgUpdateTrace = mgmt->spurs->m.sysSrvMsgUpdateTrace; + mgmt->spurs->m.sysSrvMsgUpdateTrace &= ~(1 << mgmt->spuNum); + mgmt->spurs->m.xCC &= ~(1 << mgmt->spuNum); + mgmt->spurs->m.xCC |= arg2 << mgmt->spuNum; + + bool notify = false; + if ((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum) != 0) && (mgmt->spurs->m.sysSrvMsgUpdateTrace == 0) && (mgmt->spurs->m.xCD != 0)) { + mgmt->spurs->m.xCD = 0; + notify = true; + } + + if (arg4 && mgmt->spurs->m.xCD != 0) { + mgmt->spurs->m.xCD = 0; + notify = true; + } + + if ((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum) != 0) || (arg3 != 0)) { + if (mgmt->traceMsgCount != 0xFF || mgmt->traceBuffer == 0 || mgmt->spurs->m.traceBuffer.addr() == 0) { + spursSysServiceUpdateTraceCount(spu, mgmt); + } else { + mgmt->traceMsgCount = mgmt->spurs->m.traceBuffer->count[mgmt->spuNum]; + } + + mgmt->traceBuffer = mgmt->spurs->m.traceBuffer.addr() + (mgmt->spurs->m.traceStartIndex[mgmt->spuNum] << 4); + mgmt->traceMaxCount = mgmt->spurs->m.traceStartIndex[1] - mgmt->spurs->m.traceStartIndex[0]; + if (mgmt->traceBuffer == 0) { + mgmt->traceMsgCount = 0; + } + } + + if (notify) { + // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 2, 0); + } } +/// Update events in CellSpurs void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownMask) { u32 wklNotifyMask = 0; for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { @@ -48,7 +114,7 @@ void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 } } -/// Update workload information in the LS from main memory +/// Update workload information in the SPU LS from CellSpurs void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) { u32 wklShutdownMask = 0; mgmt->wklRunnable1 = 0; @@ -65,7 +131,7 @@ void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) } if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && ((mgmt->spurs->m.wklStatus1[i] & (1 << mgmt->spuNum)) == 0)) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus1[i] == 0)) { mgmt->spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); wklShutdownMask |= 0x80000000 >> i; } @@ -88,7 +154,7 @@ void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) } if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && ((mgmt->spurs->m.wklStatus2[i] & (1 << mgmt->spuNum)) == 0)) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus2[i] == 0)) { mgmt->spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); wklShutdownMask |= 0x8000 >> i; } @@ -103,23 +169,82 @@ void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) /// Process any messages void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { + // Process update workload message if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); spursSysServiceUpdateWorkload(spu, mgmt); } + // Process update trace message if (mgmt->spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0); } + // Process terminate request if (mgmt->spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { mgmt->spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); // TODO: Rest of the terminate processing } } -void spursSysServiceExitIfRequired() { - // TODO: Implement this +/// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled +void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { + while (true) { + u32 nIdlingSpus = 0; + for (u32 i = 0; i < 8; i++) { + if (mgmt->spurs->m.spuIdling & (1 << i)) { + nIdlingSpus++; + } + } + + bool shouldExit = nIdlingSpus != mgmt->spurs->m.nSpus ? false : mgmt->spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; + bool foundSchedulableWorkload = false; + if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + foundSchedulableWorkload = true; + } else { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if ((mgmt->wklRunnable1 & (0x8000 >> i)) && + (mgmt->priority[i] & 0x0F) != 0 && + (mgmt->spurs->m.wklMaxContention[i].read_relaxed() & 0x0F) > (mgmt->spurs->m.wklCurrentContention[i] & 0x0F)) { + foundSchedulableWorkload = true; + break; + } + } + + if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS && foundSchedulableWorkload == false) { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if ((mgmt->wklRunnable2 & (0x8000 >> i)) && + (mgmt->priority[i] & 0xF0) != 0 && + (mgmt->spurs->m.wklMaxContention[i].read_relaxed() & 0xF0) > (mgmt->spurs->m.wklCurrentContention[i] & 0xF0)) { + foundSchedulableWorkload = true; + break; + } + } + } + } + + if ((mgmt->spurs->m.spuIdling & (1 << mgmt->spuNum)) && shouldExit == false && foundSchedulableWorkload == false) { + // TODO: Wait for events + } + + if (shouldExit || foundSchedulableWorkload == false) { + mgmt->spurs->m.spuIdling |= 1 << mgmt->spuNum; + } else { + mgmt->spurs->m.spuIdling &= ~(1 << mgmt->spuNum); + } + + if (shouldExit == false && foundSchedulableWorkload == false) { + continue; + } + + if (shouldExit == false) { + return; + } + + break; + } + + // TODO: exit spu thread group } /// Main function for the system service workload @@ -127,15 +252,15 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { auto mgmt = vm::get_ptr(spu.ls_offset); if (mgmt->spurs.addr() % CellSpurs::align) { - // TODO: Halt + assert(0); } // Initialise the system service if this is the first time its being started on this SPU - if (mgmt->sysSrvInitialised != 0) { + if (mgmt->sysSrvInitialised == 0) { mgmt->sysSrvInitialised = 1; if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { - // TODO: Halt + assert(0); } mgmt->spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; @@ -143,7 +268,7 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { mgmt->traceMsgCount = -1; spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0); - spursSysServiceCleanup(spu, mgmt); + spursSysServiceCleanupAfterPreemption(spu, mgmt); // Trace - SERVICE: INIT CellSpursTracePacket pkt; @@ -163,8 +288,10 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); while (true) { + // Process messages for the system service workload spursSysServiceProcessMessages(spu, mgmt); +poll: if (cellSpursModulePollStatus(nullptr)) { // Trace - SERVICE: EXIT CellSpursTracePacket pkt; @@ -181,10 +308,16 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { break; } + // If we reach here it means that either there are more system service messages to be processed + // or there are no workloads that can be scheduled. + + // If the SPU is not idling then process the remaining system service messages if (mgmt->spuIdling == 0) { continue; } + // If we reach here it means that the SPU is idling + // Trace - SERVICE: WAIT CellSpursTracePacket pkt; memset(&pkt, 0, sizeof(pkt)); @@ -192,7 +325,8 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - spursSysServiceExitIfRequired(); + spursSysServiceWaitOrExit(spu, mgmt); + goto poll; } } @@ -206,8 +340,6 @@ void spursSysServiceWorkloadEntry(SPUThread & spu) { *(vm::ptr::make(spu.GPR[1]._u32[3])) = 0x3FFF0; memset(vm::get_ptr(spu.ls_offset + 0x3FFE0), 0, 32); - LV2_LOCK(0); - if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { spursSysServiceWorkloadMain(spu, pollStatus); } else { From c1df79b7139f21faa0de83bceaa602f3fed46ed9 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 3 Jan 2015 15:59:22 +0530 Subject: [PATCH 11/94] SPURS: Integrate SPURS kernel and system service workload. Also, fixed some bugs. --- rpcs3/Emu/Cell/SPUThread.cpp | 2 +- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 403 +--------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 193 +++-- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 786 ++++++++++++++++++++ rpcs3/cellSpursSpu.cpp | 352 --------- rpcs3/emucore.vcxproj | 2 +- rpcs3/emucore.vcxproj.filters | 2 +- 8 files changed, 897 insertions(+), 845 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp delete mode 100644 rpcs3/cellSpursSpu.cpp diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 719cdc8cab..bc6d1d681f 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1029,7 +1029,7 @@ void SPUThread::StopAndSignal(u32 code) case 0x003: { - GPR[3]._u64[1] = m_code3_func(*this); + m_code3_func(*this); break; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index e7c28ed8ff..4bebaf1baf 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -511,7 +511,7 @@ public: void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); } std::function m_custom_task; - std::function m_code3_func; + std::function m_code3_func; public: SPUThread(CPUThreadType type = CPU_THREAD_SPU); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 4cac04ffad..343ca9ecbb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -21,6 +21,8 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif +void spursKernelMain(SPUThread & spu); + s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr port, s32 size, u64 name_u64) { #ifdef PRX_DEBUG_XXX @@ -112,7 +114,7 @@ s64 spursInit( spurs->m.wklInfoSysSrv.addr.set(be_t::make(vm::read32(libsre_rtoc - 0x7EA4))); spurs->m.wklInfoSysSrv.size = 0x2200; #else - spurs->m.wklInfoSysSrv.addr.set(be_t::make(0x100)); // wrong 64-bit address + spurs->m.wklInfoSysSrv.addr.set(be_t::make(SPURS_IMG_ADDR_SYS_SRV_WORKLOAD)); #endif spurs->m.wklInfoSysSrv.arg = 0; spurs->m.wklInfoSysSrv.uniqueId.write_relaxed(0xff); @@ -170,399 +172,16 @@ s64 spursInit( name += "CellSpursKernel0"; for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) { - spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num, isSecond](SPUThread& SPU) + spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num](SPUThread& SPU) { -#ifdef PRX_DEBUG_XXX SPU.GPR[3]._u32[3] = num; SPU.GPR[4]._u64[1] = spurs.addr(); + +#ifdef PRX_DEBUG_XXX return SPU.FastCall(SPU.PC); #endif - // code replacement: - { - const u32 addr = /*SPU.ReadLS32(0x1e0) +*/ 8; //SPU.ReadLS32(0x1e4); - SPU.WriteLS32(addr + 0, 3); // hack for cellSpursModulePollStatus - SPU.WriteLS32(addr + 4, 0x35000000); // bi $0 - SPU.WriteLS32(0x1e4, addr); - - SPU.WriteLS32(SPU.ReadLS32(0x1e0), 2); // hack for cellSpursModuleExit - } - - if (!isSecond) SPU.m_code3_func = [spurs, num](SPUThread& SPU) -> u64 // first kernel - { - LV2_LOCK(0); // TODO: lock-free implementation if possible - - auto mgmt = vm::get_ptr(SPU.ls_offset); - - // The first and only argument to this function is a boolean that is set to false if the function - // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. - // If the first argument is true then the shared data is not updated with the result. - const auto isPoll = SPU.GPR[3]._u32[3]; - - // Calculate the contention (number of SPUs used) for each workload - u8 contention[CELL_SPURS_MAX_WORKLOAD]; - u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) - { - contention[i] = mgmt->spurs->m.wklCurrentContention[i] - mgmt->wklLocContention[i]; - - // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably - // to prevent unnecessary jumps to the kernel - if (isPoll) - { - pendingContention[i] = mgmt->spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; - if (i != mgmt->wklCurrentId) - { - contention[i] += pendingContention[i]; - } - } - } - - u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - u32 pollStatus = 0; - - // The system service workload has the highest priority. Select the system service workload if - // the system service message bit for this SPU is set. - if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) - { - mgmt->spuIdling = 0; - if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - // Clear the message bit - mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); - } - } - else - { - // Caclulate the scheduling weight for each workload - u16 maxWeight = 0; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) - { - u8 runnable = mgmt->wklRunnable1 & (0x8000 >> i); - u8 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); - u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); - u8 idleSpuCount = mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); - u8 requestCount = readyCount + idleSpuCount; - - // For a workload to be considered for scheduling: - // 1. Its priority must not be 0 - // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The workload should be in runnable state - // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // OR the workload must be signalled - // OR the workload flag is 0 and the workload is configured as the wokload flag receiver - if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) - { - if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) - { - // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: - // 1. Wokload signal set or workload flag or ready count > contention - // 2. Priority of the workload on the SPU - // 3. Is the workload the last selected workload - // 4. Minimum contention of the workload - // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) - // 6. Is the workload executable same as the currently loaded executable - // 7. The workload id (lesser the number, more the weight) - u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; - weight |= (u16)(mgmt->priority[i] & 0x7F) << 16; - weight |= i == mgmt->wklCurrentId ? 0x80 : 0x00; - weight |= (contention[i] > 0 && mgmt->spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00; - weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; - weight |= mgmt->wklUniqueId[i] == mgmt->wklCurrentId ? 0x02 : 0x00; - weight |= 0x01; - - // In case of a tie the lower numbered workload is chosen - if (weight > maxWeight) - { - wklSelectedId = i; - maxWeight = weight; - pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; - pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; - pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; - } - } - } - } - - // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - - if (!isPoll || wklSelectedId == mgmt->wklCurrentId) - { - // Clear workload signal for the selected workload - mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); - mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); - - // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s - if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) - { - mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); - } - } - } - - if (!isPoll) - { - // Called by kernel - // Increment the contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - contention[wklSelectedId]++; - } - - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) - { - mgmt->spurs->m.wklCurrentContention[i] = contention[i]; - mgmt->wklLocContention[i] = 0; - mgmt->wklLocPendingContention[i] = 0; - } - - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - mgmt->wklLocContention[wklSelectedId] = 1; - } - - mgmt->wklCurrentId = wklSelectedId; - } - else if (wklSelectedId != mgmt->wklCurrentId) - { - // Not called by kernel but a context switch is required - // Increment the pending contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - pendingContention[wklSelectedId]++; - } - - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) - { - mgmt->spurs->m.wklPendingContention[i] = pendingContention[i]; - mgmt->wklLocPendingContention[i] = 0; - } - - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - mgmt->wklLocPendingContention[wklSelectedId] = 1; - } - } - - u64 result = (u64)wklSelectedId << 32; - result |= pollStatus; - return result; - }; - else SPU.m_code3_func = [spurs, num](SPUThread& SPU) -> u64 // second kernel - { - LV2_LOCK(0); // TODO: lock-free implementation if possible - - auto mgmt = vm::get_ptr(SPU.ls_offset); - - // The first and only argument to this function is a boolean that is set to false if the function - // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. - // If the first argument is true then the shared data is not updated with the result. - const auto isPoll = SPU.GPR[3]._u32[3]; - - // Calculate the contention (number of SPUs used) for each workload - u8 contention[CELL_SPURS_MAX_WORKLOAD2]; - u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) - { - contention[i] = mgmt->spurs->m.wklCurrentContention[i & 0x0F] - mgmt->wklLocContention[i & 0x0F]; - contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; - - // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably - // to prevent unnecessary jumps to the kernel - if (isPoll) - { - pendingContention[i] = mgmt->spurs->m.wklPendingContention[i & 0x0F] - mgmt->wklLocPendingContention[i & 0x0F]; - pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; - if (i != mgmt->wklCurrentId) - { - contention[i] += pendingContention[i]; - } - } - } - - u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - u32 pollStatus = 0; - - // The system service workload has the highest priority. Select the system service workload if - // the system service message bit for this SPU is set. - if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) - { - // Not sure what this does. Possibly Mark the SPU as in use. - mgmt->spuIdling = 0; - if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - // Clear the message bit - mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); - } - } - else - { - // Caclulate the scheduling weight for each workload - u8 maxWeight = 0; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) - { - auto j = i & 0x0F; - u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); - u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; - u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; - u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); - u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklReadyCount1[j].read_relaxed() : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); - - // For a workload to be considered for scheduling: - // 1. Its priority must be greater than 0 - // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The workload should be in runnable state - // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // OR the workload must be signalled - // OR the workload flag is 0 and the workload is configured as the wokload receiver - if (runnable && priority > 0 && maxContention > contention[i]) - { - if (wklFlag || wklSignal || readyCount > contention[i]) - { - // The scheduling weight of the workload is equal to the priority of the workload for the SPU. - // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. - // In case of a tie the lower numbered workload is chosen. - u8 weight = priority << 4; - if (mgmt->wklCurrentId == i) - { - weight |= 0x04; - } - - if (weight > maxWeight) - { - wklSelectedId = i; - maxWeight = weight; - pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; - pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; - pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; - } - } - } - } - - // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - - if (!isPoll || wklSelectedId == mgmt->wklCurrentId) - { - // Clear workload signal for the selected workload - mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); - mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); - - // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s - if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) - { - mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); - } - } - } - - if (!isPoll) - { - // Called by kernel - // Increment the contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - contention[wklSelectedId]++; - } - - for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) - { - mgmt->spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); - mgmt->wklLocContention[i] = 0; - mgmt->wklLocPendingContention[i] = 0; - } - - mgmt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - mgmt->wklCurrentId = wklSelectedId; - } - else if (wklSelectedId != mgmt->wklCurrentId) - { - // Not called by kernel but a context switch is required - // Increment the pending contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) - { - pendingContention[wklSelectedId]++; - } - - for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) - { - mgmt->spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); - mgmt->wklLocPendingContention[i] = 0; - } - - mgmt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - } - - u64 result = (u64)wklSelectedId << 32; - result |= pollStatus; - return result; - }; - //SPU.m_code3_func = [spurs, num](SPUThread& SPU) -> u64 // test - //{ - // LV2_LOCK(0); - // SPU.FastCall(0x290); - // u64 vRES = SPU.GPR[3]._u64[1]; - // return vRES; - //}; - - SpursKernelMgmtData * mgmt = vm::get_ptr(SPU.ls_offset); - mgmt->spurs = spurs; - mgmt->spuNum = num; - mgmt->dmaTagId = 0x1F; - - u32 wid = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - u32 pollStatus = 0; - while (true) - { - if (Emu.IsStopped()) - { - cellSpurs->Warning("Spurs Kernel aborted"); - return; - } - - // get current workload info: - auto& wkl = wid < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isSecond ? spurs->m.wklInfo2[wid & 0xf] : spurs->m.wklInfoSysSrv); - - if (mgmt->wklCurrentAddr != wkl.addr) - { - // load executable code: - memcpy(vm::get_ptr(SPU.ls_offset + 0xa00), wkl.addr.get_ptr(), wkl.size); - mgmt->wklCurrentAddr = wkl.addr; - mgmt->wklCurrentUniqueId = wkl.uniqueId.read_relaxed(); - } - - if (!isSecond) SPU.WriteLS16(0x1e8, 0); - - // run workload: - SPU.GPR[1]._u32[3] = 0x3FFB0; - SPU.GPR[3]._u32[3] = 0x100; - SPU.GPR[4]._u64[1] = wkl.arg; - SPU.GPR[5]._u32[3] = pollStatus; - SPU.FastCall(0xa00); - - // check status: - auto status = SPU.SPU.Status.GetValue(); - if (status == SPU_STATUS_STOPPED_BY_STOP) - { - return; - } - else - { - assert(status == SPU_STATUS_RUNNING); - } - - // get workload id: - SPU.GPR[3].clear(); - assert(SPU.m_code3_func); - u64 res = SPU.m_code3_func(SPU); - pollStatus = (u32)(res); - wid = (u32)(res >> 32); - } - + spursKernelMain(SPU); })->GetId(); } @@ -653,7 +272,7 @@ s64 spursInit( for (u32 i = 0; i < 16; i++) { if (spurs->m.wklState1[i].read_relaxed() == 2 && - spurs->m.wklInfo1[i].priority.ToBE() != 0 && + *((u64 *)spurs->m.wklInfo1[i].priority) != 0 && spurs->m.wklMaxContention[i].read_relaxed() & 0xf ) { @@ -671,7 +290,7 @@ s64 spursInit( if (spurs->m.flags1 & SF1_32_WORKLOADS) for (u32 i = 0; i < 16; i++) { if (spurs->m.wklState2[i].read_relaxed() == 2 && - spurs->m.wklInfo2[i].priority.ToBE() != 0 && + *((u64 *)spurs->m.wklInfo2[i].priority) != 0 && spurs->m.wklMaxContention[i].read_relaxed() & 0xf0 ) { @@ -3383,7 +3002,7 @@ void spursTraceStatusUpdate(vm::ptr spurs) spurs->m.xCD = 1; spurs->m.sysSrvMsgUpdateTrace = (1 << spurs->m.nSpus) - 1; spurs->m.sysSrvMessage.write_relaxed(0xFF); - sys_semaphore_wait(spurs->m.semPrv, 0); + sys_semaphore_wait((u32)spurs->m.semPrv, 0); } } @@ -3421,7 +3040,7 @@ s64 spursTraceInitialize(vm::ptr spurs, vm::ptr b spurs->m.traceBuffer.set(buffer.addr() | (mode & CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER ? 1 : 0)); spurs->m.traceMode = mode; - u32 spuTraceDataCount = (spurs->m.traceDataSize / CellSpursTracePacket::size) / spurs->m.nSpus; + u32 spuTraceDataCount = (u32)((spurs->m.traceDataSize / CellSpursTracePacket::size) / spurs->m.nSpus); for (u32 i = 0, j = 8; i < 6; i++) { spurs->m.traceStartIndex[i] = j; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 3d817e4a4d..771406b3af 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -140,7 +140,7 @@ enum SpursFlags1 : u8 SF1_EXIT_IF_NO_WORK = 0x80, }; -enum SpursWorkloadConstants +enum SpursWorkloadConstants : u64 { // Workload states SPURS_WKL_STATE_NON_EXISTENT = 0, @@ -149,6 +149,12 @@ enum SpursWorkloadConstants SPURS_WKL_STATE_SHUTTING_DOWN = 3, SPURS_WKL_STATE_REMOVABLE = 4, SPURS_WKL_STATE_INVALID = 5, + + // GUID + SPURS_GUID_SYS_WKL = 0x1BB841BF38F89D33ull, + + // Image addresses + SPURS_IMG_ADDR_SYS_SRV_WORKLOAD = 0x100, }; enum CellSpursModulePollStatus @@ -199,7 +205,6 @@ enum SpursTaskConstants class SPURSManager; class SPURSManagerEventFlag; class SPURSManagerTaskset; - struct CellSpurs; struct CellSpursAttribute @@ -249,7 +254,65 @@ struct CellSpursWorkloadFlag typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); -struct CellSpursTraceInfo; +struct CellSpursTraceInfo +{ + static const u32 size = 0x80; + static const u32 align = 16; + + be_t spu_thread[8]; // 0x00 + be_t count[8]; // 0x20 + be_t spu_thread_grp; // 0x40 + be_t nspu; // 0x44 + //u8 padding[]; +}; + +struct CellSpursTracePacket +{ + static const u32 size = 16; + + struct + { + u8 tag; + u8 length; + u8 spu; + u8 workload; + be_t time; + } header; + + union + { + struct + { + be_t incident; + be_t reserved; + } service; + + struct + { + be_t ea; + be_t ls; + be_t size; + } load; + + struct + { + be_t offset; + be_t ls; + be_t size; + } map; + + struct + { + s8 module[4]; + be_t level; + be_t ls; + } start; + + be_t user; + be_t guid; + be_t stop; + } data; +}; // Core CellSpurs structures struct CellSpurs @@ -289,7 +352,7 @@ struct CellSpurs be_t arg; // spu argument be_t size; atomic_t uniqueId; // The unique id is the same for all workloads with the same addr - be_t priority[8]; + u8 priority[8]; }; static_assert(sizeof(WorkloadInfo) == 0x20, "Wrong WorkloadInfo size"); @@ -311,10 +374,6 @@ struct CellSpurs // real data struct { - // The first 0x80 bytes of the CellSpurs structure is shared by all instances of the SPURS kernel in a SPURS instance and the PPU. - // The SPURS kernel copies this from main memory to the LS (address 0x100) then runs its scheduling algorithm using this as one - // of the inputs. After selecting a new workload, the SPURS kernel updates this and writes it back to main memory. - // The read-modify-write is performed atomically by the SPURS kernel. atomic_t wklReadyCount1[0x10]; // 0x00 Number of SPUs requested by each workload (0..15 wids). atomic_t wklIdleSpuCountOrReadyCount2[0x10]; // 0x10 SPURS1: Number of idle SPUs requested by each workload (0..15 wids). SPURS2: Number of SPUs requested by each workload (16..31 wids). u8 wklCurrentContention[0x10]; // 0x20 Number of SPUs used by each workload. SPURS1: index = wid. SPURS2: packed 4-bit data, index = wid % 16, internal index = wid / 16. @@ -332,33 +391,34 @@ struct CellSpurs atomic_t wklSignal2; // 0x78 (bitset for 16..32 wids) u8 x7A[6]; // 0x7A atomic_t wklState1[0x10]; // 0x80 SPURS_WKL_STATE_* - u8 wklStatus1[0x10]; // 0x90 - u8 wklEvent1[0x10]; // 0xA0 - atomic_t wklMskA; // 0xB0 - System service - Available workloads (32*u1) - atomic_t wklMskB; // 0xB4 - System service - Available module id - u8 xB8[5]; // 0xB8 - 0xBC - Syetem service exit barrier - atomic_t sysSrvMsgUpdateWorkload; // 0xBD - u8 xBE; // 0xBE - u8 sysSrvMsgTerminate; // 0xBF - u8 sysSrvWorkload[8]; // 0xC0 - u8 sysSrvOnSpu; // 0xC8 - u8 spuPort; // 0xC9 - SPU port for system service - u8 xCA; // 0xCA - u8 xCB; // 0xCB - u8 xCC; // 0xCC - u8 xCD; // 0xCD - u8 sysSrvMsgUpdateTrace; // 0xCE - u8 xCF; // 0xCF - atomic_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* - u8 wklStatus2[0x10]; // 0xE0 - u8 wklEvent2[0x10]; // 0xF0 - _sub_str1 wklF1[0x10]; // 0x100 - vm::bptr traceBuffer; // 0x900 - be_t traceStartIndex[6]; // 0x908 - u8 unknown7[0x948 - 0x920]; // 0x920 - be_t traceDataSize; // 0x948 - be_t traceMode; // 0x950 - u8 unknown8[0x980 - 0x954]; // 0x954 + u8 wklStatus1[0x10]; // 0x90 + u8 wklEvent1[0x10]; // 0xA0 + atomic_t wklMskA; // 0xB0 - System service - Available workloads (32*u1) + atomic_t wklMskB; // 0xB4 - System service - Available module id + u32 xB8; // 0xB8 + u8 sysSrvExitBarrier; // 0xBC + atomic_t sysSrvMsgUpdateWorkload; // 0xBD + u8 xBE; // 0xBE + u8 sysSrvMsgTerminate; // 0xBF + u8 sysSrvWorkload[8]; // 0xC0 + u8 sysSrvOnSpu; // 0xC8 + u8 spuPort; // 0xC9 + u8 xCA; // 0xCA + u8 xCB; // 0xCB + u8 xCC; // 0xCC + u8 xCD; // 0xCD + u8 sysSrvMsgUpdateTrace; // 0xCE + u8 xCF; // 0xCF + atomic_t wklState2[0x10]; // 0xD0 SPURS_WKL_STATE_* + u8 wklStatus2[0x10]; // 0xE0 + u8 wklEvent2[0x10]; // 0xF0 + _sub_str1 wklF1[0x10]; // 0x100 + vm::bptr traceBuffer; // 0x900 + be_t traceStartIndex[6]; // 0x908 + u8 unknown7[0x948 - 0x920]; // 0x920 + be_t traceDataSize; // 0x948 + be_t traceMode; // 0x950 + u8 unknown8[0x980 - 0x954]; // 0x954 be_t semPrv; // 0x980 be_t unk11; // 0x988 be_t unk12; // 0x98C @@ -559,66 +619,6 @@ struct CellSpursExceptionInfo be_t option; }; -struct CellSpursTraceInfo -{ - static const u32 size = 0x80; - static const u32 align = 16; - - be_t spu_thread[8]; // 0x00 - be_t count[8]; // 0x20 - be_t spu_thread_grp; // 0x40 - be_t nspu; // 0x44 - //u8 padding[]; -}; - -struct CellSpursTracePacket -{ - static const u32 size = 16; - - struct - { - u8 tag; - u8 length; - u8 spu; - u8 workload; - be_t time; - } header; - - union - { - struct - { - be_t incident; - be_t reserved; - } service; - - struct - { - be_t ea; - be_t ls; - be_t size; - } load; - - struct - { - be_t offset; - be_t ls; - be_t size; - } map; - - struct - { - s8 module[4]; - be_t level; - be_t ls; - } start; - - be_t user; - be_t guid; - be_t stop; - } data; -}; - // Exception handlers. //typedef void (*CellSpursGlobalExceptionEventHandler)(vm::ptr spurs, vm::ptr info, // u32 id, vm::ptr arg); @@ -793,7 +793,6 @@ struct CellSpursTaskBinInfo // The SPURS kernel data store. This resides at 0x00 of the LS. struct SpursKernelMgmtData { - u8 unk0[0x100]; // 0x00 u8 tempArea[0x80]; // 0x100 u8 wklLocContention[0x10]; // 0x180 u8 wklLocPendingContention[0x10]; // 0x190 @@ -804,7 +803,7 @@ struct SpursKernelMgmtData { be_t dmaTagId; // 0x1CC vm::bptr wklCurrentAddr; // 0x1D0 be_t wklCurrentUniqueId; // 0x1D8 - u32 wklCurrentId; // 0x1DC + be_t wklCurrentId; // 0x1DC be_t yieldToKernelAddr; // 0x1E0 be_t selectWorkloadAddr; // 0x1E4 u8 x1E8; // 0x1E8 diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp new file mode 100644 index 0000000000..643aed981c --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -0,0 +1,786 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/System.h" +#include "Emu/Cell/SPUThread.h" +#include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Modules/cellSpurs.h" + +// +// SPURS utility functions +// +void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag); +u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status); + +// +// SPURS Kernel functions +// +void spursKernelSelectWorkload(SPUThread & spu); +void spursKernelSelectWorkload2(SPUThread & spu); + +// +// SPURS system service workload functions +// +void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt); +void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt); +void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4); +void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownBitSet); +void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt); +void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt); +void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt); +void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus); +void spursSysServiceWorkloadEntry(SPUThread & spu); + +extern Module *cellSpurs; + +////////////////////////////////////////////////////////////////////////////// +// SPURS utility functions +////////////////////////////////////////////////////////////////////////////// + +/// Output trace information +void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag) { + // TODO: Implement this +} + +/// Check for execution right requests +u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + + spu.GPR[3]._u32[3] = 1; + if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { + spursKernelSelectWorkload2(spu); + } else { + spursKernelSelectWorkload(spu); + } + + auto result = spu.GPR[3]._u64[1]; + if (status) { + *status = (u32)result; + } + + u32 wklId = result >> 32; + return wklId == mgmt->wklCurrentId ? 0 : 1; +} + +////////////////////////////////////////////////////////////////////////////// +// SPURS kernel functions +////////////////////////////////////////////////////////////////////////////// + +/// Select a workload to run +void spursKernelSelectWorkload(SPUThread & spu) { + LV2_LOCK(0); // TODO: lock-free implementation if possible + + auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + + // The first and only argument to this function is a boolean that is set to false if the function + // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. + // If the first argument is true then the shared data is not updated with the result. + const auto isPoll = spu.GPR[3]._u32[3]; + + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + contention[i] = mgmt->spurs->m.wklCurrentContention[i] - mgmt->wklLocContention[i]; + + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) { + pendingContention[i] = mgmt->spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; + if (i != mgmt->wklCurrentId) { + contention[i] += pendingContention[i]; + } + } + } + + u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + u32 pollStatus = 0; + + // The system service workload has the highest priority. Select the system service workload if + // the system service message bit for this SPU is set. + if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + mgmt->spuIdling = 0; + if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + // Clear the message bit + mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + } + } else { + // Caclulate the scheduling weight for each workload + u16 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + u16 runnable = mgmt->wklRunnable1 & (0x8000 >> i); + u16 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); + u8 idleSpuCount = mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); + u8 requestCount = readyCount + idleSpuCount; + + // For a workload to be considered for scheduling: + // 1. Its priority must not be 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The workload should be in runnable state + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload flag receiver + if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { + // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: + // 1. Wokload signal set or workload flag or ready count > contention + // 2. Priority of the workload on the SPU + // 3. Is the workload the last selected workload + // 4. Minimum contention of the workload + // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) + // 6. Is the workload executable same as the currently loaded executable + // 7. The workload id (lesser the number, more the weight) + u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; + weight |= (u16)(mgmt->priority[i] & 0x7F) << 16; + weight |= i == mgmt->wklCurrentId ? 0x80 : 0x00; + weight |= (contention[i] > 0 && mgmt->spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00; + weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; + weight |= mgmt->wklUniqueId[i] == mgmt->wklCurrentId ? 0x02 : 0x00; + weight |= 0x01; + + // In case of a tie the lower numbered workload is chosen + if (weight > maxWeight) { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { + // Clear workload signal for the selected workload + mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); + mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) { + mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + } + } + } + + if (!isPoll) { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + contention[wklSelectedId]++; + } + + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + mgmt->spurs->m.wklCurrentContention[i] = contention[i]; + mgmt->wklLocContention[i] = 0; + mgmt->wklLocPendingContention[i] = 0; + } + + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + mgmt->wklLocContention[wklSelectedId] = 1; + } + + mgmt->wklCurrentId = wklSelectedId; + } else if (wklSelectedId != mgmt->wklCurrentId) { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + pendingContention[wklSelectedId]++; + } + + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + mgmt->spurs->m.wklPendingContention[i] = pendingContention[i]; + mgmt->wklLocPendingContention[i] = 0; + } + + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + mgmt->wklLocPendingContention[wklSelectedId] = 1; + } + } + + u64 result = (u64)wklSelectedId << 32; + result |= pollStatus; + spu.GPR[3]._u64[1] = result; +} + +/// Select a workload to run +void spursKernelSelectWorkload2(SPUThread & spu) { + LV2_LOCK(0); // TODO: lock-free implementation if possible + + auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + + // The first and only argument to this function is a boolean that is set to false if the function + // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. + // If the first argument is true then the shared data is not updated with the result. + const auto isPoll = spu.GPR[3]._u32[3]; + + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD2]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { + contention[i] = mgmt->spurs->m.wklCurrentContention[i & 0x0F] - mgmt->wklLocContention[i & 0x0F]; + contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; + + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) { + pendingContention[i] = mgmt->spurs->m.wklPendingContention[i & 0x0F] - mgmt->wklLocPendingContention[i & 0x0F]; + pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; + if (i != mgmt->wklCurrentId) { + contention[i] += pendingContention[i]; + } + } + } + + u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + u32 pollStatus = 0; + + // The system service workload has the highest priority. Select the system service workload if + // the system service message bit for this SPU is set. + if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + // Not sure what this does. Possibly Mark the SPU as in use. + mgmt->spuIdling = 0; + if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + // Clear the message bit + mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + } + } else { + // Caclulate the scheduling weight for each workload + u8 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { + auto j = i & 0x0F; + u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; + u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklReadyCount1[j].read_relaxed() : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); + + // For a workload to be considered for scheduling: + // 1. Its priority must be greater than 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The workload should be in runnable state + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload receiver + if (runnable && priority > 0 && maxContention > contention[i]) { + if (wklFlag || wklSignal || readyCount > contention[i]) { + // The scheduling weight of the workload is equal to the priority of the workload for the SPU. + // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. + // In case of a tie the lower numbered workload is chosen. + u8 weight = priority << 4; + if (mgmt->wklCurrentId == i) { + weight |= 0x04; + } + + if (weight > maxWeight) { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { + // Clear workload signal for the selected workload + mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); + mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) { + mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + } + } + } + + if (!isPoll) { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + contention[wklSelectedId]++; + } + + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { + mgmt->spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); + mgmt->wklLocContention[i] = 0; + mgmt->wklLocPendingContention[i] = 0; + } + + mgmt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + mgmt->wklCurrentId = wklSelectedId; + } else if (wklSelectedId != mgmt->wklCurrentId) { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + pendingContention[wklSelectedId]++; + } + + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { + mgmt->spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); + mgmt->wklLocPendingContention[i] = 0; + } + + mgmt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + } + + u64 result = (u64)wklSelectedId << 32; + result |= pollStatus; + spu.GPR[3]._u64[1] = result; +} + +/// Entry point of the SPURS kernel +void spursKernelMain(SPUThread & spu) { + SpursKernelMgmtData * mgmt = vm::get_ptr(spu.ls_offset + 0x100); + mgmt->spuNum = spu.GPR[3]._u32[3]; + mgmt->dmaTagId = 0x1F; + mgmt->spurs.set(spu.GPR[4]._u64[1]); + mgmt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + mgmt->wklCurrentUniqueId = 0x20; + + bool isSecond = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; + mgmt->yieldToKernelAddr = isSecond ? 0x838 : 0x808; + mgmt->selectWorkloadAddr = 0x290; + spu.WriteLS32(mgmt->yieldToKernelAddr, 2); // hack for cellSpursModuleExit + spu.WriteLS32(mgmt->selectWorkloadAddr, 3); // hack for cellSpursModulePollStatus + spu.WriteLS32(mgmt->selectWorkloadAddr + 4, 0x35000000); // bi $0 + spu.m_code3_func = isSecond ? spursKernelSelectWorkload2 : spursKernelSelectWorkload; + + u32 wid = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + u32 pollStatus = 0; + while (true) { + if (Emu.IsStopped()) { + cellSpurs->Warning("Spurs Kernel aborted"); + return; + } + + // Get current workload info + auto & wkl = wid < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isSecond ? mgmt->spurs->m.wklInfo2[wid & 0xf] : mgmt->spurs->m.wklInfoSysSrv); + + if (mgmt->wklCurrentAddr != wkl.addr) { + if (wkl.addr.addr() != SPURS_IMG_ADDR_SYS_SRV_WORKLOAD) { + // Load executable code + memcpy(vm::get_ptr(spu.ls_offset + 0xA00), wkl.addr.get_ptr(), wkl.size); + } + mgmt->wklCurrentAddr = wkl.addr; + mgmt->wklCurrentUniqueId = wkl.uniqueId.read_relaxed(); + } + + if (!isSecond) { + mgmt->x1E8 = 0; + mgmt->x1E9 = 0; + } + + // Run workload + spu.GPR[1]._u32[3] = 0x3FFB0; + spu.GPR[3]._u32[3] = 0x100; + spu.GPR[4]._u64[1] = wkl.arg; + spu.GPR[5]._u32[3] = pollStatus; + switch (mgmt->wklCurrentAddr.addr()) { + case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: + spursSysServiceWorkloadEntry(spu); + break; + default: + spu.FastCall(0xA00); + break; + } + + // Check status + auto status = spu.SPU.Status.GetValue(); + if (status == SPU_STATUS_STOPPED_BY_STOP) { + return; + } else { + assert(status == SPU_STATUS_RUNNING); + } + + // Select next workload to run + spu.GPR[3].clear(); + if (isSecond) { + spursKernelSelectWorkload2(spu); + } else { + spursKernelSelectWorkload(spu); + } + u64 res = spu.GPR[3]._u64[1]; + pollStatus = (u32)(res); + wid = (u32)(res >> 32); + } +} + +////////////////////////////////////////////////////////////////////////////// +// SPURS system workload functions +////////////////////////////////////////////////////////////////////////////// + +/// Restore scheduling parameters after a workload has been preempted by the system service workload +void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt) { + if (mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] != 0xFF) { + auto wklId = mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum]; + mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] = 0xFF; + + spursSysServiceUpdateWorkload(spu, mgmt); + if (wklId >= CELL_SPURS_MAX_WORKLOAD) { + mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; + mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); + } else { + mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; + mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); + } + + // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace + // uses the current worload id to determine the workload to which the trace belongs + auto wklIdSaved = mgmt->wklCurrentId; + mgmt->wklCurrentId = wklId; + + // Trace - STOP: GUID + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + mgmt->wklCurrentId = wklIdSaved; + } +} + +/// Update the trace count for this SPU in CellSpurs +void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt) { + if (mgmt->traceBuffer) { + auto traceInfo = vm::ptr::make((u32)(mgmt->traceBuffer - (mgmt->spurs->m.traceStartIndex[mgmt->spuNum] << 4))); + traceInfo->count[mgmt->spuNum] = mgmt->traceMsgCount; + } +} + +/// Update trace control in SPU from CellSpurs +void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) { + auto sysSrvMsgUpdateTrace = mgmt->spurs->m.sysSrvMsgUpdateTrace; + mgmt->spurs->m.sysSrvMsgUpdateTrace &= ~(1 << mgmt->spuNum); + mgmt->spurs->m.xCC &= ~(1 << mgmt->spuNum); + mgmt->spurs->m.xCC |= arg2 << mgmt->spuNum; + + bool notify = false; + if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.sysSrvMsgUpdateTrace == 0) && (mgmt->spurs->m.xCD != 0)) { + mgmt->spurs->m.xCD = 0; + notify = true; + } + + if (arg4 && mgmt->spurs->m.xCD != 0) { + mgmt->spurs->m.xCD = 0; + notify = true; + } + + // Get trace parameters from CellSpurs and store them in the LS + if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) || (arg3 != 0)) { + if (mgmt->traceMsgCount != 0xFF || mgmt->spurs->m.traceBuffer.addr() == 0) { + spursSysServiceUpdateTraceCount(spu, mgmt); + } else { + mgmt->traceMsgCount = mgmt->spurs->m.traceBuffer->count[mgmt->spuNum]; + } + + mgmt->traceBuffer = mgmt->spurs->m.traceBuffer.addr() + (mgmt->spurs->m.traceStartIndex[mgmt->spuNum] << 4); + mgmt->traceMaxCount = mgmt->spurs->m.traceStartIndex[1] - mgmt->spurs->m.traceStartIndex[0]; + if (mgmt->traceBuffer == 0) { + mgmt->traceMsgCount = 0; + } + } + + if (notify) { + // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 2, 0); + } +} + +/// Update events in CellSpurs +void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownBitSet) { + // Mark the workloads in wklShutdownBitSet as completed and also generate a bit set of the completed + // workloads that have a shutdown completion hook registered + u32 wklNotifyBitSet = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if (wklShutdownBitSet & (0x80000000u >> i)) { + mgmt->spurs->m.wklEvent1[i] |= 0x01; + if (mgmt->spurs->m.wklEvent1[i] & 0x02 || mgmt->spurs->m.wklEvent1[i] & 0x10) { + wklNotifyBitSet |= 0x80000000u >> i; + } + } + + if (wklShutdownBitSet & (0x8000 >> i)) { + mgmt->spurs->m.wklEvent2[i] |= 0x01; + if (mgmt->spurs->m.wklEvent2[i] & 0x02 || mgmt->spurs->m.wklEvent2[i] & 0x10) { + wklNotifyBitSet |= 0x8000 >> i; + } + } + } + + if (wklNotifyBitSet) { + // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 0, wklNotifyMask); + } +} + +/// Update workload information in the SPU from CellSpurs +void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) { + u32 wklShutdownBitSet = 0; + mgmt->wklRunnable1 = 0; + mgmt->wklRunnable2 = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + // Copy the priority of the workload for this SPU and its unique id to the LS + mgmt->priority[i] = mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum]; + mgmt->wklUniqueId[i] = mgmt->spurs->m.wklInfo1[i].uniqueId.read_relaxed(); + + // Update workload status and runnable flag based on the workload state + auto wklStatus = mgmt->spurs->m.wklStatus1[i]; + if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + mgmt->spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum; + mgmt->wklRunnable1 |= 0x8000 >> i; + } else { + mgmt->spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus1[i] == 0)) { + mgmt->spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownBitSet |= 0x80000000u >> i; + } + } + + if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { + // Copy the priority of the workload for this SPU to the LS + if (mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) { + mgmt->priority[i] |= (0x10 - mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) << 4; + } + + // Update workload status and runnable flag based on the workload state + wklStatus = mgmt->spurs->m.wklStatus2[i]; + if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + mgmt->spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum; + mgmt->wklRunnable2 |= 0x8000 >> i; + } else { + mgmt->spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus2[i] == 0)) { + mgmt->spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownBitSet |= 0x8000 >> i; + } + } + } + } + + if (wklShutdownBitSet) { + spursSysServiceUpdateEvent(spu, mgmt, wklShutdownBitSet); + } +} + +/// Process any messages +void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { + // Process update workload message + if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { + mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); + spursSysServiceUpdateWorkload(spu, mgmt); + } + + // Process update trace message + if (mgmt->spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { + spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0); + } + + // Process terminate request + if (mgmt->spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { + mgmt->spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); + // TODO: Rest of the terminate processing + } +} + +/// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled +void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { + while (true) { + // Find the number of SPUs that are idling in this SPURS instance + u32 nIdlingSpus = 0; + for (u32 i = 0; i < 8; i++) { + if (mgmt->spurs->m.spuIdling & (1 << i)) { + nIdlingSpus++; + } + } + + bool allSpusIdle = nIdlingSpus == mgmt->spurs->m.nSpus ? true: false; + bool exitIfNoWork = mgmt->spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; + + // Check if any workloads can be scheduled + bool foundReadyWorkload = false; + if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + foundReadyWorkload = true; + } else { + if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { + u32 j = i & 0x0F; + u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; + u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklCurrentContention[j] & 0x0F : mgmt->spurs->m.wklCurrentContention[j] >> 4; + u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklReadyCount1[j].read_relaxed() : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); + + if (runnable && priority > 0 && maxContention > contention) { + if (wklFlag || wklSignal || readyCount > contention) { + foundReadyWorkload = true; + break; + } + } + } + } else { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + u8 runnable = mgmt->wklRunnable1 & (0x8000 >> i); + u8 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); + u8 idleSpuCount = mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); + u8 requestCount = readyCount + idleSpuCount; + + if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > mgmt->spurs->m.wklCurrentContention[i]) { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > mgmt->spurs->m.wklCurrentContention[i])) { + foundReadyWorkload = true; + break; + } + } + } + } + } + + // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. + if ((mgmt->spurs->m.spuIdling & (1 << mgmt->spuNum)) && (allSpusIdle == false || exitIfNoWork == false) && foundReadyWorkload == false) { + // The system service blocks by making a reservation and waiting on the reservation lost event. This is unfortunately + // not yet completely implemented in rpcs3. So we busy wait here. + //u128 r; + //spu.ReadChannel(r, 0); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + if ((allSpusIdle == true && exitIfNoWork == true) || foundReadyWorkload == false) { + mgmt->spurs->m.spuIdling |= 1 << mgmt->spuNum; + } else { + mgmt->spurs->m.spuIdling &= ~(1 << mgmt->spuNum); + } + + if (allSpusIdle == false || exitIfNoWork == false) { + if (foundReadyWorkload == true) { + return; + } + } else { + // TODO: exit spu thread group + } + } +} + +/// Main function for the system service workload +void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + + if (mgmt->spurs.addr() % CellSpurs::align) { + assert(0); + } + + // Initialise the system service if this is the first time its being started on this SPU + if (mgmt->sysSrvInitialised == 0) { + mgmt->sysSrvInitialised = 1; + + if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { + assert(0); + } + + mgmt->spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; + mgmt->traceBuffer = 0; + mgmt->traceMsgCount = -1; + + spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0); + spursSysServiceCleanupAfterPreemption(spu, mgmt); + + // Trace - SERVICE: INIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + } + + // Trace - START: Module='SYS ' + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_START; + memcpy(pkt.data.start.module, "SYS ", 4); + pkt.data.start.level = 1; // Policy module + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + while (true) { + // Process messages for the system service workload + spursSysServiceProcessMessages(spu, mgmt); + +poll: + if (cellSpursModulePollStatus(spu, nullptr)) { + // Trace - SERVICE: EXIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + // Trace - STOP: GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + break; + } + + // If we reach here it means that either there are more system service messages to be processed + // or there are no workloads that can be scheduled. + + // If the SPU is not idling then process the remaining system service messages + if (mgmt->spuIdling == 0) { + continue; + } + + // If we reach here it means that the SPU is idling + + // Trace - SERVICE: WAIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + spursSysServiceWaitOrExit(spu, mgmt); + goto poll; + } +} + +/// Entry point of the system service workload +void spursSysServiceWorkloadEntry(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); + auto arg = spu.GPR[4]._u64[1]; + auto pollStatus = spu.GPR[5]._u32[3]; + + spu.GPR[1]._u32[3] = 0x3FFD0; + *(vm::ptr::make(spu.GPR[1]._u32[3])) = 0x3FFF0; + memset(vm::get_ptr(spu.ls_offset + 0x3FFE0), 0, 32); + + if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + spursSysServiceWorkloadMain(spu, pollStatus); + } else { + // TODO: If we reach here it means the current workload was preempted to start the + // system service workload. Need to implement this. + } + + // TODO: Ensure that this function always returns to the SPURS kernel + return; +} diff --git a/rpcs3/cellSpursSpu.cpp b/rpcs3/cellSpursSpu.cpp deleted file mode 100644 index 33c75e8a44..0000000000 --- a/rpcs3/cellSpursSpu.cpp +++ /dev/null @@ -1,352 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/System.h" -#include "Emu/Cell/SPUThread.h" -#include "Emu/SysCalls/Modules/cellSpurs.h" - -/// Output trace information -void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag) { - // TODO: Implement this -} - -/// Check for execution right requests -unsigned cellSpursModulePollStatus(CellSpursModulePollStatus * status) { - // TODO: Implement this - return 0; -} - -/// Restore scheduling paraneters to the right values after a workload has been preempted by the system service workload -void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt) { - if (mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] != -1) { - auto wklId = mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum]; - mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] = -1; - - spursSysServiceUpdateWorkload(spu, mgmt); - if (wklId >= CELL_SPURS_MAX_WORKLOAD) { - mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; - mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); - } else { - mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; - mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); - } - - auto wklIdSaved = mgmt->wklCurrentId; - mgmt->wklCurrentId = wklId; - - // Trace - STOP: GUID - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = 0; // TODO: Put GUID of the sys service workload here - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - mgmt->wklCurrentId = wklIdSaved; - } -} - -/// Updatre the trace count for this SPU in CellSpurs -void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt) { - if (mgmt->traceBuffer) { - mgmt->spurs->m.traceBuffer->count[mgmt->spuNum] = mgmt->traceMsgCount; - } -} - -/// Update trace control in SPU from CellSpurs -void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) { - auto sysSrvMsgUpdateTrace = mgmt->spurs->m.sysSrvMsgUpdateTrace; - mgmt->spurs->m.sysSrvMsgUpdateTrace &= ~(1 << mgmt->spuNum); - mgmt->spurs->m.xCC &= ~(1 << mgmt->spuNum); - mgmt->spurs->m.xCC |= arg2 << mgmt->spuNum; - - bool notify = false; - if ((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum) != 0) && (mgmt->spurs->m.sysSrvMsgUpdateTrace == 0) && (mgmt->spurs->m.xCD != 0)) { - mgmt->spurs->m.xCD = 0; - notify = true; - } - - if (arg4 && mgmt->spurs->m.xCD != 0) { - mgmt->spurs->m.xCD = 0; - notify = true; - } - - if ((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum) != 0) || (arg3 != 0)) { - if (mgmt->traceMsgCount != 0xFF || mgmt->traceBuffer == 0 || mgmt->spurs->m.traceBuffer.addr() == 0) { - spursSysServiceUpdateTraceCount(spu, mgmt); - } else { - mgmt->traceMsgCount = mgmt->spurs->m.traceBuffer->count[mgmt->spuNum]; - } - - mgmt->traceBuffer = mgmt->spurs->m.traceBuffer.addr() + (mgmt->spurs->m.traceStartIndex[mgmt->spuNum] << 4); - mgmt->traceMaxCount = mgmt->spurs->m.traceStartIndex[1] - mgmt->spurs->m.traceStartIndex[0]; - if (mgmt->traceBuffer == 0) { - mgmt->traceMsgCount = 0; - } - } - - if (notify) { - // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 2, 0); - } -} - -/// Update events in CellSpurs -void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownMask) { - u32 wklNotifyMask = 0; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if (wklShutdownMask & (0x80000000 >> i)) { - mgmt->spurs->m.wklEvent1[i] |= 0x01; - if (mgmt->spurs->m.wklEvent1[i] & 0x02 || mgmt->spurs->m.wklEvent1[i] & 0x10) { - wklNotifyMask |= 0x80000000 >> i; - } - } - } - - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if (wklShutdownMask & (0x8000 >> i)) { - mgmt->spurs->m.wklEvent2[i] |= 0x01; - if (mgmt->spurs->m.wklEvent2[i] & 0x02 || mgmt->spurs->m.wklEvent2[i] & 0x10) { - wklNotifyMask |= 0x8000 >> i; - } - } - } - - if (wklNotifyMask) { - // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 0, wklNotifyMask); - } -} - -/// Update workload information in the SPU LS from CellSpurs -void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) { - u32 wklShutdownMask = 0; - mgmt->wklRunnable1 = 0; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - mgmt->priority[i] = mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum]; - mgmt->wklUniqueId[i] = mgmt->spurs->m.wklInfo1[i].uniqueId.read_relaxed(); - - auto wklStatus = mgmt->spurs->m.wklStatus1[i]; - if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { - mgmt->spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum; - mgmt->wklRunnable1 |= 0x8000 >> i; - } else { - mgmt->spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum); - } - - if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus1[i] == 0)) { - mgmt->spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); - wklShutdownMask |= 0x80000000 >> i; - } - } - } - - if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { - mgmt->wklRunnable2 = 0; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if (mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) { - mgmt->priority[i] |= (0x10 - mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) << 4; - } - - auto wklStatus = mgmt->spurs->m.wklStatus2[i]; - if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { - mgmt->spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum; - mgmt->wklRunnable2 |= 0x8000 >> i; - } else { - mgmt->spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum); - } - - if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus2[i] == 0)) { - mgmt->spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); - wklShutdownMask |= 0x8000 >> i; - } - } - } - } - - if (wklShutdownMask) { - spursSysServiceUpdateEvent(spu, mgmt, wklShutdownMask); - } -} - -/// Process any messages -void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { - // Process update workload message - if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { - mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); - spursSysServiceUpdateWorkload(spu, mgmt); - } - - // Process update trace message - if (mgmt->spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { - spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0); - } - - // Process terminate request - if (mgmt->spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { - mgmt->spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); - // TODO: Rest of the terminate processing - } -} - -/// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled -void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { - while (true) { - u32 nIdlingSpus = 0; - for (u32 i = 0; i < 8; i++) { - if (mgmt->spurs->m.spuIdling & (1 << i)) { - nIdlingSpus++; - } - } - - bool shouldExit = nIdlingSpus != mgmt->spurs->m.nSpus ? false : mgmt->spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; - bool foundSchedulableWorkload = false; - if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - foundSchedulableWorkload = true; - } else { - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if ((mgmt->wklRunnable1 & (0x8000 >> i)) && - (mgmt->priority[i] & 0x0F) != 0 && - (mgmt->spurs->m.wklMaxContention[i].read_relaxed() & 0x0F) > (mgmt->spurs->m.wklCurrentContention[i] & 0x0F)) { - foundSchedulableWorkload = true; - break; - } - } - - if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS && foundSchedulableWorkload == false) { - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if ((mgmt->wklRunnable2 & (0x8000 >> i)) && - (mgmt->priority[i] & 0xF0) != 0 && - (mgmt->spurs->m.wklMaxContention[i].read_relaxed() & 0xF0) > (mgmt->spurs->m.wklCurrentContention[i] & 0xF0)) { - foundSchedulableWorkload = true; - break; - } - } - } - } - - if ((mgmt->spurs->m.spuIdling & (1 << mgmt->spuNum)) && shouldExit == false && foundSchedulableWorkload == false) { - // TODO: Wait for events - } - - if (shouldExit || foundSchedulableWorkload == false) { - mgmt->spurs->m.spuIdling |= 1 << mgmt->spuNum; - } else { - mgmt->spurs->m.spuIdling &= ~(1 << mgmt->spuNum); - } - - if (shouldExit == false && foundSchedulableWorkload == false) { - continue; - } - - if (shouldExit == false) { - return; - } - - break; - } - - // TODO: exit spu thread group -} - -/// Main function for the system service workload -void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { - auto mgmt = vm::get_ptr(spu.ls_offset); - - if (mgmt->spurs.addr() % CellSpurs::align) { - assert(0); - } - - // Initialise the system service if this is the first time its being started on this SPU - if (mgmt->sysSrvInitialised == 0) { - mgmt->sysSrvInitialised = 1; - - if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { - assert(0); - } - - mgmt->spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; - mgmt->traceBuffer = 0; - mgmt->traceMsgCount = -1; - - spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0); - spursSysServiceCleanupAfterPreemption(spu, mgmt); - - // Trace - SERVICE: INIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - } - - // Trace - START: Module='SYS ' - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_START; - memcpy(pkt.data.start.module, "SYS ", 4); - pkt.data.start.level = 1; // Policy module - pkt.data.start.ls = 0xA00 >> 2; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - while (true) { - // Process messages for the system service workload - spursSysServiceProcessMessages(spu, mgmt); - -poll: - if (cellSpursModulePollStatus(nullptr)) { - // Trace - SERVICE: EXIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - // Trace - STOP: GUID - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = 0; // TODO: Put GUID of the sys service workload here - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - break; - } - - // If we reach here it means that either there are more system service messages to be processed - // or there are no workloads that can be scheduled. - - // If the SPU is not idling then process the remaining system service messages - if (mgmt->spuIdling == 0) { - continue; - } - - // If we reach here it means that the SPU is idling - - // Trace - SERVICE: WAIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - spursSysServiceWaitOrExit(spu, mgmt); - goto poll; - } -} - -/// Entry point of the system service workload -void spursSysServiceWorkloadEntry(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); - auto arg = spu.GPR[4]._u64[1]; - auto pollStatus = spu.GPR[5]._u32[3]; - - spu.GPR[1]._u32[3] = 0x3FFD0; - *(vm::ptr::make(spu.GPR[1]._u32[3])) = 0x3FFF0; - memset(vm::get_ptr(spu.ls_offset + 0x3FFE0), 0, 32); - - if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - spursSysServiceWorkloadMain(spu, pollStatus); - } else { - // TODO: If we reach here it means the current workload was preempted to start the - // system service workload. Need to implement this. - } - - // TODO: Ensure that this function always returns to the SPURS kernel - return; -} diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 3599cd2cd3..dbac3af5be 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -54,7 +54,7 @@ - + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index a1e6732cc9..3166265186 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -653,7 +653,7 @@ Emu\CPU\ARMv7\Modules - + Emu\SysCalls\Modules From b01c17d1a0048e71fb232c462e0c20430255720f Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Mon, 5 Jan 2015 21:54:03 +0530 Subject: [PATCH 12/94] SPURS: Add locks in the system service workload --- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 2d696666aa..06ff2553be 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -585,6 +585,8 @@ void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) /// Process any messages void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { + LV2_LOCK(0); + // Process update workload message if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); @@ -606,6 +608,8 @@ void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) /// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { while (true) { + Emu.GetCoreMutex().lock(); + // Find the number of SPUs that are idling in this SPURS instance u32 nIdlingSpus = 0; for (u32 i = 0; i < 8; i++) { @@ -665,7 +669,10 @@ void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { // not yet completely implemented in rpcs3. So we busy wait here. //u128 r; //spu.ReadChannel(r, 0); + + Emu.GetCoreMutex().unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); + Emu.GetCoreMutex().lock(); } if ((allSpusIdle == true && exitIfNoWork == true) || foundReadyWorkload == false) { @@ -674,6 +681,8 @@ void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { mgmt->spurs->m.spuIdling &= ~(1 << mgmt->spuNum); } + Emu.GetCoreMutex().unlock(); + if (allSpusIdle == false || exitIfNoWork == false) { if (foundReadyWorkload == true) { return; @@ -696,6 +705,7 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { if (mgmt->sysSrvInitialised == 0) { mgmt->sysSrvInitialised = 1; + LV2_LOCK(0); if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { assert(0); } From 17f34f512777cc56b923beb18316722d47227dea Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Wed, 21 Jan 2015 00:47:20 +0530 Subject: [PATCH 13/94] SPURS: Implement cellSpursSendSignal, cellSpursSendWorkloadSignal and some cellSpursEventFlag functions --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 370 +++++++++++++++++++++-- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 59 +++- 2 files changed, 399 insertions(+), 30 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 10c2348d4b..a9a50e2bbe 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1460,13 +1460,63 @@ s64 cellSpursGetWorkloadFlag(vm::ptr spurs, vm::ptr spurs, u32 workloadId) { + cellSpurs->Warning("%s(spurs=0x%x, workloadId=0x%x)", __FUNCTION__, spurs.addr(), workloadId); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0xA658, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!spurs) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + if (workloadId >= CELL_SPURS_MAX_WORKLOAD2 || (workloadId >= CELL_SPURS_MAX_WORKLOAD && (spurs->m.flags1 & SF1_32_WORKLOADS) == 0)) + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + + if ((spurs->m.wklMskA.read_relaxed() & (0x80000000u >> workloadId)) == 0) + { + return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; + } + + if (spurs->m.exception) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + u8 state; + if (workloadId >= CELL_SPURS_MAX_WORKLOAD) + { + state = spurs->m.wklState2[workloadId & 0x0F].read_relaxed(); + } + else + { + state = spurs->m.wklState1[workloadId].read_relaxed(); + } + + if (state != SPURS_WKL_STATE_RUNNABLE) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + // TODO: Make the below block execute atomically + if (workloadId >= CELL_SPURS_MAX_WORKLOAD) + { + spurs->m.wklSignal2 |= be_t::make(0x8000 >> (workloadId & 0x0F)); + } + else + { + spurs->m.wklSignal1 |= be_t::make(0x8000 >> workloadId); + } + return CELL_OK; #endif } @@ -1611,64 +1661,250 @@ s64 cellSpursUnsetExceptionEventHandler() s64 _cellSpursEventFlagInitialize(vm::ptr spurs, vm::ptr taskset, vm::ptr eventFlag, u32 flagClearMode, u32 flagDirection) { -#ifdef PRX_DEBUG cellSpurs->Warning("_cellSpursEventFlagInitialize(spurs_addr=0x%x, taskset_addr=0x%x, eventFlag_addr=0x%x, flagClearMode=%d, flagDirection=%d)", spurs.addr(), taskset.addr(), eventFlag.addr(), flagClearMode, flagDirection); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1564C, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (taskset.addr() == 0 || spurs.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align || taskset.addr() % CellSpursTaskset::align || eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (taskset.addr() && taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD2) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + if (flagDirection > CELL_SPURS_EVENT_FLAG_LAST || flagClearMode > CELL_SPURS_EVENT_FLAG_CLEAR_LAST) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + memset(eventFlag.get_ptr(), 0, CellSpursEventFlag::size); + eventFlag->m.direction = flagDirection; + eventFlag->m.clearMode = flagClearMode; + eventFlag->m.spuPort = -1; + + if (taskset.addr()) + { + eventFlag->m.addr = taskset.addr(); + } + else + { + eventFlag->m.isIwl = 1; + eventFlag->m.addr = spurs.addr(); + } + return CELL_OK; #endif } s64 cellSpursEventFlagAttachLv2EventQueue(vm::ptr eventFlag) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagAttachLv2EventQueue(eventFlag_addr=0x%x)", eventFlag.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x157B8, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!eventFlag) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_AGAIN; + } + + if (eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_SPU2PPU && eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + return CELL_SPURS_TASK_ERROR_PERM; + } + + if (eventFlag->m.spuPort != -1) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + + vm::ptr spurs; + if (eventFlag->m.isIwl == 1) + { + spurs.set((u32)eventFlag->m.addr); + } + else + { + auto taskset = vm::ptr::make((u32)eventFlag->m.addr); + spurs.set((u32)taskset->m.spurs.addr()); + } + + u32 eventQueueId; + auto _port = vm::ptr::make((u32)Memory.Alloc(1, 1)); + auto rc = spursCreateLv2EventQueue(spurs, eventQueueId, _port, 1, *((u64 *)"_spuEvF")); + auto port = *_port; + Memory.Free(_port.addr()); + if (rc != CELL_OK) + { + return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); + } + + if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + auto _eventPortId = vm::ptr::make((u32)Memory.Alloc(4, 4)); + rc = sys_event_port_create(_eventPortId, SYS_EVENT_PORT_LOCAL, 0); + auto eventPortId = *_eventPortId; + Memory.Free(_eventPortId.addr()); + if (rc == CELL_OK) + { + rc = sys_event_port_connect_local(eventPortId, eventQueueId); + if (rc == CELL_OK) + { + eventFlag->m.eventPortId = eventPortId; + goto success; + } + + sys_event_port_destroy(eventPortId); + } + + // TODO: Implement the following + // if (spursDetachLv2EventQueue(spurs, port, 1) == CELL_OK) + // { + // sys_event_queue_destroy(eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE); + // } + return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); + } + +success: + eventFlag->m.eventQueueId = eventQueueId; + eventFlag->m.spuPort = port; return CELL_OK; #endif } s64 cellSpursEventFlagDetachLv2EventQueue(vm::ptr eventFlag) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagDetachLv2EventQueue(eventFlag_addr=0x%x)", eventFlag.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x15998, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!eventFlag) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_AGAIN; + } + + if (eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_SPU2PPU && eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + return CELL_SPURS_TASK_ERROR_PERM; + } + + if (eventFlag->m.spuPort == -1) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + + if (eventFlag->m.x04 || eventFlag->m.x06 & 0xFF00) + { + return CELL_SPURS_TASK_ERROR_BUSY; + } + + auto port = eventFlag->m.spuPort; + eventFlag->m.spuPort = -1; // TODO: Make this execute atomically + + vm::ptr spurs; + if (eventFlag->m.isIwl == 1) + { + spurs.set((u32)eventFlag->m.addr); + } + else + { + auto taskset = vm::ptr::make((u32)eventFlag->m.addr); + spurs.set((u32)taskset->m.spurs.addr()); + } + + if(eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + sys_event_port_disconnect(eventFlag->m.eventPortId); + sys_event_port_destroy(eventFlag->m.eventPortId); + } + + s64 rc = CELL_OK; + // TODO: Implement the following + // auto rc = spursDetachLv2EventQueue(spurs, port, 1); + // if (rc == CELL_OK) + // { + // rc = sys_event_queue_destroy(eventFlag->m.eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE); + // } + + if (rc != CELL_OK) + { + return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); + } + return CELL_OK; #endif } -s64 cellSpursEventFlagWait(vm::ptr eventFlag, vm::ptr mask, u32 mode) +s64 _cellSpursEventFlagWait(vm::ptr eventFlag, vm::ptr mask, u32 mode, u32 block) { -#ifdef PRX_DEBUG - cellSpurs->Warning("cellSpursEventFlagWait(eventFlag_addr=0x%x, mask_addr=0x%x, mode=%d)", eventFlag.addr(), mask.addr(), mode); - return GetCurrentPPUThread().FastCall2(libsre + 0x15E68, libsre_rtoc); -#else UNIMPLEMENTED_FUNC(cellSpurs); return CELL_OK; +} + +s64 cellSpursEventFlagWait(vm::ptr eventFlag, vm::ptr mask, u32 mode) +{ + cellSpurs->Warning("cellSpursEventFlagWait(eventFlag_addr=0x%x, mask_addr=0x%x, mode=%d)", eventFlag.addr(), mask.addr(), mode); + +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libsre + 0x15E68, libsre_rtoc); +#else + return _cellSpursEventFlagWait(eventFlag, mask, mode, 1/*block*/); #endif } s64 cellSpursEventFlagClear(vm::ptr eventFlag, u16 bits) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagClear(eventFlag_addr=0x%x, bits=0x%x)", eventFlag.addr(), bits); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x15E9C, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (eventFlag.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + eventFlag->m.bits &= ~bits; // TODO: Make this execute atomically return CELL_OK; #endif } s64 cellSpursEventFlagSet(vm::ptr eventFlag, u16 bits) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagSet(eventFlag_addr=0x%x, bits=0x%x)", eventFlag.addr(), bits); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x15F04, libsre_rtoc); #else UNIMPLEMENTED_FUNC(cellSpurs); @@ -1678,44 +1914,77 @@ s64 cellSpursEventFlagSet(vm::ptr eventFlag, u16 bits) s64 cellSpursEventFlagTryWait(vm::ptr eventFlag, vm::ptr mask, u32 mode) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagTryWait(eventFlag_addr=0x%x, mask_addr=0x%x, mode=0x%x)", eventFlag.addr(), mask.addr(), mode); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x15E70, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; + return _cellSpursEventFlagWait(eventFlag, mask, mode, 0/*block*/); #endif } s64 cellSpursEventFlagGetDirection(vm::ptr eventFlag, vm::ptr direction) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagGetDirection(eventFlag_addr=0x%x, direction_addr=0x%x)", eventFlag.addr(), direction.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x162C4, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (eventFlag.addr() == 0 || direction.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + *direction = eventFlag->m.direction; return CELL_OK; #endif } s64 cellSpursEventFlagGetClearMode(vm::ptr eventFlag, vm::ptr clear_mode) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagGetClearMode(eventFlag_addr=0x%x, clear_mode_addr=0x%x)", eventFlag.addr(), clear_mode.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x16310, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (eventFlag.addr() == 0 || clear_mode.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + *clear_mode = eventFlag->m.clearMode; return CELL_OK; #endif } s64 cellSpursEventFlagGetTasksetAddress(vm::ptr eventFlag, vm::ptr taskset) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursEventFlagGetTasksetAddress(eventFlag_addr=0x%x, taskset_addr=0x%x)", eventFlag.addr(), taskset.addr()); + +#ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x1635C, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (eventFlag.addr() == 0 || taskset.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + taskset.set(eventFlag->m.isIwl ? 0 : eventFlag->m.addr); return CELL_OK; #endif } @@ -2302,7 +2571,54 @@ s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID) cellSpurs->Warning("_cellSpursSendSignal(taskset_addr=0x%x, taskID=%d)", taskset.addr(), taskID); return GetCurrentPPUThread().FastCall2(libsre + 0x124CC, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!taskset) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (taskset.addr() % CellSpursTaskset::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (taskID >= CELL_SPURS_MAX_TASK || taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD2) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + auto word = taskID >> 5; + auto mask = 0x80000000u >> (taskID & 0x1F); + auto disabled = taskset->m.enabled_set[word] & mask ? false : true; + auto running = taskset->m.running_set[word]; + auto ready = taskset->m.ready_set[word]; + auto ready2 = taskset->m.ready2_set[word]; + auto waiting = taskset->m.waiting_set[word]; + auto signalled = taskset->m.signal_received_set[word]; + auto enabled = taskset->m.enabled_set[word]; + auto invalid = (ready & ready2) || (running & waiting) || ((running | ready | ready2 | waiting | signalled) & ~enabled) || disabled; + + if (invalid) + { + return CELL_SPURS_TASK_ERROR_SRCH; + } + + auto shouldSignal = waiting & ~signalled & mask ? true : false; + taskset->m.signal_received_set[word] |= mask; // TODO: Make this execute atomically + if (shouldSignal) + { + cellSpursSendWorkloadSignal(vm::ptr::make((u32)taskset->m.spurs.addr()), taskset->m.wid); + auto rc = cellSpursWakeUp(GetCurrentPPUThread(), vm::ptr::make((u32)taskset->m.spurs.addr())); + if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + + if (rc != CELL_OK) + { + assert(0); + } + } + return CELL_OK; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index dab014f898..32798e6006 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -199,6 +199,28 @@ enum SpursTaskConstants CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, }; +enum CellSpursEventFlagWaitMode +{ + CELL_SPURS_EVENT_FLAG_OR = 0, + CELL_SPURS_EVENT_FLAG_AND = 1 +}; + +enum CellSpursEventFlagClearMode +{ + CELL_SPURS_EVENT_FLAG_CLEAR_AUTO = 0, + CELL_SPURS_EVENT_FLAG_CLEAR_MANUAL = 1, + CELL_SPURS_EVENT_FLAG_CLEAR_LAST = CELL_SPURS_EVENT_FLAG_CLEAR_MANUAL, +}; + +enum CellSpursEventFlagDirection +{ + CELL_SPURS_EVENT_FLAG_SPU2SPU, + CELL_SPURS_EVENT_FLAG_SPU2PPU, + CELL_SPURS_EVENT_FLAG_PPU2SPU, + CELL_SPURS_EVENT_FLAG_ANY2ANY, + CELL_SPURS_EVENT_FLAG_LAST = CELL_SPURS_EVENT_FLAG_ANY2ANY, +}; + class SPURSManager; class SPURSManagerEventFlag; class SPURSManagerTaskset; @@ -519,7 +541,38 @@ struct CellSpursWorkloadAttribute struct CellSpursEventFlag { - SPURSManagerEventFlag *eventFlag; + static const u32 align = 128; + static const u32 size = 128; + + union + { + // Raw data + u8 _u8[size]; + + // Real data + struct _CellSpursEventFlag + { + be_t bits; // 0x00 + be_t x02; // 0x02 + be_t x04; // 0x04 + be_t x06; // 0x06 + be_t x08; // 0x08 + be_t x0A; // 0x0A + u8 spuPort; // 0x0C + u8 isIwl; // 0x0D + u8 direction; // 0x0E + u8 clearMode; // 0x0F + u16 x10[16]; // 0x10 + u8 x30[0x70 - 0x30]; // 0x30 + be_t addr; // 0x70 + be_t eventPortId; // 0x78 + be_t eventQueueId; // 0x7C + } m; + + static_assert(sizeof(_CellSpursEventFlag) == size, "Wrong _CellSpursEventFlag size"); + + SPURSManagerEventFlag *eventFlag; + }; }; union CellSpursTaskArgument @@ -559,7 +612,7 @@ struct CellSpursTaskset { be_t running_set[4]; // 0x00 be_t ready_set[4]; // 0x10 - be_t unk_set[4]; // 0x20 - TODO: Find out what this is + be_t ready2_set[4]; // 0x20 - TODO: Find out what this is be_t enabled_set[4]; // 0x30 be_t signal_received_set[4]; // 0x40 be_t waiting_set[4]; // 0x50 @@ -668,7 +721,7 @@ struct CellSpursTaskset2 { be_t running_set[4]; // 0x00 be_t ready_set[4]; // 0x10 - be_t unk_set[4]; // 0x20 - TODO: Find out what this is + be_t ready2_set[4]; // 0x20 - TODO: Find out what this is be_t enabled_set[4]; // 0x30 be_t signal_received_set[4]; // 0x40 be_t waiting_set[4]; // 0x50 From 8717bdffa9e58b56ae31476cb003aab9033e0f79 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Fri, 23 Jan 2015 03:01:46 +0530 Subject: [PATCH 14/94] SPURS: Implement cellSpursEventFlagWait and cellSpursEventFlagSet. Also modify implementation to make use of vm::var --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 293 +++++++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 24 +- 2 files changed, 259 insertions(+), 58 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 25bf599222..1c15206a46 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -27,6 +27,8 @@ extern u32 libsre_rtoc; #endif void spursKernelMain(SPUThread & spu); +s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id); +s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID); s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr port, s32 size, u64 name_u64) { @@ -1302,7 +1304,7 @@ s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook(vm::ptr spurs, vm::ptr wid, vm::ptr attr) +s64 cellSpursAddWorkloadWithAttribute(vm::ptr spurs, const vm::ptr wid, vm::ptr attr) { cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, attr_addr=0x%x)", __FUNCTION__, spurs.addr(), wid.addr(), attr.addr()); #ifdef PRX_DEBUG_XXX @@ -1507,7 +1509,6 @@ s64 cellSpursSendWorkloadSignal(vm::ptr spurs, u32 workloadId) return CELL_SPURS_POLICY_MODULE_ERROR_STAT; } - // TODO: Make the below block execute atomically if (workloadId >= CELL_SPURS_MAX_WORKLOAD) { spurs->m.wklSignal2 |= be_t::make(0x8000 >> (workloadId & 0x0F)); @@ -1750,10 +1751,8 @@ s64 cellSpursEventFlagAttachLv2EventQueue(vm::ptr eventFlag) } u32 eventQueueId; - auto _port = vm::ptr::make((u32)Memory.Alloc(1, 1)); - auto rc = spursCreateLv2EventQueue(spurs, eventQueueId, _port, 1, *((u64 *)"_spuEvF")); - auto port = *_port; - Memory.Free(_port.addr()); + vm::var port; + auto rc = spursCreateLv2EventQueue(spurs, eventQueueId, port, 1, *((u64 *)"_spuEvF")); if (rc != CELL_OK) { return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); @@ -1761,20 +1760,18 @@ s64 cellSpursEventFlagAttachLv2EventQueue(vm::ptr eventFlag) if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) { - auto _eventPortId = vm::ptr::make((u32)Memory.Alloc(4, 4)); - rc = sys_event_port_create(_eventPortId, SYS_EVENT_PORT_LOCAL, 0); - auto eventPortId = *_eventPortId; - Memory.Free(_eventPortId.addr()); + vm::var> eventPortId; + rc = sys_event_port_create(vm::ptr::make(eventPortId.addr()), SYS_EVENT_PORT_LOCAL, 0); if (rc == CELL_OK) { - rc = sys_event_port_connect_local(eventPortId, eventQueueId); + rc = sys_event_port_connect_local(eventPortId.value(), eventQueueId); if (rc == CELL_OK) { eventFlag->m.eventPortId = eventPortId; goto success; } - sys_event_port_destroy(eventPortId); + sys_event_port_destroy(eventPortId.value()); } // TODO: Implement the following @@ -1819,13 +1816,13 @@ s64 cellSpursEventFlagDetachLv2EventQueue(vm::ptr eventFlag) return CELL_SPURS_TASK_ERROR_STAT; } - if (eventFlag->m.x04 || eventFlag->m.x06 & 0xFF00) + if (eventFlag->m.x04 || eventFlag->m.x07) { return CELL_SPURS_TASK_ERROR_BUSY; } auto port = eventFlag->m.spuPort; - eventFlag->m.spuPort = -1; // TODO: Make this execute atomically + eventFlag->m.spuPort = -1; vm::ptr spurs; if (eventFlag->m.isIwl == 1) @@ -1863,7 +1860,121 @@ s64 cellSpursEventFlagDetachLv2EventQueue(vm::ptr eventFlag) s64 _cellSpursEventFlagWait(vm::ptr eventFlag, vm::ptr mask, u32 mode, u32 block) { - UNIMPLEMENTED_FUNC(cellSpurs); + if (eventFlag.addr() == 0 || mask.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (mode > CELL_SPURS_EVENT_FLAG_WAIT_MODE_LAST) + { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + if (eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_SPU2PPU && eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + return CELL_SPURS_TASK_ERROR_PERM; + } + + if (block && eventFlag->m.spuPort == -1) + { + return CELL_SPURS_TASK_ERROR_STAT; + } + + if (eventFlag->m.x04 || eventFlag->m.x07) + { + return CELL_SPURS_TASK_ERROR_BUSY; + } + + u16 bits = eventFlag->m.bits & *mask; + if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + u16 tmp = eventFlag->m.x08 & ~eventFlag->m.x02; + if (mode != CELL_SPURS_EVENT_FLAG_AND) + { + tmp &= eventFlag->m.x0A; + } + + int i = 15; + while (tmp) + { + if (tmp & 0x1) + { + if (eventFlag->m.x10[i] & *mask && eventFlag->m.x10[i] != *mask) + { + return CELL_SPURS_TASK_ERROR_AGAIN; + } + } + + tmp >>= 1; + i--; + } + } + + bool recv; + if ((*mask & ~bits) == 0 || (mode == CELL_SPURS_EVENT_FLAG_OR && bits)) + { + if (eventFlag->m.clearMode == CELL_SPURS_EVENT_FLAG_CLEAR_AUTO) + { + eventFlag->m.bits &= ~bits; + } + + recv = false; + } + else + { + if (block == 0) + { + return CELL_SPURS_TASK_ERROR_BUSY; + } + + eventFlag->m.x06 = 0; + if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + u8 i = 0; + u16 tmp = eventFlag->m.x08; + while (tmp & 0x01) + { + tmp >>= 1; + i++; + } + + if (i == 16) + { + return CELL_SPURS_TASK_ERROR_BUSY; + } + + eventFlag->m.x06 = (15 - i) << 4; + } + + eventFlag->m.x06 |= mode; + eventFlag->m.x04 = *mask; + recv = true; + } + + if (recv) { + vm::var data; + auto rc = sys_event_queue_receive(eventFlag->m.eventQueueId, data, 0); + if (rc != CELL_OK) + { + assert(0); + } + + u8 i = 0; + if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + i = eventFlag->m.x06 >> 4; + } + + bits = eventFlag->m.x30[i]; + eventFlag->m.x07 = 0; + } + + *mask = bits; return CELL_OK; } @@ -1895,7 +2006,7 @@ s64 cellSpursEventFlagClear(vm::ptr eventFlag, u16 bits) return CELL_SPURS_TASK_ERROR_ALIGN; } - eventFlag->m.bits &= ~bits; // TODO: Make this execute atomically + eventFlag->m.bits &= ~bits; return CELL_OK; #endif } @@ -1907,7 +2018,110 @@ s64 cellSpursEventFlagSet(vm::ptr eventFlag, u16 bits) #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x15F04, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (eventFlag.addr() == 0) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (eventFlag.addr() % CellSpursEventFlag::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + if (eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_PPU2SPU && eventFlag->m.direction != CELL_SPURS_EVENT_FLAG_ANY2ANY) + { + return CELL_SPURS_TASK_ERROR_PERM; + } + + u16 tmp1 = 0; + auto send = false; + u16 tmp3 = 0; + u16 tmp4 = 0; + + if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY && eventFlag->m.x04) + { + u16 tmp = (eventFlag->m.bits | bits) & eventFlag->m.x04; + if ((eventFlag->m.x04 & ~tmp) == 0 || ((eventFlag->m.x06 & 0x0F) == 0 && tmp != 0)) + { + eventFlag->m.x07 = 1; + eventFlag->m.x04 = 0; + tmp1 = tmp; + send = true; + tmp3 = eventFlag->m.x06 >> 4; + tmp4 = tmp; + } + } + + u16 i = 15; + u16 j = 0; + u16 tmp = eventFlag->m.x08 & ~eventFlag->m.x02; + u16 tmp5 = 0; + u16 x30[16]; + while (tmp) + { + if (tmp & 0x0001) + { + u16 tmp6 = (eventFlag->m.bits | bits) & eventFlag->m.x10[i]; + if ((eventFlag->m.x10[i] & ~tmp6) == 0 || (((eventFlag->m.x0A >> j) & 0x01) == 0 && (eventFlag->m.x10[i] & ~tmp6) != 0)) + { + tmp4 |= tmp6; + tmp5 |= 1 << j; + x30[j] = tmp6; + } + } + + tmp >>= 1; + i--; + j++; + } + + eventFlag->m.bits |= bits; + eventFlag->m.x02 |= tmp5; + if (eventFlag->m.clearMode == CELL_SPURS_EVENT_FLAG_CLEAR_AUTO) + { + eventFlag->m.bits &= ~tmp4; + } + + if (send) + { + eventFlag->m.x30[tmp3] = tmp1; + if (sys_event_port_send(eventFlag->m.eventPortId, 0, 0, 0) != CELL_OK) + { + assert(0); + } + } + + if (tmp5) + { + for (auto i = 0; i < 16; i++) + { + if (tmp5 & (0x8000 >> i)) + { + eventFlag->m.x30[i] = x30[i]; + vm::var taskset; + if (eventFlag->m.isIwl) + { + cellSpursLookUpTasksetAddress(vm::ptr::make((u32)eventFlag->m.addr), vm::ptr::make(taskset.addr()), eventFlag->m.x60[i]); + } + else + { + taskset.value() = (u32)eventFlag->m.addr; + } + + auto rc = _cellSpursSendSignal(vm::ptr::make(taskset.addr()), eventFlag->m.x50[i]); + if (rc == CELL_SPURS_TASK_ERROR_INVAL || rc == CELL_SPURS_TASK_ERROR_STAT) + { + return CELL_SPURS_TASK_ERROR_FATAL; + } + + if (rc != CELL_OK) + { + assert(0); + } + } + } + } + return CELL_OK; #endif } @@ -2306,30 +2520,26 @@ s64 spursCreateTaskset(vm::ptr spurs, vm::ptr tasks taskset->m.enable_clear_ls = enable_clear_ls > 0 ? 1 : 0; taskset->m.size = size; - auto wkl_attr = vm::ptr::make((u32)Memory.Alloc(CellSpursWorkloadAttribute::size, CellSpursWorkloadAttribute::align)); + vm::var wkl_attr; _cellSpursWorkloadAttributeInitialize(wkl_attr, 1 /*revision*/, 0x33 /*sdk_version*/, vm::ptr::make(16) /*pm*/, 0x1E40 /*pm_size*/, taskset.addr(), priority, 8 /*min_contention*/, max_contention); // TODO: Check return code - auto cls = vm::ptr::make((u32)Memory.Alloc(1, 1)); - *((char *)cls.get_ptr()) = 0; - cellSpursWorkloadAttributeSetName(wkl_attr, cls, name); + cellSpursWorkloadAttributeSetName(wkl_attr, vm::ptr::make(0), name); // TODO: Check return code // TODO: cellSpursWorkloadAttributeSetShutdownCompletionEventHook(wkl_attr, hook, taskset); // TODO: Check return code - auto wid = vm::ptr::make((u32)Memory.Alloc(4, 4)); - cellSpursAddWorkloadWithAttribute(spurs, wid, vm::ptr::make(wkl_attr.addr())); + vm::var> wid; + cellSpursAddWorkloadWithAttribute(spurs, vm::ptr::make(wid.addr()), vm::ptr::make(wkl_attr.addr())); // TODO: Check return code taskset->m.x72 = 0x80; - taskset->m.wid = *wid; + taskset->m.wid = wid.value(); // TODO: cellSpursSetExceptionEventHandler(spurs, wid, hook, taskset); // TODO: Check return code - Memory.Free(wkl_attr.addr()); - Memory.Free(wid.addr()); return CELL_OK; } @@ -2439,14 +2649,13 @@ s64 cellSpursShutdownTaskset(vm::ptr taskset) u32 _cellSpursGetSdkVersion() { - static u32 sdk_version = -2; + static s32 sdk_version = -2; if (sdk_version == -2) { - auto version = vm::ptr::make((u32)Memory.Alloc(sizeof(u32), sizeof(u32))); - sys_process_get_sdk_version(sys_process_getpid(), version); - sdk_version = *version; - Memory.Free(version.addr()); + vm::var> version; + sys_process_get_sdk_version(sys_process_getpid(), vm::ptr::make(version.addr())); + sdk_version = version.value(); } return sdk_version; @@ -2522,7 +2731,6 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: // TODO: Verify the ELF header is proper and all its load segments are at address >= 0x3000 - // TODO: Make the following block execute atomically u32 tmp_task_id; for (tmp_task_id = 0; tmp_task_id < CELL_SPURS_MAX_TASK; tmp_task_id++) { @@ -2603,7 +2811,7 @@ s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID) } auto shouldSignal = waiting & ~signalled & mask ? true : false; - taskset->m.signal_received_set[word] |= mask; // TODO: Make this execute atomically + taskset->m.signal_received_set[word] |= mask; if (shouldSignal) { cellSpursSendWorkloadSignal(vm::ptr::make((u32)taskset->m.spurs.addr()), taskset->m.wid); @@ -2872,11 +3080,11 @@ s64 cellSpursCreateTaskset2(vm::ptr spurs, vm::ptr #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x15108, libsre_rtoc); #else - auto free_attr = false; + vm::ptr tmp_attr; + if (!attr) { - attr.set(Memory.Alloc(CellSpursTasksetAttribute2::size, CellSpursTasksetAttribute2::align)); - free_attr = true; + attr.set(tmp_attr.addr()); _cellSpursTasksetAttribute2Initialize(attr, 0); } @@ -2885,10 +3093,6 @@ s64 cellSpursCreateTaskset2(vm::ptr spurs, vm::ptr attr->m.max_contention, vm::ptr::make(attr->m.name.addr()), CellSpursTaskset2::size, (u8)attr->m.enable_clear_ls); if (rc != CELL_OK) { - if (free_attr) - { - Memory.Free(attr.addr()); - } return rc; } @@ -2898,11 +3102,6 @@ s64 cellSpursCreateTaskset2(vm::ptr spurs, vm::ptr } // TODO: Implement rest of the function - - if (free_attr) - { - Memory.Free(attr.addr()); - } return CELL_OK; #endif } @@ -3028,7 +3227,7 @@ s64 cellSpursTasksetUnsetExceptionEventHandler(vm::ptr taskset #endif } -s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id) +s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id) { cellSpurs->Warning("%s(spurs=0x%x, taskset=0x%x, id=0x%x)", __FUNCTION__, spurs.addr(), taskset.addr(), id); @@ -3660,6 +3859,4 @@ void cellSpurs_init(Module *pxThis) REG_FUNC(cellSpurs, cellSpursTraceStart); REG_FUNC(cellSpurs, cellSpursTraceStop); REG_FUNC(cellSpurs, cellSpursTraceFinalize); - - // TODO: some trace funcs } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index ecbfc03efc..1946675c54 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -201,8 +201,9 @@ enum SpursTaskConstants enum CellSpursEventFlagWaitMode { - CELL_SPURS_EVENT_FLAG_OR = 0, - CELL_SPURS_EVENT_FLAG_AND = 1 + CELL_SPURS_EVENT_FLAG_OR = 0, + CELL_SPURS_EVENT_FLAG_AND = 1, + CELL_SPURS_EVENT_FLAG_WAIT_MODE_LAST = CELL_SPURS_EVENT_FLAG_AND, }; enum CellSpursEventFlagClearMode @@ -552,18 +553,21 @@ struct CellSpursEventFlag // Real data struct _CellSpursEventFlag { - be_t bits; // 0x00 - be_t x02; // 0x02 - be_t x04; // 0x04 - be_t x06; // 0x06 - be_t x08; // 0x08 - be_t x0A; // 0x0A + be_t bits; // 0x00 Bit mask of event set bits + be_t x02; // 0x02 Bit mask of SPU thread slots whose conditions have met + be_t x04; // 0x04 Wait mask for PPU thread + u8 x06; // 0x06 Top 4 bits: Bit number for PPU thread. Bottom 4 bits: Wait mode of PPU thread + u8 x07; // 0x07 Set to 1 if the blocked PPU thread's condition has been met + be_t x08; // 0x08 Bit mask of used wait slots + be_t x0A; // 0x0A Bit mask of used wait slots whose wait mode is AND u8 spuPort; // 0x0C u8 isIwl; // 0x0D u8 direction; // 0x0E u8 clearMode; // 0x0F - u16 x10[16]; // 0x10 - u8 x30[0x70 - 0x30]; // 0x30 + be_t x10[16]; // 0x10 Wait mask for SPU threads + be_t x30[16]; // 0x30 Received event flag mask for SPU threads + u8 x50[16]; // 0x50 Task id of waiting SPU threads + u8 x60[16]; // 0x50 Workload Ids of waiting SPU threads be_t addr; // 0x70 be_t eventPortId; // 0x78 be_t eventQueueId; // 0x7C From 173fb060cb5dea6c008aabf371e26566eb31a77d Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 24 Jan 2015 00:17:37 +0530 Subject: [PATCH 15/94] SPURS: Improve the readability of the event flag functions --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 180 ++++++++++++++--------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 43 +++--- 2 files changed, 134 insertions(+), 89 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 1c15206a46..c8fc774ad8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1696,7 +1696,7 @@ s64 _cellSpursEventFlagInitialize(vm::ptr spurs, vm::ptrm.direction = flagDirection; eventFlag->m.clearMode = flagClearMode; - eventFlag->m.spuPort = -1; + eventFlag->m.spuPort = CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT; if (taskset.addr()) { @@ -1734,7 +1734,7 @@ s64 cellSpursEventFlagAttachLv2EventQueue(vm::ptr eventFlag) return CELL_SPURS_TASK_ERROR_PERM; } - if (eventFlag->m.spuPort != -1) + if (eventFlag->m.spuPort != CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT) { return CELL_SPURS_TASK_ERROR_STAT; } @@ -1755,6 +1755,7 @@ s64 cellSpursEventFlagAttachLv2EventQueue(vm::ptr eventFlag) auto rc = spursCreateLv2EventQueue(spurs, eventQueueId, port, 1, *((u64 *)"_spuEvF")); if (rc != CELL_OK) { + // Return rc if its an error code from SPURS otherwise convert the error code to a SPURS task error code return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); } @@ -1779,6 +1780,8 @@ s64 cellSpursEventFlagAttachLv2EventQueue(vm::ptr eventFlag) // { // sys_event_queue_destroy(eventQueueId, SYS_EVENT_QUEUE_DESTROY_FORCE); // } + + // Return rc if its an error code from SPURS otherwise convert the error code to a SPURS task error code return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); } @@ -1811,18 +1814,18 @@ s64 cellSpursEventFlagDetachLv2EventQueue(vm::ptr eventFlag) return CELL_SPURS_TASK_ERROR_PERM; } - if (eventFlag->m.spuPort == -1) + if (eventFlag->m.spuPort == CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT) { return CELL_SPURS_TASK_ERROR_STAT; } - if (eventFlag->m.x04 || eventFlag->m.x07) + if (eventFlag->m.ppuWaitMask || eventFlag->m.ppuPendingRecv) { return CELL_SPURS_TASK_ERROR_BUSY; } auto port = eventFlag->m.spuPort; - eventFlag->m.spuPort = -1; + eventFlag->m.spuPort = CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT; vm::ptr spurs; if (eventFlag->m.isIwl == 1) @@ -1851,6 +1854,7 @@ s64 cellSpursEventFlagDetachLv2EventQueue(vm::ptr eventFlag) if (rc != CELL_OK) { + // Return rc if its an error code from SPURS otherwise convert the error code to a SPURS task error code return (rc & 0x0FFF0000) == 0x00410000 ? rc : (0x80410900 | (rc & 0xFF)); } @@ -1880,83 +1884,104 @@ s64 _cellSpursEventFlagWait(vm::ptr eventFlag, vm::ptr return CELL_SPURS_TASK_ERROR_PERM; } - if (block && eventFlag->m.spuPort == -1) + if (block && eventFlag->m.spuPort == CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT) { return CELL_SPURS_TASK_ERROR_STAT; } - if (eventFlag->m.x04 || eventFlag->m.x07) + if (eventFlag->m.ppuWaitMask || eventFlag->m.ppuPendingRecv) { return CELL_SPURS_TASK_ERROR_BUSY; } - u16 bits = eventFlag->m.bits & *mask; + u16 relevantEvents = eventFlag->m.events & *mask; if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) { - u16 tmp = eventFlag->m.x08 & ~eventFlag->m.x02; - if (mode != CELL_SPURS_EVENT_FLAG_AND) + // Make sure the wait mask and mode specified does not conflict with that of the already waiting tasks. + // Conflict scenarios: + // OR vs OR - A conflict never occurs + // OR vs AND - A conflict occurs if the masks for the two tasks overlap + // AND vs AND - A conflict occurs if the masks for the two tasks are not the same + + // Determine the set of all already waiting tasks whose wait mode/mask can possibly conflict with the specified wait mode/mask. + // This set is equal to 'set of all tasks waiting' - 'set of all tasks whose wait conditions have been met'. + // If the wait mode is OR, we prune the set of all tasks that are waiting in OR mode from the set since a conflict cannot occur + // with an already waiting task in OR mode. + u16 relevantWaitSlots = eventFlag->m.spuTaskUsedWaitSlots & ~eventFlag->m.spuTaskPendingRecv; + if (mode == CELL_SPURS_EVENT_FLAG_OR) { - tmp &= eventFlag->m.x0A; + relevantWaitSlots &= eventFlag->m.spuTaskWaitMode; } - int i = 15; - while (tmp) + int i = CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS - 1; + while (relevantWaitSlots) { - if (tmp & 0x1) + if (relevantWaitSlots & 0x0001) { - if (eventFlag->m.x10[i] & *mask && eventFlag->m.x10[i] != *mask) + if (eventFlag->m.spuTaskWaitMask[i] & *mask && eventFlag->m.spuTaskWaitMask[i] != *mask) { return CELL_SPURS_TASK_ERROR_AGAIN; } } - tmp >>= 1; + relevantWaitSlots >>= 1; i--; } } + // There is no need to block if all bits required by the wait operation have already been set or + // if the wait mode is OR and atleast one of the bits required by the wait operation has been set. bool recv; - if ((*mask & ~bits) == 0 || (mode == CELL_SPURS_EVENT_FLAG_OR && bits)) + if ((*mask & ~relevantEvents) == 0 || (mode == CELL_SPURS_EVENT_FLAG_OR && relevantEvents)) { + // If the clear flag is AUTO then clear the bits comnsumed by this thread if (eventFlag->m.clearMode == CELL_SPURS_EVENT_FLAG_CLEAR_AUTO) { - eventFlag->m.bits &= ~bits; + eventFlag->m.events &= ~relevantEvents; } recv = false; } else { + // If we reach here it means that the conditions for this thread have not been met. + // If this is a try wait operation then do not block but return an error code. if (block == 0) { return CELL_SPURS_TASK_ERROR_BUSY; } - eventFlag->m.x06 = 0; + eventFlag->m.ppuWaitSlotAndMode = 0; if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) { - u8 i = 0; - u16 tmp = eventFlag->m.x08; - while (tmp & 0x01) + // Find an unsed wait slot + int i = 0; + u16 spuTaskUsedWaitSlots = eventFlag->m.spuTaskUsedWaitSlots; + while (spuTaskUsedWaitSlots & 0x0001) { - tmp >>= 1; + spuTaskUsedWaitSlots >>= 1; i++; } - if (i == 16) + if (i == CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS) { + // Event flag has no empty wait slots return CELL_SPURS_TASK_ERROR_BUSY; } - eventFlag->m.x06 = (15 - i) << 4; + // Mark the found wait slot as used by this thread + eventFlag->m.ppuWaitSlotAndMode = (CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS - 1 - i) << 4; } - eventFlag->m.x06 |= mode; - eventFlag->m.x04 = *mask; - recv = true; + // Save the wait mask and mode for this thread + eventFlag->m.ppuWaitSlotAndMode |= mode; + eventFlag->m.ppuWaitMask = *mask; + recv = true; } + u16 receivedEventFlag; if (recv) { + // Block till something happens vm::var data; auto rc = sys_event_queue_receive(eventFlag->m.eventQueueId, data, 0); if (rc != CELL_OK) @@ -1964,17 +1989,17 @@ s64 _cellSpursEventFlagWait(vm::ptr eventFlag, vm::ptr assert(0); } - u8 i = 0; + int i = 0; if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY) { - i = eventFlag->m.x06 >> 4; + i = eventFlag->m.ppuWaitSlotAndMode >> 4; } - bits = eventFlag->m.x30[i]; - eventFlag->m.x07 = 0; + receivedEventFlag = eventFlag->m.pendingRecvTaskEvents[i]; + eventFlag->m.ppuPendingRecv = 0; } - *mask = bits; + *mask = receivedEventFlag; return CELL_OK; } @@ -2006,7 +2031,7 @@ s64 cellSpursEventFlagClear(vm::ptr eventFlag, u16 bits) return CELL_SPURS_TASK_ERROR_ALIGN; } - eventFlag->m.bits &= ~bits; + eventFlag->m.events &= ~bits; return CELL_OK; #endif } @@ -2033,82 +2058,95 @@ s64 cellSpursEventFlagSet(vm::ptr eventFlag, u16 bits) return CELL_SPURS_TASK_ERROR_PERM; } - u16 tmp1 = 0; - auto send = false; - u16 tmp3 = 0; - u16 tmp4 = 0; - - if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY && eventFlag->m.x04) + u16 ppuEventFlag = 0; + bool send = false; + int ppuWaitSlot = 0; + u16 eventsToClear = 0; + if (eventFlag->m.direction == CELL_SPURS_EVENT_FLAG_ANY2ANY && eventFlag->m.ppuWaitMask) { - u16 tmp = (eventFlag->m.bits | bits) & eventFlag->m.x04; - if ((eventFlag->m.x04 & ~tmp) == 0 || ((eventFlag->m.x06 & 0x0F) == 0 && tmp != 0)) + u16 ppuRelevantEvents = (eventFlag->m.events | bits) & eventFlag->m.ppuWaitMask; + + // Unblock the waiting PPU thread if either all the bits being waited by the thread have been set or + // if the wait mode of the thread is OR and atleast one bit the thread is waiting on has been set + if ((eventFlag->m.ppuWaitMask & ~ppuRelevantEvents) == 0 || + ((eventFlag->m.ppuWaitSlotAndMode & 0x0F) == CELL_SPURS_EVENT_FLAG_OR && ppuRelevantEvents != 0)) { - eventFlag->m.x07 = 1; - eventFlag->m.x04 = 0; - tmp1 = tmp; - send = true; - tmp3 = eventFlag->m.x06 >> 4; - tmp4 = tmp; + eventFlag->m.ppuPendingRecv = 1; + eventFlag->m.ppuWaitMask = 0; + ppuEventFlag = ppuRelevantEvents; + eventsToClear = ppuRelevantEvents; + ppuWaitSlot = eventFlag->m.ppuWaitSlotAndMode >> 4; + send = true; } } - u16 i = 15; - u16 j = 0; - u16 tmp = eventFlag->m.x08 & ~eventFlag->m.x02; - u16 tmp5 = 0; - u16 x30[16]; - while (tmp) + int i = CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS - 1; + int j = 0; + u16 relevantWaitSlots = eventFlag->m.spuTaskUsedWaitSlots & ~eventFlag->m.spuTaskPendingRecv; + u16 spuTaskPendingRecv = 0; + u16 pendingRecvTaskEvents[16]; + while (relevantWaitSlots) { - if (tmp & 0x0001) + if (relevantWaitSlots & 0x0001) { - u16 tmp6 = (eventFlag->m.bits | bits) & eventFlag->m.x10[i]; - if ((eventFlag->m.x10[i] & ~tmp6) == 0 || (((eventFlag->m.x0A >> j) & 0x01) == 0 && (eventFlag->m.x10[i] & ~tmp6) != 0)) + u16 spuTaskRelevantEvents = (eventFlag->m.events | bits) & eventFlag->m.spuTaskWaitMask[i]; + + // Unblock the waiting SPU task if either all the bits being waited by the task have been set or + // if the wait mode of the task is OR and atleast one bit the thread is waiting on has been set + if ((eventFlag->m.spuTaskWaitMask[i] & ~spuTaskRelevantEvents) == 0 || + (((eventFlag->m.spuTaskWaitMode >> j) & 0x0001) == CELL_SPURS_EVENT_FLAG_OR && spuTaskRelevantEvents != 0)) { - tmp4 |= tmp6; - tmp5 |= 1 << j; - x30[j] = tmp6; + eventsToClear |= spuTaskRelevantEvents; + spuTaskPendingRecv |= 1 << j; + pendingRecvTaskEvents[j] = spuTaskRelevantEvents; } } - tmp >>= 1; + relevantWaitSlots >>= 1; i--; j++; } - eventFlag->m.bits |= bits; - eventFlag->m.x02 |= tmp5; + eventFlag->m.events |= bits; + eventFlag->m.spuTaskPendingRecv |= spuTaskPendingRecv; + + // If the clear flag is AUTO then clear the bits comnsumed by all tasks marked to be unblocked if (eventFlag->m.clearMode == CELL_SPURS_EVENT_FLAG_CLEAR_AUTO) { - eventFlag->m.bits &= ~tmp4; + eventFlag->m.events &= ~eventsToClear; } if (send) { - eventFlag->m.x30[tmp3] = tmp1; + // Signal the PPU thread to be woken up + eventFlag->m.pendingRecvTaskEvents[ppuWaitSlot] = ppuEventFlag; if (sys_event_port_send(eventFlag->m.eventPortId, 0, 0, 0) != CELL_OK) { assert(0); } } - if (tmp5) + if (spuTaskPendingRecv) { - for (auto i = 0; i < 16; i++) + // Signal each SPU task whose conditions have been met to be woken up + for (int i = 0; i < CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS; i++) { - if (tmp5 & (0x8000 >> i)) + if (spuTaskPendingRecv & (0x8000 >> i)) { - eventFlag->m.x30[i] = x30[i]; + eventFlag->m.pendingRecvTaskEvents[i] = pendingRecvTaskEvents[i]; vm::var taskset; if (eventFlag->m.isIwl) { - cellSpursLookUpTasksetAddress(vm::ptr::make((u32)eventFlag->m.addr), vm::ptr::make(taskset.addr()), eventFlag->m.x60[i]); + cellSpursLookUpTasksetAddress(vm::ptr::make((u32)eventFlag->m.addr), + vm::ptr::make(taskset.addr()), + eventFlag->m.waitingTaskWklId[i]); } else { taskset.value() = (u32)eventFlag->m.addr; } - auto rc = _cellSpursSendSignal(vm::ptr::make(taskset.addr()), eventFlag->m.x50[i]); + auto rc = _cellSpursSendSignal(vm::ptr::make(taskset.addr()), eventFlag->m.waitingTaskId[i]); if (rc == CELL_SPURS_TASK_ERROR_INVAL || rc == CELL_SPURS_TASK_ERROR_STAT) { return CELL_SPURS_TASK_ERROR_FATAL; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 1946675c54..172bd43b23 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -222,6 +222,13 @@ enum CellSpursEventFlagDirection CELL_SPURS_EVENT_FLAG_LAST = CELL_SPURS_EVENT_FLAG_ANY2ANY, }; +// Event flag constants +enum SpursEventFlagConstants +{ + CELL_SPURS_EVENT_FLAG_MAX_WAIT_SLOTS = 16, + CELL_SPURS_EVENT_FLAG_INVALID_SPU_PORT = 0xFF, +}; + class SPURSManager; class SPURSManagerEventFlag; class SPURSManagerTaskset; @@ -553,24 +560,24 @@ struct CellSpursEventFlag // Real data struct _CellSpursEventFlag { - be_t bits; // 0x00 Bit mask of event set bits - be_t x02; // 0x02 Bit mask of SPU thread slots whose conditions have met - be_t x04; // 0x04 Wait mask for PPU thread - u8 x06; // 0x06 Top 4 bits: Bit number for PPU thread. Bottom 4 bits: Wait mode of PPU thread - u8 x07; // 0x07 Set to 1 if the blocked PPU thread's condition has been met - be_t x08; // 0x08 Bit mask of used wait slots - be_t x0A; // 0x0A Bit mask of used wait slots whose wait mode is AND - u8 spuPort; // 0x0C - u8 isIwl; // 0x0D - u8 direction; // 0x0E - u8 clearMode; // 0x0F - be_t x10[16]; // 0x10 Wait mask for SPU threads - be_t x30[16]; // 0x30 Received event flag mask for SPU threads - u8 x50[16]; // 0x50 Task id of waiting SPU threads - u8 x60[16]; // 0x50 Workload Ids of waiting SPU threads - be_t addr; // 0x70 - be_t eventPortId; // 0x78 - be_t eventQueueId; // 0x7C + be_t events; // 0x00 Event bits + be_t spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks + be_t ppuWaitMask; // 0x04 Wait mask for blocked PPU thread + u8 ppuWaitSlotAndMode; // 0x06 Top 4 bits: Wait slot number of the blocked PPU threa, Bottom 4 bits: Wait mode of the blocked PPU thread + u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is ublocked + be_t spuTaskUsedWaitSlots; // 0x08 A bit is set to 1 if the wait slot corresponding to the bit is used by an SPU task and 0 otherwise + be_t spuTaskWaitMode; // 0x0A A bit is set to 1 if the wait mode for the SPU task corresponding to the bit is AND and 0 otherwise + u8 spuPort; // 0x0C + u8 isIwl; // 0x0D + u8 direction; // 0x0E + u8 clearMode; // 0x0F + be_t spuTaskWaitMask[16]; // 0x10 Wait mask for blocked SPU tasks + be_t pendingRecvTaskEvents[16]; // 0x30 The value of event flag when the wait condition for the thread/task was met + u8 waitingTaskId[16]; // 0x50 Task id of waiting SPU threads + u8 waitingTaskWklId[16]; // 0x60 Workload id of waiting SPU threads + be_t addr; // 0x70 + be_t eventPortId; // 0x78 + be_t eventQueueId; // 0x7C } m; static_assert(sizeof(_CellSpursEventFlag) == size, "Wrong _CellSpursEventFlag size"); From 430aa9af8912c0c00944e62a91f309153b15dd69 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 24 Jan 2015 00:41:29 +0530 Subject: [PATCH 16/94] SPURS: Implement cellSpursGetWorkloadData and cellSpursLookUpTasksetAddress --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 59 +++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index c8fc774ad8..294331a6b3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1469,12 +1469,12 @@ s64 cellSpursSendWorkloadSignal(vm::ptr spurs, u32 workloadId) #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0xA658, libsre_rtoc); #else - if (!spurs) + if (spurs.addr() == 0) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; } - if (spurs.addr() % CellSpurs::align) + if (spurs.addr() % CellSpurs::align) { return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; } @@ -1522,13 +1522,47 @@ s64 cellSpursSendWorkloadSignal(vm::ptr spurs, u32 workloadId) #endif } -s64 cellSpursGetWorkloadData() +s64 cellSpursGetWorkloadData(vm::ptr spurs, vm::ptr data, u32 workloadId) { + cellSpurs->Warning("%s(spurs_addr=0x%x, data=0x%x, workloadId=%d)", __FUNCTION__, spurs.addr(), data.addr(), workloadId); + #ifdef PRX_DEBUG - cellSpurs->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libsre + 0xA78C, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (spurs.addr() == 0 || data.addr() == 0) + { + return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; + } + + if (spurs.addr() % CellSpurs::align) + { + return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN; + } + + if (workloadId >= CELL_SPURS_MAX_WORKLOAD2 || (workloadId >= CELL_SPURS_MAX_WORKLOAD && (spurs->m.flags1 & SF1_32_WORKLOADS) == 0)) + { + return CELL_SPURS_POLICY_MODULE_ERROR_INVAL; + } + + if ((spurs->m.wklMskA.read_relaxed() & (0x80000000u >> workloadId)) == 0) + { + return CELL_SPURS_POLICY_MODULE_ERROR_SRCH; + } + + if (spurs->m.exception) + { + return CELL_SPURS_POLICY_MODULE_ERROR_STAT; + } + + if (workloadId >= CELL_SPURS_MAX_WORKLOAD) + { + *data = spurs->m.wklInfo2[workloadId & 0x0F].arg; + } + else + { + *data = spurs->m.wklInfo1[workloadId].arg; + } + return CELL_OK; #endif } @@ -3272,7 +3306,20 @@ s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr> data; + auto rc = cellSpursGetWorkloadData(spurs, vm::ptr::make(data.addr()), id); + if (rc != CELL_OK) + { + // Convert policy module error code to a task error code + return rc ^ 0x100; + } + + taskset.set((u32)data.value()); return CELL_OK; #endif } From 93504762632b7152029d44ba3a9d001b4b480f96 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 26 Jan 2015 01:38:50 +0300 Subject: [PATCH 17/94] psv_object_list_t template concept --- rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp | 8 ++ rpcs3/Emu/ARMv7/Modules/psv_sema_object.h | 11 +++ rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 15 +++- rpcs3/Emu/ARMv7/Modules/sceLibKernel.h | 14 +++ rpcs3/Emu/ARMv7/PSVObjectList.cpp | 3 + rpcs3/Emu/ARMv7/PSVObjectList.h | 96 +++++++++++++++++++++ rpcs3/emucore.vcxproj | 4 + rpcs3/emucore.vcxproj.filters | 15 ++++ 8 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_sema_object.h create mode 100644 rpcs3/Emu/ARMv7/PSVObjectList.cpp create mode 100644 rpcs3/Emu/ARMv7/PSVObjectList.h diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp new file mode 100644 index 0000000000..4e6046bd25 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp @@ -0,0 +1,8 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_sema_object.h" + +psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h new file mode 100644 index 0000000000..ee643cab4c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h @@ -0,0 +1,11 @@ +#pragma once + +struct psv_sema_t +{ + char name[32]; + u32 attr; + s32 initCount; + s32 maxCount; +}; + +extern psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index ac2600dc4b..fd852feae7 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -1,12 +1,14 @@ #include "stdafx.h" #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/SysCalls/Callback.h" #include "Emu/ARMv7/ARMv7Thread.h" #include "sceLibKernel.h" +#include "psv_sema_object.h" #define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; } @@ -450,7 +452,18 @@ s32 sceKernelCreateSema(vm::psv::ptr pName, u32 attr, s32 initCount, { sceLibKernel.Error("sceKernelCreateSema(pName=0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=0x%x)", pName, attr, initCount, maxCount, pOptParam); - throw __FUNCTION__; + std::shared_ptr sema(new psv_sema_t); + + strcpy_trunc(sema->name, pName.get_ptr()); + sema->attr = attr; + sema->initCount = initCount; + sema->maxCount = maxCount; + + const s32 id = g_psv_sema_list.add(sema); + + sceLibKernel.Error("*** semaphore created -> id=0x%x", id); + + return id; } s32 sceKernelDeleteSema(s32 semaId) diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h index dca20547c1..186c470b1c 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h @@ -251,6 +251,20 @@ enum SCE_KERNEL_ERROR_NO_AUTH = 0x8002F001, }; +enum psv_object_class_t : u32 +{ + SCE_KERNEL_UID_CLASS_PROCESS = 0, + SCE_KERNEL_THREADMGR_UID_CLASS_THREAD = 1, + SCE_KERNEL_THREADMGR_UID_CLASS_SEMA = 2, + SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG = 3, + SCE_KERNEL_THREADMGR_UID_CLASS_MUTEX = 4, + SCE_KERNEL_THREADMGR_UID_CLASS_COND = 5, + SCE_KERNEL_THREADMGR_UID_CLASS_TIMER = 6, + SCE_KERNEL_THREADMGR_UID_CLASS_MSG_PIPE = 7, + SCE_KERNEL_THREADMGR_UID_CLASS_CALLBACK = 8, + SCE_KERNEL_THREADMGR_UID_CLASS_THREAD_EVENT = 9, +}; + union SceKernelSysClock { struct diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.cpp b/rpcs3/Emu/ARMv7/PSVObjectList.cpp new file mode 100644 index 0000000000..d9cb43aeef --- /dev/null +++ b/rpcs3/Emu/ARMv7/PSVObjectList.cpp @@ -0,0 +1,3 @@ +#include "stdafx.h" +#include "PSVObjectList.h" + diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h new file mode 100644 index 0000000000..16d026f21e --- /dev/null +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -0,0 +1,96 @@ +#pragma once + +union uid_t +{ + // true UID format is partially unknown + s32 uid; + + struct + { + u32 oddness : 1; // always 1 for UIDs (to not mess it up with addresses) + u32 number : 15; // ID from 0 to 2^15-1 + u32 type : 15; // UID class (psv_object_class_t) + u32 sign : 1; // UIDs are positive, error codes are negative + }; + + static uid_t make(s32 uid) + { + uid_t result; + result.uid = uid; + return result; + } +}; + +template +class psv_object_list_t // Class for managing object data +{ + std::array, 0x8000> m_data; + +public: + static const u32 uid_class = type; + + // check if UID is potentially valid (will return true if the object doesn't exist) + bool check(s32 uid) + { + const uid_t id = uid_t::make(uid); + + // check sign bit, uid class and ensure that value is odd + return !id.sign && id.type == uid_class && id.oddness == 1; + } + + // share object with UID specified (will return empty pointer if the object doesn't exist or the UID is invalid) + std::shared_ptr find(s32 uid) + { + if (!check(uid)) + { + return nullptr; + } + + return m_data[uid_t::make(uid).number]; + } + + std::shared_ptr operator [](s32 uid) + { + return find(uid); + } + + // generate UID for newly created object (will return zero if the limit exceeded) + s32 add(std::shared_ptr& data) + { + for (auto& value : m_data) + { + // find an empty position and move the pointer + std::shared_ptr old_ptr = nullptr; + if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) + { + uid_t id = uid_t::make(1); // odd number + id.type = uid_class; // set type + id.number = &value - m_data.data(); // set position + return id.uid; + } + } + + return 0; + } + + // remove object with UID specified and share it for the last time (will return empty pointer if the object doesn't exists or the UID is invalid) + std::shared_ptr remove(s32 uid) + { + if (!check(uid)) + { + return nullptr; + } + + return std::atomic_exchange(&m_data[uid_t::make(uid).number], nullptr); + } + + // remove all objects + void clear() + { + for (auto& value : m_data) + { + value = nullptr; + } + } +}; + diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 4b4a2d6539..da233b2c30 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -56,11 +56,13 @@ + + @@ -274,8 +276,10 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index fdd71b410a..887600c974 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -87,6 +87,9 @@ {1d6abf72-0f18-43ec-9351-1fed1a3d1a1e} + + {368770cf-c8d9-4f4a-9ac3-5bdf48101ffe} + @@ -665,6 +668,12 @@ Emu\CPU\ARMv7 + + Emu\CPU\ARMv7\Thread Manager + + + Emu\CPU\ARMv7 + @@ -1294,5 +1303,11 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Thread Manager + + + Emu\CPU\ARMv7 + \ No newline at end of file From 12c13e619321365c66067cf545dcc143704efd5b Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 26 Jan 2015 09:13:11 +0300 Subject: [PATCH 18/94] Fix --- rpcs3/Emu/ARMv7/PSVObjectList.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 16d026f21e..5fb6b5da93 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -1,6 +1,6 @@ #pragma once -union uid_t +union psv_uid_t { // true UID format is partially unknown s32 uid; @@ -13,9 +13,9 @@ union uid_t u32 sign : 1; // UIDs are positive, error codes are negative }; - static uid_t make(s32 uid) + static psv_uid_t make(s32 uid) { - uid_t result; + psv_uid_t result; result.uid = uid; return result; } @@ -32,7 +32,7 @@ public: // check if UID is potentially valid (will return true if the object doesn't exist) bool check(s32 uid) { - const uid_t id = uid_t::make(uid); + const psv_uid_t id = psv_uid_t::make(uid); // check sign bit, uid class and ensure that value is odd return !id.sign && id.type == uid_class && id.oddness == 1; @@ -46,7 +46,7 @@ public: return nullptr; } - return m_data[uid_t::make(uid).number]; + return m_data[psv_uid_t::make(uid).number]; } std::shared_ptr operator [](s32 uid) @@ -63,7 +63,7 @@ public: std::shared_ptr old_ptr = nullptr; if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) { - uid_t id = uid_t::make(1); // odd number + psv_uid_t id = psv_uid_t::make(1); // odd number id.type = uid_class; // set type id.number = &value - m_data.data(); // set position return id.uid; @@ -81,7 +81,7 @@ public: return nullptr; } - return std::atomic_exchange(&m_data[uid_t::make(uid).number], nullptr); + return std::atomic_exchange(&m_data[psv_uid_t::make(uid).number], nullptr); } // remove all objects From a7d85480a85b3c632919f6ccee3b3bc4dcfc7dbc Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 26 Jan 2015 15:55:26 +0300 Subject: [PATCH 19/94] Fixes --- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 +- rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp | 2 -- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 9 ++++++++- rpcs3/Emu/ARMv7/PSVObjectList.cpp | 12 +++++++++++- rpcs3/Emu/ARMv7/PSVObjectList.h | 19 ++++++++++++++++--- rpcs3/Emu/System.cpp | 2 ++ 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 491e0a0845..c0aebaff78 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -79,8 +79,8 @@ struct ARMv7Context { struct { - u8 cond : 3; u8 state : 5; + u8 cond : 3; }; u8 IT; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp index 4e6046bd25..0e67d72444 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp @@ -4,5 +4,3 @@ #include "Emu/ARMv7/PSVObjectList.h" #include "sceLibKernel.h" #include "psv_sema_object.h" - -psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index fd852feae7..e033e4ef22 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -468,7 +468,14 @@ s32 sceKernelCreateSema(vm::psv::ptr pName, u32 attr, s32 initCount, s32 sceKernelDeleteSema(s32 semaId) { - throw __FUNCTION__; + sceLibKernel.Error("sceKernelDeleteSema(semaId=0x%x)", semaId); + + if (!g_psv_sema_list.remove(semaId)) + { + RETURN_ERROR(SCE_KERNEL_ERROR_INVALID_UID); + } + + throw SCE_OK; } s32 sceKernelOpenSema(vm::psv::ptr pName) diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.cpp b/rpcs3/Emu/ARMv7/PSVObjectList.cpp index d9cb43aeef..c90ebf20da 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.cpp +++ b/rpcs3/Emu/ARMv7/PSVObjectList.cpp @@ -1,3 +1,13 @@ #include "stdafx.h" -#include "PSVObjectList.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "Modules/sceLibKernel.h" +#include "Modules/psv_sema_object.h" +psv_object_list_t g_psv_sema_list; + +void clear_all_psv_objects() +{ + g_psv_sema_list.clear(); +} diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 5fb6b5da93..d25c6e39ce 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -25,6 +25,7 @@ template class psv_object_list_t // Class for managing object data { std::array, 0x8000> m_data; + std::mutex m_mutex; // TODO: remove it when shared_ptr atomic ops are fully available public: static const u32 uid_class = type; @@ -57,12 +58,16 @@ public: // generate UID for newly created object (will return zero if the limit exceeded) s32 add(std::shared_ptr& data) { + std::lock_guard lock(m_mutex); + for (auto& value : m_data) { // find an empty position and move the pointer - std::shared_ptr old_ptr = nullptr; - if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) + //std::shared_ptr old_ptr = nullptr; + //if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) + if (!value) { + value = data; psv_uid_t id = psv_uid_t::make(1); // odd number id.type = uid_class; // set type id.number = &value - m_data.data(); // set position @@ -81,12 +86,19 @@ public: return nullptr; } - return std::atomic_exchange(&m_data[psv_uid_t::make(uid).number], nullptr); + std::lock_guard lock(m_mutex); + + std::shared_ptr old_ptr = nullptr; + m_data[psv_uid_t::make(uid).number].swap(old_ptr); + return old_ptr; + //return std::atomic_exchange>(&m_data[psv_uid_t::make(uid).number], nullptr); } // remove all objects void clear() { + std::lock_guard lock(m_mutex); + for (auto& value : m_data) { value = nullptr; @@ -94,3 +106,4 @@ public: } }; +void clear_all_psv_objects(); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 9e17b56ddf..8324e0e54f 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -6,6 +6,7 @@ #include "Emu/GameInfo.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" #include "Emu/SysCalls/Static.h" #include "Emu/SysCalls/ModuleManager.h" #include "Emu/Cell/PPUThread.h" @@ -363,6 +364,7 @@ void Emulator::Stop() LOG_NOTICE(HLE, "All threads stopped..."); finalize_psv_modules(); + clear_all_psv_objects(); m_rsx_callback = 0; // TODO: check finalization order From 2e2f92f4f64a7ddea7a020a907cc1dcb9dfb7aba Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Mon, 26 Jan 2015 20:15:58 +0530 Subject: [PATCH 20/94] SPURS: Implement some portions of taskset policy module --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 33 ++++- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 142 +++++++++++++++++++- 3 files changed, 170 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 294331a6b3..99d2d35eea 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1702,7 +1702,7 @@ s64 _cellSpursEventFlagInitialize(vm::ptr spurs, vm::ptr attribute, u32 revision, u32 sdk_version, u64 args, vm::ptr priority, u32 max_contention) { - cellSpurs->Warning("%s(attribute=0x%x, revision=%u, skd_version=%u, args=0x%llx, priority=0x%x, max_contention=%u)", + cellSpurs->Warning("%s(attribute=0x%x, revision=%d, skd_version=%d, args=0x%llx, priority=0x%x, max_contention=%d)", __FUNCTION__, attribute.addr(), revision, sdk_version, args, priority.addr(), max_contention); #ifdef PRX_DEBUG diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 172bd43b23..196fedd3a8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -564,7 +564,7 @@ struct CellSpursEventFlag be_t spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks be_t ppuWaitMask; // 0x04 Wait mask for blocked PPU thread u8 ppuWaitSlotAndMode; // 0x06 Top 4 bits: Wait slot number of the blocked PPU threa, Bottom 4 bits: Wait mode of the blocked PPU thread - u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is ublocked + u8 ppuPendingRecv; // 0x07 Set to 1 when the blocked PPU thread's conditions are met and back to 0 when the PPU thread is unblocked be_t spuTaskUsedWaitSlots; // 0x08 A bit is set to 1 if the wait slot corresponding to the bit is used by an SPU task and 0 otherwise be_t spuTaskWaitMode; // 0x0A A bit is set to 1 if the wait mode for the SPU task corresponding to the bit is AND and 0 otherwise u8 spuPort; // 0x0C @@ -852,8 +852,9 @@ struct CellSpursTaskBinInfo CellSpursTaskLsPattern lsPattern; }; -// The SPURS kernel data store. This resides at 0x00 of the LS. -struct SpursKernelMgmtData { +// The SPURS kernel data store. This resides at 0x100 of the LS. +struct SpursKernelMgmtData +{ u8 tempArea[0x80]; // 0x100 u8 wklLocContention[0x10]; // 0x180 u8 wklLocPendingContention[0x10]; // 0x190 @@ -867,8 +868,7 @@ struct SpursKernelMgmtData { be_t wklCurrentId; // 0x1DC be_t yieldToKernelAddr; // 0x1E0 be_t selectWorkloadAddr; // 0x1E4 - u8 x1E8; // 0x1E8 - u8 x1E9; // 0x1E9 + u8 moduleId[2]; // 0x1E8 u8 sysSrvInitialised; // 0x1EA u8 spuIdling; // 0x1EB be_t wklRunnable1; // 0x1EC @@ -880,5 +880,28 @@ struct SpursKernelMgmtData { u8 wklUniqueId[0x10]; // 0x220 }; +static_assert(sizeof(SpursKernelMgmtData) == 0x130, "Incorrect size for SpursKernelMgmtData"); + +// The SPURS taskset policy module data store. This resides at 0x2700 of the LS. +struct SpursTasksetPmMgmtData +{ + u8 tempArea[0x80]; // 0x2700 + u8 x2780[0x27B8 - 0x2780]; // 0x2780 + vm::bptr taskset; // 0x27B8 + be_t kernelMgmt; // 0x27C0 + be_t yieldAddr; // 0x27C4 + be_t x27C8; // 0x27C8 + be_t spuNum; // 0x27CC + be_t dmaTagId; // 0x27D0 + be_t taskId; // 0x27D4 + u8 x27D8[0x2840 - 0x27D8]; // 0x27D8 + u8 moduleId[16]; // 0x2840 + u8 x2850[0x2C80 - 0x2850]; // 0x2850 + be_t contextSaveArea[50]; // 0x2C80 + u8 x2FA0[0x3000 - 0x2FA0]; // 0x2FA0 +}; + +static_assert(sizeof(SpursTasksetPmMgmtData) == 0x900, "Incorrect size for SpursTasksetPmMgmtData"); + s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); s64 spursWakeUp(PPUThread& CPU, vm::ptr spurs); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 06ff2553be..624be7e805 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -33,6 +33,10 @@ void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt); void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus); void spursSysServiceWorkloadEntry(SPUThread & spu); +// +// SPURS taskset polict module functions +// + extern Module *cellSpurs; ////////////////////////////////////////////////////////////////////////////// @@ -378,8 +382,8 @@ void spursKernelMain(SPUThread & spu) { } if (!isSecond) { - mgmt->x1E8 = 0; - mgmt->x1E9 = 0; + mgmt->moduleId[0] = 0; + mgmt->moduleId[1] = 0; } // Run workload @@ -387,6 +391,7 @@ void spursKernelMain(SPUThread & spu) { spu.GPR[3]._u32[3] = 0x100; spu.GPR[4]._u64[1] = wkl.arg; spu.GPR[5]._u32[3] = pollStatus; + spu.SetPc(0xA00); switch (mgmt->wklCurrentAddr.addr()) { case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: spursSysServiceWorkloadEntry(spu); @@ -797,3 +802,136 @@ void spursSysServiceWorkloadEntry(SPUThread & spu) { // TODO: Ensure that this function always returns to the SPURS kernel return; } + +////////////////////////////////////////////////////////////////////////////// +// SPURS taskset policy module functions +////////////////////////////////////////////////////////////////////////////// + +bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting) { + auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + + // Verify taskset state is valid + for (auto i = 0; i < 4; i ++) { + if ((mgmt->taskset->m.waiting_set[i] & mgmt->taskset->m.running_set[i]) || + (mgmt->taskset->m.ready_set[i] & mgmt->taskset->m.ready2_set[i]) || + ((mgmt->taskset->m.running_set[i] | mgmt->taskset->m.ready_set[i] | + mgmt->taskset->m.ready2_set[i] | mgmt->taskset->m.signal_received_set[i] | + mgmt->taskset->m.waiting_set[i]) & ~mgmt->taskset->m.enabled_set[i])) { + assert(0); + } + } + + // TODO: Implement cases + s32 delta = 0; + switch (request + 1) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + default: + assert(0); + break; + } + + // Set the ready count of the workload to the number of ready tasks + do { + s32 readyCount = kernelMgmt->wklCurrentId >= CELL_SPURS_MAX_WORKLOAD ? + kernelMgmt->spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].read_relaxed() : + kernelMgmt->spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].read_relaxed(); + + auto newReadyCount = readyCount + delta > 0xFF ? 0xFF : readyCount + delta < 0 ? 0 : readyCount + delta; + + if (kernelMgmt->wklCurrentId >= CELL_SPURS_MAX_WORKLOAD) { + kernelMgmt->spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].write_relaxed(newReadyCount); + } else { + kernelMgmt->spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].write_relaxed(newReadyCount); + } + + delta += readyCount; + } while (delta > 0); + + // TODO: Implement return + return false; +} + +void spursTasksetDispatch() { +} + +void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { + if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) { + spursTasksetProcessRequest(spu, 6, nullptr, nullptr); + } +} + +bool spursTasksetShouldYield(SPUThread & spu) { + u32 pollStatus; + + if (cellSpursModulePollStatus(spu, &pollStatus)) { + return true; + } + + spursTasksetProcessPollStatus(spu, pollStatus); + return false; +} + +void spursTasksetInit(SPUThread & spu, u32 pollStatus) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); + + kernelMgmt->moduleId[0] = 'T'; + kernelMgmt->moduleId[1] = 'K'; + + // Trace - START: Module='TKST' + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = 0x52; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_START + memcpy(pkt.data.start.module, "TKST", 4); + pkt.data.start.level = 2; + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + spursTasksetProcessPollStatus(spu, pollStatus); +} + +void spursTasksetEntry(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + + // Check if the function was invoked by the SPURS kernel or because of a syscall + if (spu.PC != 0xA70) { + // Called from kernel + auto kernelMgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); + auto arg = spu.GPR[4]._u64[1]; + auto pollStatus = spu.GPR[5]._u32[3]; + + memset(mgmt, 0, sizeof(*mgmt)); + mgmt->taskset.set(arg); + memcpy(mgmt->moduleId, "SPURSTASK MODULE", 16); + mgmt->kernelMgmt = spu.GPR[3]._u32[3]; + mgmt->yieldAddr = 0xA70; + mgmt->spuNum = kernelMgmt->spuNum; + mgmt->dmaTagId = kernelMgmt->dmaTagId; + mgmt->taskId = 0xFFFFFFFF; + + spursTasksetInit(spu, pollStatus); + // TODO: Dispatch + } + + mgmt->contextSaveArea[0] = spu.GPR[0]; + mgmt->contextSaveArea[1] = spu.GPR[1]; + for (auto i = 0; i < 48; i++) { + mgmt->contextSaveArea[i + 2] = spu.GPR[80 + i]; + } + + // TODO: Process syscall +} From 81340e9d5c3667b108579a71cfcf264158a641d3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 27 Jan 2015 03:19:51 +0300 Subject: [PATCH 21/94] scePerf stub, sceSysmodule, sema, ef --- rpcs3/Emu/ARMv7/ARMv7Context.h | 20 +++-- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 57 +++++++------ rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 4 +- rpcs3/Emu/ARMv7/Modules/psv_event_flag.cpp | 13 +++ rpcs3/Emu/ARMv7/Modules/psv_event_flag.h | 21 +++++ rpcs3/Emu/ARMv7/Modules/psv_sema.cpp | 14 ++++ rpcs3/Emu/ARMv7/Modules/psv_sema.h | 23 ++++++ rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp | 6 -- rpcs3/Emu/ARMv7/Modules/psv_sema_object.h | 11 --- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 20 ++--- rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp | 9 ++- rpcs3/Emu/ARMv7/Modules/scePerf.cpp | 90 +++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp | 39 +++++++++ rpcs3/Emu/ARMv7/PSVFuncList.cpp | 6 +- rpcs3/Emu/ARMv7/PSVObjectList.cpp | 5 +- rpcs3/Emu/Memory/vm_var.h | 9 ++- rpcs3/Emu/SysCalls/Callback.h | 16 ++-- rpcs3/emucore.vcxproj | 8 +- rpcs3/emucore.vcxproj.filters | 26 ++++-- 19 files changed, 310 insertions(+), 87 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_event_flag.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_event_flag.h create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_sema.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_sema.h delete mode 100644 rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp delete mode 100644 rpcs3/Emu/ARMv7/Modules/psv_sema_object.h create mode 100644 rpcs3/Emu/ARMv7/Modules/scePerf.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index c0aebaff78..873f039555 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -79,20 +79,26 @@ struct ARMv7Context { struct { - u8 state : 5; - u8 cond : 3; + u8 shift_state : 5; + u8 cond_base : 3; + }; + + struct + { + u8 check_state : 4; + u8 condition : 4; }; u8 IT; u32 advance() { - const u32 res = (state & 0xf) ? (cond << 1 | state >> 4) : 0xe /* true */; + const u32 res = check_state ? condition : 0xe /* always true */; - state <<= 1; - if ((state & 0xf) == 0) // if no d + shift_state <<= 1; + if (!check_state) { - IT = 0; // clear ITSTATE + IT = 0; // clear } return res; @@ -100,7 +106,7 @@ struct ARMv7Context operator bool() const { - return (state & 0xf) != 0; + return check_state; } } ITSTATE; diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index f913bcbb8a..8a361014f4 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -140,7 +140,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR), - ARMv7_OP2(0xff00, 0xbf00, T1, IT), + ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )), ARMv7_OP2(0xf800, 0xc800, T1, LDM), ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM), @@ -1208,10 +1208,14 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) { LOG_ERROR(ARMv7, "Unknown instruction found at address 0x%08x: %04x %04x", addr, code.code1, code.code0); addr += 4; + continue; } - else + + // Proceed with found: + + if (dump) { - if (dump) if (found->length == 2) + if (found->length == 2) { LOG_NOTICE(ARMv7, "0x%08x: %04x %s", addr, code.code0, found->name); } @@ -1219,34 +1223,39 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) { LOG_NOTICE(ARMv7, "0x%08x: %04x %04x %s", addr, code.code1, code.code0, found->name); } + } - if (found->func == ARMv7_instrs::BLX && found->type == T2) + if (found->func == ARMv7_instrs::BLX && found->type == T2) + { + const u32 s = (code.data >> 26) & 0x1; + const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; + const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; + const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + + // possibly a call to imported function: + if (target >= end_addr && ((target - end_addr) % 16) == 0 && vm::psv::read16(target) == 0xf870) { - const u32 s = (code.data >> 26) & 0x1; - const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; - const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + const u32 instr = vm::psv::read32(target); - // possibly a call to imported function: - if (target >= end_addr && ((target - end_addr) % 16) == 0 && vm::psv::read16(target) == 0xf870) + // check if not "unimplemented" + if (instr >> 16) { - const u32 instr = vm::psv::read32(target); - - // check if not "unimplemented" - if (instr >> 16) - { - // replace BLX with "hack" instruction directly, it can help to see where it was called from - vm::psv::write32(addr, instr); - } - } - else - { - LOG_ERROR(ARMv7, "Unrecognized BLX call found at adddress 0x%08x (target=0x%08x)", addr, target); + // replace BLX with "hack" instruction directly, it can help to see where it was called from + vm::psv::write32(addr, instr); } } - - addr += found->length; + else + { + LOG_ERROR(ARMv7, "Unrecognized BLX call found at adddress 0x%08x (target=0x%08x)", addr, target); + } } + + //if (found->func == ARMv7_instrs::IT) + //{ + // LOG_ERROR(ARMv7, "IT instruction found at address 0x%08x", addr); + //} + + addr += found->length; } while (vm::psv::read16(addr) == 0xf870) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index e6cd7dc651..71d91acad9 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -965,7 +965,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ } case A2: { - cond = 15; + cond = 0xe; // always true newLR = (context.thread.PC + 4) - 4; target = (context.thread.PC + 4 | 1) + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23); break; @@ -1871,7 +1871,7 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR } case T2: { - cond = 15; + cond = 0xe; // always true d = (code.data & 0x7); m = (code.data & 0x38) >> 3; set_flags = true; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.cpp b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.cpp new file mode 100644 index 0000000000..14c9af11bc --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_event_flag.h" + +psv_event_flag_t::psv_event_flag_t(const char* name, u32 attr, u32 pattern) + : attr(attr) + , pattern(pattern) +{ + strcpy_trunc(this->name, name); +} diff --git a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h new file mode 100644 index 0000000000..bc1cb2d4e9 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h @@ -0,0 +1,21 @@ +#pragma once + +struct psv_event_flag_t +{ + char name[32]; + u32 attr; + u32 pattern; + +private: + psv_event_flag_t() = delete; + psv_event_flag_t(const psv_event_flag_t&) = delete; + psv_event_flag_t(psv_event_flag_t&&) = delete; + + psv_event_flag_t& operator =(const psv_event_flag_t&) = delete; + psv_event_flag_t& operator =(psv_event_flag_t&&) = delete; + +public: + psv_event_flag_t(const char* name, u32 attr, u32 pattern); +}; + +extern psv_object_list_t g_psv_ef_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema.cpp b/rpcs3/Emu/ARMv7/Modules/psv_sema.cpp new file mode 100644 index 0000000000..20527eb5b3 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema.cpp @@ -0,0 +1,14 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_sema.h" + +psv_sema_t::psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value) + : attr(attr) + , value(init_value) + , max(max_value) +{ + strcpy_trunc(this->name, name); +} diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema.h b/rpcs3/Emu/ARMv7/Modules/psv_sema.h new file mode 100644 index 0000000000..30b3fa6c4c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema.h @@ -0,0 +1,23 @@ +#pragma once + +struct psv_sema_t +{ + char name[32]; + u32 attr; + s32 value; + s32 max; + +private: + psv_sema_t() = delete; + psv_sema_t(const psv_sema_t&) = delete; + psv_sema_t(psv_sema_t&&) = delete; + + psv_sema_t& operator =(const psv_sema_t&) = delete; + psv_sema_t& operator =(psv_sema_t&&) = delete; + +public: + psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value); + +}; + +extern psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp deleted file mode 100644 index 0e67d72444..0000000000 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "stdafx.h" -#include "Emu/Memory/Memory.h" -#include "Emu/ARMv7/PSVFuncList.h" -#include "Emu/ARMv7/PSVObjectList.h" -#include "sceLibKernel.h" -#include "psv_sema_object.h" diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h b/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h deleted file mode 100644 index ee643cab4c..0000000000 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema_object.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -struct psv_sema_t -{ - char name[32]; - u32 attr; - s32 initCount; - s32 maxCount; -}; - -extern psv_object_list_t g_psv_sema_list; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index e033e4ef22..25fa75c47c 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -8,7 +8,8 @@ #include "Emu/ARMv7/ARMv7Thread.h" #include "sceLibKernel.h" -#include "psv_sema_object.h" +#include "psv_sema.h" +#include "psv_event_flag.h" #define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; } @@ -393,7 +394,13 @@ s32 sceKernelWaitMultipleEventsCB(vm::psv::ptr pWaitEventLis s32 sceKernelCreateEventFlag(vm::psv::ptr pName, u32 attr, u32 initPattern, vm::psv::ptr pOptParam) { - throw __FUNCTION__; + sceLibKernel.Error("sceKernelCreateEventFlag(pName=0x%x, attr=0x%x, initPattern=0x%x, pOptParam=0x%x)", pName, attr, initPattern, pOptParam); + + std::shared_ptr ef(new psv_event_flag_t(pName.get_ptr(), attr, initPattern)); + + const s32 id = g_psv_ef_list.add(ef); + + return id; } s32 sceKernelDeleteEventFlag(s32 evfId) @@ -452,17 +459,10 @@ s32 sceKernelCreateSema(vm::psv::ptr pName, u32 attr, s32 initCount, { sceLibKernel.Error("sceKernelCreateSema(pName=0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=0x%x)", pName, attr, initCount, maxCount, pOptParam); - std::shared_ptr sema(new psv_sema_t); - - strcpy_trunc(sema->name, pName.get_ptr()); - sema->attr = attr; - sema->initCount = initCount; - sema->maxCount = maxCount; + std::shared_ptr sema(new psv_sema_t(pName.get_ptr(), attr, initCount, maxCount)); const s32 id = g_psv_sema_list.add(sema); - sceLibKernel.Error("*** semaphore created -> id=0x%x", id); - return id; } diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp index 44b3b75ff8..2342f1f8c5 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp @@ -25,7 +25,8 @@ namespace sce_libstdcxx_func } } -#define REG_FUNC(nid, name) reg_psv_func(nid, &sceLibstdcxx, #name, &sce_libstdcxx_func::name) +// Attention: find and set correct original mangled name in third parameter, for example: REG_FUNC(0xAE71DC3, operator_new_nothrow, "_ZnwjRKSt9nothrow_t"); +#define REG_FUNC(nid, name, orig_name) reg_psv_func(nid, &sceLibstdcxx, orig_name, &sce_libstdcxx_func::name) psv_log_base sceLibstdcxx("SceLibstdcxx", []() { @@ -376,9 +377,9 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xE7889A5B, _Unwind_VRS_Get); //REG_FUNC(0xF106D050, _Unwind_VRS_Pop); //REG_FUNC(0x91CDA2F9, _Unwind_VRS_Set); - REG_FUNC(0x173E7421, __aeabi_unwind_cpp_pr0); - REG_FUNC(0x3C78DDE3, __aeabi_unwind_cpp_pr1); - REG_FUNC(0xF95BDD36, __aeabi_unwind_cpp_pr2); + REG_FUNC(0x173E7421, __aeabi_unwind_cpp_pr0, "__aeabi_unwind_cpp_pr0"); + REG_FUNC(0x3C78DDE3, __aeabi_unwind_cpp_pr1, "__aeabi_unwind_cpp_pr1"); + REG_FUNC(0xF95BDD36, __aeabi_unwind_cpp_pr2, "__aeabi_unwind_cpp_pr2"); //REG_FUNC(0x8C93EFDA, __cxa_allocate_exception); //REG_FUNC(0x6165EE89, __cxa_begin_catch); //REG_FUNC(0x5D74285C, __cxa_begin_cleanup); diff --git a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp new file mode 100644 index 0000000000..d83e6d5f22 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp @@ -0,0 +1,90 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base scePerf; + +s32 scePerfArmPmonReset(s32 threadId) +{ + scePerf.Todo("scePerfArmPmonReset(threadId=0x%x)", threadId); + + return SCE_OK; +} + +s32 scePerfArmPmonSelectEvent(s32 threadId, u32 counter, u8 eventCode) +{ + throw __FUNCTION__; +} + +s32 scePerfArmPmonStart(s32 threadId) +{ + throw __FUNCTION__; +} + +s32 scePerfArmPmonStop(s32 threadId) +{ + throw __FUNCTION__; +} + +s32 scePerfArmPmonGetCounterValue(s32 threadId, u32 counter, vm::psv::ptr pValue) +{ + throw __FUNCTION__; +} + +s32 scePerfArmPmonSoftwareIncrement(u32 mask) +{ + throw __FUNCTION__; +} + +u64 scePerfGetTimebaseValue() +{ + throw __FUNCTION__; +} + +u32 scePerfGetTimebaseFrequency() +{ + throw __FUNCTION__; +} + +s32 _sceRazorCpuInit(vm::psv::ptr pBufferBase, u32 bufferSize, u32 numPerfCounters, vm::psv::ptr> psceRazorVars) +{ + throw __FUNCTION__; +} + +s32 sceRazorCpuPushMarker(vm::psv::ptr szLabel) +{ + throw __FUNCTION__; +} + +s32 sceRazorCpuPopMarker() +{ + throw __FUNCTION__; +} + +s32 sceRazorCpuSync() +{ + throw __FUNCTION__; +} + +#define REG_FUNC(nid, name) reg_psv_func(nid, &scePerf, #name, name) + +psv_log_base scePerf("ScePerf", []() +{ + scePerf.on_load = nullptr; + scePerf.on_unload = nullptr; + scePerf.on_stop = nullptr; + + REG_FUNC(0x35151735, scePerfArmPmonReset); + REG_FUNC(0x63CBEA8B, scePerfArmPmonSelectEvent); + REG_FUNC(0xC9D969D5, scePerfArmPmonStart); + REG_FUNC(0xD1A40F54, scePerfArmPmonStop); + REG_FUNC(0x6132A497, scePerfArmPmonGetCounterValue); + //REG_FUNC(0x12F6C708, scePerfArmPmonSetCounterValue); + REG_FUNC(0x4264B4E7, scePerfArmPmonSoftwareIncrement); + REG_FUNC(0xBD9615E5, scePerfGetTimebaseValue); + REG_FUNC(0x78EA4FFB, scePerfGetTimebaseFrequency); + REG_FUNC(0x7AD6AC30, _sceRazorCpuInit); + REG_FUNC(0xC3DE4C0A, sceRazorCpuPushMarker); + REG_FUNC(0xDC3224C3, sceRazorCpuPopMarker); + REG_FUNC(0x4F1385E3, sceRazorCpuSync); +}); \ No newline at end of file diff --git a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp new file mode 100644 index 0000000000..6584de337a --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp @@ -0,0 +1,39 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSysmodule; + +s32 sceSysmoduleLoadModule(u16 id) +{ + sceSysmodule.Todo("sceSysmoduleLoadModule(id=0x%04x)", id); + + return SCE_OK; // loading succeeded +} + +s32 sceSysmoduleUnloadModule(u16 id) +{ + sceSysmodule.Todo("sceSysmoduleUnloadModule(id=0x%04x)", id); + + return SCE_OK; // unloading succeeded +} + +s32 sceSysmoduleIsLoaded(u16 id) +{ + sceSysmodule.Todo("sceSysmoduleIsLoaded(id=0x%04x)", id); + + return SCE_OK; // module is loaded +} + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSysmodule, #name, name) + +psv_log_base sceSysmodule("SceSysmodule", []() +{ + sceSysmodule.on_load = nullptr; + sceSysmodule.on_unload = nullptr; + sceSysmodule.on_stop = nullptr; + + REG_FUNC(0x79A0160A, sceSysmoduleLoadModule); + REG_FUNC(0x31D87805, sceSysmoduleUnloadModule); + REG_FUNC(0x53099B7A, sceSysmoduleIsLoaded); +}); diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index bd17628f20..05d9b4c483 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -48,6 +48,8 @@ extern psv_log_base sceLibc; extern psv_log_base sceLibm; extern psv_log_base sceLibstdcxx; extern psv_log_base sceLibKernel; +extern psv_log_base sceSysmodule; +extern psv_log_base scePerf; void initialize_psv_modules() { @@ -58,6 +60,8 @@ void initialize_psv_modules() g_psv_modules.push_back(&sceLibm); g_psv_modules.push_back(&sceLibstdcxx); g_psv_modules.push_back(&sceLibKernel); + g_psv_modules.push_back(&sceSysmodule); + g_psv_modules.push_back(&scePerf); // setup special functions (without NIDs) psv_func unimplemented; @@ -66,7 +70,7 @@ void initialize_psv_modules() unimplemented.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) { context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4); - throw "Unimplemented function executed"; + throw "Unimplemented function"; })); g_psv_func_list.push_back(unimplemented); diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.cpp b/rpcs3/Emu/ARMv7/PSVObjectList.cpp index c90ebf20da..cc8e97a1c0 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.cpp +++ b/rpcs3/Emu/ARMv7/PSVObjectList.cpp @@ -3,11 +3,14 @@ #include "Emu/ARMv7/PSVFuncList.h" #include "Emu/ARMv7/PSVObjectList.h" #include "Modules/sceLibKernel.h" -#include "Modules/psv_sema_object.h" +#include "Modules/psv_sema.h" +#include "Modules/psv_event_flag.h" psv_object_list_t g_psv_sema_list; +psv_object_list_t g_psv_ef_list; void clear_all_psv_objects() { g_psv_sema_list.clear(); + g_psv_ef_list.clear(); } diff --git a/rpcs3/Emu/Memory/vm_var.h b/rpcs3/Emu/Memory/vm_var.h index 95ea373f9e..06864950b9 100644 --- a/rpcs3/Emu/Memory/vm_var.h +++ b/rpcs3/Emu/Memory/vm_var.h @@ -517,11 +517,12 @@ namespace vm ptr = vm::get_ptr(addr); } + private: stack_allocation() = delete; - stack_allocation(const stack_allocation& r) = delete; - stack_allocation(stack_allocation&& r) = delete; - stack_allocation& operator = (const stack_allocation& r) = delete; - stack_allocation& operator = (stack_allocation&& r) = delete; + stack_allocation(const stack_allocation&) = delete; + stack_allocation(stack_allocation&&) = delete; + stack_allocation& operator = (const stack_allocation&) = delete; + stack_allocation& operator = (stack_allocation&&) = delete; } const m_data; diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index 2e8c64cf92..6918d338a3 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -42,6 +42,14 @@ class PauseCallbackRegisterer CallbackManager& cb_manager; u64 cb_tag; +private: + PauseCallbackRegisterer() = delete; + PauseCallbackRegisterer(const PauseCallbackRegisterer& right) = delete; + PauseCallbackRegisterer(PauseCallbackRegisterer&& right) = delete; + + PauseCallbackRegisterer& operator =(const PauseCallbackRegisterer& right) = delete; + PauseCallbackRegisterer& operator =(PauseCallbackRegisterer&& right) = delete; + public: PauseCallbackRegisterer(CallbackManager& cb_manager, const std::function& func) : cb_manager(cb_manager) @@ -49,16 +57,8 @@ public: { } - PauseCallbackRegisterer() = delete; - PauseCallbackRegisterer(const PauseCallbackRegisterer& right) = delete; - PauseCallbackRegisterer(PauseCallbackRegisterer&& right) = delete; - ~PauseCallbackRegisterer() { cb_manager.RemovePauseCallback(cb_tag); } - - PauseCallbackRegisterer& operator =(const PauseCallbackRegisterer& right) = delete; - PauseCallbackRegisterer& operator =(PauseCallbackRegisterer&& right) = delete; - }; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index da233b2c30..407ab81918 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -56,11 +56,14 @@ - + + + + @@ -276,7 +279,8 @@ - + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 887600c974..d8f1f1b884 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -87,7 +87,7 @@ {1d6abf72-0f18-43ec-9351-1fed1a3d1a1e} - + {368770cf-c8d9-4f4a-9ac3-5bdf48101ffe} @@ -668,12 +668,21 @@ Emu\CPU\ARMv7 - - Emu\CPU\ARMv7\Thread Manager - Emu\CPU\ARMv7 + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + @@ -1303,11 +1312,14 @@ Emu\CPU\ARMv7\Modules - - Emu\CPU\ARMv7\Thread Manager - Emu\CPU\ARMv7 + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Objects + \ No newline at end of file From 3141cc9bc717a6ca0598ac13b586e1f2d2d05e54 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 27 Jan 2015 04:26:05 +0300 Subject: [PATCH 22/94] NIDs fix --- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 32 ++-- rpcs3/Emu/ARMv7/Modules/sceLibm.cpp | 26 +-- rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp | 224 +++++++++++------------ 3 files changed, 141 insertions(+), 141 deletions(-) diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 25fa75c47c..f4705ab1d8 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -990,7 +990,7 @@ psv_log_base sceLibKernel("sceLibKernel", []() // REG_FUNC(???, sceKernelGetEventInfo); - //REG_FUNC(0x23EAA62, sceKernelPuts); + //REG_FUNC(0x023EAA62, sceKernelPuts); //REG_FUNC(0xB0335388, sceClibToupper); //REG_FUNC(0x4C5471BC, sceClibTolower); //REG_FUNC(0xD8EBBB7E, sceClibLookCtypeTable); @@ -1047,11 +1047,11 @@ psv_log_base sceLibKernel("sceLibKernel", []() //REG_FUNC(0x4AE9C8E6, sceKernelAtomicGetAndSub64); //REG_FUNC(0x99E1796E, sceKernelAtomicSubAndGet8); //REG_FUNC(0xC26BBBB1, sceKernelAtomicSubAndGet16); - //REG_FUNC(0x1C9CD92, sceKernelAtomicSubAndGet32); + //REG_FUNC(0x01C9CD92, sceKernelAtomicSubAndGet32); //REG_FUNC(0x9BB4A94B, sceKernelAtomicSubAndGet64); //REG_FUNC(0x53DCA02B, sceKernelAtomicGetAndAnd8); //REG_FUNC(0x7A0CB056, sceKernelAtomicGetAndAnd16); - //REG_FUNC(0x8266595, sceKernelAtomicGetAndAnd32); + //REG_FUNC(0x08266595, sceKernelAtomicGetAndAnd32); //REG_FUNC(0x4828BC43, sceKernelAtomicGetAndAnd64); //REG_FUNC(0x86B9170F, sceKernelAtomicAndAndGet8); //REG_FUNC(0xF9890F7E, sceKernelAtomicAndAndGet16); @@ -1103,9 +1103,9 @@ psv_log_base sceLibKernel("sceLibKernel", []() //REG_FUNC(0x4C7AD128, sceKernelPowerLock); //REG_FUNC(0xAF8E9C11, sceKernelPowerUnlock); //REG_FUNC(0xB295EB61, sceKernelGetTLSAddr); - REG_FUNC(0xFB972F9, sceKernelGetThreadId); + REG_FUNC(0x0FB972F9, sceKernelGetThreadId); REG_FUNC(0xA37A6057, sceKernelGetCurrentThreadVfpException); - //REG_FUNC(0xCA71EA2, sceKernelSendMsgPipe); + //REG_FUNC(0x0CA71EA2, sceKernelSendMsgPipe); //REG_FUNC(0xA5CA74AC, sceKernelSendMsgPipeCB); //REG_FUNC(0xDFC670E0, sceKernelTrySendMsgPipe); //REG_FUNC(0x4E81DD5C, sceKernelReceiveMsgPipe); @@ -1163,7 +1163,7 @@ psv_log_base sceLibKernel("sceLibKernel", []() REG_FUNC(0xC08F5BC5, sceKernelDeleteSema); REG_FUNC(0xB028AB78, sceKernelOpenSema); REG_FUNC(0x817707AB, sceKernelCloseSema); - REG_FUNC(0xC7B834B, sceKernelWaitSema); + REG_FUNC(0x0C7B834B, sceKernelWaitSema); REG_FUNC(0x174692B4, sceKernelWaitSemaCB); REG_FUNC(0x66D6BF05, sceKernelCancelSema); REG_FUNC(0x595D3FA6, sceKernelGetSemaInfo); @@ -1188,8 +1188,8 @@ psv_log_base sceLibKernel("sceLibKernel", []() REG_FUNC(0x6864DCE2, sceKernelGetCondInfo); REG_FUNC(0x10A4976F, sceKernelSignalCond); REG_FUNC(0x2EB86929, sceKernelSignalCondAll); - REG_FUNC(0x87629E6, sceKernelSignalCondTo); - //REG_FUNC(0xA10C1C8, sceKernelCreateMsgPipe); + REG_FUNC(0x087629E6, sceKernelSignalCondTo); + //REG_FUNC(0x0A10C1C8, sceKernelCreateMsgPipe); //REG_FUNC(0x69F6575D, sceKernelDeleteMsgPipe); //REG_FUNC(0x230691DA, sceKernelOpenMsgPipe); //REG_FUNC(0x7E5C0C16, sceKernelCloseMsgPipe); @@ -1218,7 +1218,7 @@ psv_log_base sceLibKernel("sceLibKernel", []() REG_FUNC(0x2F3D35A3, sceKernelOpenTimer); REG_FUNC(0x17283DE6, sceKernelCloseTimer); REG_FUNC(0x1478249B, sceKernelStartTimer); - REG_FUNC(0x75B1329, sceKernelStopTimer); + REG_FUNC(0x075B1329, sceKernelStopTimer); REG_FUNC(0x1F59E04D, sceKernelGetTimerBase); REG_FUNC(0x3223CCD1, sceKernelGetTimerBaseWide); REG_FUNC(0x381DC300, sceKernelGetTimerTime); @@ -1241,7 +1241,7 @@ psv_log_base sceLibKernel("sceLibKernel", []() REG_FUNC(0x597D4607, sceKernelTryLockWriteRWLock); REG_FUNC(0xD9369DF2, sceKernelUnlockWriteRWLock); REG_FUNC(0x190CA94B, sceKernelCancelRWLock); - REG_FUNC(0x79A573B, sceKernelGetRWLockInfo); + REG_FUNC(0x079A573B, sceKernelGetRWLockInfo); REG_FUNC(0x8AF15B5F, sceKernelGetSystemTime); //REG_FUNC(0x99B2BF15, sceKernelPMonThreadGetCounter); //REG_FUNC(0x7C21C961, sceKernelPMonCpuGetCounter); @@ -1265,14 +1265,14 @@ psv_log_base sceLibKernel("sceLibKernel", []() REG_FUNC(0xBCA5B623, sceIoGetstat); REG_FUNC(0x29482F7F, sceIoChstat); REG_FUNC(0x98ACED6D, sceIoSync); - REG_FUNC(0x4B30CB2, sceIoDevctl); + REG_FUNC(0x04B30CB2, sceIoDevctl); REG_FUNC(0x54ABACFA, sceIoIoctl); //REG_FUNC(0x6A7EA9FD, sceIoOpenAsync); //REG_FUNC(0x84201C9B, sceIoCloseAsync); //REG_FUNC(0x7B3BE857, sceIoReadAsync); //REG_FUNC(0x21329B20, sceIoWriteAsync); //REG_FUNC(0xCAC5D672, sceIoLseekAsync); - //REG_FUNC(0x99C54B9, sceIoIoctlAsync); + //REG_FUNC(0x099C54B9, sceIoIoctlAsync); //REG_FUNC(0x446A60AC, sceIoRemoveAsync); //REG_FUNC(0x73FC184B, sceIoDopenAsync); //REG_FUNC(0x4D0597D7, sceIoDcloseAsync); @@ -1305,7 +1305,7 @@ psv_log_base sceLibKernel("sceLibKernel", []() //REG_FUNC(0xCD248267, sceKernelGetCurrentProcess); //REG_FUNC(0x2252890C, sceKernelPowerTick); //REG_FUNC(0x9E45DA09, sceKernelLibcClock); - //REG_FUNC(0x39BE45, sceKernelLibcTime); + //REG_FUNC(0x0039BE45, sceKernelLibcTime); //REG_FUNC(0x4B879059, sceKernelLibcGettimeofday); //REG_FUNC(0xC1727F59, sceKernelGetStdin); //REG_FUNC(0xE5AA625C, sceKernelGetStdout); @@ -1338,12 +1338,12 @@ psv_log_base sceLibKernel("sceLibKernel", []() //REG_FUNC(0x800EDCC1, sceKernelClearDipsw); /* SceThreadmgr */ - REG_FUNC(0xC8A38E1, sceKernelExitThread); + REG_FUNC(0x0C8A38E1, sceKernelExitThread); REG_FUNC(0x1D17DECF, sceKernelExitDeleteThread); REG_FUNC(0x4B675D05, sceKernelDelayThread); REG_FUNC(0x9C0180E1, sceKernelDelayThreadCB); - //REG_FUNC(0x1173F8, sceKernelChangeActiveCpuMask); - REG_FUNC(0x1414F0B, sceKernelGetThreadCurrentPriority); + //REG_FUNC(0x001173F8, sceKernelChangeActiveCpuMask); + REG_FUNC(0x01414F0B, sceKernelGetThreadCurrentPriority); REG_FUNC(0x751C9B7A, sceKernelChangeCurrentThreadAttr); REG_FUNC(0xD9BD74EB, sceKernelCheckWaitableStatus); REG_FUNC(0x9DCB4B7A, sceKernelGetProcessId); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibm.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibm.cpp index c0b847e6e5..1cbd5cd12e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibm.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibm.cpp @@ -47,10 +47,10 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0x63F05BD6, ceil); //REG_FUNC(0x6BBFEC89, ceilf); //REG_FUNC(0x48082D81, ceill); - //REG_FUNC(0xB918D13, copysign); + //REG_FUNC(0x0B918D13, copysign); //REG_FUNC(0x16EB9E63, copysignf); //REG_FUNC(0x19DFC0AA, copysignl); - //REG_FUNC(0x61D0244, cos); + //REG_FUNC(0x061D0244, cos); //REG_FUNC(0x127F8302, cosf); //REG_FUNC(0x89B9BE1F, cosl); //REG_FUNC(0x110195E7, cosh); @@ -59,7 +59,7 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0x4B84C012, _Cosh); //REG_FUNC(0x15993458, erf); //REG_FUNC(0x524AEBFE, erfc); - //REG_FUNC(0x301F113, erfcf); + //REG_FUNC(0x0301F113, erfcf); //REG_FUNC(0xD4C92471, erfcl); //REG_FUNC(0x41DD1AB8, erff); //REG_FUNC(0xFD431619, erfl); @@ -74,7 +74,7 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0x8BF1866C, expm1l); //REG_FUNC(0x3E672BE3, fabs); //REG_FUNC(0x75348906, fabsf); - //REG_FUNC(0x3ECA514, fabsl); + //REG_FUNC(0x03ECA514, fabsl); //REG_FUNC(0xA278B20D, _FCosh); //REG_FUNC(0xD6FD5A2E, fdim); //REG_FUNC(0x8B6CC137, fdimf); @@ -96,19 +96,19 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0x1CD8F88E, fmodf); //REG_FUNC(0x986011B4, fmodl); //REG_FUNC(0x59197427, frexp); - //REG_FUNC(0xA6879AC, frexpf); + //REG_FUNC(0x0A6879AC, frexpf); //REG_FUNC(0x6DC8D877, frexpl); //REG_FUNC(0x4A496BC0, _FSin); //REG_FUNC(0x7FBB4C55, _FSinh); //REG_FUNC(0x2D2CD795, hypot); //REG_FUNC(0xA397B929, hypotf); - //REG_FUNC(0x5BFBEE8, hypotl); + //REG_FUNC(0x05BFBEE8, hypotl); //REG_FUNC(0x667EE864, ilogb); //REG_FUNC(0x80050A43, ilogbf); //REG_FUNC(0x91298DCA, ilogbl); - //REG_FUNC(0x197C9D5, _LCosh); - //REG_FUNC(0x56061B, ldexp); - //REG_FUNC(0xE61E016, ldexpf); + //REG_FUNC(0x0197C9D5, _LCosh); + //REG_FUNC(0x0056061B, ldexp); + //REG_FUNC(0x0E61E016, ldexpf); //REG_FUNC(0x8280A7B1, ldexpl); //REG_FUNC(0x2480AA54, lgamma); //REG_FUNC(0x2D9556D5, lgammaf); @@ -118,7 +118,7 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0xC1F6135B, llrintf); //REG_FUNC(0x80558247, llrintl); //REG_FUNC(0xD1251A18, llround); - //REG_FUNC(0x4595A04, llroundf); + //REG_FUNC(0x04595A04, llroundf); //REG_FUNC(0x9AB5C7AF, llroundl); //REG_FUNC(0x6037C48F, log); //REG_FUNC(0x811ED68B, logf); @@ -134,7 +134,7 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0x4095DBDB, log2f); //REG_FUNC(0x720021A9, log2l); //REG_FUNC(0x5EAE8AD4, logb); - //REG_FUNC(0x25F51CE, logbf); + //REG_FUNC(0x025F51CE, logbf); //REG_FUNC(0x86C4B75F, logbl); //REG_FUNC(0x207307D0, lrint); //REG_FUNC(0xDA903135, lrintf); @@ -200,8 +200,8 @@ psv_log_base sceLibm("SceLibm", []() //REG_FUNC(0x3A7FE686, tgamma); //REG_FUNC(0xE6067AC0, tgammaf); //REG_FUNC(0x2949109F, tgammal); - //REG_FUNC(0x212323E, trunc); - //REG_FUNC(0x90B899F, truncf); + //REG_FUNC(0x0212323E, trunc); + //REG_FUNC(0x090B899F, truncf); //REG_FUNC(0xBC0F1B1A, truncl); //REG_FUNC(0x98BBDAE0, _Dclass); //REG_FUNC(0xBD8EF217, _FDclass); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp index 2342f1f8c5..f0f2674441 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp @@ -56,14 +56,14 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x16F56E8D, std::invalid_argument::_Doraise() const); //REG_FUNC(0x6C568D20, std::_ctype::do_tolower(char*, char const*) const); //REG_FUNC(0xC334DE66, std::_ctype::do_tolower(char) const); - //REG_FUNC(0x2DD808E, std::_ctype::do_toupper(char*, char const*) const); + //REG_FUNC(0x02DD808E, std::_ctype::do_toupper(char*, char const*) const); //REG_FUNC(0xF6AF33EA, std::_ctype::do_toupper(char) const); //REG_FUNC(0x1B81D726, std::_ctype::do_widen(char const*, char const*, char*) const); //REG_FUNC(0x6471CC01, std::_ctype::do_widen(char) const); //REG_FUNC(0x9CFA56E5, std::_ctype::do_narrow(char const*, char const*, char, char*) const); //REG_FUNC(0x718669AB, std::_ctype::do_narrow(char, char) const); //REG_FUNC(0x759F105D, std::_ctype::do_scan_is(short, wchar_t const*, wchar_t const*) const); - //REG_FUNC(0x56443F, std::_ctype::do_tolower(wchar_t*, wchar_t const*) const); + //REG_FUNC(0x0056443F, std::_ctype::do_tolower(wchar_t*, wchar_t const*) const); //REG_FUNC(0x33E9ECDD, std::_ctype::do_tolower(wchar_t) const); //REG_FUNC(0x1256E6A5, std::_ctype::do_toupper(wchar_t*, wchar_t const*) const); //REG_FUNC(0x64072C2E, std::_ctype::do_toupper(wchar_t) const); @@ -91,7 +91,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x664750EE, std::bad_alloc::what() const); //REG_FUNC(0xBA89FBE7, std::bad_alloc::_Doraise() const); //REG_FUNC(0xC133E331, std::exception::what() const); - //REG_FUNC(0x656BE32, std::exception::_Raise() const); + //REG_FUNC(0x0656BE32, std::exception::_Raise() const); //REG_FUNC(0x47A5CDA2, std::exception::_Doraise() const); //REG_FUNC(0xBAE38DF9, std::type_info::name() const); //REG_FUNC(0x1F260F10, std::type_info::before(std::type_info const&) const); @@ -119,10 +119,10 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x9CF31703, std::istrstream::~istrstream()); //REG_FUNC(0x71D13A36, std::istrstream::~istrstream()); //REG_FUNC(0xAF5DF8C3, std::istrstream::~istrstream()); - //REG_FUNC(0xC1E7C7A, std::ostrstream::ostrstream(char*, int, std::_Iosb::_Openmode)); - //REG_FUNC(0xC09B290, std::ostrstream::ostrstream(char*, int, std::_Iosb::_Openmode)); + //REG_FUNC(0x0C1E7C7A, std::ostrstream::ostrstream(char*, int, std::_Iosb::_Openmode)); + //REG_FUNC(0x0C09B290, std::ostrstream::ostrstream(char*, int, std::_Iosb::_Openmode)); //REG_FUNC(0x4B8BA644, std::ostrstream::~ostrstream()); - //REG_FUNC(0xE463FB3, std::ostrstream::~ostrstream()); + //REG_FUNC(0x0E463FB3, std::ostrstream::~ostrstream()); //REG_FUNC(0xA0A34FEF, std::ostrstream::~ostrstream()); //REG_FUNC(0xC9F632FF, std::logic_error::logic_error(std::logic_error const&)); //REG_FUNC(0xE6356C5C, std::logic_error::logic_error(std::string const&)); @@ -136,12 +136,12 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x7D5412EF, std::domain_error::domain_error(std::domain_error const&)); //REG_FUNC(0x803A7D3E, std::domain_error::~domain_error()); //REG_FUNC(0xA6BCA2AD, std::domain_error::~domain_error()); - //REG_FUNC(0x36F9D2A, std::domain_error::~domain_error()); + //REG_FUNC(0x036F9D2A, std::domain_error::~domain_error()); //REG_FUNC(0x5F3428AD, std::length_error::length_error(std::length_error const&)); //REG_FUNC(0xF6FB801D, std::length_error::length_error(std::string const&)); //REG_FUNC(0xF83AA7DA, std::length_error::~length_error()); //REG_FUNC(0xA873D7F9, std::length_error::~length_error()); - //REG_FUNC(0xBB12C75, std::length_error::~length_error()); + //REG_FUNC(0x0BB12C75, std::length_error::~length_error()); //REG_FUNC(0x299AA587, std::out_of_range::out_of_range(std::out_of_range const&)); //REG_FUNC(0xC8BA5522, std::out_of_range::out_of_range(std::string const&)); //REG_FUNC(0xA8C470A4, std::out_of_range::~out_of_range()); @@ -157,7 +157,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xA9F4FABF, std::strstreambuf::underflow()); //REG_FUNC(0x1C887DDE, std::strstreambuf::~strstreambuf()); //REG_FUNC(0x29E1E930, std::strstreambuf::~strstreambuf()); - //REG_FUNC(0xA140889, std::strstreambuf::~strstreambuf()); + //REG_FUNC(0x0A140889, std::strstreambuf::~strstreambuf()); //REG_FUNC(0xA8FE6FC4, std::_codecvt_base::~_codecvt_base()); //REG_FUNC(0xB0E47AE4, std::_codecvt_base::~_codecvt_base()); //REG_FUNC(0xB7EE9CC2, std::bad_exception::bad_exception(std::bad_exception const&)); @@ -174,7 +174,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x413E813E, std::basic_filebuf >::setbuf(char*, int)); //REG_FUNC(0x9D193B65, std::basic_filebuf >::_Unlock()); //REG_FUNC(0x52E47FB5, std::basic_filebuf >::seekoff(long, std::_Iosb::_Seekdir, std::_Iosb::_Openmode)); - //REG_FUNC(0xE119B37, std::basic_filebuf >::seekpos(std::fpos, std::_Iosb::_Openmode)); + //REG_FUNC(0x0E119B37, std::basic_filebuf >::seekpos(std::fpos, std::_Iosb::_Openmode)); //REG_FUNC(0x616754BC, std::basic_filebuf >::overflow(int)); //REG_FUNC(0xCD5BD2E1, std::basic_filebuf >::_Endwrite()); //REG_FUNC(0xFC1C7F3A, std::basic_filebuf >::pbackfail(int)); @@ -197,7 +197,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xFFFA683E, std::basic_istream >::~basic_istream()); //REG_FUNC(0xB58839C5, std::basic_istream >::~basic_istream()); //REG_FUNC(0x9BF8855B, std::basic_ostream >::basic_ostream(std::basic_streambuf >*, bool)); - //REG_FUNC(0xD74F56E, std::basic_ostream >::~basic_ostream()); + //REG_FUNC(0x0D74F56E, std::basic_ostream >::~basic_ostream()); //REG_FUNC(0x9B831B60, std::basic_ostream >::~basic_ostream()); //REG_FUNC(0x396337CE, std::runtime_error::runtime_error(std::runtime_error const&)); //REG_FUNC(0xDAD26367, std::runtime_error::~runtime_error()); @@ -209,20 +209,20 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x4E45F680, std::overflow_error::~overflow_error()); //REG_FUNC(0x626515E3, std::basic_streambuf >::sync()); //REG_FUNC(0x2E55F15A, std::basic_streambuf >::_Lock()); - //REG_FUNC(0xF8535AB, std::basic_streambuf >::uflow()); + //REG_FUNC(0x0F8535AB, std::basic_streambuf >::uflow()); //REG_FUNC(0xD7933D06, std::basic_streambuf >::setbuf(char*, int)); //REG_FUNC(0xB8BCCC8D, std::basic_streambuf >::xsgetn(char*, int)); //REG_FUNC(0x43E5D0F1, std::basic_streambuf >::xsputn(char const*, int)); //REG_FUNC(0x149B193A, std::basic_streambuf >::_Unlock()); //REG_FUNC(0x600998EC, std::basic_streambuf >::seekoff(long, std::_Iosb::_Seekdir, std::_Iosb::_Openmode)); - //REG_FUNC(0x1DEFFD6, std::basic_streambuf >::seekpos(std::fpos, std::_Iosb::_Openmode)); + //REG_FUNC(0x01DEFFD6, std::basic_streambuf >::seekpos(std::fpos, std::_Iosb::_Openmode)); //REG_FUNC(0xF5F44352, std::basic_streambuf >::overflow(int)); //REG_FUNC(0xCA79344F, std::basic_streambuf >::pbackfail(int)); //REG_FUNC(0x441788B1, std::basic_streambuf >::showmanyc()); //REG_FUNC(0x797DAE94, std::basic_streambuf >::underflow()); - //REG_FUNC(0x74AD52E, std::basic_streambuf >::~basic_streambuf()); + //REG_FUNC(0x074AD52E, std::basic_streambuf >::~basic_streambuf()); //REG_FUNC(0xE449E2BF, std::basic_streambuf >::~basic_streambuf()); - //REG_FUNC(0x9FAA0AA, std::basic_streambuf >::sync()); + //REG_FUNC(0x09FAA0AA, std::basic_streambuf >::sync()); //REG_FUNC(0xA596C88C, std::basic_streambuf >::_Lock()); //REG_FUNC(0x373C2CD8, std::basic_streambuf >::uflow()); //REG_FUNC(0x3F363796, std::basic_streambuf >::setbuf(wchar_t*, int)); @@ -246,7 +246,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x9982A4FC, std::invalid_argument::~invalid_argument()); //REG_FUNC(0x1AB2B1AC, std::invalid_argument::~invalid_argument()); //REG_FUNC(0xF9FAB558, std::_Mutex::_Lock()); - //REG_FUNC(0x402C9F8, std::_Mutex::_Unlock()); + //REG_FUNC(0x0402C9F8, std::_Mutex::_Unlock()); //REG_FUNC(0x9DA92617, std::_Mutex::_Mutex(std::_Uninitialized)); //REG_FUNC(0xA4F99AE7, std::_Mutex::_Mutex()); //REG_FUNC(0x7B5A6B7F, std::_Mutex::_Mutex(std::_Uninitialized)); @@ -279,12 +279,12 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x65D88619, std::ios_base::Init::~Init()); //REG_FUNC(0x3483E01D, std::ios_base::Init::~Init()); //REG_FUNC(0x78CB190E, std::ios_base::_Init()); - //REG_FUNC(0x23B8BEE, std::ios_base::_Tidy()); + //REG_FUNC(0x023B8BEE, std::ios_base::_Tidy()); //REG_FUNC(0xC9DE8208, std::ios_base::clear(std::_Iosb::_Iostate, bool)); //REG_FUNC(0xAA9171FB, std::ios_base::_Addstd()); - //REG_FUNC(0xFC58778, std::ios_base::copyfmt(std::ios_base const&)); + //REG_FUNC(0x0FC58778, std::ios_base::copyfmt(std::ios_base const&)); //REG_FUNC(0x2DF76755, std::ios_base::failure::failure(std::ios_base::failure const&)); - //REG_FUNC(0x94048F7, std::ios_base::failure::failure(std::string const&)); + //REG_FUNC(0x094048F7, std::ios_base::failure::failure(std::string const&)); //REG_FUNC(0x20AAAB95, std::ios_base::failure::~failure()); //REG_FUNC(0x31D0197A, std::ios_base::failure::~failure()); //REG_FUNC(0x7736E940, std::ios_base::_Callfns(std::ios_base::event)); @@ -297,18 +297,18 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x6AF75467, std::bad_alloc::bad_alloc(std::bad_alloc const&)); //REG_FUNC(0x57096162, std::bad_alloc::bad_alloc()); //REG_FUNC(0xB2DAA408, std::bad_alloc::~bad_alloc()); - //REG_FUNC(0x7AEE736, std::bad_alloc::~bad_alloc()); + //REG_FUNC(0x07AEE736, std::bad_alloc::~bad_alloc()); //REG_FUNC(0xA9E9B7B7, std::bad_alloc::~bad_alloc()); //REG_FUNC(0x7853E8E5, std::bad_alloc::operator=(std::bad_alloc const&)); //REG_FUNC(0xF78468EB, std::basic_ios >::~basic_ios()); - //REG_FUNC(0x3150182, std::basic_ios >::~basic_ios()); + //REG_FUNC(0x03150182, std::basic_ios >::~basic_ios()); //REG_FUNC(0x9654168A, std::basic_ios >::~basic_ios()); //REG_FUNC(0x8FFB8524, std::basic_ios >::~basic_ios()); //REG_FUNC(0x7AF1BB16, std::exception::_Set_raise_handler(void (*)(std::exception const&))); //REG_FUNC(0x8C5A4417, std::exception::exception(std::exception const&)); //REG_FUNC(0xFC169D71, std::exception::exception()); //REG_FUNC(0x59758E74, std::exception::exception(std::exception const&)); - //REG_FUNC(0xE08376, std::exception::exception()); + //REG_FUNC(0x00E08376, std::exception::exception()); //REG_FUNC(0x82EEA67E, std::exception::~exception()); //REG_FUNC(0x30405D88, std::exception::~exception()); //REG_FUNC(0xAF7A7081, std::exception::~exception()); @@ -320,7 +320,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x7D8DFE43, std::strstream::~strstream()); //REG_FUNC(0x8D4B1A13, std::type_info::~type_info()); //REG_FUNC(0xBD786240, std::type_info::~type_info()); - //REG_FUNC(0xC04303, std::type_info::~type_info()); + //REG_FUNC(0x00C04303, std::type_info::~type_info()); //REG_FUNC(0x9983D8B9, std::unexpected()); //REG_FUNC(0x385D19B2, std::setiosflags(std::_Iosb::_Fmtflags)); //REG_FUNC(0xD8A78A61, std::setprecision(int)); @@ -329,7 +329,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x644CBAA2, std::_Debug_message(char const*, char const*)); //REG_FUNC(0x9B2F0CA6, std::set_unexpected(void (*)())); //REG_FUNC(0xC107B555, std::set_new_handler(void (*)())); - //REG_FUNC(0x11CEB00, std::uncaught_exception()); + //REG_FUNC(0x011CEB00, std::uncaught_exception()); //REG_FUNC(0x36282336, std::__gen_dummy_typeinfos()); //REG_FUNC(0x3622003F, std::setw(int)); //REG_FUNC(0x6CAFA8EF, std::_Throw(std::exception const&)); @@ -366,7 +366,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xE7FB2BF4, operator new[](unsigned int)); //REG_FUNC(0x31C62481, operator new[](unsigned int, std::nothrow_t const&)); //REG_FUNC(0xF99ED5AC, operator new(unsigned int)); - //REG_FUNC(0xAE71DC3, operator new(unsigned int, std::nothrow_t const&)); + //REG_FUNC(0x0AE71DC3, operator new(unsigned int, std::nothrow_t const&)); //REG_FUNC(0x1818C323, _SNC_get_global_vars); //REG_FUNC(0x2CFA1F15, _SNC_get_tlocal_vars); //REG_FUNC(0x7742D916, _Unwind_Backtrace); @@ -428,12 +428,12 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xBF90A45A, _PJP_CPP_Copyright); //REG_FUNC(0x3B6D9752, std::basic_string, std::allocator >::npos); //REG_FUNC(0xA3498140, std::string::npos); - //REG_FUNC(0x5273EA3, std::_Num_int_base::is_bounded); + //REG_FUNC(0x05273EA3, std::_Num_int_base::is_bounded); //REG_FUNC(0x8A0994F8, std::_Num_int_base::is_integer); //REG_FUNC(0x401F1224, std::_Num_int_base::is_specialized); //REG_FUNC(0xA65FE916, std::_Num_int_base::radix); //REG_FUNC(0xF2AA872E, std::_Num_int_base::is_exact); - //REG_FUNC(0x8FE5A4F, std::_Num_int_base::is_modulo); + //REG_FUNC(0x08FE5A4F, std::_Num_int_base::is_modulo); //REG_FUNC(0x7D4C55EC, std::numeric_limits::digits); //REG_FUNC(0xA4E5BF5E, std::numeric_limits::digits10); //REG_FUNC(0xD9938B84, std::numeric_limits::is_signed); @@ -442,7 +442,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x81B82E0E, std::numeric_limits::is_modulo); //REG_FUNC(0x9E6D2025, std::numeric_limits::is_signed); //REG_FUNC(0x810ED593, std::numeric_limits::digits); - //REG_FUNC(0xAC1A819, std::numeric_limits::digits10); + //REG_FUNC(0x0AC1A819, std::numeric_limits::digits10); //REG_FUNC(0x660E14E1, std::numeric_limits::is_signed); //REG_FUNC(0x3EEB3B23, std::numeric_limits::max_exponent); //REG_FUNC(0x13B634BE, std::numeric_limits::min_exponent); @@ -470,10 +470,10 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x3AB38CDA, std::numeric_limits::is_signed); //REG_FUNC(0xEEB7B642, std::numeric_limits::digits); //REG_FUNC(0xBCDE68B3, std::numeric_limits::digits10); - //REG_FUNC(0xDA8EFB0, std::numeric_limits::is_signed); + //REG_FUNC(0x0DA8EFB0, std::numeric_limits::is_signed); //REG_FUNC(0x65DAD8D6, std::numeric_limits::digits); //REG_FUNC(0xFB52BC0A, std::numeric_limits::digits10); - //REG_FUNC(0x63544FC, std::numeric_limits::is_signed); + //REG_FUNC(0x063544FC, std::numeric_limits::is_signed); //REG_FUNC(0x441D097A, std::numeric_limits::digits); //REG_FUNC(0xB56F1B07, std::numeric_limits::digits10); //REG_FUNC(0xA9799886, std::numeric_limits::is_signed); @@ -514,13 +514,13 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x759FD02E, std::_Iosb::app); //REG_FUNC(0x6F410A00, std::_Iosb::ate); //REG_FUNC(0xD2A42D0C, std::_Iosb::beg); - //REG_FUNC(0x9B45C3B, std::_Iosb::cur); + //REG_FUNC(0x09B45C3B, std::_Iosb::cur); //REG_FUNC(0x121A8952, std::_Iosb::dec); //REG_FUNC(0x7CC027CD, std::_Iosb::end); //REG_FUNC(0x6E2FF90B, std::_Iosb::hex); //REG_FUNC(0xB4A55C29, std::_Iosb::oct); //REG_FUNC(0x2CB2DC70, std::_Iosb::out); - //REG_FUNC(0x78E34A9, std::_Iosb::trunc); + //REG_FUNC(0x078E34A9, std::_Iosb::trunc); //REG_FUNC(0xB5EFA1B3, std::_Iosb::badbit); //REG_FUNC(0x5312A538, std::_Iosb::binary); //REG_FUNC(0xD9D32526, std::_Iosb::skipws); @@ -540,10 +540,10 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xB11D20E2, std::_Num_base::has_infinity); //REG_FUNC(0x3E169F74, std::_Num_base::max_exponent); //REG_FUNC(0xD7C041E0, std::_Num_base::min_exponent); - //REG_FUNC(0x2DA0D59, std::_Num_base::has_quiet_NaN); + //REG_FUNC(0x02DA0D59, std::_Num_base::has_quiet_NaN); //REG_FUNC(0xBE06BD79, std::_Num_base::is_specialized); //REG_FUNC(0xEBBC4DDD, std::_Num_base::max_exponent10); - //REG_FUNC(0xFFCF7FC, std::_Num_base::min_exponent10); + //REG_FUNC(0x0FFCF7FC, std::_Num_base::min_exponent10); //REG_FUNC(0xB317DDDF, std::_Num_base::has_denorm_loss); //REG_FUNC(0x245D399E, std::_Num_base::tinyness_before); //REG_FUNC(0xBD5F0B8A, std::_Num_base::has_signaling_NaN); @@ -590,7 +590,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xA4018B84, typeinfo for __simd128_float32_t); //REG_FUNC(0xA1FE4058, typeinfo for half); //REG_FUNC(0x5351829B, typeinfo for std::ios_base::failure); - //REG_FUNC(0xAC6C8F, typeinfo for __simd64_int8_t*); + //REG_FUNC(0x00AC6C8F, typeinfo for __simd64_int8_t*); //REG_FUNC(0xD5B056B8, typeinfo for __simd128_int8_t*); //REG_FUNC(0x13975DAE, typeinfo for __simd64_int16_t*); //REG_FUNC(0x963C04E3, typeinfo for __simd64_int32_t*); @@ -605,7 +605,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xEE862280, typeinfo for __simd64_uint32_t*); //REG_FUNC(0xB5CEC4FF, typeinfo for __simd128_poly16_t*); //REG_FUNC(0x46124E82, typeinfo for __simd128_uint16_t*); - //REG_FUNC(0x7E6CC17, typeinfo for __simd128_uint32_t*); + //REG_FUNC(0x07E6CC17, typeinfo for __simd128_uint32_t*); //REG_FUNC(0x588EBCAD, typeinfo for __simd64_float16_t*); //REG_FUNC(0xDFCB2417, typeinfo for __simd64_float32_t*); //REG_FUNC(0x9502D3C0, typeinfo for __simd128_float16_t*); @@ -616,8 +616,8 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x52A04C47, typeinfo for __simd64_int16_t const*); //REG_FUNC(0xBB64CCF1, typeinfo for __simd64_int32_t const*); //REG_FUNC(0x7C9D0C33, typeinfo for __simd64_poly8_t const*); - //REG_FUNC(0x21A57A1, typeinfo for __simd64_uint8_t const*); - //REG_FUNC(0x21E3DD1, typeinfo for __simd128_int16_t const*); + //REG_FUNC(0x021A57A1, typeinfo for __simd64_uint8_t const*); + //REG_FUNC(0x021E3DD1, typeinfo for __simd128_int16_t const*); //REG_FUNC(0xFF8DDBE7, typeinfo for __simd128_int32_t const*); //REG_FUNC(0xB30AB3B5, typeinfo for __simd128_poly8_t const*); //REG_FUNC(0xC8721E86, typeinfo for __simd128_uint8_t const*); @@ -654,12 +654,12 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xA6C2A25C, typeinfo for long long __vector*); //REG_FUNC(0x81B51915, typeinfo for unsigned long long __vector*); //REG_FUNC(0xA7CB4EAA, typeinfo for signed char*); - //REG_FUNC(0x87B0FB6, typeinfo for bool*); + //REG_FUNC(0x087B0FB6, typeinfo for bool*); //REG_FUNC(0xE4D24E14, typeinfo for char*); //REG_FUNC(0x6825FFE6, typeinfo for double*); //REG_FUNC(0x926B9A3A, typeinfo for long double*); //REG_FUNC(0x24072F3E, typeinfo for float*); - //REG_FUNC(0x8B5247B, typeinfo for unsigned char*); + //REG_FUNC(0x08B5247B, typeinfo for unsigned char*); //REG_FUNC(0x15C21CC8, typeinfo for int*); //REG_FUNC(0xD234CF18, typeinfo for unsigned int*); //REG_FUNC(0x50E25810, typeinfo for long*); @@ -704,7 +704,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xB93721C7, typeinfo for std::ios_base); //REG_FUNC(0x35E135A0, typeinfo for std::bad_alloc); //REG_FUNC(0x7BA61382, typeinfo for std::basic_ios >); - //REG_FUNC(0x905B8B0, typeinfo for std::basic_ios >); + //REG_FUNC(0x0905B8B0, typeinfo for std::basic_ios >); //REG_FUNC(0x1E8C6100, typeinfo for std::exception); //REG_FUNC(0x1CC15F54, typeinfo for std::strstream); //REG_FUNC(0x8A026EAD, typeinfo for std::type_info); @@ -736,16 +736,16 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xC3FA8530, typeinfo name for __simd128_int16_t); //REG_FUNC(0x67A63A08, typeinfo name for __simd128_int32_t); //REG_FUNC(0x6B26EFF8, typeinfo name for __simd128_poly8_t); - //REG_FUNC(0x8C4C69F, typeinfo name for __simd128_uint8_t); + //REG_FUNC(0x08C4C69F, typeinfo name for __simd128_uint8_t); //REG_FUNC(0x40BC2E0E, typeinfo name for __simd64_poly16_t); //REG_FUNC(0x8D1AE4A7, typeinfo name for __simd64_uint16_t); //REG_FUNC(0xC4096952, typeinfo name for __simd64_uint32_t); //REG_FUNC(0x16D366F1, typeinfo name for __simd128_poly16_t); - //REG_FUNC(0x45552A1, typeinfo name for __simd128_uint16_t); + //REG_FUNC(0x045552A1, typeinfo name for __simd128_uint16_t); //REG_FUNC(0x7DBF4FFF, typeinfo name for __simd128_uint32_t); - //REG_FUNC(0xED26DE1, typeinfo name for __simd64_float16_t); + //REG_FUNC(0x0ED26DE1, typeinfo name for __simd64_float16_t); //REG_FUNC(0xAB0D789A, typeinfo name for __simd64_float32_t); - //REG_FUNC(0x3200DDB, typeinfo name for __simd128_float16_t); + //REG_FUNC(0x03200DDB, typeinfo name for __simd128_float16_t); //REG_FUNC(0xD54CBD7C, typeinfo name for __simd128_float32_t); //REG_FUNC(0xA8E6842E, typeinfo name for half); //REG_FUNC(0x5246E71E, typeinfo name for std::ios_base::failure); @@ -777,7 +777,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xC356ACF6, typeinfo name for __simd64_poly8_t const*); //REG_FUNC(0x878C75F4, typeinfo name for __simd64_uint8_t const*); //REG_FUNC(0x68B777E3, typeinfo name for __simd128_int16_t const*); - //REG_FUNC(0x61188BD, typeinfo name for __simd128_int32_t const*); + //REG_FUNC(0x061188BD, typeinfo name for __simd128_int32_t const*); //REG_FUNC(0xC7733F13, typeinfo name for __simd128_poly8_t const*); //REG_FUNC(0x3D8A69EC, typeinfo name for __simd128_uint8_t const*); //REG_FUNC(0xCC081D58, typeinfo name for __simd64_poly16_t const*); @@ -827,12 +827,12 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xE2A0B0A8, typeinfo name for unsigned short*); //REG_FUNC(0xF7B6B02A, typeinfo name for void*); //REG_FUNC(0xF1C9A755, typeinfo name for wchar_t*); - //REG_FUNC(0x968B212, typeinfo name for long long*); - //REG_FUNC(0x9787CAD, typeinfo name for unsigned long long*); + //REG_FUNC(0x0968B212, typeinfo name for long long*); + //REG_FUNC(0x09787CAD, typeinfo name for unsigned long long*); //REG_FUNC(0xF86F5756, typeinfo name for std::iostream); //REG_FUNC(0x999300E0, typeinfo name for std::istream); //REG_FUNC(0x591C25A3, typeinfo name for std::ostream); - //REG_FUNC(0xFC9D21B, typeinfo name for std::bad_typeid); + //REG_FUNC(0x0FC9D21B, typeinfo name for std::bad_typeid); //REG_FUNC(0x867D109E, typeinfo name for std::istrstream); //REG_FUNC(0x88BFC745, typeinfo name for std::ostrstream); //REG_FUNC(0xB315CE7A, typeinfo name for std::_ctype_base); @@ -842,7 +842,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x9E317CE1, typeinfo name for std::length_error); //REG_FUNC(0xD8DAD98D, typeinfo name for std::out_of_range); //REG_FUNC(0x1C929309, typeinfo name for std::strstreambuf); - //REG_FUNC(0xE17E4D6, typeinfo name for std::_codecvt_base); + //REG_FUNC(0x0E17E4D6, typeinfo name for std::_codecvt_base); //REG_FUNC(0x918FE198, typeinfo name for std::bad_exception); //REG_FUNC(0x227B4568, typeinfo name for std::basic_filebuf >); //REG_FUNC(0xD34BAF59, typeinfo name for std::basic_filebuf >); @@ -871,7 +871,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x2856DCD6, typeinfo name for std::type_info); //REG_FUNC(0x75A1CED4, typeinfo name for long long __vector); //REG_FUNC(0x508FF61E, typeinfo name for unsigned long long __vector); - //REG_FUNC(0x8E6A51A, typeinfo name for signed char); + //REG_FUNC(0x08E6A51A, typeinfo name for signed char); //REG_FUNC(0x491DB7D3, typeinfo name for bool); //REG_FUNC(0xD657B5A0, typeinfo name for char); //REG_FUNC(0x322C7CB5, typeinfo name for double); @@ -891,7 +891,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x51B29810, VTT for std::iostream); //REG_FUNC(0x52128B13, VTT for std::istream); //REG_FUNC(0x3C508708, VTT for std::ostream); - //REG_FUNC(0x87753F6, VTT for std::istrstream); + //REG_FUNC(0x087753F6, VTT for std::istrstream); //REG_FUNC(0xE3D7CB30, VTT for std::ostrstream); //REG_FUNC(0xBC326B50, VTT for std::basic_istream >); //REG_FUNC(0x16E32018, VTT for std::basic_ostream >); @@ -914,7 +914,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x82A84E5E, vtable for std::logic_error); //REG_FUNC(0x1D583475, vtable for std::range_error); //REG_FUNC(0x80C77E16, vtable for std::domain_error); - //REG_FUNC(0x64ADA35, vtable for std::length_error); + //REG_FUNC(0x064ADA35, vtable for std::length_error); //REG_FUNC(0xDDAE7CBE, vtable for std::out_of_range); //REG_FUNC(0x11B2781A, vtable for std::strstreambuf); //REG_FUNC(0x75D16BD0, vtable for std::_codecvt_base); @@ -925,7 +925,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x48F3405B, vtable for std::basic_ostream >); //REG_FUNC(0x53F02A18, vtable for std::runtime_error); //REG_FUNC(0x177FCCDC, vtable for std::overflow_error); - //REG_FUNC(0x5548FF7, vtable for std::basic_streambuf >); + //REG_FUNC(0x05548FF7, vtable for std::basic_streambuf >); //REG_FUNC(0xE8A9F32E, vtable for std::basic_streambuf >); //REG_FUNC(0x515AE097, vtable for std::underflow_error); //REG_FUNC(0x23EEDAF0, vtable for std::invalid_argument); @@ -937,7 +937,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0xD58C5F52, vtable for std::ios_base); //REG_FUNC(0xA27EFBA3, vtable for std::bad_alloc); //REG_FUNC(0x147996ED, vtable for std::basic_ios >); - //REG_FUNC(0xDE4AFE9, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Sd__St9strstream); + //REG_FUNC(0x0DE4AFE9, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Sd__St9strstream); //REG_FUNC(0x87D18300, _ZTVSt9basic_iosIcSt11char_traitsIcEE__SiSd__St9strstream); //REG_FUNC(0x3D6A38D3, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Si__Sd); //REG_FUNC(0xA8E795AF, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Si__St10istrstream); @@ -950,7 +950,7 @@ psv_log_base sceLibstdcxx("SceLibstdcxx", []() //REG_FUNC(0x8E9879A7, vtable for std::type_info); //REG_FUNC(0xE63750C1, std::basic_filebuf >::_Init(std::_Dnk_filet*, std::basic_filebuf >::_Initfl)::_Stinit); //REG_FUNC(0x1D4E29BC, std::basic_filebuf >::_Init(std::_Dnk_filet*, std::basic_filebuf >::_Initfl)::_Stinit); - //REG_FUNC(0x8A37475, typeinfo for __cxxabiv1::__enum_type_info); + //REG_FUNC(0x08A37475, typeinfo for __cxxabiv1::__enum_type_info); //REG_FUNC(0x66CC7DBB, typeinfo for __cxxabiv1::__array_type_info); //REG_FUNC(0x81C44513, typeinfo for __cxxabiv1::__class_type_info); //REG_FUNC(0xC35024DA, typeinfo for __cxxabiv1::__pbase_type_info); @@ -1008,14 +1008,14 @@ REG_FUNC(0xB1AE6F9E, _ZNKSt15underflow_error8_DoraiseEv); REG_FUNC(0x16F56E8D, _ZNKSt16invalid_argument8_DoraiseEv); REG_FUNC(0x6C568D20, _ZNKSt6_ctypeIcE10do_tolowerEPcPKc); REG_FUNC(0xC334DE66, _ZNKSt6_ctypeIcE10do_tolowerEc); -REG_FUNC(0x2DD808E, _ZNKSt6_ctypeIcE10do_toupperEPcPKc); +REG_FUNC(0x02DD808E, _ZNKSt6_ctypeIcE10do_toupperEPcPKc); REG_FUNC(0xF6AF33EA, _ZNKSt6_ctypeIcE10do_toupperEc); REG_FUNC(0x1B81D726, _ZNKSt6_ctypeIcE8do_widenEPKcS2_Pc); REG_FUNC(0x6471CC01, _ZNKSt6_ctypeIcE8do_widenEc); REG_FUNC(0x9CFA56E5, _ZNKSt6_ctypeIcE9do_narrowEPKcS2_cPc); REG_FUNC(0x718669AB, _ZNKSt6_ctypeIcE9do_narrowEcc); REG_FUNC(0x759F105D, _ZNKSt6_ctypeIwE10do_scan_isEsPKwS2_); -REG_FUNC(0x56443F, _ZNKSt6_ctypeIwE10do_tolowerEPwPKw); +REG_FUNC(0x0056443F, _ZNKSt6_ctypeIwE10do_tolowerEPwPKw); REG_FUNC(0x33E9ECDD, _ZNKSt6_ctypeIwE10do_tolowerEw); REG_FUNC(0x1256E6A5, _ZNKSt6_ctypeIwE10do_toupperEPwPKw); REG_FUNC(0x64072C2E, _ZNKSt6_ctypeIwE10do_toupperEw); @@ -1043,7 +1043,7 @@ REG_FUNC(0xF877F51E, _ZNKSt8ios_base7failure8_DoraiseEv); REG_FUNC(0x664750EE, _ZNKSt9bad_alloc4whatEv); REG_FUNC(0xBA89FBE7, _ZNKSt9bad_alloc8_DoraiseEv); REG_FUNC(0xC133E331, _ZNKSt9exception4whatEv); -REG_FUNC(0x656BE32, _ZNKSt9exception6_RaiseEv); +REG_FUNC(0x0656BE32, _ZNKSt9exception6_RaiseEv); REG_FUNC(0x47A5CDA2, _ZNKSt9exception8_DoraiseEv); REG_FUNC(0xBAE38DF9, _ZNKSt9type_info4nameEv); REG_FUNC(0x1F260F10, _ZNKSt9type_info6beforeERKS_); @@ -1071,10 +1071,10 @@ REG_FUNC(0x55AAD6A6, _ZNSt10bad_typeidaSERKS_); REG_FUNC(0x9CF31703, _ZNSt10istrstreamD0Ev); REG_FUNC(0x71D13A36, _ZNSt10istrstreamD1Ev); REG_FUNC(0xAF5DF8C3, _ZNSt10istrstreamD2Ev); -REG_FUNC(0xC1E7C7A, _ZNSt10ostrstreamC1EPciNSt5_IosbIiE9_OpenmodeE); -REG_FUNC(0xC09B290, _ZNSt10ostrstreamC2EPciNSt5_IosbIiE9_OpenmodeE); +REG_FUNC(0x0C1E7C7A, _ZNSt10ostrstreamC1EPciNSt5_IosbIiE9_OpenmodeE); +REG_FUNC(0x0C09B290, _ZNSt10ostrstreamC2EPciNSt5_IosbIiE9_OpenmodeE); REG_FUNC(0x4B8BA644, _ZNSt10ostrstreamD0Ev); -REG_FUNC(0xE463FB3, _ZNSt10ostrstreamD1Ev); +REG_FUNC(0x0E463FB3, _ZNSt10ostrstreamD1Ev); REG_FUNC(0xA0A34FEF, _ZNSt10ostrstreamD2Ev); REG_FUNC(0xC9F632FF, _ZNSt11logic_errorC1ERKS_); REG_FUNC(0xE6356C5C, _ZNSt11logic_errorC2ERKSs); @@ -1088,12 +1088,12 @@ REG_FUNC(0xEF754EBD, _ZNSt11range_errorD2Ev); REG_FUNC(0x7D5412EF, _ZNSt12domain_errorC1ERKS_); REG_FUNC(0x803A7D3E, _ZNSt12domain_errorD0Ev); REG_FUNC(0xA6BCA2AD, _ZNSt12domain_errorD1Ev); -REG_FUNC(0x36F9D2A, _ZNSt12domain_errorD2Ev); +REG_FUNC(0x036F9D2A, _ZNSt12domain_errorD2Ev); REG_FUNC(0x5F3428AD, _ZNSt12length_errorC1ERKS_); REG_FUNC(0xF6FB801D, _ZNSt12length_errorC1ERKSs); REG_FUNC(0xF83AA7DA, _ZNSt12length_errorD0Ev); REG_FUNC(0xA873D7F9, _ZNSt12length_errorD1Ev); -REG_FUNC(0xBB12C75, _ZNSt12length_errorD2Ev); +REG_FUNC(0x0BB12C75, _ZNSt12length_errorD2Ev); REG_FUNC(0x299AA587, _ZNSt12out_of_rangeC1ERKS_); REG_FUNC(0xC8BA5522, _ZNSt12out_of_rangeC1ERKSs); REG_FUNC(0xA8C470A4, _ZNSt12out_of_rangeD0Ev); @@ -1109,7 +1109,7 @@ REG_FUNC(0xC725F896, _ZNSt12strstreambuf9pbackfailEi); REG_FUNC(0xA9F4FABF, _ZNSt12strstreambuf9underflowEv); REG_FUNC(0x1C887DDE, _ZNSt12strstreambufD0Ev); REG_FUNC(0x29E1E930, _ZNSt12strstreambufD1Ev); -REG_FUNC(0xA140889, _ZNSt12strstreambufD2Ev); +REG_FUNC(0x0A140889, _ZNSt12strstreambufD2Ev); REG_FUNC(0xA8FE6FC4, _ZNSt13_codecvt_baseD0Ev); REG_FUNC(0xB0E47AE4, _ZNSt13_codecvt_baseD1Ev); REG_FUNC(0xB7EE9CC2, _ZNSt13bad_exceptionC1ERKS_); @@ -1126,7 +1126,7 @@ REG_FUNC(0xD5F03A74, _ZNSt13basic_filebufIcSt11char_traitsIcEE5uflowEv); REG_FUNC(0x413E813E, _ZNSt13basic_filebufIcSt11char_traitsIcEE6setbufEPci); REG_FUNC(0x9D193B65, _ZNSt13basic_filebufIcSt11char_traitsIcEE7_UnlockEv); REG_FUNC(0x52E47FB5, _ZNSt13basic_filebufIcSt11char_traitsIcEE7seekoffElNSt5_IosbIiE8_SeekdirENS4_9_OpenmodeE); -REG_FUNC(0xE119B37, _ZNSt13basic_filebufIcSt11char_traitsIcEE7seekposESt4fposISt9_MbstatetENSt5_IosbIiE9_OpenmodeE); +REG_FUNC(0x0E119B37, _ZNSt13basic_filebufIcSt11char_traitsIcEE7seekposESt4fposISt9_MbstatetENSt5_IosbIiE9_OpenmodeE); REG_FUNC(0x616754BC, _ZNSt13basic_filebufIcSt11char_traitsIcEE8overflowEi); REG_FUNC(0xCD5BD2E1, _ZNSt13basic_filebufIcSt11char_traitsIcEE9_EndwriteEv); REG_FUNC(0xFC1C7F3A, _ZNSt13basic_filebufIcSt11char_traitsIcEE9pbackfailEi); @@ -1149,7 +1149,7 @@ REG_FUNC(0xD434F085, _ZNSt13basic_filebufIwSt11char_traitsIwEED1Ev); REG_FUNC(0xFFFA683E, _ZNSt13basic_istreamIwSt11char_traitsIwEED0Ev); REG_FUNC(0xB58839C5, _ZNSt13basic_istreamIwSt11char_traitsIwEED1Ev); REG_FUNC(0x9BF8855B, _ZNSt13basic_ostreamIwSt11char_traitsIwEEC1EPSt15basic_streambufIwS1_Eb); -REG_FUNC(0xD74F56E, _ZNSt13basic_ostreamIwSt11char_traitsIwEED0Ev); +REG_FUNC(0x0D74F56E, _ZNSt13basic_ostreamIwSt11char_traitsIwEED0Ev); REG_FUNC(0x9B831B60, _ZNSt13basic_ostreamIwSt11char_traitsIwEED1Ev); REG_FUNC(0x396337CE, _ZNSt13runtime_errorC1ERKS_); REG_FUNC(0xDAD26367, _ZNSt13runtime_errorD0Ev); @@ -1161,20 +1161,20 @@ REG_FUNC(0x5C666F7E, _ZNSt14overflow_errorD1Ev); REG_FUNC(0x4E45F680, _ZNSt14overflow_errorD2Ev); REG_FUNC(0x626515E3, _ZNSt15basic_streambufIcSt11char_traitsIcEE4syncEv); REG_FUNC(0x2E55F15A, _ZNSt15basic_streambufIcSt11char_traitsIcEE5_LockEv); -REG_FUNC(0xF8535AB, _ZNSt15basic_streambufIcSt11char_traitsIcEE5uflowEv); +REG_FUNC(0x0F8535AB, _ZNSt15basic_streambufIcSt11char_traitsIcEE5uflowEv); REG_FUNC(0xD7933D06, _ZNSt15basic_streambufIcSt11char_traitsIcEE6setbufEPci); REG_FUNC(0xB8BCCC8D, _ZNSt15basic_streambufIcSt11char_traitsIcEE6xsgetnEPci); REG_FUNC(0x43E5D0F1, _ZNSt15basic_streambufIcSt11char_traitsIcEE6xsputnEPKci); REG_FUNC(0x149B193A, _ZNSt15basic_streambufIcSt11char_traitsIcEE7_UnlockEv); REG_FUNC(0x600998EC, _ZNSt15basic_streambufIcSt11char_traitsIcEE7seekoffElNSt5_IosbIiE8_SeekdirENS4_9_OpenmodeE); -REG_FUNC(0x1DEFFD6, _ZNSt15basic_streambufIcSt11char_traitsIcEE7seekposESt4fposISt9_MbstatetENSt5_IosbIiE9_OpenmodeE); +REG_FUNC(0x01DEFFD6, _ZNSt15basic_streambufIcSt11char_traitsIcEE7seekposESt4fposISt9_MbstatetENSt5_IosbIiE9_OpenmodeE); REG_FUNC(0xF5F44352, _ZNSt15basic_streambufIcSt11char_traitsIcEE8overflowEi); REG_FUNC(0xCA79344F, _ZNSt15basic_streambufIcSt11char_traitsIcEE9pbackfailEi); REG_FUNC(0x441788B1, _ZNSt15basic_streambufIcSt11char_traitsIcEE9showmanycEv); REG_FUNC(0x797DAE94, _ZNSt15basic_streambufIcSt11char_traitsIcEE9underflowEv); -REG_FUNC(0x74AD52E, _ZNSt15basic_streambufIcSt11char_traitsIcEED0Ev); +REG_FUNC(0x074AD52E, _ZNSt15basic_streambufIcSt11char_traitsIcEED0Ev); REG_FUNC(0xE449E2BF, _ZNSt15basic_streambufIcSt11char_traitsIcEED1Ev); -REG_FUNC(0x9FAA0AA, _ZNSt15basic_streambufIwSt11char_traitsIwEE4syncEv); +REG_FUNC(0x09FAA0AA, _ZNSt15basic_streambufIwSt11char_traitsIwEE4syncEv); REG_FUNC(0xA596C88C, _ZNSt15basic_streambufIwSt11char_traitsIwEE5_LockEv); REG_FUNC(0x373C2CD8, _ZNSt15basic_streambufIwSt11char_traitsIwEE5uflowEv); REG_FUNC(0x3F363796, _ZNSt15basic_streambufIwSt11char_traitsIwEE6setbufEPwi); @@ -1198,7 +1198,7 @@ REG_FUNC(0x188D86CF, _ZNSt16invalid_argumentD0Ev); REG_FUNC(0x9982A4FC, _ZNSt16invalid_argumentD1Ev); REG_FUNC(0x1AB2B1AC, _ZNSt16invalid_argumentD2Ev); REG_FUNC(0xF9FAB558, _ZNSt6_Mutex5_LockEv); -REG_FUNC(0x402C9F8, _ZNSt6_Mutex7_UnlockEv); +REG_FUNC(0x0402C9F8, _ZNSt6_Mutex7_UnlockEv); REG_FUNC(0x9DA92617, _ZNSt6_MutexC1ESt14_Uninitialized); REG_FUNC(0xA4F99AE7, _ZNSt6_MutexC1Ev); REG_FUNC(0x7B5A6B7F, _ZNSt6_MutexC2ESt14_Uninitialized); @@ -1231,12 +1231,12 @@ REG_FUNC(0x5ED60DEE, _ZNSt8ios_base4InitC2Ev); REG_FUNC(0x65D88619, _ZNSt8ios_base4InitD1Ev); REG_FUNC(0x3483E01D, _ZNSt8ios_base4InitD2Ev); REG_FUNC(0x78CB190E, _ZNSt8ios_base5_InitEv); -REG_FUNC(0x23B8BEE, _ZNSt8ios_base5_TidyEv); +REG_FUNC(0x023B8BEE, _ZNSt8ios_base5_TidyEv); REG_FUNC(0xC9DE8208, _ZNSt8ios_base5clearENSt5_IosbIiE8_IostateEb); REG_FUNC(0xAA9171FB, _ZNSt8ios_base7_AddstdEv); -REG_FUNC(0xFC58778, _ZNSt8ios_base7copyfmtERKS_); +REG_FUNC(0x0FC58778, _ZNSt8ios_base7copyfmtERKS_); REG_FUNC(0x2DF76755, _ZNSt8ios_base7failureC1ERKS0_); -REG_FUNC(0x94048F7, _ZNSt8ios_base7failureC1ERKSs); +REG_FUNC(0x094048F7, _ZNSt8ios_base7failureC1ERKSs); REG_FUNC(0x20AAAB95, _ZNSt8ios_base7failureD0Ev); REG_FUNC(0x31D0197A, _ZNSt8ios_base7failureD1Ev); REG_FUNC(0x7736E940, _ZNSt8ios_base8_CallfnsENS_5eventE); @@ -1249,18 +1249,18 @@ REG_FUNC(0xEC3804D2, _ZNSt9bad_allocC1Ev); REG_FUNC(0x6AF75467, _ZNSt9bad_allocC2ERKS_); REG_FUNC(0x57096162, _ZNSt9bad_allocC2Ev); REG_FUNC(0xB2DAA408, _ZNSt9bad_allocD0Ev); -REG_FUNC(0x7AEE736, _ZNSt9bad_allocD1Ev); +REG_FUNC(0x07AEE736, _ZNSt9bad_allocD1Ev); REG_FUNC(0xA9E9B7B7, _ZNSt9bad_allocD2Ev); REG_FUNC(0x7853E8E5, _ZNSt9bad_allocaSERKS_); REG_FUNC(0xF78468EB, _ZNSt9basic_iosIcSt11char_traitsIcEED0Ev); -REG_FUNC(0x3150182, _ZNSt9basic_iosIcSt11char_traitsIcEED1Ev); +REG_FUNC(0x03150182, _ZNSt9basic_iosIcSt11char_traitsIcEED1Ev); REG_FUNC(0x9654168A, _ZNSt9basic_iosIwSt11char_traitsIwEED0Ev); REG_FUNC(0x8FFB8524, _ZNSt9basic_iosIwSt11char_traitsIwEED1Ev); REG_FUNC(0x7AF1BB16, _ZNSt9exception18_Set_raise_handlerEPFvRKS_E); REG_FUNC(0x8C5A4417, _ZNSt9exceptionC1ERKS_); REG_FUNC(0xFC169D71, _ZNSt9exceptionC1Ev); REG_FUNC(0x59758E74, _ZNSt9exceptionC2ERKS_); -REG_FUNC(0xE08376, _ZNSt9exceptionC2Ev); +REG_FUNC(0x00E08376, _ZNSt9exceptionC2Ev); REG_FUNC(0x82EEA67E, _ZNSt9exceptionD0Ev); REG_FUNC(0x30405D88, _ZNSt9exceptionD1Ev); REG_FUNC(0xAF7A7081, _ZNSt9exceptionD2Ev); @@ -1272,7 +1272,7 @@ REG_FUNC(0x98BD8AE1, _ZNSt9strstreamD1Ev); REG_FUNC(0x7D8DFE43, _ZNSt9strstreamD2Ev); REG_FUNC(0x8D4B1A13, _ZNSt9type_infoD0Ev); REG_FUNC(0xBD786240, _ZNSt9type_infoD1Ev); -REG_FUNC(0xC04303, _ZNSt9type_infoD2Ev); +REG_FUNC(0x00C04303, _ZNSt9type_infoD2Ev); REG_FUNC(0x9983D8B9, _ZSt10unexpectedv); REG_FUNC(0x385D19B2, _ZSt11setiosflagsNSt5_IosbIiE9_FmtflagsE); REG_FUNC(0xD8A78A61, _ZSt12setprecisioni); @@ -1281,7 +1281,7 @@ REG_FUNC(0x13BAEE11, _ZSt13set_terminatePFvvE); REG_FUNC(0x644CBAA2, _ZSt14_Debug_messagePKcS0_); REG_FUNC(0x9B2F0CA6, _ZSt14set_unexpectedPFvvE); REG_FUNC(0xC107B555, _ZSt15set_new_handlerPFvvE); -REG_FUNC(0x11CEB00, _ZSt18uncaught_exceptionv); +REG_FUNC(0x011CEB00, _ZSt18uncaught_exceptionv); REG_FUNC(0x36282336, _ZSt21__gen_dummy_typeinfosv); REG_FUNC(0x3622003F, _ZSt4setwi); REG_FUNC(0x6CAFA8EF, _ZSt6_ThrowRKSt9exception); @@ -1318,7 +1318,7 @@ REG_FUNC(0x1EB89099, _ZdlPvS_); REG_FUNC(0xE7FB2BF4, _Znaj); REG_FUNC(0x31C62481, _ZnajRKSt9nothrow_t); REG_FUNC(0xF99ED5AC, _Znwj); -REG_FUNC(0xAE71DC3, _ZnwjRKSt9nothrow_t); +REG_FUNC(0x0AE71DC3, _ZnwjRKSt9nothrow_t); REG_FUNC(0x1818C323, _SNC_get_global_vars); REG_FUNC(0x2CFA1F15, _SNC_get_tlocal_vars); REG_FUNC(0x7742D916, _Unwind_Backtrace); @@ -1380,12 +1380,12 @@ REG_FUNC(0xD4C11B17, _ZN10__cxxabiv129__pointer_to_member_type_infoD2Ev); REG_FUNC(0xBF90A45A, _PJP_CPP_Copyright); REG_FUNC(0x3B6D9752, _ZNSbIwSt11char_traitsIwESaIwEE4nposE); REG_FUNC(0xA3498140, _ZNSs4nposE); -REG_FUNC(0x5273EA3, _ZNSt13_Num_int_base10is_boundedE); +REG_FUNC(0x05273EA3, _ZNSt13_Num_int_base10is_boundedE); REG_FUNC(0x8A0994F8, _ZNSt13_Num_int_base10is_integerE); REG_FUNC(0x401F1224, _ZNSt13_Num_int_base14is_specializedE); REG_FUNC(0xA65FE916, _ZNSt13_Num_int_base5radixE); REG_FUNC(0xF2AA872E, _ZNSt13_Num_int_base8is_exactE); -REG_FUNC(0x8FE5A4F, _ZNSt13_Num_int_base9is_moduloE); +REG_FUNC(0x08FE5A4F, _ZNSt13_Num_int_base9is_moduloE); REG_FUNC(0x7D4C55EC, _ZNSt14numeric_limitsIaE6digitsE); REG_FUNC(0xA4E5BF5E, _ZNSt14numeric_limitsIaE8digits10E); REG_FUNC(0xD9938B84, _ZNSt14numeric_limitsIaE9is_signedE); @@ -1394,7 +1394,7 @@ REG_FUNC(0xF52E5F76, _ZNSt14numeric_limitsIbE8digits10E); REG_FUNC(0x81B82E0E, _ZNSt14numeric_limitsIbE9is_moduloE); REG_FUNC(0x9E6D2025, _ZNSt14numeric_limitsIbE9is_signedE); REG_FUNC(0x810ED593, _ZNSt14numeric_limitsIcE6digitsE); -REG_FUNC(0xAC1A819, _ZNSt14numeric_limitsIcE8digits10E); +REG_FUNC(0x0AC1A819, _ZNSt14numeric_limitsIcE8digits10E); REG_FUNC(0x660E14E1, _ZNSt14numeric_limitsIcE9is_signedE); REG_FUNC(0x3EEB3B23, _ZNSt14numeric_limitsIdE12max_exponentE); REG_FUNC(0x13B634BE, _ZNSt14numeric_limitsIdE12min_exponentE); @@ -1422,10 +1422,10 @@ REG_FUNC(0xE8EB3133, _ZNSt14numeric_limitsIiE8digits10E); REG_FUNC(0x3AB38CDA, _ZNSt14numeric_limitsIiE9is_signedE); REG_FUNC(0xEEB7B642, _ZNSt14numeric_limitsIjE6digitsE); REG_FUNC(0xBCDE68B3, _ZNSt14numeric_limitsIjE8digits10E); -REG_FUNC(0xDA8EFB0, _ZNSt14numeric_limitsIjE9is_signedE); +REG_FUNC(0x0DA8EFB0, _ZNSt14numeric_limitsIjE9is_signedE); REG_FUNC(0x65DAD8D6, _ZNSt14numeric_limitsIlE6digitsE); REG_FUNC(0xFB52BC0A, _ZNSt14numeric_limitsIlE8digits10E); -REG_FUNC(0x63544FC, _ZNSt14numeric_limitsIlE9is_signedE); +REG_FUNC(0x063544FC, _ZNSt14numeric_limitsIlE9is_signedE); REG_FUNC(0x441D097A, _ZNSt14numeric_limitsImE6digitsE); REG_FUNC(0xB56F1B07, _ZNSt14numeric_limitsImE8digits10E); REG_FUNC(0xA9799886, _ZNSt14numeric_limitsImE9is_signedE); @@ -1466,13 +1466,13 @@ REG_FUNC(0xE615A657, _ZNSt5_IosbIiE2inE); REG_FUNC(0x759FD02E, _ZNSt5_IosbIiE3appE); REG_FUNC(0x6F410A00, _ZNSt5_IosbIiE3ateE); REG_FUNC(0xD2A42D0C, _ZNSt5_IosbIiE3begE); -REG_FUNC(0x9B45C3B, _ZNSt5_IosbIiE3curE); +REG_FUNC(0x09B45C3B, _ZNSt5_IosbIiE3curE); REG_FUNC(0x121A8952, _ZNSt5_IosbIiE3decE); REG_FUNC(0x7CC027CD, _ZNSt5_IosbIiE3endE); REG_FUNC(0x6E2FF90B, _ZNSt5_IosbIiE3hexE); REG_FUNC(0xB4A55C29, _ZNSt5_IosbIiE3octE); REG_FUNC(0x2CB2DC70, _ZNSt5_IosbIiE3outE); -REG_FUNC(0x78E34A9, _ZNSt5_IosbIiE5truncE); +REG_FUNC(0x078E34A9, _ZNSt5_IosbIiE5truncE); REG_FUNC(0xB5EFA1B3, _ZNSt5_IosbIiE6badbitE); REG_FUNC(0x5312A538, _ZNSt5_IosbIiE6binaryE); REG_FUNC(0xD9D32526, _ZNSt5_IosbIiE6skipwsE); @@ -1492,10 +1492,10 @@ REG_FUNC(0x13B38354, _ZNSt9_Num_base11round_styleE); REG_FUNC(0xB11D20E2, _ZNSt9_Num_base12has_infinityE); REG_FUNC(0x3E169F74, _ZNSt9_Num_base12max_exponentE); REG_FUNC(0xD7C041E0, _ZNSt9_Num_base12min_exponentE); -REG_FUNC(0x2DA0D59, _ZNSt9_Num_base13has_quiet_NaNE); +REG_FUNC(0x02DA0D59, _ZNSt9_Num_base13has_quiet_NaNE); REG_FUNC(0xBE06BD79, _ZNSt9_Num_base14is_specializedE); REG_FUNC(0xEBBC4DDD, _ZNSt9_Num_base14max_exponent10E); -REG_FUNC(0xFFCF7FC, _ZNSt9_Num_base14min_exponent10E); +REG_FUNC(0x0FFCF7FC, _ZNSt9_Num_base14min_exponent10E); REG_FUNC(0xB317DDDF, _ZNSt9_Num_base15has_denorm_lossE); REG_FUNC(0x245D399E, _ZNSt9_Num_base15tinyness_beforeE); REG_FUNC(0xBD5F0B8A, _ZNSt9_Num_base17has_signaling_NaNE); @@ -1542,7 +1542,7 @@ REG_FUNC(0x525557F3, _ZTI19__simd128_float16_t); REG_FUNC(0xA4018B84, _ZTI19__simd128_float32_t); REG_FUNC(0xA1FE4058, _ZTIDh); REG_FUNC(0x5351829B, _ZTINSt8ios_base7failureE); -REG_FUNC(0xAC6C8F, _ZTIP15__simd64_int8_t); +REG_FUNC(0x00AC6C8F, _ZTIP15__simd64_int8_t); REG_FUNC(0xD5B056B8, _ZTIP16__simd128_int8_t); REG_FUNC(0x13975DAE, _ZTIP16__simd64_int16_t); REG_FUNC(0x963C04E3, _ZTIP16__simd64_int32_t); @@ -1557,7 +1557,7 @@ REG_FUNC(0xA96D02B1, _ZTIP17__simd64_uint16_t); REG_FUNC(0xEE862280, _ZTIP17__simd64_uint32_t); REG_FUNC(0xB5CEC4FF, _ZTIP18__simd128_poly16_t); REG_FUNC(0x46124E82, _ZTIP18__simd128_uint16_t); -REG_FUNC(0x7E6CC17, _ZTIP18__simd128_uint32_t); +REG_FUNC(0x07E6CC17, _ZTIP18__simd128_uint32_t); REG_FUNC(0x588EBCAD, _ZTIP18__simd64_float16_t); REG_FUNC(0xDFCB2417, _ZTIP18__simd64_float32_t); REG_FUNC(0x9502D3C0, _ZTIP19__simd128_float16_t); @@ -1568,8 +1568,8 @@ REG_FUNC(0x60D7D920, _ZTIPK16__simd128_int8_t); REG_FUNC(0x52A04C47, _ZTIPK16__simd64_int16_t); REG_FUNC(0xBB64CCF1, _ZTIPK16__simd64_int32_t); REG_FUNC(0x7C9D0C33, _ZTIPK16__simd64_poly8_t); -REG_FUNC(0x21A57A1, _ZTIPK16__simd64_uint8_t); -REG_FUNC(0x21E3DD1, _ZTIPK17__simd128_int16_t); +REG_FUNC(0x021A57A1, _ZTIPK16__simd64_uint8_t); +REG_FUNC(0x021E3DD1, _ZTIPK17__simd128_int16_t); REG_FUNC(0xFF8DDBE7, _ZTIPK17__simd128_int32_t); REG_FUNC(0xB30AB3B5, _ZTIPK17__simd128_poly8_t); REG_FUNC(0xC8721E86, _ZTIPK17__simd128_uint8_t); @@ -1606,12 +1606,12 @@ REG_FUNC(0xA0F5E8F5, _ZTIPKy); REG_FUNC(0xA6C2A25C, _ZTIPU8__vectorx); REG_FUNC(0x81B51915, _ZTIPU8__vectory); REG_FUNC(0xA7CB4EAA, _ZTIPa); -REG_FUNC(0x87B0FB6, _ZTIPb); +REG_FUNC(0x087B0FB6, _ZTIPb); REG_FUNC(0xE4D24E14, _ZTIPc); REG_FUNC(0x6825FFE6, _ZTIPd); REG_FUNC(0x926B9A3A, _ZTIPe); REG_FUNC(0x24072F3E, _ZTIPf); -REG_FUNC(0x8B5247B, _ZTIPh); +REG_FUNC(0x08B5247B, _ZTIPh); REG_FUNC(0x15C21CC8, _ZTIPi); REG_FUNC(0xD234CF18, _ZTIPj); REG_FUNC(0x50E25810, _ZTIPl); @@ -1656,7 +1656,7 @@ REG_FUNC(0xA7CA7C93, _ZTISt8bad_cast); REG_FUNC(0xB93721C7, _ZTISt8ios_base); REG_FUNC(0x35E135A0, _ZTISt9bad_alloc); REG_FUNC(0x7BA61382, _ZTISt9basic_iosIcSt11char_traitsIcEE); -REG_FUNC(0x905B8B0, _ZTISt9basic_iosIwSt11char_traitsIwEE); +REG_FUNC(0x0905B8B0, _ZTISt9basic_iosIwSt11char_traitsIwEE); REG_FUNC(0x1E8C6100, _ZTISt9exception); REG_FUNC(0x1CC15F54, _ZTISt9strstream); REG_FUNC(0x8A026EAD, _ZTISt9type_info); @@ -1688,16 +1688,16 @@ REG_FUNC(0xCD2802B5, _ZTS16__simd64_uint8_t); REG_FUNC(0xC3FA8530, _ZTS17__simd128_int16_t); REG_FUNC(0x67A63A08, _ZTS17__simd128_int32_t); REG_FUNC(0x6B26EFF8, _ZTS17__simd128_poly8_t); -REG_FUNC(0x8C4C69F, _ZTS17__simd128_uint8_t); +REG_FUNC(0x08C4C69F, _ZTS17__simd128_uint8_t); REG_FUNC(0x40BC2E0E, _ZTS17__simd64_poly16_t); REG_FUNC(0x8D1AE4A7, _ZTS17__simd64_uint16_t); REG_FUNC(0xC4096952, _ZTS17__simd64_uint32_t); REG_FUNC(0x16D366F1, _ZTS18__simd128_poly16_t); -REG_FUNC(0x45552A1, _ZTS18__simd128_uint16_t); +REG_FUNC(0x045552A1, _ZTS18__simd128_uint16_t); REG_FUNC(0x7DBF4FFF, _ZTS18__simd128_uint32_t); -REG_FUNC(0xED26DE1, _ZTS18__simd64_float16_t); +REG_FUNC(0x0ED26DE1, _ZTS18__simd64_float16_t); REG_FUNC(0xAB0D789A, _ZTS18__simd64_float32_t); -REG_FUNC(0x3200DDB, _ZTS19__simd128_float16_t); +REG_FUNC(0x03200DDB, _ZTS19__simd128_float16_t); REG_FUNC(0xD54CBD7C, _ZTS19__simd128_float32_t); REG_FUNC(0xA8E6842E, _ZTSDh); REG_FUNC(0x5246E71E, _ZTSNSt8ios_base7failureE); @@ -1729,7 +1729,7 @@ REG_FUNC(0x6A472A63, _ZTSPK16__simd64_int32_t); REG_FUNC(0xC356ACF6, _ZTSPK16__simd64_poly8_t); REG_FUNC(0x878C75F4, _ZTSPK16__simd64_uint8_t); REG_FUNC(0x68B777E3, _ZTSPK17__simd128_int16_t); -REG_FUNC(0x61188BD, _ZTSPK17__simd128_int32_t); +REG_FUNC(0x061188BD, _ZTSPK17__simd128_int32_t); REG_FUNC(0xC7733F13, _ZTSPK17__simd128_poly8_t); REG_FUNC(0x3D8A69EC, _ZTSPK17__simd128_uint8_t); REG_FUNC(0xCC081D58, _ZTSPK17__simd64_poly16_t); @@ -1779,12 +1779,12 @@ REG_FUNC(0x982D9703, _ZTSPs); REG_FUNC(0xE2A0B0A8, _ZTSPt); REG_FUNC(0xF7B6B02A, _ZTSPv); REG_FUNC(0xF1C9A755, _ZTSPw); -REG_FUNC(0x968B212, _ZTSPx); -REG_FUNC(0x9787CAD, _ZTSPy); +REG_FUNC(0x0968B212, _ZTSPx); +REG_FUNC(0x09787CAD, _ZTSPy); REG_FUNC(0xF86F5756, _ZTSSd); REG_FUNC(0x999300E0, _ZTSSi); REG_FUNC(0x591C25A3, _ZTSSo); -REG_FUNC(0xFC9D21B, _ZTSSt10bad_typeid); +REG_FUNC(0x0FC9D21B, _ZTSSt10bad_typeid); REG_FUNC(0x867D109E, _ZTSSt10istrstream); REG_FUNC(0x88BFC745, _ZTSSt10ostrstream); REG_FUNC(0xB315CE7A, _ZTSSt11_ctype_base); @@ -1794,7 +1794,7 @@ REG_FUNC(0xBE23707A, _ZTSSt12domain_error); REG_FUNC(0x9E317CE1, _ZTSSt12length_error); REG_FUNC(0xD8DAD98D, _ZTSSt12out_of_range); REG_FUNC(0x1C929309, _ZTSSt12strstreambuf); -REG_FUNC(0xE17E4D6, _ZTSSt13_codecvt_base); +REG_FUNC(0x0E17E4D6, _ZTSSt13_codecvt_base); REG_FUNC(0x918FE198, _ZTSSt13bad_exception); REG_FUNC(0x227B4568, _ZTSSt13basic_filebufIcSt11char_traitsIcEE); REG_FUNC(0xD34BAF59, _ZTSSt13basic_filebufIwSt11char_traitsIwEE); @@ -1823,7 +1823,7 @@ REG_FUNC(0xE5C789D4, _ZTSSt9strstream); REG_FUNC(0x2856DCD6, _ZTSSt9type_info); REG_FUNC(0x75A1CED4, _ZTSU8__vectorx); REG_FUNC(0x508FF61E, _ZTSU8__vectory); -REG_FUNC(0x8E6A51A, _ZTSa); +REG_FUNC(0x08E6A51A, _ZTSa); REG_FUNC(0x491DB7D3, _ZTSb); REG_FUNC(0xD657B5A0, _ZTSc); REG_FUNC(0x322C7CB5, _ZTSd); @@ -1843,7 +1843,7 @@ REG_FUNC(0x402717E4, _ZTSy); REG_FUNC(0x51B29810, _ZTTSd); REG_FUNC(0x52128B13, _ZTTSi); REG_FUNC(0x3C508708, _ZTTSo); -REG_FUNC(0x87753F6, _ZTTSt10istrstream); +REG_FUNC(0x087753F6, _ZTTSt10istrstream); REG_FUNC(0xE3D7CB30, _ZTTSt10ostrstream); REG_FUNC(0xBC326B50, _ZTTSt13basic_istreamIwSt11char_traitsIwEE); REG_FUNC(0x16E32018, _ZTTSt13basic_ostreamIwSt11char_traitsIwEE); @@ -1866,7 +1866,7 @@ REG_FUNC(0xA81AD21D, _ZTVSt10ostrstream); REG_FUNC(0x82A84E5E, _ZTVSt11logic_error); REG_FUNC(0x1D583475, _ZTVSt11range_error); REG_FUNC(0x80C77E16, _ZTVSt12domain_error); -REG_FUNC(0x64ADA35, _ZTVSt12length_error); +REG_FUNC(0x064ADA35, _ZTVSt12length_error); REG_FUNC(0xDDAE7CBE, _ZTVSt12out_of_range); REG_FUNC(0x11B2781A, _ZTVSt12strstreambuf); REG_FUNC(0x75D16BD0, _ZTVSt13_codecvt_base); @@ -1877,7 +1877,7 @@ REG_FUNC(0xB952752B, _ZTVSt13basic_istreamIwSt11char_traitsIwEE); REG_FUNC(0x48F3405B, _ZTVSt13basic_ostreamIwSt11char_traitsIwEE); REG_FUNC(0x53F02A18, _ZTVSt13runtime_error); REG_FUNC(0x177FCCDC, _ZTVSt14overflow_error); -REG_FUNC(0x5548FF7, _ZTVSt15basic_streambufIcSt11char_traitsIcEE); +REG_FUNC(0x05548FF7, _ZTVSt15basic_streambufIcSt11char_traitsIcEE); REG_FUNC(0xE8A9F32E, _ZTVSt15basic_streambufIwSt11char_traitsIwEE); REG_FUNC(0x515AE097, _ZTVSt15underflow_error); REG_FUNC(0x23EEDAF0, _ZTVSt16invalid_argument); @@ -1889,7 +1889,7 @@ REG_FUNC(0xAA09FD32, _ZTVSt8bad_cast); REG_FUNC(0xD58C5F52, _ZTVSt8ios_base); REG_FUNC(0xA27EFBA3, _ZTVSt9bad_alloc); REG_FUNC(0x147996ED, _ZTVSt9basic_iosIcSt11char_traitsIcEE); -REG_FUNC(0xDE4AFE9, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Sd__St9strstream); +REG_FUNC(0x0DE4AFE9, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Sd__St9strstream); REG_FUNC(0x87D18300, _ZTVSt9basic_iosIcSt11char_traitsIcEE__SiSd__St9strstream); REG_FUNC(0x3D6A38D3, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Si__Sd); REG_FUNC(0xA8E795AF, _ZTVSt9basic_iosIcSt11char_traitsIcEE__Si__St10istrstream); @@ -1902,7 +1902,7 @@ REG_FUNC(0xFD21E1F1, _ZTVSt9strstream); REG_FUNC(0x8E9879A7, _ZTVSt9type_info); REG_FUNC(0xE63750C1, _ZZNSt13basic_filebufIcSt11char_traitsIcEE5_InitEPSt10_Dnk_filetNS2_7_InitflEE7_Stinit); REG_FUNC(0x1D4E29BC, _ZZNSt13basic_filebufIwSt11char_traitsIwEE5_InitEPSt10_Dnk_filetNS2_7_InitflEE7_Stinit); -REG_FUNC(0x8A37475, _ZTIN10__cxxabiv116__enum_type_infoE); +REG_FUNC(0x08A37475, _ZTIN10__cxxabiv116__enum_type_infoE); REG_FUNC(0x66CC7DBB, _ZTIN10__cxxabiv117__array_type_infoE); REG_FUNC(0x81C44513, _ZTIN10__cxxabiv117__class_type_infoE); REG_FUNC(0xC35024DA, _ZTIN10__cxxabiv117__pbase_type_infoE); From 912e3fc2133ac2af5485b12a86543e2b4dfa3264 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 27 Jan 2015 04:39:43 +0300 Subject: [PATCH 23/94] sceCtrl stub --- rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp | 85 +++++++++++++++++++++++++++++ rpcs3/Emu/ARMv7/PSVFuncList.cpp | 2 + rpcs3/Loader/ELF32.cpp | 6 +- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp diff --git a/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp b/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp new file mode 100644 index 0000000000..1f7d65c5df --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp @@ -0,0 +1,85 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceCtrl; + +struct SceCtrlData +{ + u64 timeStamp; + u32 buttons; + u8 lx; + u8 ly; + u8 rx; + u8 ry; + u8 rsrv[16]; +}; + +struct SceCtrlRapidFireRule +{ + u32 uiMask; + u32 uiTrigger; + u32 uiTarget; + u32 uiDelay; + u32 uiMake; + u32 uiBreak; +}; + +s32 sceCtrlSetSamplingMode(u32 uiMode) +{ + throw __FUNCTION__; +} + +s32 sceCtrlGetSamplingMode(vm::psv::ptr puiMode) +{ + throw __FUNCTION__; +} + +s32 sceCtrlPeekBufferPositive(s32 port, vm::psv::ptrpData, s32 nBufs) +{ + throw __FUNCTION__; +} + +s32 sceCtrlPeekBufferNegative(s32 port, vm::psv::ptrpData, s32 nBufs) +{ + throw __FUNCTION__; +} + +s32 sceCtrlReadBufferPositive(s32 port, vm::psv::ptrpData, s32 nBufs) +{ + throw __FUNCTION__; +} + +s32 sceCtrlReadBufferNegative(s32 port, vm::psv::ptrpData, s32 nBufs) +{ + throw __FUNCTION__; +} + +s32 sceCtrlSetRapidFire(s32 port, s32 idx, vm::psv::ptr pRule) +{ + throw __FUNCTION__; +} + +s32 sceCtrlClearRapidFire(s32 port, s32 idx) +{ + throw __FUNCTION__; +} + + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCtrl, #name, name) + +psv_log_base sceCtrl("SceCtrl", []() +{ + sceCtrl.on_load = nullptr; + sceCtrl.on_unload = nullptr; + sceCtrl.on_stop = nullptr; + + REG_FUNC(0xA497B150, sceCtrlSetSamplingMode); + REG_FUNC(0xEC752AAF, sceCtrlGetSamplingMode); + REG_FUNC(0xA9C3CED6, sceCtrlPeekBufferPositive); + REG_FUNC(0x104ED1A7, sceCtrlPeekBufferNegative); + REG_FUNC(0x67E7AB83, sceCtrlReadBufferPositive); + REG_FUNC(0x15F96FB0, sceCtrlReadBufferNegative); + REG_FUNC(0xE9CB69C8, sceCtrlSetRapidFire); + REG_FUNC(0xD8294C9C, sceCtrlClearRapidFire); +}); \ No newline at end of file diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index 05d9b4c483..b011da905b 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -50,6 +50,7 @@ extern psv_log_base sceLibstdcxx; extern psv_log_base sceLibKernel; extern psv_log_base sceSysmodule; extern psv_log_base scePerf; +extern psv_log_base sceCtrl; void initialize_psv_modules() { @@ -62,6 +63,7 @@ void initialize_psv_modules() g_psv_modules.push_back(&sceLibKernel); g_psv_modules.push_back(&sceSysmodule); g_psv_modules.push_back(&scePerf); + g_psv_modules.push_back(&sceCtrl); // setup special functions (without NIDs) psv_func unimplemented; diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 520fb8f991..80cac220ad 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -215,7 +215,7 @@ namespace loader const u32 addr = *++code; vm::psv::write16(addr + 0, 0xf240 | (data & 0x800) >> 1 | (data & 0xf000) >> 12); // MOVW vm::psv::write16(addr + 2, 0x0c00 | (data & 0x700) << 4 | (data & 0xff)); - LOG_NOTICE(LOADER, "sceRefs: movw written at 0x%x (data=0x%x)", addr, data); + //LOG_NOTICE(LOADER, "sceRefs: movw written at 0x%x (data=0x%x)", addr, data); break; } case 0x00000030: @@ -224,13 +224,13 @@ namespace loader const u32 addr = *++code; vm::psv::write16(addr + 0, 0xf2c0 | (data & 0x8000000) >> 17 | (data & 0xf0000000) >> 28); // MOVT vm::psv::write16(addr + 2, 0x0c00 | (data & 0x7000000) >> 12 | (data & 0xff0000) >> 16); - LOG_NOTICE(LOADER, "sceRefs: movt written at 0x%x (data=0x%x)", addr, data); + //LOG_NOTICE(LOADER, "sceRefs: movt written at 0x%x (data=0x%x)", addr, data); break; } case 0x00000000: { // probably, no operation - LOG_NOTICE(LOADER, "sceRefs: zero code"); + //LOG_NOTICE(LOADER, "sceRefs: zero code"); break; } default: diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 407ab81918..50c1a279b4 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -58,6 +58,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index d8f1f1b884..beeae1db31 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -683,6 +683,9 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + From f15c679fea693368422b2f35897c1b087579506b Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 17:14:15 +0200 Subject: [PATCH 24/94] Add support for "test mode" Since @devmapal hasn't made a PR for this and this would be probably useful for Coveralls and unit tests I'm making a PR for it myself. More info: https://github.com/devmapal/rpcs3/commit/c72f5d40f521b955faec024e6b788aa1e027ccfc --- rpcs3/rpcs3.cpp | 41 +++++++++++++++++++++++++++++++++++++---- rpcs3/rpcs3.h | 7 ++++++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index d7549972fe..4f2bc92078 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -202,6 +202,22 @@ void compile_shader(std::string path) bool Rpcs3App::OnInit() { + static const wxCmdLineEntryDesc desc[] + { + { wxCMD_LINE_SWITCH, "h", "help", "Command line options:\nh (help): Help and commands\nt (test): For directly executing a (S)ELF", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, + { wxCMD_LINE_SWITCH, "t", "test", "Run in test mode on (S)ELF", wxCMD_LINE_VAL_NONE }, + { wxCMD_LINE_PARAM, NULL, NULL, "(S)ELF", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, + { wxCMD_LINE_NONE } + }; + + parser.SetDesc(desc); + parser.SetCmdLine(argc, argv); + if (parser.Parse()) + { + // help was given, terminating + this->Exit(); + } + SetSendDbgCommandCallback([](DbgCommand id, CPUThread* t) { wxGetApp().SendDbgCommand(id, t); @@ -296,7 +312,7 @@ bool Rpcs3App::OnInit() m_MainFrame->Show(); m_MainFrame->DoSettings(true); - OnArguments(); + OnArguments(parser); //compile_shader("compile_shader0.spo"); //compile_shader("compile_shader1.spo"); @@ -304,14 +320,26 @@ bool Rpcs3App::OnInit() return true; } -void Rpcs3App::OnArguments() +void Rpcs3App::OnArguments(const wxCmdLineParser& parser) { // Usage: // rpcs3-*.exe Initializes RPCS3 // rpcs3-*.exe [(S)ELF] Initializes RPCS3, then loads and runs the specified (S)ELF file. - if (Rpcs3App::argc > 1) { - Emu.SetPath(fmt::ToUTF8(argv[1])); + if (parser.FoundSwitch("t")) + { + HLEExitOnStop = Ini.HLEExitOnStop.GetValue(); + Ini.HLEExitOnStop.SetValue(true); + if (parser.GetParamCount() != 1) + { + wxLogDebug(wxT("A (S)ELF file needs to be given in test mode, exiting.")); + this->Exit(); + } + } + + if (parser.GetParamCount() > 0) + { + Emu.SetPath(fmt::ToUTF8(parser.GetParam(0))); Emu.Load(); Emu.Run(); } @@ -319,6 +347,11 @@ void Rpcs3App::OnArguments() void Rpcs3App::Exit() { + if (parser.FoundSwitch("t")) + { + Ini.HLEExitOnStop.SetValue(HLEExitOnStop); + } + Emu.Stop(); Ini.Save(); diff --git a/rpcs3/rpcs3.h b/rpcs3/rpcs3.h index 77b35aa7fc..bf745cdfe1 100644 --- a/rpcs3/rpcs3.h +++ b/rpcs3/rpcs3.h @@ -3,6 +3,7 @@ #include "Emu/DbgCommand.h" #include "Utilities/Thread.h" #include +#include class CPUThread; @@ -11,11 +12,15 @@ wxDECLARE_EVENT(wxEVT_DBG_COMMAND, wxCommandEvent); class Rpcs3App : public wxApp { +private: + wxCmdLineParser parser; + // Used to restore the configuration state after a test run + bool HLEExitOnStop; public: MainFrame* m_MainFrame; virtual bool OnInit(); // RPCS3's entry point - virtual void OnArguments(); // Handle arguments: Rpcs3App::argc, Rpcs3App::argv + virtual void OnArguments(const wxCmdLineParser& parser); // Handle arguments: Rpcs3App::argc, Rpcs3App::argv virtual void Exit(); Rpcs3App(); From 3a51a6ded7be80d0e24052161167218a52e78449 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 19:22:56 +0200 Subject: [PATCH 25/94] Revert RSXIO changes This revert fixes many games, while seeming to break none. --- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 96e693d4ea..a279e2b57c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1196,7 +1196,7 @@ s32 cellGcmCallback(vm::ptr context, u32 count) //cmd[3] = 0; // some incrementing by module value //context->current += 0x10; - if (1) + if (0) { const u32 address = context->begin; const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits From e12cfc89deedc7046d3f5756f504a3ef920ab559 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 27 Jan 2015 21:04:40 +0200 Subject: [PATCH 26/94] Experimental DMA implementation, bug fixes The experimental DMA implementation is ported from Nucleus. --- rpcs3/Emu/RSX/RSXDMA.cpp | 124 ++++++++++++++++++++++++++++++++++ rpcs3/Emu/RSX/RSXDMA.h | 45 ++++++++++++ rpcs3/Emu/RSX/RSXThread.cpp | 25 ++++--- rpcs3/Emu/RSX/RSXThread.h | 3 + rpcs3/emucore.vcxproj | 2 + rpcs3/emucore.vcxproj.filters | 6 ++ 6 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 rpcs3/Emu/RSX/RSXDMA.cpp create mode 100644 rpcs3/Emu/RSX/RSXDMA.h diff --git a/rpcs3/Emu/RSX/RSXDMA.cpp b/rpcs3/Emu/RSX/RSXDMA.cpp new file mode 100644 index 0000000000..476448474f --- /dev/null +++ b/rpcs3/Emu/RSX/RSXDMA.cpp @@ -0,0 +1,124 @@ +#include "stdafx.h" +#include "RSXDMA.h" +#include "Emu/Memory/Memory.h" +#include "Utilities/Log.h" + +DMAObject dma_address(u32 dma_object) +{ + // NOTE: RAMIN is not emulated, therefore DMA Objects are hardcoded in this function + switch (dma_object) { + case RSX_CONTEXT_DMA_REPORT_LOCATION_LOCAL: + return DMAObject{ 0x40300000, 0x8000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R starting at 0x1400, test says RW starting at 0x0. + case RSX_CONTEXT_DMA_DEVICE_RW: + return DMAObject{ 0x40000000, 0x1000, DMAObject::READWRITE }; + case RSX_CONTEXT_DMA_DEVICE_R: + return DMAObject{ 0x40000000, 0x1000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R, test says RW + case RSX_CONTEXT_DMA_SEMAPHORE_RW: + return DMAObject{ 0x40100000, 0x1000, DMAObject::READWRITE }; + case RSX_CONTEXT_DMA_SEMAPHORE_R: + return DMAObject{ 0x40100000, 0x1000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R, test says RW + default: + LOG_WARNING(RSX, "Unknown DMA object (0x%08X)", dma_object); + return DMAObject{}; + } +} + +u8 dma_read8(u32 dma_object, u8 offset) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::READ) + { + return vm::read8(dma.addr + offset); + } + + LOG_WARNING(RSX, "Illegal DMA 8-bit read"); + return 0; +} + +u16 dma_read16(u32 dma_object, u16 offset) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::READ) + { + return vm::read16(dma.addr + offset); + } + + LOG_WARNING(RSX, "Illegal DMA 16-bit read"); + return 0; +} + +u32 dma_read32(u32 dma_object, u32 offset) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::READ) + { + return vm::read32(dma.addr + offset); + } + + LOG_WARNING(RSX, "Illegal DMA 32-bit read"); + return 0; +} + +u64 dma_read64(u32 dma_object, u64 offset) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::READ) + { + return vm::read64(dma.addr + offset); + } + + LOG_WARNING(RSX, "Illegal DMA 64-bit read"); + return 0; +} + +void dma_write8(u32 dma_object, u32 offset, u8 value) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::WRITE) + { + return vm::write8(dma.addr + offset, value); + } + + LOG_WARNING(RSX, "Illegal DMA 32-bit write"); +} + +void dma_write16(u32 dma_object, u32 offset, u16 value) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::WRITE) + { + return vm::write16(dma.addr + offset, value); + } + + LOG_WARNING(RSX, "Illegal DMA 32-bit write"); +} + +void dma_write32(u32 dma_object, u32 offset, u32 value) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::WRITE) + { + return vm::write32(dma.addr + offset, value); + } + + LOG_WARNING(RSX, "Illegal DMA 32-bit write"); +} + +void dma_write64(u32 dma_object, u32 offset, u64 value) +{ + const DMAObject& dma = dma_address(dma_object); + + if (dma.addr && dma.flags & DMAObject::WRITE) + { + return vm::write64(dma.addr + offset, value); + } + + LOG_WARNING(RSX, "Illegal DMA 64-bit write"); +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/RSXDMA.h b/rpcs3/Emu/RSX/RSXDMA.h new file mode 100644 index 0000000000..b432375506 --- /dev/null +++ b/rpcs3/Emu/RSX/RSXDMA.h @@ -0,0 +1,45 @@ +#pragma once + +enum { + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 = 0x66604200, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY1 = 0x66604201, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY2 = 0x66604202, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY3 = 0x66604203, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY4 = 0x66604204, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY5 = 0x66604205, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY6 = 0x66604206, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY7 = 0x66604207, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY8 = 0x66604208, // Target: lpar_reports[0x1000 : 0x????] + RSX_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F, + RSX_CONTEXT_DMA_SEMAPHORE_RW = 0x66606660, // Target: lpar_reports[0x0000 : 0x1000] (Read/Write) + RSX_CONTEXT_DMA_SEMAPHORE_R = 0x66616661, // Target: lpar_reports[0x0000 : 0x1000] (Read) + RSX_CONTEXT_DMA_REPORT_LOCATION_LOCAL = 0x66626660, // Target: lpar_reports[0x1400 : 0x9400] + RSX_CONTEXT_DMA_REPORT_LOCATION_MAIN = 0xBAD68000, + RSX_CONTEXT_DMA_DEVICE_RW = 0x56616660, + RSX_CONTEXT_DMA_DEVICE_R = 0x56616661, +}; + +struct DMAObject { + // Flags + enum { + READ = 1 << 0, + WRITE = 1 << 1, + READWRITE = READ | WRITE, + }; + u32 addr; + u32 size; + u32 flags; +}; + +// RSX Direct Memory Access +DMAObject dma_address(u32 dma_object); + +u8 dma_read8(u32 dma_object, u32 offset); +u16 dma_read16(u32 dma_object, u32 offset); +u32 dma_read32(u32 dma_object, u32 offset); +u64 dma_read64(u32 dma_object, u32 offset); + +void dma_write8(u32 dma_object, u32 offset, u8 value); +void dma_write16(u32 dma_object, u32 offset, u16 value); +void dma_write32(u32 dma_object, u32 offset, u32 value); +void dma_write64(u32 dma_object, u32 offset, u64 value); \ No newline at end of file diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 906b0281c3..ed7b539005 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -4,6 +4,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/RSX/GSManager.h" +#include "Emu/RSX/RSXDMA.h" #include "RSXThread.h" #include "Emu/SysCalls/Callback.h" @@ -333,6 +334,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_REPORT: 0x%x", ARGS(0)); } + + dma_report = ARGS(0); } break; @@ -891,9 +894,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_CLEAR_SURFACE: { - const u32 mask = ARGS(0); - - ClearSurface(mask); + ClearSurface(ARGS(0)); } break; @@ -901,8 +902,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { const u32 value = ARGS(0); - ClearStencil(value & 0xff); ClearDepth(value >> 8); + ClearStencil(value & 0xff); } break; @@ -1076,7 +1077,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { m_cur_fragment_prog = &m_fragment_progs[m_cur_fragment_prog_num]; - const u32 a0 = ARGS(0); + const u32 a0 = ARGS(0); m_cur_fragment_prog->offset = a0 & ~0x3; m_cur_fragment_prog->addr = GetAddress(m_cur_fragment_prog->offset, (a0 & 0x3) - 1); m_cur_fragment_prog->ctrl = 0x40; @@ -1091,8 +1092,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_SHADE_MODE: { - const u32 value = ARGS(0); - ShadeModel(value); + ShadeModel(ARGS(0)); } break; @@ -1867,9 +1867,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u64 timestamp = get_system_time() * 1000; // TODO: Reports can be written to the main memory or the local memory (controlled by NV4097_SET_CONTEXT_DMA_REPORT) - vm::write64(m_local_mem_addr + offset + 0x0, timestamp); - vm::write32(m_local_mem_addr + offset + 0x8, value); - vm::write32(m_local_mem_addr + offset + 0xc, 0); + // NOTE: Uncomment these, if DMA implementation is broken + //vm::write64(m_local_mem_addr + offset + 0x0, timestamp); + //vm::write32(m_local_mem_addr + offset + 0x8, value); + //vm::write32(m_local_mem_addr + offset + 0xc, 0); + + dma_write64(dma_report, offset + 0x0, timestamp); + dma_write32(dma_report, offset + 0x8, value); + dma_write32(dma_report, offset + 0xc, 0); } break; diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 618573d21a..4a5fe782ca 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -136,6 +136,9 @@ public: u32 m_ctxt_addr; u32 m_report_main_addr; + // DMA + u32 dma_report; + u32 m_local_mem_addr, m_main_mem_addr; bool m_strict_ordering[0x1000]; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 4b4a2d6539..b52ff1c3ba 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -107,6 +107,7 @@ + @@ -348,6 +349,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index fdd71b410a..d222f71c07 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -665,6 +665,9 @@ Emu\CPU\ARMv7 + + Emu\GPU\RSX + @@ -1294,5 +1297,8 @@ Emu\CPU\ARMv7\Modules + + Emu\GPU\RSX + \ No newline at end of file From 14efde91900ceab0e02bafc44532eeabe0d5eb20 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 27 Jan 2015 22:57:44 +0300 Subject: [PATCH 27/94] ARMv7: LDRB_IMM, STRB_IMM --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 8 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 116 +++++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp | 2 +- rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp | 6 +- 4 files changed, 124 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 8a361014f4..e5a7b4b87f 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -44,20 +44,20 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM), ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM), ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )), - ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM), + ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )), ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM), ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG), ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )), - ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG), + ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )), ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR), ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI), ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI), - ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI), + ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI), ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI), ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR), - ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR), + ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR, SKIP_IF( BF(3, 6) == 13 )), ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR), ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 71d91acad9..954e07dfcc 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -1355,6 +1355,7 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR reject((wback && n == t) || (t == 15 && context.ITSTATE), "UNPREDICTABLE"); break; } + case A1: throw __FUNCTION__; default: throw __FUNCTION__; } @@ -1441,11 +1442,70 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = (code.data & 0x7c0) >> 4; + index = true; + add = true; + wback = false; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(t == 15, "PLD"); + reject(n == 15, "LDRB (literal)"); + reject(t == 13, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(t == 15 && index && !add && !wback, "PLD"); + reject(n == 15, "LDRB (literal)"); + reject(index && add && !wback, "LDRBT"); + reject(!index && !wback, "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + context.write_gpr(t, vm::psv::read8(addr)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::LDRB_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2999,11 +3059,67 @@ void ARMv7_instrs::STR_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = (code.data & 0x7c0) >> 4; + index = true; + add = true; + wback = false; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(index && add && !wback, "STRBT"); + reject(n == 15 || (!index && !wback), "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write8(addr, (u8)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp b/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp index 1f7d65c5df..972bd85d4c 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp @@ -82,4 +82,4 @@ psv_log_base sceCtrl("SceCtrl", []() REG_FUNC(0x15F96FB0, sceCtrlReadBufferNegative); REG_FUNC(0xE9CB69C8, sceCtrlSetRapidFire); REG_FUNC(0xD8294C9C, sceCtrlClearRapidFire); -}); \ No newline at end of file +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp index 6584de337a..a845595c87 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp @@ -6,21 +6,21 @@ extern psv_log_base sceSysmodule; s32 sceSysmoduleLoadModule(u16 id) { - sceSysmodule.Todo("sceSysmoduleLoadModule(id=0x%04x)", id); + sceSysmodule.Error("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id); return SCE_OK; // loading succeeded } s32 sceSysmoduleUnloadModule(u16 id) { - sceSysmodule.Todo("sceSysmoduleUnloadModule(id=0x%04x)", id); + sceSysmodule.Error("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id); return SCE_OK; // unloading succeeded } s32 sceSysmoduleIsLoaded(u16 id) { - sceSysmodule.Todo("sceSysmoduleIsLoaded(id=0x%04x)", id); + sceSysmodule.Error("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id); return SCE_OK; // module is loaded } From 1c4db01e196af6ce0549e6f13b69d4553e7474b3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 28 Jan 2015 01:39:16 +0300 Subject: [PATCH 28/94] sceDisplay, sceDeci4p stub --- rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp | 48 +++++++++++ rpcs3/Emu/ARMv7/Modules/sceDisplay.cpp | 113 +++++++++++++++++++++++++ rpcs3/emucore.vcxproj | 3 + rpcs3/emucore.vcxproj.filters | 9 ++ 4 files changed, 173 insertions(+) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceDisplay.cpp diff --git a/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp b/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp new file mode 100644 index 0000000000..bdd5e58e5d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp @@ -0,0 +1,48 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceDeci4p; + +typedef s32(*SceKernelDeci4pCallback)(s32 notifyId, s32 notifyCount, s32 notifyArg, vm::psv::ptr pCommon); + +s32 sceKernelDeci4pOpen(vm::psv::ptr protoname, u32 protonum, u32 bufsize) +{ + throw __FUNCTION__; +} + +s32 sceKernelDeci4pClose(s32 socketid) +{ + throw __FUNCTION__; +} + +s32 sceKernelDeci4pRead(s32 socketid, vm::psv::ptr buffer, u32 size, u32 reserved) +{ + throw __FUNCTION__; +} + +s32 sceKernelDeci4pWrite(s32 socketid, vm::psv::ptr buffer, u32 size, u32 reserved) +{ + throw __FUNCTION__; +} + +s32 sceKernelDeci4pRegisterCallback(s32 socketid, s32 cbid) +{ + throw __FUNCTION__; +} + + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceDeci4p, #name, name) + +psv_log_base sceDeci4p("SceDeci4pUserp", []() +{ + sceDeci4p.on_load = nullptr; + sceDeci4p.on_unload = nullptr; + sceDeci4p.on_stop = nullptr; + + REG_FUNC(0x28578FE8, sceKernelDeci4pOpen); + REG_FUNC(0x63B0C50F, sceKernelDeci4pClose); + REG_FUNC(0x971E1C66, sceKernelDeci4pRead); + REG_FUNC(0xCDA3AAAC, sceKernelDeci4pWrite); + REG_FUNC(0x73371F35, sceKernelDeci4pRegisterCallback); +}); \ No newline at end of file diff --git a/rpcs3/Emu/ARMv7/Modules/sceDisplay.cpp b/rpcs3/Emu/ARMv7/Modules/sceDisplay.cpp new file mode 100644 index 0000000000..c03dbe24dd --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceDisplay.cpp @@ -0,0 +1,113 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceDisplay; + +struct SceDisplayFrameBuf +{ + u32 size; + vm::psv::ptr base; + u32 pitch; + u32 pixelformat; + u32 width; + u32 height; +}; + +s32 sceDisplayGetRefreshRate(vm::psv::ptr pFps) +{ + throw __FUNCTION__; +} + +s32 sceDisplaySetFrameBuf(vm::psv::ptr pFrameBuf, s32 iUpdateTimingMode) +{ + throw __FUNCTION__; +} + +s32 sceDisplayGetFrameBuf(vm::psv::ptr pFrameBuf, s32 iUpdateTimingMode) +{ + throw __FUNCTION__; +} + +s32 sceDisplayGetVcount() +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitVblankStart() +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitVblankStartCB() +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitVblankStartMulti(u32 vcount) +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitVblankStartMultiCB(u32 vcount) +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitSetFrameBuf() +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitSetFrameBufCB() +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitSetFrameBufMulti(u32 vcount) +{ + throw __FUNCTION__; +} + +s32 sceDisplayWaitSetFrameBufMultiCB(u32 vcount) +{ + throw __FUNCTION__; +} + +s32 sceDisplayRegisterVblankStartCallback(s32 uid) +{ + throw __FUNCTION__; +} + +s32 sceDisplayUnregisterVblankStartCallback(s32 uid) +{ + throw __FUNCTION__; +} + + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceDisplay, #name, name) + +psv_log_base sceDisplay("SceDisplay", []() +{ + sceDisplay.on_load = nullptr; + sceDisplay.on_unload = nullptr; + sceDisplay.on_stop = nullptr; + + // SceDisplayUser + REG_FUNC(0x7A410B64, sceDisplaySetFrameBuf); + REG_FUNC(0x42AE6BBC, sceDisplayGetFrameBuf); + + // SceDisplay + REG_FUNC(0xA08CA60D, sceDisplayGetRefreshRate); + REG_FUNC(0xB6FDE0BA, sceDisplayGetVcount); + REG_FUNC(0x5795E898, sceDisplayWaitVblankStart); + REG_FUNC(0x78B41B92, sceDisplayWaitVblankStartCB); + REG_FUNC(0xDD0A13B8, sceDisplayWaitVblankStartMulti); + REG_FUNC(0x05F27764, sceDisplayWaitVblankStartMultiCB); + REG_FUNC(0x9423560C, sceDisplayWaitSetFrameBuf); + REG_FUNC(0x814C90AF, sceDisplayWaitSetFrameBufCB); + REG_FUNC(0x7D9864A8, sceDisplayWaitSetFrameBufMulti); + REG_FUNC(0x3E796EF5, sceDisplayWaitSetFrameBufMultiCB); + REG_FUNC(0x6BDF4C4D, sceDisplayRegisterVblankStartCallback); + REG_FUNC(0x98436A80, sceDisplayUnregisterVblankStartCallback); +}); \ No newline at end of file diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 50c1a279b4..e70afa794c 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -59,6 +59,9 @@ + + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index beeae1db31..69e962dbfc 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -686,6 +686,15 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + From 579a88b7c43dcc1b005a3eae22a7364125904762 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 28 Jan 2015 15:59:16 +0300 Subject: [PATCH 29/94] vm_ptr: function format changed --- Utilities/BEType.h | 48 ++++++++-- rpcs3/Emu/ARMv7/ARMv7Callback.h | 4 +- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 +- rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp | 8 +- rpcs3/Emu/ARMv7/Modules/sceLibKernel.h | 6 +- rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 2 +- rpcs3/Emu/Cell/PPUThread.h | 2 +- rpcs3/Emu/Memory/vm_ptr.h | 49 ++++++---- rpcs3/Emu/RSX/GCM.h | 2 +- rpcs3/Emu/RSX/RSXThread.h | 7 +- rpcs3/Emu/SysCalls/CB_FUNC.h | 5 +- rpcs3/Emu/SysCalls/Modules.h | 6 +- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 16 ++-- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellNetCtl.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellPngDec.h | 12 +-- rpcs3/Emu/SysCalls/Modules/cellResc.cpp | 22 ++--- rpcs3/Emu/SysCalls/Modules/cellResc.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellSail.h | 102 ++++++++++----------- rpcs3/Emu/SysCalls/Modules/cellSaveData.h | 10 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 8 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 6 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.h | 20 ++-- rpcs3/Emu/SysCalls/Modules/cellVdec.h | 2 +- rpcs3/Emu/SysCalls/Modules/libmixer.h | 2 +- rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h | 2 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h | 2 +- rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 8 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h | 2 +- rpcs3/Loader/ELF64.cpp | 2 +- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 37 files changed, 216 insertions(+), 171 deletions(-) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 27997618bd..4965eac336 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -708,7 +708,7 @@ class to_be_t public: //true if need swap endianes for be - static const bool value = (sizeof(T2) > 1) && (std::is_arithmetic::value || std::is_enum::value); + static const bool value = std::is_arithmetic::value || std::is_enum::value; //be_t if need swap endianes, T otherwise typedef typename _be_type_selector< T, T2, value >::type type; @@ -716,26 +716,58 @@ public: typedef typename _be_type_selector< T, T2, !is_be_t::value >::type forced_type; }; +template +class to_be_t +{ +public: + static const bool value = to_be_t::value; + typedef const typename to_be_t::type type; + typedef const typename to_be_t::forced_type forced_type; +}; + template class to_be_t { public: - //true if need swap endianes for be static const bool value = false; - - //be_t if need swap endianes, T otherwise typedef void type; + typedef void forced_type; }; template -class to_be_t +class to_be_t { public: - //true if need swap endianes for be static const bool value = false; + typedef u8 type; + typedef u8 forced_type; +}; - //be_t if need swap endianes, T otherwise - typedef const void type; +template +class to_be_t +{ +public: + static const bool value = false; + typedef s8 type; + typedef s8 forced_type; +}; + +template +class to_be_t +{ +public: + static const bool value = false; + typedef char type; + typedef char forced_type; +}; + +template +class to_be_t +{ +public: + static const bool value = false; + typedef bool type; + typedef bool forced_type; }; template diff --git a/rpcs3/Emu/ARMv7/ARMv7Callback.h b/rpcs3/Emu/ARMv7/ARMv7Callback.h index 4f9c72d1e0..18c39fe49d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Callback.h +++ b/rpcs3/Emu/ARMv7/ARMv7Callback.h @@ -5,7 +5,7 @@ namespace vm { template - __forceinline RT _ptr_base::operator()(ARMv7Context& context, T... args) const + __forceinline RT _ptr_base::operator()(ARMv7Context& context, T... args) const { return psv_func_detail::func_caller::call(context, vm::cast(this->addr()), args...); } @@ -15,4 +15,4 @@ template __forceinline RT cb_call(ARMv7Context& context, u32 addr, T... args) { return psv_func_detail::func_caller::call(context, addr, args...); -} \ No newline at end of file +} diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 873f039555..962f5dcc19 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -266,7 +266,7 @@ struct cast_armv7_gpr return value; } - __forceinline static bool from_gpr(const u32 reg) + __forceinline static bool from_gpr(const u32& reg) { return reinterpret_cast(reg); } diff --git a/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp b/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp index 972bd85d4c..b858e40972 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceCtrl.cpp @@ -35,22 +35,22 @@ s32 sceCtrlGetSamplingMode(vm::psv::ptr puiMode) throw __FUNCTION__; } -s32 sceCtrlPeekBufferPositive(s32 port, vm::psv::ptrpData, s32 nBufs) +s32 sceCtrlPeekBufferPositive(s32 port, vm::psv::ptr pData, s32 nBufs) { throw __FUNCTION__; } -s32 sceCtrlPeekBufferNegative(s32 port, vm::psv::ptrpData, s32 nBufs) +s32 sceCtrlPeekBufferNegative(s32 port, vm::psv::ptr pData, s32 nBufs) { throw __FUNCTION__; } -s32 sceCtrlReadBufferPositive(s32 port, vm::psv::ptrpData, s32 nBufs) +s32 sceCtrlReadBufferPositive(s32 port, vm::psv::ptr pData, s32 nBufs) { throw __FUNCTION__; } -s32 sceCtrlReadBufferNegative(s32 port, vm::psv::ptrpData, s32 nBufs) +s32 sceCtrlReadBufferNegative(s32 port, vm::psv::ptr pData, s32 nBufs) { throw __FUNCTION__; } diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h index 186c470b1c..df2bbd3d3d 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.h @@ -306,7 +306,7 @@ struct SceKernelAllocMemBlockOpt // Thread Manager definitions (threads) -typedef s32(*SceKernelThreadEntry)(u32 argSize, vm::psv::ptr pArgBlock); +typedef s32(SceKernelThreadEntry)(u32 argSize, vm::psv::ptr pArgBlock); struct SceKernelThreadOptParam { @@ -371,7 +371,7 @@ struct SceKernelSystemInfo // Thread Manager definitions (callbacks) -typedef s32(*SceKernelCallbackFunction)(s32 notifyId, s32 notifyCount, s32 notifyArg, vm::psv::ptr pCommon); +typedef s32(SceKernelCallbackFunction)(s32 notifyId, s32 notifyCount, s32 notifyArg, vm::psv::ptr pCommon); struct SceKernelCallbackInfo { @@ -389,7 +389,7 @@ struct SceKernelCallbackInfo // Thread Manager definitions (events) -typedef s32(*SceKernelThreadEventHandler)(s32 type, s32 threadId, s32 arg, vm::psv::ptr pCommon); +typedef s32(SceKernelThreadEventHandler)(s32 type, s32 threadId, s32 arg, vm::psv::ptr pCommon); struct SceKernelEventInfo { diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index f0e596af2b..611be74629 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -8,7 +8,7 @@ extern psv_log_base sceLibc; vm::psv::ptr g_dso; -typedef void(*atexit_func_t)(vm::psv::ptr); +typedef void(atexit_func_t)(vm::psv::ptr); std::vector> g_atexit; diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 2c5c13246d..3def8675d6 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -969,7 +969,7 @@ struct cast_ppu_gpr return value; } - __forceinline static bool from_gpr(const u64 reg) + __forceinline static bool from_gpr(const u64& reg) { return reinterpret_cast(reg); } diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 23c7123b2d..ead6e577a0 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -109,7 +109,11 @@ namespace vm public: typedef typename std::remove_cv::type type; - static const u32 data_size = sizeof(T); + + __forceinline static const u32 data_size() + { + return sizeof(T); + } __forceinline T* const operator -> () const { @@ -119,45 +123,45 @@ namespace vm _ptr_base operator++ (int) { AT result = m_addr; - m_addr += data_size; + m_addr += data_size(); return make(result); } _ptr_base& operator++ () { - m_addr += data_size; + m_addr += data_size(); return *this; } _ptr_base operator-- (int) { AT result = m_addr; - m_addr -= data_size; + m_addr -= data_size(); return make(result); } _ptr_base& operator-- () { - m_addr -= data_size; + m_addr -= data_size(); return *this; } _ptr_base& operator += (AT count) { - m_addr += count * data_size; + m_addr += count * data_size(); return *this; } _ptr_base& operator -= (AT count) { - m_addr -= count * data_size; + m_addr -= count * data_size(); return *this; } - _ptr_base operator + (typename remove_be_t::type count) const { return make(m_addr + count * data_size); } - _ptr_base operator + (typename to_be_t::type count) const { return make(m_addr + count * data_size); } - _ptr_base operator - (typename remove_be_t::type count) const { return make(m_addr - count * data_size); } - _ptr_base operator - (typename to_be_t::type count) const { return make(m_addr - count * data_size); } + _ptr_base operator + (typename remove_be_t::type count) const { return make(m_addr + count * data_size()); } + _ptr_base operator + (typename to_be_t::type count) const { return make(m_addr + count * data_size()); } + _ptr_base operator - (typename remove_be_t::type count) const { return make(m_addr - count * data_size()); } + _ptr_base operator - (typename to_be_t::type count) const { return make(m_addr - count * data_size()); } __forceinline T& operator *() const { @@ -166,12 +170,12 @@ namespace vm __forceinline T& operator [](typename remove_be_t::type index) const { - return vm::get_ref(vm::cast(m_addr + data_size * index)); + return vm::get_ref(vm::cast(m_addr + data_size() * index)); } __forceinline T& operator [](typename to_be_t::forced_type index) const { - return vm::get_ref(vm::cast(m_addr + data_size * index)); + return vm::get_ref(vm::cast(m_addr + data_size() * index)); } __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } @@ -326,12 +330,12 @@ namespace vm }; template - class _ptr_base + class _ptr_base { AT m_addr; public: - typedef RT(*type)(T...); + typedef RT(type)(T...); RT operator()(CPUThread& CPU, T... args) const; // defined in CB_FUNC.h, call using specified PPU thread context @@ -360,10 +364,10 @@ namespace vm explicit operator bool() const { return m_addr != 0; } template - operator const _ptr_base() const + operator const _ptr_base() const { const AT2 addr = convert_le_be(m_addr); - return reinterpret_cast&>(addr); + return reinterpret_cast&>(addr); } static const _ptr_base make(const AT& addr) @@ -371,7 +375,7 @@ namespace vm return reinterpret_cast(addr); } - operator const std::function() const + operator const std::function() const { const AT addr = convert_le_be(m_addr); return [addr](T... args) -> RT { return make(addr)(args...); }; @@ -380,6 +384,15 @@ namespace vm _ptr_base& operator = (const _ptr_base& right) = default; }; + template + class _ptr_base + { + AT m_addr; + + public: + static_assert(!sizeof(AT), "vm::_ptr_base<> error: use RT(T...) format for functions instead of RT(*)(T...)"); + }; + //BE pointer to LE data template struct bptrl : public _ptr_base::type> { diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index 7b216aa87f..929b968503 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -220,7 +220,7 @@ struct CellGcmConfig struct CellGcmContextData; -typedef s32(*CellGcmContextCallback)(vm::ptr, u32); +typedef s32(CellGcmContextCallback)(vm::ptr, u32); struct CellGcmContextData { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 618573d21a..c0f412f648 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -154,10 +154,10 @@ public: SSemaphore m_sem_flush; SSemaphore m_sem_flip; u64 m_last_flip_time; - vm::ptr m_flip_handler; - vm::ptr m_user_handler; + vm::ptr m_flip_handler; + vm::ptr m_user_handler; u64 m_vblank_count; - vm::ptr m_vblank_handler; + vm::ptr m_vblank_handler; public: // Dither @@ -442,6 +442,7 @@ protected: , m_flip_mode(CELL_GCM_DISPLAY_VSYNC) , m_debug_level(CELL_GCM_DEBUG_LEVEL0) , m_frequency_mode(CELL_GCM_DISPLAY_FREQUENCY_DISABLE) + , m_report_main_addr(0) , m_main_mem_addr(0) , m_local_mem_addr(0) , m_draw_mode(0) diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 403a703db5..160eab9559 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -163,7 +163,7 @@ namespace cb_detail namespace vm { template - __forceinline RT _ptr_base::operator()(CPUThread& CPU, T... args) const + __forceinline RT _ptr_base::operator()(CPUThread& CPU, T... args) const { auto data = vm::get_ptr>(vm::cast(m_addr)); const u32 pc = data[0]; @@ -174,7 +174,7 @@ namespace vm } template - __forceinline RT _ptr_base::operator()(T... args) const + __forceinline RT _ptr_base::operator()(T... args) const { return operator()(GetCurrentPPUThread(), args...); } @@ -186,6 +186,7 @@ __forceinline RT cb_call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) return cb_detail::_func_caller::call(CPU, pc, rtoc, args...); } +// Something is wrong with it (but cb_call() should work anyway) //template //void cb_call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) //{ diff --git a/rpcs3/Emu/SysCalls/Modules.h b/rpcs3/Emu/SysCalls/Modules.h index 5874dc6fc5..6172e623fc 100644 --- a/rpcs3/Emu/SysCalls/Modules.h +++ b/rpcs3/Emu/SysCalls/Modules.h @@ -9,9 +9,9 @@ struct ModuleFunc { u32 id; func_caller* func; - vm::ptr lle_func; + vm::ptr lle_func; - ModuleFunc(u32 id, func_caller* func, vm::ptr lle_func = vm::ptr::make(0)) + ModuleFunc(u32 id, func_caller* func, vm::ptr lle_func = vm::ptr::make(0)) : id(id) , func(func) , lle_func(lle_func) @@ -129,7 +129,7 @@ public: bool RemoveId(u32 id); - void RegisterLLEFunc(u32 id, vm::ptr func) + void RegisterLLEFunc(u32 id, vm::ptr func) { if (auto f = GetFunc(id)) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index a0a3fb2a8e..00c5a58c3e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -366,7 +366,7 @@ enum CellAdecMsgType CELL_ADEC_MSG_TYPE_SEQDONE, }; -typedef s32(*CellAdecCbMsg)(u32 handle, CellAdecMsgType msgType, s32 msgData, u32 cbArg); +typedef s32(CellAdecCbMsg)(u32 handle, CellAdecMsgType msgType, s32 msgData, u32 cbArg); struct CellAdecCb { diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index 8a2a70cc5b..edca677727 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -217,7 +217,7 @@ struct CellDmuxResource2 be_t shit[4]; }; -typedef u32(*CellDmuxCbMsg)(u32 demuxerHandle, vm::ptr demuxerMsg, u32 cbArg); +typedef u32(CellDmuxCbMsg)(u32 demuxerHandle, vm::ptr demuxerMsg, u32 cbArg); struct CellDmuxCb { @@ -225,7 +225,7 @@ struct CellDmuxCb be_t cbArg; }; -typedef u32(*CellDmuxCbEsMsg)(u32 demuxerHandle, u32 esHandle, vm::ptr esMsg, u32 cbArg); +typedef u32(CellDmuxCbEsMsg)(u32 demuxerHandle, u32 esHandle, vm::ptr esMsg, u32 cbArg); struct CellDmuxEsCb { diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 6fb4df09ca..e54aedb7e2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -202,7 +202,7 @@ int cellGameContentPermit(vm::ptr contentInfoPath, vm: } int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, - vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container) + vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container) { cellGame->Warning("cellGameDataCheckCreate(2)(version=0x%x, dirName_addr=0x%x, errDialog=0x%x, funcStat_addr=0x%x, container=%d)", version, dirName.addr(), errDialog, funcStat.addr(), container); @@ -307,7 +307,7 @@ int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr di } int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, - vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container) + vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container) { // TODO: almost identical, the only difference is that this function will always calculate the size of game data return cellGameDataCheckCreate2(CPU, version, dirName, errDialog, funcStat, container); diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index f91f4cb1c6..908012920c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -125,12 +125,8 @@ u32 cellGcmGetNotifyDataAddress(u32 index) { cellGcmSys->Warning("cellGcmGetNotifyDataAddress(index=%d)", index); - // Get address of 'IO table' and 'EA table' - vm::var table; - cellGcmGetOffsetTable(table); - // If entry not in use, return NULL - u16 entry = table->eaAddress[241]; + u16 entry = offsetTable.eaAddress[241]; if (entry == 0xFFFF) { return 0; } @@ -455,7 +451,7 @@ int cellGcmSetFlip(vm::ptr ctxt, u32 id) return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; } -void cellGcmSetFlipHandler(vm::ptr handler) +void cellGcmSetFlipHandler(vm::ptr handler) { cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler.addr()); @@ -596,14 +592,14 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u return CELL_OK; } -void cellGcmSetUserHandler(vm::ptr handler) +void cellGcmSetUserHandler(vm::ptr handler) { cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler.addr()); Emu.GetGSManager().GetRender().m_user_handler = handler; } -void cellGcmSetVBlankHandler(vm::ptr handler) +void cellGcmSetVBlankHandler(vm::ptr handler) { cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler.addr()); @@ -1191,7 +1187,7 @@ s32 cellGcmCallback(vm::ptr context, u32 count) //auto& ctrl = vm::get_ref(gcm_info.control_addr); // preparations for changing the place (for optimized FIFO mode) - //auto cmd = vm::ptr::make(context->current.ToLE()); + //auto cmd = vm::ptr::make(context->current); //cmd[0] = 0x41D6C; //cmd[1] = 0x20; //cmd[2] = 0x41D74; @@ -1207,7 +1203,7 @@ s32 cellGcmCallback(vm::ptr context, u32 count) vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | offset); // set JUMP cmd auto& ctrl = vm::get_ref(gcm_info.control_addr); - ctrl.put.write_relaxed(be_t::make(offset)); + ctrl.put.exchange(be_t::make(offset)); } else { diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h index 4b76eb975c..3ce4d78e0b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h @@ -79,7 +79,7 @@ enum CELL_MSGDIALOG_BUTTON_ESCAPE = 3, }; -typedef void(*CellMsgDialogCallback)(s32 buttonType, u32 userData); +typedef void(CellMsgDialogCallback)(s32 buttonType, u32 userData); s32 cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr callback, u32 userData, u32 extParam); s32 cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr callback, u32 userData, u32 extParam); diff --git a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.h b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.h index 4cb89a6962..a09167848e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.h +++ b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.h @@ -224,7 +224,7 @@ union CellNetCtlInfo be_t ip_config; s8 dhcp_hostname[256]; s8 pppoe_auth_name[128]; - s8 ip_address[16]; + char ip_address[16]; s8 netmask[16]; s8 default_route[16]; s8 primary_dns[16]; @@ -257,4 +257,4 @@ struct CellNetCtlNatInfo be_t mapped_addr; }; -typedef void(*cellNetCtlHandler)(s32 prev_state, s32 new_state, s32 event, s32 error_code, vm::ptr arg); +typedef void(cellNetCtlHandler)(s32 prev_state, s32 new_state, s32 event, s32 error_code, vm::ptr arg); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index e0a5473584..86170f7508 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -87,8 +87,8 @@ enum CellPngDecDecodeStatus : u32 }; // Callbacks -typedef vm::ptr(*CellPngDecCbControlMalloc)(u32 size, vm::ptr cbCtrlMallocArg); -typedef s32(*CellPngDecCbControlFree)(vm::ptr ptr, vm::ptr cbCtrlFreeArg); +typedef vm::ptr(CellPngDecCbControlMalloc)(u32 size, vm::ptr cbCtrlMallocArg); +typedef s32(CellPngDecCbControlFree)(vm::ptr ptr, vm::ptr cbCtrlFreeArg); // Structs struct CellPngDecThreadInParam @@ -283,11 +283,7 @@ struct CellPngDecStrmParam be_t strmSize; }; -typedef s32(*CellPngDecCbControlStream)( - vm::ptr strmInfo, - vm::ptr strmParam, - vm::ptr cbCtrlStrmArg - ); +typedef s32(CellPngDecCbControlStream)(vm::ptr strmInfo, vm::ptr strmParam, vm::ptr cbCtrlStrmArg); struct CellPngDecDispInfo { @@ -310,7 +306,7 @@ struct CellPngDecDispParam }; // Callback -typedef s32(*CellPngDecCbControlDisp)(vm::ptr dispInfo, vm::ptr dispParam, vm::ptr cbCtrlDispArg); +typedef s32(CellPngDecCbControlDisp)(vm::ptr dispInfo, vm::ptr dispParam, vm::ptr cbCtrlDispArg); // Structs struct CellPngDecOpnParam diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index 7cf2717bea..d10da00a1f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -12,8 +12,8 @@ Module *cellResc = nullptr; extern s32 cellVideoOutConfigure(u32 videoOut, vm::ptr config, vm::ptr option, u32 waitForEvent); extern int cellGcmSetFlipMode(u32 mode); -extern void cellGcmSetFlipHandler(vm::ptr handler); -extern void cellGcmSetVBlankHandler(vm::ptr handler); +extern void cellGcmSetFlipHandler(vm::ptr handler); +extern void cellGcmSetVBlankHandler(vm::ptr handler); extern int cellGcmAddressToOffset(u64 address, vm::ptr> offset); extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); extern int cellGcmSetPrepareFlip(vm::ptr ctx, u32 id); @@ -603,7 +603,7 @@ void cellRescExit() if (IsPalTemporal()) { cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE); - cellGcmSetVBlankHandler(vm::ptr::make(0)); + cellGcmSetVBlankHandler(vm::ptr::make(0)); //GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL); if (IsPalInterpolate()) @@ -667,7 +667,7 @@ int cellRescSetDsts(u32 dstsMode, vm::ptr dsts) return CELL_OK; } -void SetVBlankHandler(vm::ptr handler) +void SetVBlankHandler(vm::ptr handler) { if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) { @@ -693,7 +693,7 @@ void SetVBlankHandler(vm::ptr handler) } -void SetFlipHandler(vm::ptr handler) +void SetFlipHandler(vm::ptr handler) { if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) { @@ -780,20 +780,20 @@ int cellRescSetDisplayMode(u32 displayMode) cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); //cellGcmSetVBlankHandler(IntrHandler50); //cellGcmSetSecondVHandler(IntrHandler60); - cellGcmSetFlipHandler(vm::ptr::make(0)); + cellGcmSetFlipHandler(vm::ptr::make(0)); } else if (IsPalDrop()) { //InitLabels(); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler(vm::ptr::make(0)); + cellGcmSetVBlankHandler(vm::ptr::make(0)); //cellGcmSetSecondVHandler(IntrHandler60Drop); - cellGcmSetFlipHandler(vm::ptr::make(0)); + cellGcmSetFlipHandler(vm::ptr::make(0)); } else if (IsPal60Hsync()) { cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler(vm::ptr::make(0)); + cellGcmSetVBlankHandler(vm::ptr::make(0)); } if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler); @@ -1073,7 +1073,7 @@ int cellRescSetBufferAddress(vm::ptr colorBuffers, vm::ptr vertexArray return CELL_OK; } -void cellRescSetFlipHandler(vm::ptr handler) +void cellRescSetFlipHandler(vm::ptr handler) { cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler.addr()); @@ -1113,7 +1113,7 @@ int cellRescSetRegisterCount() return CELL_OK; } -void cellRescSetVBlankHandler(vm::ptr handler) +void cellRescSetVBlankHandler(vm::ptr handler) { cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler.addr()); diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.h b/rpcs3/Emu/SysCalls/Modules/cellResc.h index 74a7652397..a2d577a061 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.h +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.h @@ -137,8 +137,8 @@ struct CCellRescInternal bool m_isDummyFlipped; u8 m_cgParamIndex[RESC_PARAM_NUM]; u64 m_commandIdxCaF, m_rcvdCmdIdx; - vm::ptr s_applicationFlipHandler; - vm::ptr s_applicationVBlankHandler; + vm::ptr s_applicationFlipHandler; + vm::ptr s_applicationVBlankHandler; CCellRescInternal() : m_bInitialized(false) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSail.h b/rpcs3/Emu/SysCalls/Modules/cellSail.h index d0244fed6d..3f77c94d98 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSail.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSail.h @@ -618,64 +618,64 @@ union CellSailEvent }; }; -typedef u32(*CellSailMemAllocatorFuncAlloc)(u32 pArg, u32 boundary, u32 size); -typedef u32(*CellSailMemAllocatorFuncFree)(u32 pArg, u32 boundary, u32 pMemory); +typedef u32(CellSailMemAllocatorFuncAlloc)(u32 pArg, u32 boundary, u32 size); +typedef u32(CellSailMemAllocatorFuncFree)(u32 pArg, u32 boundary, u32 pMemory); -typedef int(*CellSailSoundAdapterFuncMakeup)(u32 pArg); -typedef int(*CellSailSoundAdapterFuncCleanup)(u32 pArg); -typedef void(*CellSailSoundAdapterFuncFormatChanged)(u32 pArg, vm::ptr pFormat, u32 sessionId); +typedef int(CellSailSoundAdapterFuncMakeup)(u32 pArg); +typedef int(CellSailSoundAdapterFuncCleanup)(u32 pArg); +typedef void(CellSailSoundAdapterFuncFormatChanged)(u32 pArg, vm::ptr pFormat, u32 sessionId); -typedef int(*CellSailGraphicsAdapterFuncMakeup)(u32 pArg); -typedef int(*CellSailGraphicsAdapterFuncCleanup)(u32 pArg); -typedef void(*CellSailGraphicsAdapterFuncFormatChanged)(u32 pArg, vm::ptr pFormat, u32 sessionId); -typedef int(*CellSailGraphicsAdapterFuncAllocFrame)(u32 pArg, u32 size, s32 num, u8 ppFrame); -typedef int(*CellSailGraphicsAdapterFuncFreeFrame)(u32 pArg, s32 num, u8 ppFrame); +typedef int(CellSailGraphicsAdapterFuncMakeup)(u32 pArg); +typedef int(CellSailGraphicsAdapterFuncCleanup)(u32 pArg); +typedef void(CellSailGraphicsAdapterFuncFormatChanged)(u32 pArg, vm::ptr pFormat, u32 sessionId); +typedef int(CellSailGraphicsAdapterFuncAllocFrame)(u32 pArg, u32 size, s32 num, u8 ppFrame); +typedef int(CellSailGraphicsAdapterFuncFreeFrame)(u32 pArg, s32 num, u8 ppFrame); -typedef int(*CellSailSourceFuncMakeup)(u32 pArg, s8 pProtocolNames); -typedef int(*CellSailSourceFuncCleanup)(u32 pArg); -typedef void(*CellSailSourceFuncOpen)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, vm::ptr pProfile); -typedef void(*CellSailSourceFuncClose)(u32 pArg); -typedef void(*CellSailSourceFuncStart)(u32 pArg, vm::ptr pCommand, u32 sessionId); -typedef void(*CellSailSourceFuncStop)(u32 pArg); -typedef void(*CellSailSourceFuncCancel)(u32 pArg); -typedef int(*CellSailSourceFuncCheckout)(u32 pArg, vm::ptr ppItem); -typedef int(*CellSailSourceFuncCheckin)(u32 pArg, vm::ptr pItem); -typedef int(*CellSailSourceFuncClear)(u32 pArg); -typedef int(*CellSailSourceFuncRead)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, u64 offset, u8 pBuf, u32 size, u64 pTotalSize); -typedef int(*CellSailSourceFuncReadSync)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, u64 offset, u8 pBuf, u32 size, u64 pTotalSize); -typedef int(*CellSailSourceFuncGetCapabilities)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, u64 pCapabilities); -typedef int(*CellSailSourceFuncInquireCapability)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, vm::ptr pCommand); -typedef void(*CellSailSourceCheckFuncError)(u32 pArg, s8 pMsg, s32 line); +typedef int(CellSailSourceFuncMakeup)(u32 pArg, s8 pProtocolNames); +typedef int(CellSailSourceFuncCleanup)(u32 pArg); +typedef void(CellSailSourceFuncOpen)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, vm::ptr pProfile); +typedef void(CellSailSourceFuncClose)(u32 pArg); +typedef void(CellSailSourceFuncStart)(u32 pArg, vm::ptr pCommand, u32 sessionId); +typedef void(CellSailSourceFuncStop)(u32 pArg); +typedef void(CellSailSourceFuncCancel)(u32 pArg); +typedef int(CellSailSourceFuncCheckout)(u32 pArg, vm::ptr ppItem); +typedef int(CellSailSourceFuncCheckin)(u32 pArg, vm::ptr pItem); +typedef int(CellSailSourceFuncClear)(u32 pArg); +typedef int(CellSailSourceFuncRead)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, u64 offset, u8 pBuf, u32 size, u64 pTotalSize); +typedef int(CellSailSourceFuncReadSync)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, u64 offset, u8 pBuf, u32 size, u64 pTotalSize); +typedef int(CellSailSourceFuncGetCapabilities)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, u64 pCapabilities); +typedef int(CellSailSourceFuncInquireCapability)(u32 pArg, s32 streamType, u32 pMediaInfo, s8 pUri, vm::ptr pCommand); +typedef void(CellSailSourceCheckFuncError)(u32 pArg, s8 pMsg, s32 line); -typedef int(*CellSailFsFuncOpen)(s8 pPath, s32 flag, s32 pFd, u32 pArg, u64 size); -typedef int(*CellSailFsFuncOpenSecond)(s8 pPath, s32 flag, s32 fd, u32 pArg, u64 size); -typedef int(*CellSailFsFuncClose)(s32 fd); -typedef int(*CellSailFsFuncFstat)(s32 fd, u32 pStat_addr); -typedef int(*CellSailFsFuncRead)(s32 fd, u32 pBuf, u64 numBytes, u64 pNumRead); -typedef int(*CellSailFsFuncLseek)(s32 fd, s64 offset, s32 whence, u64 pPosition); -typedef int(*CellSailFsFuncCancel)(s32 fd); +typedef int(CellSailFsFuncOpen)(s8 pPath, s32 flag, s32 pFd, u32 pArg, u64 size); +typedef int(CellSailFsFuncOpenSecond)(s8 pPath, s32 flag, s32 fd, u32 pArg, u64 size); +typedef int(CellSailFsFuncClose)(s32 fd); +typedef int(CellSailFsFuncFstat)(s32 fd, u32 pStat_addr); +typedef int(CellSailFsFuncRead)(s32 fd, u32 pBuf, u64 numBytes, u64 pNumRead); +typedef int(CellSailFsFuncLseek)(s32 fd, s64 offset, s32 whence, u64 pPosition); +typedef int(CellSailFsFuncCancel)(s32 fd); -typedef int(*CellSailRendererAudioFuncMakeup)(u32 pArg); -typedef int(*CellSailRendererAudioFuncCleanup)(u32 pArg); -typedef void(*CellSailRendererAudioFuncOpen)(u32 pArg, vm::ptr pInfo, u32 frameNum); -typedef void(*CellSailRendererAudioFuncClose)(u32 pArg); -typedef void(*CellSailRendererAudioFuncStart)(u32 pArg, bool buffering); -typedef void(*CellSailRendererAudioFuncStop)(u32 pArg, bool flush); -typedef void(*CellSailRendererAudioFuncCancel)(u32 pArg); -typedef int(*CellSailRendererAudioFuncCheckout)(u32 pArg, vm::ptr ppInfo); -typedef int(*CellSailRendererAudioFuncCheckin)(u32 pArg, vm::ptr pInfo); +typedef int(CellSailRendererAudioFuncMakeup)(u32 pArg); +typedef int(CellSailRendererAudioFuncCleanup)(u32 pArg); +typedef void(CellSailRendererAudioFuncOpen)(u32 pArg, vm::ptr pInfo, u32 frameNum); +typedef void(CellSailRendererAudioFuncClose)(u32 pArg); +typedef void(CellSailRendererAudioFuncStart)(u32 pArg, bool buffering); +typedef void(CellSailRendererAudioFuncStop)(u32 pArg, bool flush); +typedef void(CellSailRendererAudioFuncCancel)(u32 pArg); +typedef int(CellSailRendererAudioFuncCheckout)(u32 pArg, vm::ptr ppInfo); +typedef int(CellSailRendererAudioFuncCheckin)(u32 pArg, vm::ptr pInfo); -typedef int(*CellSailRendererVideoFuncMakeup)(u32 pArg); -typedef int(*CellSailRendererVideoFuncCleanup)(u32 pArg); -typedef void(*CellSailRendererVideoFuncOpen)(u32 pArg, vm::ptr pInfo, u32 frameNum, u32 minFrameNum); -typedef void(*CellSailRendererVideoFuncClose)(u32 pArg); -typedef void(*CellSailRendererVideoFuncStart)(u32 pArg, bool buffering); -typedef void(*CellSailRendererVideoFuncStop)(u32 pArg, bool flush, bool keepRendering); -typedef void(*CellSailRendererVideoFuncCancel)(u32 pArg); -typedef int(*CellSailRendererVideoFuncCheckout)(u32 pArg, vm::ptr ppInfo); -typedef int(*CellSailRendererVideoFuncCheckin)(u32 pArg, vm::ptr pInfo); +typedef int(CellSailRendererVideoFuncMakeup)(u32 pArg); +typedef int(CellSailRendererVideoFuncCleanup)(u32 pArg); +typedef void(CellSailRendererVideoFuncOpen)(u32 pArg, vm::ptr pInfo, u32 frameNum, u32 minFrameNum); +typedef void(CellSailRendererVideoFuncClose)(u32 pArg); +typedef void(CellSailRendererVideoFuncStart)(u32 pArg, bool buffering); +typedef void(CellSailRendererVideoFuncStop)(u32 pArg, bool flush, bool keepRendering); +typedef void(CellSailRendererVideoFuncCancel)(u32 pArg); +typedef int(CellSailRendererVideoFuncCheckout)(u32 pArg, vm::ptr ppInfo); +typedef int(CellSailRendererVideoFuncCheckin)(u32 pArg, vm::ptr pInfo); -typedef void(*CellSailPlayerFuncNotified)(u32 pArg, vm::ptr event, u64 arg0, u64 arg1); +typedef void(CellSailPlayerFuncNotified)(u32 pArg, vm::ptr event, u64 arg0, u64 arg1); struct CellSailMemAllocatorFuncs { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.h b/rpcs3/Emu/SysCalls/Modules/cellSaveData.h index 3daa006334..48a7f0c60f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.h @@ -256,11 +256,11 @@ struct CellSaveDataDoneGet // Callback Functions -typedef void(*CellSaveDataFixedCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); -typedef void(*CellSaveDataListCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); -typedef void(*CellSaveDataStatCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); -typedef void(*CellSaveDataFileCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); -typedef void(*CellSaveDataDoneCallback)(vm::ptr cbResult, vm::ptr get); +typedef void(CellSaveDataFixedCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); +typedef void(CellSaveDataListCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); +typedef void(CellSaveDataStatCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); +typedef void(CellSaveDataFileCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); +typedef void(CellSaveDataDoneCallback)(vm::ptr cbResult, vm::ptr get); // Auxiliary Structs diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 6291ffb3c4..64be4a99cb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -206,7 +206,7 @@ struct CellSpursWorkloadFlag atomic_t flag; }; -typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); +typedef void(CellSpursShutdownCompletionEventHook)(vm::ptr, u32 wid, vm::ptr arg); // Core CellSpurs structures struct CellSpurs diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 0c372e82e8..57ddf51598 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1262,7 +1262,7 @@ s32 syncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, } } -s32 _cellSyncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) +s32 _cellSyncLFQueueCompletePushPointer(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) { cellSync->Todo("_cellSyncLFQueueCompletePushPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x)", queue.addr(), pointer, fpSendSignal.addr()); @@ -1278,7 +1278,7 @@ s32 syncLFQueueCompletePushPointer2(vm::ptr queue, s32 pointer, return CELL_OK; } -s32 _cellSyncLFQueueCompletePushPointer2(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) +s32 _cellSyncLFQueueCompletePushPointer2(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal) { // arguments copied from _cellSyncLFQueueCompletePushPointer cellSync->Todo("_cellSyncLFQueueCompletePushPointer2(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x)", @@ -1638,7 +1638,7 @@ s32 syncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, c } } -s32 _cellSyncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) +s32 _cellSyncLFQueueCompletePopPointer(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) { // arguments copied from _cellSyncLFQueueCompletePushPointer + unknown argument (noQueueFull taken from LFQueue2CompletePopPointer) cellSync->Todo("_cellSyncLFQueueCompletePopPointer(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x, noQueueFull=%d)", @@ -1655,7 +1655,7 @@ s32 syncLFQueueCompletePopPointer2(vm::ptr queue, s32 pointer, return CELL_OK; } -s32 _cellSyncLFQueueCompletePopPointer2(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) +s32 _cellSyncLFQueueCompletePopPointer2(vm::ptr queue, s32 pointer, vm::ptr fpSendSignal, u32 noQueueFull) { // arguments copied from _cellSyncLFQueueCompletePopPointer cellSync->Todo("_cellSyncLFQueueCompletePopPointer2(queue_addr=0x%x, pointer=%d, fpSendSignal_addr=0x%x, noQueueFull=%d)", diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 33059ed1aa..99555c70cf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -19,7 +19,7 @@ #include "cellGame.h" #include "cellSysutil.h" -typedef void (*CellHddGameStatCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); +typedef void (CellHddGameStatCallback)(vm::ptr cbResult, vm::ptr get, vm::ptr set); Module *cellSysutil = nullptr; @@ -835,10 +835,10 @@ int cellWebBrowserEstimate2(const vm::ptr config, v } extern int cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, - vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container); + vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container); extern int cellGameDataCheckCreate(PPUThread& CPU, u32 version, vm::ptr dirName, u32 errDialog, - vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container); + vm::ptr cbResult, vm::ptr get, vm::ptr set)> funcStat, u32 container); extern void cellSysutil_SaveData_init(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h index 7b8c4fb8d6..7554b95bf1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h @@ -78,7 +78,7 @@ enum CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_PAUSED = 0x0164, }; -typedef void(*CellSysutilCallback)(u64 status, u64 param, vm::ptr userdata); +typedef void(CellSysutilCallback)(u64 status, u64 param, vm::ptr userdata); void sysutilSendSystemCommand(u64 status, u64 param); @@ -238,16 +238,16 @@ struct CellHddGameCBResult }; typedef s32 CellWebBrowserId; -typedef void* CellWebBrowserClientSession; -typedef void(*CellWebBrowserCallback)(s32 cb_type, vm::ptr, vm::ptr usrdata); -typedef void(*CellWebComponentCallback)(CellWebBrowserId, s32 cb_type, vm::ptr, vm::ptr usrdata); -typedef void(*CellWebBrowserSystemCallback)(s32 cb_type, vm::ptr usrdata); +typedef vm::ptr CellWebBrowserClientSession; +typedef void(CellWebBrowserCallback)(s32 cb_type, CellWebBrowserClientSession, vm::ptr usrdata); +typedef void(CellWebComponentCallback)(CellWebBrowserId, s32 cb_type, CellWebBrowserClientSession, vm::ptr usrdata); +typedef void(CellWebBrowserSystemCallback)(s32 cb_type, vm::ptr usrdata); -typedef void(*CellWebBrowserMIMETypeCallback)(vm::ptr mimetype, vm::ptr url, vm::ptr usrdata); -typedef void(*CellWebBrowserErrorCallback)(s32 err_type, vm::ptr usrdata); -typedef void(*CellWebBrowserStatusCallback)(s32 err_type, vm::ptr usrdata); -typedef void(*CellWebBrowserNotify)(vm::ptr message, vm::ptr usrdata); -typedef void(*CellWebBrowserUsrdata)(vm::ptr usrdata); +typedef void(CellWebBrowserMIMETypeCallback)(vm::ptr mimetype, vm::ptr url, vm::ptr usrdata); +typedef void(CellWebBrowserErrorCallback)(s32 err_type, vm::ptr usrdata); +typedef void(CellWebBrowserStatusCallback)(s32 err_type, vm::ptr usrdata); +typedef void(CellWebBrowserNotify)(vm::ptr message, vm::ptr usrdata); +typedef void(CellWebBrowserUsrdata)(vm::ptr usrdata); struct CellWebBrowserMimeSet { diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index e53955e70e..4770a10d13 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -163,7 +163,7 @@ struct CellVdecPicFormat u8 alpha; }; -typedef u32(*CellVdecCbMsg)(u32 handle, CellVdecMsgType msgType, s32 msgData, u32 cbArg); +typedef u32(CellVdecCbMsg)(u32 handle, CellVdecMsgType msgType, s32 msgData, u32 cbArg); // Callback Function Information struct CellVdecCb diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.h b/rpcs3/Emu/SysCalls/Modules/libmixer.h index 9a7978f9a5..b2f0a19dcd 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.h +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.h @@ -110,7 +110,7 @@ enum CELL_SSPLAYER_STATE_ON = 0x20, }; -typedef s32(*CellSurMixerNotifyCallbackFunction)(vm::ptr arg, u32 counter, u32 samples); +typedef s32(CellSurMixerNotifyCallbackFunction)(vm::ptr arg, u32 counter, u32 samples); struct CellSSPlayerConfig { diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h index 4fee4d990c..bcb857cc04 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h @@ -134,4 +134,4 @@ enum SCE_NP_TROPHY_STATUS_CHANGES_DETECTED = 9, }; -typedef s32 (*SceNpTrophyStatusCallback)(u32 context, u32 status, s32 completed, s32 total, u32 arg_addr); +typedef s32 (SceNpTrophyStatusCallback)(u32 context, u32 status, s32 completed, s32 total, u32 arg_addr); diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h index 8c020f3ecc..76234c5c4b 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.h @@ -14,7 +14,7 @@ struct HeapInfo } }; -typedef s32(*spu_printf_cb_t)(u32 arg); +typedef s32(spu_printf_cb_t)(u32 arg); // Aux extern vm::ptr spu_printf_agcb; diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 79df2eece7..218221deab 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -738,7 +738,7 @@ s32 cellFsStReadWait(u32 fd, u64 size) return CELL_OK; } -s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr func) +s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr func) { sys_fs->Todo("cellFsStReadWaitCallback(fd=0x%x, size=0x%llx, func=0x%x)", fd, size, func); @@ -886,7 +886,7 @@ std::atomic g_FsAioReadID(0); std::atomic g_FsAioReadCur(0); bool aio_init = false; -void fsAioRead(u32 fd, vm::ptr aio, int xid, vm::ptr xaio, int error, int xid, u64 size)> func) +void fsAioRead(u32 fd, vm::ptr aio, int xid, vm::ptr xaio, int error, int xid, u64 size)> func) { while (g_FsAioReadCur != xid) { @@ -941,7 +941,7 @@ void fsAioRead(u32 fd, vm::ptr aio, int xid, vm::ptr aio, vm::ptr id, vm::ptr xaio, s32 error, s32 xid, u64 size)> func) +s32 cellFsAioRead(vm::ptr aio, vm::ptr id, vm::ptr xaio, s32 error, s32 xid, u64 size)> func) { sys_fs->Warning("cellFsAioRead(aio=0x%x, id=0x%x, func=0x%x)", aio, id, func); @@ -966,7 +966,7 @@ s32 cellFsAioRead(vm::ptr aio, vm::ptr id, vm::ptr aio, vm::ptr id, vm::ptr xaio, s32 error, s32 xid, u64 size)> func) +s32 cellFsAioWrite(vm::ptr aio, vm::ptr id, vm::ptr xaio, s32 error, s32 xid, u64 size)> func) { sys_fs->Todo("cellFsAioWrite(aio=0x%x, id=0x%x, func=0x%x)", aio, id, func); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index 9a7e1768bc..b182ecd4b5 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -210,10 +210,12 @@ s32 sys_ppu_thread_create(vm::ptr thread_id, u32 entry, u64 arg, s32 prio, return CELL_OK; } -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) { sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, init_addr=0x%x)", once_ctrl.addr(), init.addr()); + LV2_LOCK(0); + if (once_ctrl->compare_and_swap_test(be_t::make(SYS_PPU_THREAD_ONCE_INIT), be_t::make(SYS_PPU_THREAD_DONE_INIT))) { init(CPU); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index 83fe511b8f..eb3e343b97 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -30,6 +30,6 @@ s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, u32 info_addr); s32 sys_ppu_thread_stop(u64 thread_id); s32 sys_ppu_thread_restart(u64 thread_id); s32 sys_ppu_thread_create(vm::ptr thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr threadname); -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init); +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init); s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr thread_id); s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr name); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index c943495597..b5d9850335 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -325,7 +325,7 @@ namespace loader for (auto &e : m.second.exports) { - module->RegisterLLEFunc(e.first, vm::ptr::make(e.second)); + module->RegisterLLEFunc(e.first, vm::ptr::make(e.second)); } } } diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index e70afa794c..9b3c761dde 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -285,6 +285,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 69e962dbfc..9b46ecec23 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1333,5 +1333,8 @@ Emu\CPU\ARMv7\Objects + + Emu\CPU\ARMv7\Modules + \ No newline at end of file From 084106ced6808f3e5be4e7ef9280159152da5e80 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Wed, 28 Jan 2015 15:17:13 +0200 Subject: [PATCH 30/94] Disable DMA writes and add copyright notices --- rpcs3/Emu/RSX/RSXDMA.cpp | 3 ++- rpcs3/Emu/RSX/RSXDMA.h | 1 + rpcs3/Emu/RSX/RSXThread.cpp | 15 +++++++-------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXDMA.cpp b/rpcs3/Emu/RSX/RSXDMA.cpp index 476448474f..ad6bc06a74 100644 --- a/rpcs3/Emu/RSX/RSXDMA.cpp +++ b/rpcs3/Emu/RSX/RSXDMA.cpp @@ -1,3 +1,4 @@ +// Copyright (C) 2015 AlexAltea (https://github.com/AlexAltea/nucleus) #include "stdafx.h" #include "RSXDMA.h" #include "Emu/Memory/Memory.h" @@ -18,7 +19,7 @@ DMAObject dma_address(u32 dma_object) case RSX_CONTEXT_DMA_SEMAPHORE_R: return DMAObject{ 0x40100000, 0x1000, DMAObject::READWRITE }; // TODO: Inconsistency: Gitbrew says R, test says RW default: - LOG_WARNING(RSX, "Unknown DMA object (0x%08X)", dma_object); + LOG_WARNING(RSX, "Unknown DMA object (0x%08x)", dma_object); return DMAObject{}; } } diff --git a/rpcs3/Emu/RSX/RSXDMA.h b/rpcs3/Emu/RSX/RSXDMA.h index b432375506..e5da8918eb 100644 --- a/rpcs3/Emu/RSX/RSXDMA.h +++ b/rpcs3/Emu/RSX/RSXDMA.h @@ -1,3 +1,4 @@ +// Copyright (C) 2015 AlexAltea (https://github.com/AlexAltea/nucleus) #pragma once enum { diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ed7b539005..d4041f8571 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1866,15 +1866,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const // Get timestamp, and convert it from microseconds to nanoseconds u64 timestamp = get_system_time() * 1000; - // TODO: Reports can be written to the main memory or the local memory (controlled by NV4097_SET_CONTEXT_DMA_REPORT) - // NOTE: Uncomment these, if DMA implementation is broken - //vm::write64(m_local_mem_addr + offset + 0x0, timestamp); - //vm::write32(m_local_mem_addr + offset + 0x8, value); - //vm::write32(m_local_mem_addr + offset + 0xc, 0); + // NOTE: DMA broken, implement proper lpar mapping (sys_rsx) + //dma_write64(dma_report, offset + 0x0, timestamp); + //dma_write32(dma_report, offset + 0x8, value); + //dma_write32(dma_report, offset + 0xc, 0); - dma_write64(dma_report, offset + 0x0, timestamp); - dma_write32(dma_report, offset + 0x8, value); - dma_write32(dma_report, offset + 0xc, 0); + vm::write64(m_local_mem_addr + offset + 0x0, timestamp); + vm::write32(m_local_mem_addr + offset + 0x8, value); + vm::write32(m_local_mem_addr + offset + 0xc, 0); } break; From e508d6db5dc7b50013844bd8dc44851ee08a478d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 28 Jan 2015 17:17:12 +0300 Subject: [PATCH 31/94] sceGxm stub --- rpcs3/Emu/ARMv7/Modules/sceGxm.cpp | 1290 ++++++++++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceGxm.h | 1244 +++++++++++++++++++++++++++ rpcs3/Emu/ARMv7/PSVFuncList.cpp | 6 + 3 files changed, 2540 insertions(+) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceGxm.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceGxm.h diff --git a/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp b/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp new file mode 100644 index 0000000000..3614803537 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp @@ -0,0 +1,1290 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +#include "sceGxm.h" + +s32 sceGxmInitialize(vm::psv::ptr params) +{ + throw __FUNCTION__; +} + +s32 sceGxmTerminate() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmGetNotificationRegion() +{ + throw __FUNCTION__; +} + +s32 sceGxmNotificationWait(vm::psv::ptr notification) +{ + throw __FUNCTION__; +} + +s32 sceGxmMapMemory(vm::psv::ptr base, u32 size, SceGxmMemoryAttribFlags attr) +{ + throw __FUNCTION__; +} + +s32 sceGxmUnmapMemory(vm::psv::ptr base) +{ + throw __FUNCTION__; +} + +s32 sceGxmMapVertexUsseMemory(vm::psv::ptr base, u32 size, vm::psv::ptr offset) +{ + throw __FUNCTION__; +} + +s32 sceGxmUnmapVertexUsseMemory(vm::psv::ptr base) +{ + throw __FUNCTION__; +} + +s32 sceGxmMapFragmentUsseMemory(vm::psv::ptr base, u32 size, vm::psv::ptr offset) +{ + throw __FUNCTION__; +} + +s32 sceGxmUnmapFragmentUsseMemory(vm::psv::ptr base) +{ + throw __FUNCTION__; +} + +s32 sceGxmDisplayQueueAddEntry(vm::psv::ptr oldBuffer, vm::psv::ptr newBuffer, vm::psv::ptr callbackData) +{ + throw __FUNCTION__; +} + +s32 sceGxmDisplayQueueFinish() +{ + throw __FUNCTION__; +} + +s32 sceGxmSyncObjectCreate(vm::psv::ptr> syncObject) +{ + throw __FUNCTION__; +} + +s32 sceGxmSyncObjectDestroy(vm::psv::ptr syncObject) +{ + throw __FUNCTION__; +} + + +s32 sceGxmCreateContext(vm::psv::ptr params, vm::psv::ptr> context) +{ + throw __FUNCTION__; +} + +s32 sceGxmDestroyContext(vm::psv::ptr context) +{ + throw __FUNCTION__; +} + +void sceGxmSetValidationEnable(vm::psv::ptr context, bool enable) +{ + throw __FUNCTION__; +} + + +void sceGxmSetVertexProgram(vm::psv::ptr context, vm::psv::ptr vertexProgram) +{ + throw __FUNCTION__; +} + +void sceGxmSetFragmentProgram(vm::psv::ptr context, vm::psv::ptr fragmentProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmReserveVertexDefaultUniformBuffer(vm::psv::ptr context, vm::psv::ptr> uniformBuffer) +{ + throw __FUNCTION__; +} + +s32 sceGxmReserveFragmentDefaultUniformBuffer(vm::psv::ptr context, vm::psv::ptr> uniformBuffer) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetVertexStream(vm::psv::ptr context, u32 streamIndex, vm::psv::ptr streamData) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetVertexTexture(vm::psv::ptr context, u32 textureIndex, vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetFragmentTexture(vm::psv::ptr context, u32 textureIndex, vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetVertexUniformBuffer(vm::psv::ptr context, u32 bufferIndex, vm::psv::ptr bufferData) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetFragmentUniformBuffer(vm::psv::ptr context, u32 bufferIndex, vm::psv::ptr bufferData) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetAuxiliarySurface(vm::psv::ptr context, u32 surfaceIndex, vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + + +void sceGxmSetPrecomputedFragmentState(vm::psv::ptr context, vm::psv::ptr precomputedState) +{ + throw __FUNCTION__; +} + +void sceGxmSetPrecomputedVertexState(vm::psv::ptr context, vm::psv::ptr precomputedState) +{ + throw __FUNCTION__; +} + +s32 sceGxmDrawPrecomputed(vm::psv::ptr context, vm::psv::ptr precomputedDraw) +{ + throw __FUNCTION__; +} + +s32 sceGxmDraw(vm::psv::ptr context, SceGxmPrimitiveType primType, SceGxmIndexFormat indexType, vm::psv::ptr indexData, u32 indexCount) +{ + throw __FUNCTION__; +} + +s32 sceGxmDrawInstanced(vm::psv::ptr context, SceGxmPrimitiveType primType, SceGxmIndexFormat indexType, vm::psv::ptr indexData, u32 indexCount, u32 indexWrap) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetVisibilityBuffer(vm::psv::ptr context, vm::psv::ptr bufferBase, u32 stridePerCore) +{ + throw __FUNCTION__; +} + +s32 sceGxmBeginScene(vm::psv::ptr context, u32 flags, vm::psv::ptr renderTarget, vm::psv::ptr validRegion, vm::psv::ptr vertexSyncObject, vm::psv::ptr fragmentSyncObject, vm::psv::ptr colorSurface, vm::psv::ptr depthStencil) +{ + throw __FUNCTION__; +} + +s32 sceGxmMidSceneFlush(vm::psv::ptr context, u32 flags, vm::psv::ptr vertexSyncObject, vm::psv::ptr vertexNotification) +{ + throw __FUNCTION__; +} + +s32 sceGxmEndScene(vm::psv::ptr context, vm::psv::ptr vertexNotification, vm::psv::ptr fragmentNotification) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontDepthFunc(vm::psv::ptr context, SceGxmDepthFunc depthFunc) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackDepthFunc(vm::psv::ptr context, SceGxmDepthFunc depthFunc) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontFragmentProgramEnable(vm::psv::ptr context, SceGxmFragmentProgramMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackFragmentProgramEnable(vm::psv::ptr context, SceGxmFragmentProgramMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontDepthWriteEnable(vm::psv::ptr context, SceGxmDepthWriteMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackDepthWriteEnable(vm::psv::ptr context, SceGxmDepthWriteMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontLineFillLastPixelEnable(vm::psv::ptr context, SceGxmLineFillLastPixelMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackLineFillLastPixelEnable(vm::psv::ptr context, SceGxmLineFillLastPixelMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontStencilRef(vm::psv::ptr context, u32 sref) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackStencilRef(vm::psv::ptr context, u32 sref) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontPointLineWidth(vm::psv::ptr context, u32 width) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackPointLineWidth(vm::psv::ptr context, u32 width) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontPolygonMode(vm::psv::ptr context, SceGxmPolygonMode mode) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackPolygonMode(vm::psv::ptr context, SceGxmPolygonMode mode) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontStencilFunc(vm::psv::ptr context, SceGxmStencilFunc func, SceGxmStencilOp stencilFail, SceGxmStencilOp depthFail, SceGxmStencilOp depthPass, uint8_t compareMask, uint8_t writeMask) +{ + throw __FUNCTION__; +} + + +void sceGxmSetBackStencilFunc(vm::psv::ptr context, SceGxmStencilFunc func, SceGxmStencilOp stencilFail, SceGxmStencilOp depthFail, SceGxmStencilOp depthPass, uint8_t compareMask, uint8_t writeMask) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontDepthBias(vm::psv::ptr context, int32_t factor, int32_t units) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackDepthBias(vm::psv::ptr context, int32_t factor, int32_t units) +{ + throw __FUNCTION__; +} + +void sceGxmSetTwoSidedEnable(vm::psv::ptr context, SceGxmTwoSidedMode enable) +{ + throw __FUNCTION__; +} + +//void sceGxmSetViewport(vm::psv::ptr context, float xOffset, float xScale, float yOffset, float yScale, float zOffset, float zScale) +//{ +// throw __FUNCTION__; +//} +// +//void sceGxmSetWClampValue(vm::psv::ptr context, float clampValue) +//{ +// throw __FUNCTION__; +//} + +void sceGxmSetWClampEnable(vm::psv::ptr context, SceGxmWClampMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetRegionClip(vm::psv::ptr context, SceGxmRegionClipMode mode, u32 xMin, u32 yMin, u32 xMax, u32 yMax) +{ + throw __FUNCTION__; +} + +void sceGxmSetCullMode(vm::psv::ptr context, SceGxmCullMode mode) +{ + throw __FUNCTION__; +} + +void sceGxmSetViewportEnable(vm::psv::ptr context, SceGxmViewportMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetWBufferEnable(vm::psv::ptr context, SceGxmWBufferMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontVisibilityTestIndex(vm::psv::ptr context, u32 index) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackVisibilityTestIndex(vm::psv::ptr context, u32 index) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontVisibilityTestOp(vm::psv::ptr context, SceGxmVisibilityTestOp op) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackVisibilityTestOp(vm::psv::ptr context, SceGxmVisibilityTestOp op) +{ + throw __FUNCTION__; +} + +void sceGxmSetFrontVisibilityTestEnable(vm::psv::ptr context, SceGxmVisibilityTestMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmSetBackVisibilityTestEnable(vm::psv::ptr context, SceGxmVisibilityTestMode enable) +{ + throw __FUNCTION__; +} + +void sceGxmFinish(vm::psv::ptr context) +{ + throw __FUNCTION__; +} + +s32 sceGxmPushUserMarker(vm::psv::ptr context, vm::psv::ptr tag) +{ + throw __FUNCTION__; +} + +s32 sceGxmPopUserMarker(vm::psv::ptr context) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetUserMarker(vm::psv::ptr context, vm::psv::ptr tag) +{ + throw __FUNCTION__; +} + +s32 sceGxmPadHeartbeat(vm::psv::ptr displaySurface, vm::psv::ptr displaySyncObject) +{ + throw __FUNCTION__; +} + +s32 sceGxmPadTriggerGpuPaTrace() +{ + throw __FUNCTION__; +} + +s32 sceGxmColorSurfaceInit(vm::psv::ptr surface, SceGxmColorFormat colorFormat, SceGxmColorSurfaceType surfaceType, SceGxmColorSurfaceScaleMode scaleMode, SceGxmOutputRegisterSize outputRegisterSize, u32 width, u32 height, u32 strideInPixels, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +s32 sceGxmColorSurfaceInitDisabled(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +bool sceGxmColorSurfaceIsEnabled(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +void sceGxmColorSurfaceGetClip(vm::psv::ptr surface, vm::psv::ptr xMin, vm::psv::ptr yMin, vm::psv::ptr xMax, vm::psv::ptr yMax) +{ + throw __FUNCTION__; +} + +void sceGxmColorSurfaceSetClip(vm::psv::ptr surface, u32 xMin, u32 yMin, u32 xMax, u32 yMax) +{ + throw __FUNCTION__; +} + +SceGxmColorSurfaceScaleMode sceGxmColorSurfaceGetScaleMode(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +void sceGxmColorSurfaceSetScaleMode(vm::psv::ptr surface, SceGxmColorSurfaceScaleMode scaleMode) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmColorSurfaceGetData(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +s32 sceGxmColorSurfaceSetData(vm::psv::ptr surface, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +SceGxmColorFormat sceGxmColorSurfaceGetFormat(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +s32 sceGxmColorSurfaceSetFormat(vm::psv::ptr surface, SceGxmColorFormat format) +{ + throw __FUNCTION__; +} + +SceGxmColorSurfaceType sceGxmColorSurfaceGetType(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +u32 sceGxmColorSurfaceGetStrideInPixels(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +s32 sceGxmDepthStencilSurfaceInit(vm::psv::ptr surface, SceGxmDepthStencilFormat depthStencilFormat, SceGxmDepthStencilSurfaceType surfaceType, u32 strideInSamples, vm::psv::ptr depthData, vm::psv::ptr stencilData) +{ + throw __FUNCTION__; +} + +s32 sceGxmDepthStencilSurfaceInitDisabled(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +//float sceGxmDepthStencilSurfaceGetBackgroundDepth(vm::psv::ptr surface) +//{ +// throw __FUNCTION__; +//} + +//void sceGxmDepthStencilSurfaceSetBackgroundDepth(vm::psv::ptr surface, float backgroundDepth) +//{ +// throw __FUNCTION__; +//} + +uint8_t sceGxmDepthStencilSurfaceGetBackgroundStencil(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +void sceGxmDepthStencilSurfaceSetBackgroundStencil(vm::psv::ptr surface, uint8_t backgroundStencil) +{ + throw __FUNCTION__; +} + +bool sceGxmDepthStencilSurfaceIsEnabled(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +void sceGxmDepthStencilSurfaceSetForceLoadMode(vm::psv::ptr surface, SceGxmDepthStencilForceLoadMode forceLoad) +{ + throw __FUNCTION__; +} + +SceGxmDepthStencilForceLoadMode sceGxmDepthStencilSurfaceGetForceLoadMode(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +void sceGxmDepthStencilSurfaceSetForceStoreMode(vm::psv::ptr surface, SceGxmDepthStencilForceStoreMode forceStore) +{ + throw __FUNCTION__; +} + +SceGxmDepthStencilForceStoreMode sceGxmDepthStencilSurfaceGetForceStoreMode(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +SceGxmColorSurfaceGammaMode sceGxmColorSurfaceGetGammaMode(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +s32 sceGxmColorSurfaceSetGammaMode(vm::psv::ptr surface, SceGxmColorSurfaceGammaMode gammaMode) +{ + throw __FUNCTION__; +} + +SceGxmColorSurfaceDitherMode sceGxmColorSurfaceGetDitherMode(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +s32 sceGxmColorSurfaceSetDitherMode(vm::psv::ptr surface, SceGxmColorSurfaceDitherMode ditherMode) +{ + throw __FUNCTION__; +} + +SceGxmDepthStencilFormat sceGxmDepthStencilSurfaceGetFormat(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + +u32 sceGxmDepthStencilSurfaceGetStrideInSamples(vm::psv::ptr surface) +{ + throw __FUNCTION__; +} + + +s32 sceGxmProgramCheck(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramGetSize(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +SceGxmProgramType sceGxmProgramGetType(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +bool sceGxmProgramIsDiscardUsed(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +bool sceGxmProgramIsDepthReplaceUsed(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +bool sceGxmProgramIsSpriteCoordUsed(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramGetDefaultUniformBufferSize(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramGetParameterCount(vm::psv::ptr program) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmProgramGetParameter(vm::psv::ptr program, u32 index) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmProgramFindParameterByName(vm::psv::ptr program, vm::psv::ptr name) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmProgramFindParameterBySemantic(vm::psv::ptr program, SceGxmParameterSemantic semantic, u32 index) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramParameterGetIndex(vm::psv::ptr program, vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +SceGxmParameterCategory sceGxmProgramParameterGetCategory(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmProgramParameterGetName(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +SceGxmParameterSemantic sceGxmProgramParameterGetSemantic(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramParameterGetSemanticIndex(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +SceGxmParameterType sceGxmProgramParameterGetType(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramParameterGetComponentCount(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramParameterGetArraySize(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramParameterGetResourceIndex(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +u32 sceGxmProgramParameterGetContainerIndex(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +bool sceGxmProgramParameterIsSamplerCube(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmFragmentProgramGetProgram(vm::psv::ptr fragmentProgram) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmVertexProgramGetProgram(vm::psv::ptr vertexProgram) +{ + throw __FUNCTION__; +} + + +s32 sceGxmShaderPatcherCreate(vm::psv::ptr params, vm::psv::ptr> shaderPatcher) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherSetUserData(vm::psv::ptr shaderPatcher, vm::psv::ptr userData) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmShaderPatcherGetUserData(vm::psv::ptr shaderPatcher) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherDestroy(vm::psv::ptr shaderPatcher) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherRegisterProgram(vm::psv::ptr shaderPatcher, vm::psv::ptr programHeader, vm::psv::ptr programId) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherUnregisterProgram(vm::psv::ptr shaderPatcher, SceGxmShaderPatcherId programId) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmShaderPatcherGetProgramFromId(SceGxmShaderPatcherId programId) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherSetAuxiliarySurface(vm::psv::ptr shaderPatcher, u32 auxSurfaceIndex, vm::psv::ptr auxSurface) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherCreateVertexProgram(vm::psv::ptr shaderPatcher, SceGxmShaderPatcherId programId, vm::psv::ptr attributes, u32 attributeCount, vm::psv::ptr streams, u32 streamCount, vm::psv::ptr> vertexProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherCreateFragmentProgram(vm::psv::ptr shaderPatcher, SceGxmShaderPatcherId programId, SceGxmOutputRegisterFormat outputFormat, SceGxmMultisampleMode multisampleMode, vm::psv::ptr blendInfo, vm::psv::ptr vertexProgram, vm::psv::ptr> fragmentProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherAddRefVertexProgram(vm::psv::ptr shaderPatcher, vm::psv::ptr vertexProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherAddRefFragmentProgram(vm::psv::ptr shaderPatcher, vm::psv::ptr fragmentProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherReleaseVertexProgram(vm::psv::ptr shaderPatcher, vm::psv::ptr vertexProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmShaderPatcherReleaseFragmentProgram(vm::psv::ptr shaderPatcher, vm::psv::ptr fragmentProgram) +{ + throw __FUNCTION__; +} + +u32 sceGxmShaderPatcherGetHostMemAllocated(vm::psv::ptr shaderPatcher) +{ + throw __FUNCTION__; +} + +u32 sceGxmShaderPatcherGetBufferMemAllocated(vm::psv::ptr shaderPatcher) +{ + throw __FUNCTION__; +} + +u32 sceGxmShaderPatcherGetVertexUsseMemAllocated(vm::psv::ptr shaderPatcher) +{ + throw __FUNCTION__; +} + +u32 sceGxmShaderPatcherGetFragmentUsseMemAllocated(vm::psv::ptr shaderPatcher) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureInitSwizzled(vm::psv::ptr texture, vm::psv::ptr data, SceGxmTextureFormat texFormat, u32 width, u32 height, u32 mipCount) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureInitLinear(vm::psv::ptr texture, vm::psv::ptr data, SceGxmTextureFormat texFormat, u32 width, u32 height, u32 mipCount) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureInitLinearStrided(vm::psv::ptr texture, vm::psv::ptr data, SceGxmTextureFormat texFormat, u32 width, u32 height, u32 byteStride) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureInitTiled(vm::psv::ptr texture, vm::psv::ptr data, SceGxmTextureFormat texFormat, u32 width, u32 height, u32 mipCount) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureInitCube(vm::psv::ptr texture, vm::psv::ptr data, SceGxmTextureFormat texFormat, u32 width, u32 height, u32 mipCount) +{ + throw __FUNCTION__; +} + +SceGxmTextureType sceGxmTextureGetType(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetMinFilter(vm::psv::ptr texture, SceGxmTextureFilter minFilter) +{ + throw __FUNCTION__; +} + +SceGxmTextureFilter sceGxmTextureGetMinFilter(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetMagFilter(vm::psv::ptr texture, SceGxmTextureFilter magFilter) +{ + throw __FUNCTION__; +} + +SceGxmTextureFilter sceGxmTextureGetMagFilter(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetMipFilter(vm::psv::ptr texture, SceGxmTextureMipFilter mipFilter) +{ + throw __FUNCTION__; +} + +SceGxmTextureMipFilter sceGxmTextureGetMipFilter(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetAnisoMode(vm::psv::ptr texture, SceGxmTextureAnisoMode anisoMode) +{ + throw __FUNCTION__; +} + +SceGxmTextureAnisoMode sceGxmTextureGetAnisoMode(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetUAddrMode(vm::psv::ptr texture, SceGxmTextureAddrMode addrMode) +{ + throw __FUNCTION__; +} + +SceGxmTextureAddrMode sceGxmTextureGetUAddrMode(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetVAddrMode(vm::psv::ptr texture, SceGxmTextureAddrMode addrMode) +{ + throw __FUNCTION__; +} + +SceGxmTextureAddrMode sceGxmTextureGetVAddrMode(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetFormat(vm::psv::ptr texture, SceGxmTextureFormat texFormat) +{ + throw __FUNCTION__; +} + +SceGxmTextureFormat sceGxmTextureGetFormat(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetLodBias(vm::psv::ptr texture, u32 bias) +{ + throw __FUNCTION__; +} + +u32 sceGxmTextureGetLodBias(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetStride(vm::psv::ptr texture, u32 byteStride) +{ + throw __FUNCTION__; +} + +u32 sceGxmTextureGetStride(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetWidth(vm::psv::ptr texture, u32 width) +{ + throw __FUNCTION__; +} + +u32 sceGxmTextureGetWidth(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetHeight(vm::psv::ptr texture, u32 height) +{ + throw __FUNCTION__; +} + +u32 sceGxmTextureGetHeight(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetData(vm::psv::ptr texture, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmTextureGetData(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetMipmapCount(vm::psv::ptr texture, u32 mipCount) +{ + throw __FUNCTION__; +} + +u32 sceGxmTextureGetMipmapCount(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetPalette(vm::psv::ptr texture, vm::psv::ptr paletteData) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmTextureGetPalette(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +SceGxmTextureGammaMode sceGxmTextureGetGammaMode(vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmTextureSetGammaMode(vm::psv::ptr texture, SceGxmTextureGammaMode gammaMode) +{ + throw __FUNCTION__; +} + +u32 sceGxmGetPrecomputedVertexStateSize(vm::psv::ptr vertexProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedVertexStateInit(vm::psv::ptr precomputedState, vm::psv::ptr vertexProgram, vm::psv::ptr memBlock) +{ + throw __FUNCTION__; +} + +void sceGxmPrecomputedVertexStateSetDefaultUniformBuffer(vm::psv::ptr precomputedState, vm::psv::ptr defaultBuffer) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmPrecomputedVertexStateGetDefaultUniformBuffer(vm::psv::ptr precomputedState) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedVertexStateSetAllTextures(vm::psv::ptr precomputedState, vm::psv::ptr textures) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedVertexStateSetTexture(vm::psv::ptr precomputedState, u32 textureIndex, vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedVertexStateSetAllUniformBuffers(vm::psv::ptr precomputedState, vm::psv::ptr> bufferDataArray) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedVertexStateSetUniformBuffer(vm::psv::ptr precomputedState, u32 bufferIndex, vm::psv::ptr bufferData) +{ + throw __FUNCTION__; +} + +u32 sceGxmGetPrecomputedFragmentStateSize(vm::psv::ptr fragmentProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedFragmentStateInit(vm::psv::ptr precomputedState, vm::psv::ptr fragmentProgram, vm::psv::ptr memBlock) +{ + throw __FUNCTION__; +} + +void sceGxmPrecomputedFragmentStateSetDefaultUniformBuffer(vm::psv::ptr precomputedState, vm::psv::ptr defaultBuffer) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGxmPrecomputedFragmentStateGetDefaultUniformBuffer(vm::psv::ptr precomputedState) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedFragmentStateSetAllTextures(vm::psv::ptr precomputedState, vm::psv::ptr textureArray) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedFragmentStateSetTexture(vm::psv::ptr precomputedState, u32 textureIndex, vm::psv::ptr texture) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedFragmentStateSetAllUniformBuffers(vm::psv::ptr precomputedState, vm::psv::ptr> bufferDataArray) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedFragmentStateSetUniformBuffer(vm::psv::ptr precomputedState, u32 bufferIndex, vm::psv::ptr bufferData) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedFragmentStateSetAllAuxiliarySurfaces(vm::psv::ptr precomputedState, vm::psv::ptr auxSurfaceArray) +{ + throw __FUNCTION__; +} + +u32 sceGxmGetPrecomputedDrawSize(vm::psv::ptr vertexProgram) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedDrawInit(vm::psv::ptr precomputedDraw, vm::psv::ptr vertexProgram, vm::psv::ptr memBlock) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedDrawSetAllVertexStreams(vm::psv::ptr precomputedDraw, vm::psv::ptr> streamDataArray) +{ + throw __FUNCTION__; +} + +s32 sceGxmPrecomputedDrawSetVertexStream(vm::psv::ptr precomputedDraw, u32 streamIndex, vm::psv::ptr streamData) +{ + throw __FUNCTION__; +} + +void sceGxmPrecomputedDrawSetParams(vm::psv::ptr precomputedDraw, SceGxmPrimitiveType primType, SceGxmIndexFormat indexType, vm::psv::ptr indexData, u32 indexCount) +{ + throw __FUNCTION__; +} + +void sceGxmPrecomputedDrawSetParamsInstanced(vm::psv::ptr precomputedDraw, SceGxmPrimitiveType primType, SceGxmIndexFormat indexType, vm::psv::ptr indexData, u32 indexCount, u32 indexWrap) +{ + throw __FUNCTION__; +} + + +s32 sceGxmGetRenderTargetMemSizes(vm::psv::ptr params, vm::psv::ptr hostMemSize, vm::psv::ptr driverMemSize) +{ + throw __FUNCTION__; +} + +s32 sceGxmCreateRenderTarget(vm::psv::ptr params, vm::psv::ptr> renderTarget) +{ + throw __FUNCTION__; +} + +s32 sceGxmRenderTargetGetHostMem(vm::psv::ptr renderTarget, vm::psv::ptr> hostMem) +{ + throw __FUNCTION__; +} + +s32 sceGxmRenderTargetGetDriverMemBlock(vm::psv::ptr renderTarget, vm::psv::ptr driverMemBlock) +{ + throw __FUNCTION__; +} + +s32 sceGxmDestroyRenderTarget(vm::psv::ptr renderTarget) +{ + throw __FUNCTION__; +} + +s32 sceGxmSetUniformDataF(vm::psv::ptr uniformBuffer, vm::psv::ptr parameter, u32 componentOffset, u32 componentCount, vm::psv::ptr sourceData) +{ + throw __FUNCTION__; +} + + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceGxm, #name, name) + +psv_log_base sceGxm("SceGxm", []() +{ + sceGxm.on_load = nullptr; + sceGxm.on_unload = nullptr; + sceGxm.on_stop = nullptr; + + REG_FUNC(0xB0F1E4EC, sceGxmInitialize); + REG_FUNC(0xB627DE66, sceGxmTerminate); + //REG_FUNC(0x48C134AB, sceGxmBug9255RaisePrimitiveSplitThresholdEs2); + //REG_FUNC(0xA3A41A42, sceGxmBug9255SetPrimitiveSplitThresholdEs2); + REG_FUNC(0xC61E34FC, sceGxmMapMemory); + REG_FUNC(0x828C68E8, sceGxmUnmapMemory); + REG_FUNC(0xFA437510, sceGxmMapVertexUsseMemory); + REG_FUNC(0x008402C6, sceGxmMapFragmentUsseMemory); + REG_FUNC(0x099134F5, sceGxmUnmapVertexUsseMemory); + REG_FUNC(0x80CCEDBB, sceGxmUnmapFragmentUsseMemory); + REG_FUNC(0xEC5C26B5, sceGxmDisplayQueueAddEntry); + REG_FUNC(0xB98C5B0D, sceGxmDisplayQueueFinish); + REG_FUNC(0x6A6013E1, sceGxmSyncObjectCreate); + REG_FUNC(0x889AE88C, sceGxmSyncObjectDestroy); + REG_FUNC(0x8BDE825A, sceGxmGetNotificationRegion); + REG_FUNC(0x9F448E79, sceGxmNotificationWait); + REG_FUNC(0x3D25FCE9, sceGxmPadHeartbeat); + REG_FUNC(0x47E06984, sceGxmPadTriggerGpuPaTrace); + REG_FUNC(0x2DB6026C, sceGxmColorSurfaceGetData); + REG_FUNC(0x200A96E1, sceGxmColorSurfaceGetDitherMode); + REG_FUNC(0xF3C1C6C6, sceGxmColorSurfaceGetFormat); + REG_FUNC(0x6E3FA74D, sceGxmColorSurfaceGetScaleMode); + REG_FUNC(0xF33D9980, sceGxmColorSurfaceGetStrideInPixels); + REG_FUNC(0x52FDE962, sceGxmColorSurfaceGetType); + REG_FUNC(0xED0F6E25, sceGxmColorSurfaceInit); + REG_FUNC(0x613639FA, sceGxmColorSurfaceInitDisabled); + REG_FUNC(0x0E0EBB57, sceGxmColorSurfaceIsEnabled); + REG_FUNC(0x07DFEE4B, sceGxmColorSurfaceGetClip); + REG_FUNC(0x86456F7B, sceGxmColorSurfaceSetClip); + REG_FUNC(0x537CA400, sceGxmColorSurfaceSetData); + REG_FUNC(0x45027BAB, sceGxmColorSurfaceSetDitherMode); + REG_FUNC(0x5F9A3A16, sceGxmColorSurfaceSetFormat); + REG_FUNC(0x6B96EDF7, sceGxmColorSurfaceSetScaleMode); + //REG_FUNC(0x269B56BE, sceGxmDepthStencilSurfaceGetBackgroundDepth); + REG_FUNC(0xAAFC062B, sceGxmDepthStencilSurfaceGetBackgroundStencil); + REG_FUNC(0x2F5CC20C, sceGxmDepthStencilSurfaceGetForceLoadMode); + REG_FUNC(0x544AA05A, sceGxmDepthStencilSurfaceGetForceStoreMode); + REG_FUNC(0x8504038D, sceGxmDepthStencilSurfaceGetFormat); + REG_FUNC(0x11628789, sceGxmDepthStencilSurfaceGetStrideInSamples); + REG_FUNC(0xCA9D41D1, sceGxmDepthStencilSurfaceInit); + REG_FUNC(0xA41DB0D6, sceGxmDepthStencilSurfaceInitDisabled); + REG_FUNC(0x082200E1, sceGxmDepthStencilSurfaceIsEnabled); + //REG_FUNC(0x32F280F0, sceGxmDepthStencilSurfaceSetBackgroundDepth); + REG_FUNC(0xF5D3F3E8, sceGxmDepthStencilSurfaceSetBackgroundStencil); + REG_FUNC(0x0C44ACD7, sceGxmDepthStencilSurfaceSetForceLoadMode); + REG_FUNC(0x12AAA7AF, sceGxmDepthStencilSurfaceSetForceStoreMode); + REG_FUNC(0xF5C89643, sceGxmColorSurfaceSetGammaMode); + REG_FUNC(0xEE0B4DF0, sceGxmColorSurfaceGetGammaMode); + REG_FUNC(0xE0E3B3F8, sceGxmFragmentProgramGetProgram); + REG_FUNC(0xBC52320E, sceGxmVertexProgramGetProgram); + REG_FUNC(0xDE9D5911, sceGxmTextureGetAnisoMode); + REG_FUNC(0x5341BD46, sceGxmTextureGetData); + REG_FUNC(0xE868D2B3, sceGxmTextureGetFormat); + REG_FUNC(0x5420A086, sceGxmTextureGetHeight); + REG_FUNC(0x2DE55DA5, sceGxmTextureGetLodBias); + REG_FUNC(0xAE7FBB51, sceGxmTextureGetMagFilter); + REG_FUNC(0x920666C6, sceGxmTextureGetMinFilter); + REG_FUNC(0xCE94CA15, sceGxmTextureGetMipFilter); + REG_FUNC(0x4CC42929, sceGxmTextureGetMipmapCount); + REG_FUNC(0xB0BD52F3, sceGxmTextureGetStride); + REG_FUNC(0xF65D4917, sceGxmTextureGetType); + REG_FUNC(0xC037DA83, sceGxmTextureGetUAddrMode); + REG_FUNC(0xD2F0D9C1, sceGxmTextureGetVAddrMode); + REG_FUNC(0x126A3EB3, sceGxmTextureGetWidth); + REG_FUNC(0x11DC8DC9, sceGxmTextureInitCube); + REG_FUNC(0x4811AECB, sceGxmTextureInitLinear); + REG_FUNC(0x6679BEF0, sceGxmTextureInitLinearStrided); + REG_FUNC(0xD572D547, sceGxmTextureInitSwizzled); + REG_FUNC(0xE6F0DB27, sceGxmTextureInitTiled); + REG_FUNC(0xE719CBD4, sceGxmTextureSetAnisoMode); + REG_FUNC(0x855814C4, sceGxmTextureSetData); + REG_FUNC(0xFC943596, sceGxmTextureSetFormat); + REG_FUNC(0x1B20D5DF, sceGxmTextureSetHeight); + REG_FUNC(0xB65EE6F7, sceGxmTextureSetLodBias); + REG_FUNC(0xFA695FD7, sceGxmTextureSetMagFilter); + REG_FUNC(0x416764E3, sceGxmTextureSetMinFilter); + REG_FUNC(0x1CA9FE0B, sceGxmTextureSetMipFilter); + REG_FUNC(0xD2DC4643, sceGxmTextureSetMipmapCount); + REG_FUNC(0x58D0EB0A, sceGxmTextureSetStride); + REG_FUNC(0x8699ECF4, sceGxmTextureSetUAddrMode); + REG_FUNC(0xFA22F6CC, sceGxmTextureSetVAddrMode); + REG_FUNC(0x5A690B60, sceGxmTextureSetWidth); + REG_FUNC(0xDD6AABFA, sceGxmTextureSetPalette); + REG_FUNC(0x0D189C30, sceGxmTextureGetPalette); + REG_FUNC(0xA6D9F4DA, sceGxmTextureSetGammaMode); + REG_FUNC(0xF23FCE81, sceGxmTextureGetGammaMode); + REG_FUNC(0x85DE8506, sceGxmGetPrecomputedFragmentStateSize); + REG_FUNC(0x9D83CA3B, sceGxmGetPrecomputedVertexStateSize); + REG_FUNC(0x41BBD792, sceGxmGetPrecomputedDrawSize); + REG_FUNC(0xA197F096, sceGxmPrecomputedDrawInit); + REG_FUNC(0xB6C6F571, sceGxmPrecomputedDrawSetAllVertexStreams); + REG_FUNC(0x884D0D08, sceGxmPrecomputedDrawSetParams); + REG_FUNC(0x3A7B1633, sceGxmPrecomputedDrawSetParamsInstanced); + REG_FUNC(0x6C936214, sceGxmPrecomputedDrawSetVertexStream); + REG_FUNC(0xCECB584A, sceGxmPrecomputedFragmentStateGetDefaultUniformBuffer); + REG_FUNC(0x91236858, sceGxmPrecomputedFragmentStateSetDefaultUniformBuffer); + REG_FUNC(0xE297D7AF, sceGxmPrecomputedFragmentStateInit); + REG_FUNC(0x29118BF1, sceGxmPrecomputedFragmentStateSetTexture); + REG_FUNC(0xB452F1FB, sceGxmPrecomputedFragmentStateSetUniformBuffer); + REG_FUNC(0xC383DE39, sceGxmPrecomputedFragmentStateSetAllTextures); + REG_FUNC(0x5A783DC3, sceGxmPrecomputedFragmentStateSetAllUniformBuffers); + REG_FUNC(0x9D93B63A, sceGxmPrecomputedFragmentStateSetAllAuxiliarySurfaces); + REG_FUNC(0xBE5A68EF, sceGxmPrecomputedVertexStateGetDefaultUniformBuffer); + REG_FUNC(0x34BF64E3, sceGxmPrecomputedVertexStateSetDefaultUniformBuffer); + REG_FUNC(0xBE937F8D, sceGxmPrecomputedVertexStateInit); + REG_FUNC(0x1625D348, sceGxmPrecomputedVertexStateSetTexture); + REG_FUNC(0xDBF97ED6, sceGxmPrecomputedVertexStateSetUniformBuffer); + REG_FUNC(0x8FF68274, sceGxmPrecomputedVertexStateSetAllTextures); + REG_FUNC(0x0389861D, sceGxmPrecomputedVertexStateSetAllUniformBuffers); + REG_FUNC(0x1F856E5D, sceGxmGetRenderTargetMemSizes); + REG_FUNC(0xD56CD7B1, sceGxmCreateRenderTarget); + REG_FUNC(0x0B94C50A, sceGxmDestroyRenderTarget); + REG_FUNC(0xD0EDAB4C, sceGxmRenderTargetGetHostMem); + REG_FUNC(0x49553737, sceGxmRenderTargetGetDriverMemBlock); + REG_FUNC(0xDBA33160, sceGxmBeginScene); + REG_FUNC(0xE84CE5B4, sceGxmCreateContext); + REG_FUNC(0xEDDC5FB2, sceGxmDestroyContext); + REG_FUNC(0xBC059AFC, sceGxmDraw); + REG_FUNC(0x14C4E7D3, sceGxmDrawInstanced); + REG_FUNC(0xED3F78B8, sceGxmDrawPrecomputed); + REG_FUNC(0xFE300E2F, sceGxmEndScene); + REG_FUNC(0x0733D8AE, sceGxmFinish); + REG_FUNC(0x51FE0899, sceGxmMidSceneFlush); + REG_FUNC(0x4FA073A6, sceGxmPopUserMarker); + REG_FUNC(0x3276C475, sceGxmPushUserMarker); + REG_FUNC(0x7B1FABB6, sceGxmReserveFragmentDefaultUniformBuffer); + REG_FUNC(0x97118913, sceGxmReserveVertexDefaultUniformBuffer); + REG_FUNC(0x91B4F7F4, sceGxmSetAuxiliarySurface); + REG_FUNC(0x17B3BF86, sceGxmSetBackDepthBias); + REG_FUNC(0xB042A4D2, sceGxmSetBackDepthFunc); + REG_FUNC(0xC18B706B, sceGxmSetBackDepthWriteEnable); + REG_FUNC(0xE26B4834, sceGxmSetBackFragmentProgramEnable); + REG_FUNC(0xC88EB702, sceGxmSetBackLineFillLastPixelEnable); + REG_FUNC(0x8DCB0EDB, sceGxmSetBackPointLineWidth); + REG_FUNC(0xF66EC6FE, sceGxmSetBackPolygonMode); + REG_FUNC(0x1A68C8D2, sceGxmSetBackStencilFunc); + REG_FUNC(0x866A0517, sceGxmSetBackStencilRef); + REG_FUNC(0xE1CA72AE, sceGxmSetCullMode); + REG_FUNC(0xAD2F48D9, sceGxmSetFragmentProgram); + REG_FUNC(0x29C34DF5, sceGxmSetFragmentTexture); + REG_FUNC(0xEA0FC310, sceGxmSetFragmentUniformBuffer); + REG_FUNC(0xAAA97F81, sceGxmSetFrontDepthBias); + REG_FUNC(0x14BD831F, sceGxmSetFrontDepthFunc); + REG_FUNC(0xF32CBF34, sceGxmSetFrontDepthWriteEnable); + REG_FUNC(0x575958A8, sceGxmSetFrontFragmentProgramEnable); + REG_FUNC(0x5765DE9F, sceGxmSetFrontLineFillLastPixelEnable); + REG_FUNC(0x06752183, sceGxmSetFrontPointLineWidth); + REG_FUNC(0xFD93209D, sceGxmSetFrontPolygonMode); + REG_FUNC(0xB8645A9A, sceGxmSetFrontStencilFunc); + REG_FUNC(0x8FA6FE44, sceGxmSetFrontStencilRef); + REG_FUNC(0xF8952750, sceGxmSetPrecomputedFragmentState); + REG_FUNC(0xB7626A93, sceGxmSetPrecomputedVertexState); + REG_FUNC(0x70C86868, sceGxmSetRegionClip); + REG_FUNC(0x0DE9AEB7, sceGxmSetTwoSidedEnable); + REG_FUNC(0xC7A8CB77, sceGxmSetUserMarker); + REG_FUNC(0x8C6A24C9, sceGxmSetValidationEnable); + REG_FUNC(0x31FF8ABD, sceGxmSetVertexProgram); + REG_FUNC(0x895DF2E9, sceGxmSetVertexStream); + REG_FUNC(0x16C9D339, sceGxmSetVertexTexture); + REG_FUNC(0xC68015E4, sceGxmSetVertexUniformBuffer); + //REG_FUNC(0x3EB3380B, sceGxmSetViewport); + REG_FUNC(0x814F61EB, sceGxmSetViewportEnable); + REG_FUNC(0x7767EC49, sceGxmSetVisibilityBuffer); + REG_FUNC(0xEED86975, sceGxmSetWBufferEnable); + REG_FUNC(0x1BF8B853, sceGxmSetWClampEnable); + //REG_FUNC(0xD096336E, sceGxmSetWClampValue); + REG_FUNC(0x12625C34, sceGxmSetFrontVisibilityTestIndex); + REG_FUNC(0xAE7886FE, sceGxmSetBackVisibilityTestIndex); + REG_FUNC(0xD0E3CD9A, sceGxmSetFrontVisibilityTestOp); + REG_FUNC(0xC83F0AB3, sceGxmSetBackVisibilityTestOp); + REG_FUNC(0x30459117, sceGxmSetFrontVisibilityTestEnable); + REG_FUNC(0x17CF46B9, sceGxmSetBackVisibilityTestEnable); + REG_FUNC(0xED8B6C69, sceGxmProgramCheck); + REG_FUNC(0x277794C4, sceGxmProgramFindParameterByName); + REG_FUNC(0x7FFFDD7A, sceGxmProgramFindParameterBySemantic); + REG_FUNC(0x06FF9151, sceGxmProgramGetParameter); + REG_FUNC(0xD5D5FCCD, sceGxmProgramGetParameterCount); + REG_FUNC(0xBF5E2090, sceGxmProgramGetSize); + REG_FUNC(0x04BB3C59, sceGxmProgramGetType); + REG_FUNC(0x89613EF2, sceGxmProgramIsDepthReplaceUsed); + REG_FUNC(0x029B4F1C, sceGxmProgramIsDiscardUsed); + REG_FUNC(0x8FA3F9C3, sceGxmProgramGetDefaultUniformBufferSize); + REG_FUNC(0xDBA8D061, sceGxmProgramParameterGetArraySize); + REG_FUNC(0x1997DC17, sceGxmProgramParameterGetCategory); + REG_FUNC(0xBD2998D1, sceGxmProgramParameterGetComponentCount); + REG_FUNC(0xBB58267D, sceGxmProgramParameterGetContainerIndex); + REG_FUNC(0x6E61DDF5, sceGxmProgramParameterGetIndex); + REG_FUNC(0x6AF88A5D, sceGxmProgramParameterGetName); + REG_FUNC(0x5C79D59A, sceGxmProgramParameterGetResourceIndex); + REG_FUNC(0xAAFD61D5, sceGxmProgramParameterGetSemantic); + REG_FUNC(0xB85CC13E, sceGxmProgramParameterGetSemanticIndex); + REG_FUNC(0x7B9023C3, sceGxmProgramParameterGetType); + REG_FUNC(0xF7AA978B, sceGxmProgramParameterIsSamplerCube); + REG_FUNC(0x4CD2D19F, sceGxmShaderPatcherAddRefFragmentProgram); + REG_FUNC(0x0FD1E589, sceGxmShaderPatcherAddRefVertexProgram); + REG_FUNC(0x05032658, sceGxmShaderPatcherCreate); + REG_FUNC(0x4ED2E49D, sceGxmShaderPatcherCreateFragmentProgram); + REG_FUNC(0xB7BBA6D5, sceGxmShaderPatcherCreateVertexProgram); + REG_FUNC(0xEAA5B100, sceGxmShaderPatcherDestroy); + REG_FUNC(0xA949A803, sceGxmShaderPatcherGetProgramFromId); + REG_FUNC(0x2B528462, sceGxmShaderPatcherRegisterProgram); + REG_FUNC(0xBE2743D1, sceGxmShaderPatcherReleaseFragmentProgram); + REG_FUNC(0xAC1FF2DA, sceGxmShaderPatcherReleaseVertexProgram); + REG_FUNC(0x8E5FCC2A, sceGxmShaderPatcherSetAuxiliarySurface); + REG_FUNC(0xF103AF8A, sceGxmShaderPatcherUnregisterProgram); + REG_FUNC(0x9DBBC71C, sceGxmShaderPatcherGetHostMemAllocated); + REG_FUNC(0xC694D039, sceGxmShaderPatcherGetBufferMemAllocated); + REG_FUNC(0x7D2F83C1, sceGxmShaderPatcherGetVertexUsseMemAllocated); + REG_FUNC(0x3C9DDB4A, sceGxmShaderPatcherGetFragmentUsseMemAllocated); + REG_FUNC(0x96A7E6DD, sceGxmShaderPatcherGetUserData); + REG_FUNC(0xF9B8FCFD, sceGxmShaderPatcherSetUserData); + REG_FUNC(0x65DD0C84, sceGxmSetUniformDataF); +}); \ No newline at end of file diff --git a/rpcs3/Emu/ARMv7/Modules/sceGxm.h b/rpcs3/Emu/ARMv7/Modules/sceGxm.h new file mode 100644 index 0000000000..28cdac4daf --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceGxm.h @@ -0,0 +1,1244 @@ +#pragma once + +// Error Codes + +enum +{ + SCE_GXM_ERROR_UNINITIALIZED = 0x805B0000, + SCE_GXM_ERROR_ALREADY_INITIALIZED = 0x805B0001, + SCE_GXM_ERROR_OUT_OF_MEMORY = 0x805B0002, + SCE_GXM_ERROR_INVALID_VALUE = 0x805B0003, + SCE_GXM_ERROR_INVALID_POINTER = 0x805B0004, + SCE_GXM_ERROR_INVALID_ALIGNMENT = 0x805B0005, + SCE_GXM_ERROR_NOT_WITHIN_SCENE = 0x805B0006, + SCE_GXM_ERROR_WITHIN_SCENE = 0x805B0007, + SCE_GXM_ERROR_NULL_PROGRAM = 0x805B0008, + SCE_GXM_ERROR_UNSUPPORTED = 0x805B0009, + SCE_GXM_ERROR_PATCHER_INTERNAL = 0x805B000A, + SCE_GXM_ERROR_RESERVE_FAILED = 0x805B000B, + SCE_GXM_ERROR_PROGRAM_IN_USE = 0x805B000C, + SCE_GXM_ERROR_INVALID_INDEX_COUNT = 0x805B000D, + SCE_GXM_ERROR_INVALID_POLYGON_MODE = 0x805B000E, + SCE_GXM_ERROR_INVALID_SAMPLER_RESULT_TYPE_PRECISION = 0x805B000F, + SCE_GXM_ERROR_INVALID_SAMPLER_RESULT_TYPE_COMPONENT_COUNT = 0x805B0010, + SCE_GXM_ERROR_UNIFORM_BUFFER_NOT_RESERVED = 0x805B0011, + SCE_GXM_ERROR_INVALID_AUXILIARY_SURFACE = 0x805B0013, + SCE_GXM_ERROR_INVALID_PRECOMPUTED_DRAW = 0x805B0014, + SCE_GXM_ERROR_INVALID_PRECOMPUTED_VERTEX_STATE = 0x805B0015, + SCE_GXM_ERROR_INVALID_PRECOMPUTED_FRAGMENT_STATE = 0x805B0016, + SCE_GXM_ERROR_DRIVER = 0x805B0017, +}; + +typedef void(SceGxmDisplayQueueCallback)(vm::psv::ptr callbackData); + +struct SceGxmInitializeParams +{ + u32 flags; + u32 displayQueueMaxPendingCount; + vm::psv::ptr displayQueueCallback; + u32 displayQueueCallbackDataSize; + s32 parameterBufferSize; +}; + +enum SceGxmMemoryAttribFlags : u32 +{ + SCE_GXM_MEMORY_ATTRIB_READ = 1, + SCE_GXM_MEMORY_ATTRIB_WRITE = 2, +}; + +enum SceGxmAttributeFormat : u8 +{ + SCE_GXM_ATTRIBUTE_FORMAT_U8, + SCE_GXM_ATTRIBUTE_FORMAT_S8, + SCE_GXM_ATTRIBUTE_FORMAT_U16, + SCE_GXM_ATTRIBUTE_FORMAT_S16, + SCE_GXM_ATTRIBUTE_FORMAT_U8N, + SCE_GXM_ATTRIBUTE_FORMAT_S8N, + SCE_GXM_ATTRIBUTE_FORMAT_U16N, + SCE_GXM_ATTRIBUTE_FORMAT_S16N, + SCE_GXM_ATTRIBUTE_FORMAT_F16, + SCE_GXM_ATTRIBUTE_FORMAT_F32 +}; + +enum SceGxmDepthStencilFormat : u32 +{ + SCE_GXM_DEPTH_STENCIL_FORMAT_DF32 = 0x00044000u, + SCE_GXM_DEPTH_STENCIL_FORMAT_S8 = 0x00022000u, + SCE_GXM_DEPTH_STENCIL_FORMAT_DF32_S8 = 0x00066000u, + SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24 = 0x01266000u, + SCE_GXM_DEPTH_STENCIL_FORMAT_D16 = 0x02444000u +}; + +enum SceGxmPrimitiveType : u32 +{ + SCE_GXM_PRIMITIVE_TRIANGLES = 0x00000000u, + SCE_GXM_PRIMITIVE_LINES = 0x04000000u, + SCE_GXM_PRIMITIVE_POINTS = 0x08000000u, + SCE_GXM_PRIMITIVE_TRIANGLE_STRIP = 0x0c000000u, + SCE_GXM_PRIMITIVE_TRIANGLE_FAN = 0x10000000u, + SCE_GXM_PRIMITIVE_TRIANGLE_EDGES = 0x14000000u +}; + +enum SceGxmEdgeEnableFlags : u32 +{ + SCE_GXM_EDGE_ENABLE_01 = 0x00000100u, + SCE_GXM_EDGE_ENABLE_12 = 0x00000200u, + SCE_GXM_EDGE_ENABLE_20 = 0x00000400u +}; + +enum SceGxmRegionClipMode : u32 +{ + SCE_GXM_REGION_CLIP_NONE = 0x00000000u, + SCE_GXM_REGION_CLIP_ALL = 0x40000000u, + SCE_GXM_REGION_CLIP_OUTSIDE = 0x80000000u, + SCE_GXM_REGION_CLIP_INSIDE = 0xc0000000u +}; + +enum SceGxmDepthFunc : u32 +{ + SCE_GXM_DEPTH_FUNC_NEVER = 0x00000000u, + SCE_GXM_DEPTH_FUNC_LESS = 0x00400000u, + SCE_GXM_DEPTH_FUNC_EQUAL = 0x00800000u, + SCE_GXM_DEPTH_FUNC_LESS_EQUAL = 0x00c00000u, + SCE_GXM_DEPTH_FUNC_GREATER = 0x01000000u, + SCE_GXM_DEPTH_FUNC_NOT_EQUAL = 0x01400000u, + SCE_GXM_DEPTH_FUNC_GREATER_EQUAL = 0x01800000u, + SCE_GXM_DEPTH_FUNC_ALWAYS = 0x01c00000u +}; + +enum SceGxmStencilFunc : u32 +{ + SCE_GXM_STENCIL_FUNC_NEVER = 0x00000000u, + SCE_GXM_STENCIL_FUNC_LESS = 0x02000000u, + SCE_GXM_STENCIL_FUNC_EQUAL = 0x04000000u, + SCE_GXM_STENCIL_FUNC_LESS_EQUAL = 0x06000000u, + SCE_GXM_STENCIL_FUNC_GREATER = 0x08000000u, + SCE_GXM_STENCIL_FUNC_NOT_EQUAL = 0x0a000000u, + SCE_GXM_STENCIL_FUNC_GREATER_EQUAL = 0x0c000000u, + SCE_GXM_STENCIL_FUNC_ALWAYS = 0x0e000000u +}; + +enum SceGxmStencilOp : u32 +{ + SCE_GXM_STENCIL_OP_KEEP = 0x00000000u, + SCE_GXM_STENCIL_OP_ZERO = 0x00000001u, + SCE_GXM_STENCIL_OP_REPLACE = 0x00000002u, + SCE_GXM_STENCIL_OP_INCR = 0x00000003u, + SCE_GXM_STENCIL_OP_DECR = 0x00000004u, + SCE_GXM_STENCIL_OP_INVERT = 0x00000005u, + SCE_GXM_STENCIL_OP_INCR_WRAP = 0x00000006u, + SCE_GXM_STENCIL_OP_DECR_WRAP = 0x00000007u +}; + +enum SceGxmCullMode : u32 +{ + SCE_GXM_CULL_NONE = 0x00000000u, + SCE_GXM_CULL_CW = 0x00000001u, + SCE_GXM_CULL_CCW = 0x00000002u +}; + +enum SceGxmPolygonMode : u32 +{ + SCE_GXM_POLYGON_MODE_TRIANGLE_FILL = 0x00000000u, + SCE_GXM_POLYGON_MODE_LINE = 0x00008000u, + SCE_GXM_POLYGON_MODE_POINT_10UV = 0x00010000u, + SCE_GXM_POLYGON_MODE_POINT = 0x00018000u, + SCE_GXM_POLYGON_MODE_POINT_01UV = 0x00020000u, + SCE_GXM_POLYGON_MODE_TRIANGLE_LINE = 0x00028000u, + SCE_GXM_POLYGON_MODE_TRIANGLE_POINT = 0x00030000u +}; + +enum SceGxmColorSwizzle4Mode : u32 +{ + SCE_GXM_COLOR_SWIZZLE4_ABGR = 0x00000000u, + SCE_GXM_COLOR_SWIZZLE4_ARGB = 0x00100000u, + SCE_GXM_COLOR_SWIZZLE4_RGBA = 0x00200000u, + SCE_GXM_COLOR_SWIZZLE4_BGRA = 0x00300000u +}; + +enum SceGxmColorSwizzle3Mode : u32 +{ + SCE_GXM_COLOR_SWIZZLE3_BGR = 0x00000000u, + SCE_GXM_COLOR_SWIZZLE3_RGB = 0x00100000u +}; + +enum SceGxmColorSwizzle2Mode : u32 +{ + SCE_GXM_COLOR_SWIZZLE2_GR = 0x00000000u, + SCE_GXM_COLOR_SWIZZLE2_RG = 0x00100000u, + SCE_GXM_COLOR_SWIZZLE2_RA = 0x00200000u, + SCE_GXM_COLOR_SWIZZLE2_AR = 0x00300000u +}; + +enum SceGxmColorSwizzle1Mode : u32 +{ + SCE_GXM_COLOR_SWIZZLE1_R = 0x00000000u, + SCE_GXM_COLOR_SWIZZLE1_G = 0x00100000u, + SCE_GXM_COLOR_SWIZZLE1_A = 0x00100000u +}; + +enum SceGxmColorBaseFormat : u32 +{ + SCE_GXM_COLOR_BASE_FORMAT_U8U8U8U8 = 0x00000000u, + SCE_GXM_COLOR_BASE_FORMAT_U8U8U8 = 0x10000000u, + SCE_GXM_COLOR_BASE_FORMAT_U5U6U5 = 0x30000000u, + SCE_GXM_COLOR_BASE_FORMAT_U1U5U5U5 = 0x40000000u, + SCE_GXM_COLOR_BASE_FORMAT_U4U4U4U4 = 0x50000000u, + SCE_GXM_COLOR_BASE_FORMAT_U8U3U3U2 = 0x60000000u, + SCE_GXM_COLOR_BASE_FORMAT_F16 = 0xf0000000u, + SCE_GXM_COLOR_BASE_FORMAT_F16F16 = 0x00800000u, + SCE_GXM_COLOR_BASE_FORMAT_F32 = 0x10800000u, + SCE_GXM_COLOR_BASE_FORMAT_S16 = 0x20800000u, + SCE_GXM_COLOR_BASE_FORMAT_S16S16 = 0x30800000u, + SCE_GXM_COLOR_BASE_FORMAT_U16 = 0x40800000u, + SCE_GXM_COLOR_BASE_FORMAT_U16U16 = 0x50800000u, + SCE_GXM_COLOR_BASE_FORMAT_U2U10U10U10 = 0x60800000u, + SCE_GXM_COLOR_BASE_FORMAT_U8 = 0x80800000u, + SCE_GXM_COLOR_BASE_FORMAT_S8 = 0x90800000u, + SCE_GXM_COLOR_BASE_FORMAT_S5S5U6 = 0xa0800000u, + SCE_GXM_COLOR_BASE_FORMAT_U8U8 = 0xb0800000u, + SCE_GXM_COLOR_BASE_FORMAT_S8S8 = 0xc0800000u, + SCE_GXM_COLOR_BASE_FORMAT_U8S8S8U8 = 0xd0800000u, + SCE_GXM_COLOR_BASE_FORMAT_S8S8S8S8 = 0xe0800000u, + SCE_GXM_COLOR_BASE_FORMAT_F16F16F16F16 = 0x01000000u, + SCE_GXM_COLOR_BASE_FORMAT_F32F32 = 0x11000000u, + SCE_GXM_COLOR_BASE_FORMAT_F11F11F10 = 0x21000000u, + SCE_GXM_COLOR_BASE_FORMAT_SE5M9M9M9 = 0x31000000u, + SCE_GXM_COLOR_BASE_FORMAT_U2F10F10F10 = 0x41000000u +}; + +enum SceGxmColorFormat : u32 +{ + // Supported formats + + SCE_GXM_COLOR_FORMAT_U8U8U8U8_ABGR = SCE_GXM_COLOR_BASE_FORMAT_U8U8U8U8 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_U8U8U8U8_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U8U8U8U8 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_U8U8U8U8_RGBA = SCE_GXM_COLOR_BASE_FORMAT_U8U8U8U8 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_U8U8U8U8_BGRA = SCE_GXM_COLOR_BASE_FORMAT_U8U8U8U8 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_U8U8U8_BGR = SCE_GXM_COLOR_BASE_FORMAT_U8U8U8 | SCE_GXM_COLOR_SWIZZLE3_BGR, + SCE_GXM_COLOR_FORMAT_U8U8U8_RGB = SCE_GXM_COLOR_BASE_FORMAT_U8U8U8 | SCE_GXM_COLOR_SWIZZLE3_RGB, + + SCE_GXM_COLOR_FORMAT_U5U6U5_BGR = SCE_GXM_COLOR_BASE_FORMAT_U5U6U5 | SCE_GXM_COLOR_SWIZZLE3_BGR, + SCE_GXM_COLOR_FORMAT_U5U6U5_RGB = SCE_GXM_COLOR_BASE_FORMAT_U5U6U5 | SCE_GXM_COLOR_SWIZZLE3_RGB, + + SCE_GXM_COLOR_FORMAT_U1U5U5U5_ABGR = SCE_GXM_COLOR_BASE_FORMAT_U1U5U5U5 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_U1U5U5U5_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U1U5U5U5 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_U5U5U5U1_RGBA = SCE_GXM_COLOR_BASE_FORMAT_U1U5U5U5 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_U5U5U5U1_BGRA = SCE_GXM_COLOR_BASE_FORMAT_U1U5U5U5 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_U4U4U4U4_ABGR = SCE_GXM_COLOR_BASE_FORMAT_U4U4U4U4 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_U4U4U4U4_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U4U4U4U4 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_U4U4U4U4_RGBA = SCE_GXM_COLOR_BASE_FORMAT_U4U4U4U4 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_U4U4U4U4_BGRA = SCE_GXM_COLOR_BASE_FORMAT_U4U4U4U4 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_U8U3U3U2_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U8U3U3U2, + + SCE_GXM_COLOR_FORMAT_F16_R = SCE_GXM_COLOR_BASE_FORMAT_F16 | SCE_GXM_COLOR_SWIZZLE1_R, + SCE_GXM_COLOR_FORMAT_F16_G = SCE_GXM_COLOR_BASE_FORMAT_F16 | SCE_GXM_COLOR_SWIZZLE1_G, + + SCE_GXM_COLOR_FORMAT_F16F16_GR = SCE_GXM_COLOR_BASE_FORMAT_F16F16 | SCE_GXM_COLOR_SWIZZLE2_GR, + SCE_GXM_COLOR_FORMAT_F16F16_RG = SCE_GXM_COLOR_BASE_FORMAT_F16F16 | SCE_GXM_COLOR_SWIZZLE2_RG, + + SCE_GXM_COLOR_FORMAT_F32_R = SCE_GXM_COLOR_BASE_FORMAT_F32 | SCE_GXM_COLOR_SWIZZLE1_R, + + SCE_GXM_COLOR_FORMAT_S16_R = SCE_GXM_COLOR_BASE_FORMAT_S16 | SCE_GXM_COLOR_SWIZZLE1_R, + SCE_GXM_COLOR_FORMAT_S16_G = SCE_GXM_COLOR_BASE_FORMAT_S16 | SCE_GXM_COLOR_SWIZZLE1_G, + + SCE_GXM_COLOR_FORMAT_S16S16_GR = SCE_GXM_COLOR_BASE_FORMAT_S16S16 | SCE_GXM_COLOR_SWIZZLE2_GR, + SCE_GXM_COLOR_FORMAT_S16S16_RG = SCE_GXM_COLOR_BASE_FORMAT_S16S16 | SCE_GXM_COLOR_SWIZZLE2_RG, + + SCE_GXM_COLOR_FORMAT_U16_R = SCE_GXM_COLOR_BASE_FORMAT_U16 | SCE_GXM_COLOR_SWIZZLE1_R, + SCE_GXM_COLOR_FORMAT_U16_G = SCE_GXM_COLOR_BASE_FORMAT_U16 | SCE_GXM_COLOR_SWIZZLE1_G, + + SCE_GXM_COLOR_FORMAT_U16U16_GR = SCE_GXM_COLOR_BASE_FORMAT_U16U16 | SCE_GXM_COLOR_SWIZZLE2_GR, + SCE_GXM_COLOR_FORMAT_U16U16_RG = SCE_GXM_COLOR_BASE_FORMAT_U16U16 | SCE_GXM_COLOR_SWIZZLE2_RG, + + SCE_GXM_COLOR_FORMAT_U2U10U10U10_ABGR = SCE_GXM_COLOR_BASE_FORMAT_U2U10U10U10 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_U2U10U10U10_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U2U10U10U10 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_U10U10U10U2_RGBA = SCE_GXM_COLOR_BASE_FORMAT_U2U10U10U10 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_U10U10U10U2_BGRA = SCE_GXM_COLOR_BASE_FORMAT_U2U10U10U10 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_U8_R = SCE_GXM_COLOR_BASE_FORMAT_U8 | SCE_GXM_COLOR_SWIZZLE1_R, + SCE_GXM_COLOR_FORMAT_U8_A = SCE_GXM_COLOR_BASE_FORMAT_U8 | SCE_GXM_COLOR_SWIZZLE1_A, + + SCE_GXM_COLOR_FORMAT_S8_R = SCE_GXM_COLOR_BASE_FORMAT_S8 | SCE_GXM_COLOR_SWIZZLE1_R, + SCE_GXM_COLOR_FORMAT_S8_A = SCE_GXM_COLOR_BASE_FORMAT_S8 | SCE_GXM_COLOR_SWIZZLE1_A, + + SCE_GXM_COLOR_FORMAT_U6S5S5_BGR = SCE_GXM_COLOR_BASE_FORMAT_S5S5U6 | SCE_GXM_COLOR_SWIZZLE3_BGR, + SCE_GXM_COLOR_FORMAT_S5S5U6_RGB = SCE_GXM_COLOR_BASE_FORMAT_S5S5U6 | SCE_GXM_COLOR_SWIZZLE3_RGB, + + SCE_GXM_COLOR_FORMAT_U8U8_GR = SCE_GXM_COLOR_BASE_FORMAT_U8U8 | SCE_GXM_COLOR_SWIZZLE2_GR, + SCE_GXM_COLOR_FORMAT_U8U8_RG = SCE_GXM_COLOR_BASE_FORMAT_U8U8 | SCE_GXM_COLOR_SWIZZLE2_RG, + SCE_GXM_COLOR_FORMAT_U8U8_RA = SCE_GXM_COLOR_BASE_FORMAT_U8U8 | SCE_GXM_COLOR_SWIZZLE2_RA, + SCE_GXM_COLOR_FORMAT_U8U8_AR = SCE_GXM_COLOR_BASE_FORMAT_U8U8 | SCE_GXM_COLOR_SWIZZLE2_AR, + + SCE_GXM_COLOR_FORMAT_S8S8_GR = SCE_GXM_COLOR_BASE_FORMAT_S8S8 | SCE_GXM_COLOR_SWIZZLE2_GR, + SCE_GXM_COLOR_FORMAT_S8S8_RG = SCE_GXM_COLOR_BASE_FORMAT_S8S8 | SCE_GXM_COLOR_SWIZZLE2_RG, + SCE_GXM_COLOR_FORMAT_S8S8_RA = SCE_GXM_COLOR_BASE_FORMAT_S8S8 | SCE_GXM_COLOR_SWIZZLE2_RA, + SCE_GXM_COLOR_FORMAT_S8S8_AR = SCE_GXM_COLOR_BASE_FORMAT_S8S8 | SCE_GXM_COLOR_SWIZZLE2_AR, + + SCE_GXM_COLOR_FORMAT_U8S8S8U8_ABGR = SCE_GXM_COLOR_BASE_FORMAT_U8S8S8U8 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_U8U8S8S8_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U8S8S8U8 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_U8S8S8U8_RGBA = SCE_GXM_COLOR_BASE_FORMAT_U8S8S8U8 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_S8S8U8U8_BGRA = SCE_GXM_COLOR_BASE_FORMAT_U8S8S8U8 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_S8S8S8S8_ABGR = SCE_GXM_COLOR_BASE_FORMAT_S8S8S8S8 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_S8S8S8S8_ARGB = SCE_GXM_COLOR_BASE_FORMAT_S8S8S8S8 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_S8S8S8S8_RGBA = SCE_GXM_COLOR_BASE_FORMAT_S8S8S8S8 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_S8S8S8S8_BGRA = SCE_GXM_COLOR_BASE_FORMAT_S8S8S8S8 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_F16F16F16F16_ABGR = SCE_GXM_COLOR_BASE_FORMAT_F16F16F16F16 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_F16F16F16F16_ARGB = SCE_GXM_COLOR_BASE_FORMAT_F16F16F16F16 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_F16F16F16F16_RGBA = SCE_GXM_COLOR_BASE_FORMAT_F16F16F16F16 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_F16F16F16F16_BGRA = SCE_GXM_COLOR_BASE_FORMAT_F16F16F16F16 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + SCE_GXM_COLOR_FORMAT_F32F32_GR = SCE_GXM_COLOR_BASE_FORMAT_F32F32 | SCE_GXM_COLOR_SWIZZLE2_GR, + SCE_GXM_COLOR_FORMAT_F32F32_RG = SCE_GXM_COLOR_BASE_FORMAT_F32F32 | SCE_GXM_COLOR_SWIZZLE2_RG, + + SCE_GXM_COLOR_FORMAT_F10F11F11_BGR = SCE_GXM_COLOR_BASE_FORMAT_F11F11F10 | SCE_GXM_COLOR_SWIZZLE3_BGR, + SCE_GXM_COLOR_FORMAT_F11F11F10_RGB = SCE_GXM_COLOR_BASE_FORMAT_F11F11F10 | SCE_GXM_COLOR_SWIZZLE3_RGB, + + SCE_GXM_COLOR_FORMAT_SE5M9M9M9_BGR = SCE_GXM_COLOR_BASE_FORMAT_SE5M9M9M9 | SCE_GXM_COLOR_SWIZZLE3_BGR, + SCE_GXM_COLOR_FORMAT_SE5M9M9M9_RGB = SCE_GXM_COLOR_BASE_FORMAT_SE5M9M9M9 | SCE_GXM_COLOR_SWIZZLE3_RGB, + + SCE_GXM_COLOR_FORMAT_U2F10F10F10_ABGR = SCE_GXM_COLOR_BASE_FORMAT_U2F10F10F10 | SCE_GXM_COLOR_SWIZZLE4_ABGR, + SCE_GXM_COLOR_FORMAT_U2F10F10F10_ARGB = SCE_GXM_COLOR_BASE_FORMAT_U2F10F10F10 | SCE_GXM_COLOR_SWIZZLE4_ARGB, + SCE_GXM_COLOR_FORMAT_F10F10F10U2_RGBA = SCE_GXM_COLOR_BASE_FORMAT_U2F10F10F10 | SCE_GXM_COLOR_SWIZZLE4_RGBA, + SCE_GXM_COLOR_FORMAT_F10F10F10U2_BGRA = SCE_GXM_COLOR_BASE_FORMAT_U2F10F10F10 | SCE_GXM_COLOR_SWIZZLE4_BGRA, + + // Legacy formats + + SCE_GXM_COLOR_FORMAT_A8B8G8R8 = SCE_GXM_COLOR_FORMAT_U8U8U8U8_ABGR, + SCE_GXM_COLOR_FORMAT_A8R8G8B8 = SCE_GXM_COLOR_FORMAT_U8U8U8U8_ARGB, + SCE_GXM_COLOR_FORMAT_R5G6B5 = SCE_GXM_COLOR_FORMAT_U5U6U5_RGB, + SCE_GXM_COLOR_FORMAT_A1R5G5B5 = SCE_GXM_COLOR_FORMAT_U1U5U5U5_ARGB, + SCE_GXM_COLOR_FORMAT_A4R4G4B4 = SCE_GXM_COLOR_FORMAT_U4U4U4U4_ARGB, + SCE_GXM_COLOR_FORMAT_A8 = SCE_GXM_COLOR_FORMAT_U8_A +}; + +enum SceGxmColorSurfaceType : u32 +{ + SCE_GXM_COLOR_SURFACE_LINEAR = 0x00000000u, + SCE_GXM_COLOR_SURFACE_TILED = 0x04000000u, + SCE_GXM_COLOR_SURFACE_SWIZZLED = 0x08000000u +}; + +enum SceGxmColorSurfaceGammaMode : u32 +{ + SCE_GXM_COLOR_SURFACE_GAMMA_NONE = 0x00000000u, + SCE_GXM_COLOR_SURFACE_GAMMA_R = 0x00001000u, + SCE_GXM_COLOR_SURFACE_GAMMA_GR = 0x00003000u, + SCE_GXM_COLOR_SURFACE_GAMMA_BGR = 0x00001000u +}; + +enum SceGxmColorSurfaceDitherMode : u32 +{ + SCE_GXM_COLOR_SURFACE_DITHER_DISABLED = 0x00000000u, + SCE_GXM_COLOR_SURFACE_DITHER_ENABLED = 0x00000008u +}; + +enum SceGxmDepthStencilSurfaceType : u32 +{ + SCE_GXM_DEPTH_STENCIL_SURFACE_LINEAR = 0x00000000u, + SCE_GXM_DEPTH_STENCIL_SURFACE_TILED = 0x00011000u +}; + +enum SceGxmOutputRegisterFormat : s32 +{ + SCE_GXM_OUTPUT_REGISTER_FORMAT_DECLARED, + SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, + SCE_GXM_OUTPUT_REGISTER_FORMAT_CHAR4, + SCE_GXM_OUTPUT_REGISTER_FORMAT_USHORT2, + SCE_GXM_OUTPUT_REGISTER_FORMAT_SHORT2, + SCE_GXM_OUTPUT_REGISTER_FORMAT_HALF4, + SCE_GXM_OUTPUT_REGISTER_FORMAT_HALF2, + SCE_GXM_OUTPUT_REGISTER_FORMAT_FLOAT2, + SCE_GXM_OUTPUT_REGISTER_FORMAT_FLOAT +}; + +enum SceGxmMultisampleMode : u16 +{ + SCE_GXM_MULTISAMPLE_NONE, + SCE_GXM_MULTISAMPLE_2X, + SCE_GXM_MULTISAMPLE_4X +}; + +enum SceGxmTextureSwizzle4Mode : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE4_ABGR = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE4_ARGB = 0x00001000u, + SCE_GXM_TEXTURE_SWIZZLE4_RGBA = 0x00002000u, + SCE_GXM_TEXTURE_SWIZZLE4_BGRA = 0x00003000u, + SCE_GXM_TEXTURE_SWIZZLE4_1BGR = 0x00004000u, + SCE_GXM_TEXTURE_SWIZZLE4_1RGB = 0x00005000u, + SCE_GXM_TEXTURE_SWIZZLE4_RGB1 = 0x00006000u, + SCE_GXM_TEXTURE_SWIZZLE4_BGR1 = 0x00007000u +}; + +enum SceGxmTextureSwizzle3Mode : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE3_BGR = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE3_RGB = 0x00001000u +}; + +enum SceGxmTextureSwizzle2Mode : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE2_GR = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE2_00GR = 0x00001000u, + SCE_GXM_TEXTURE_SWIZZLE2_GRRR = 0x00002000u, + SCE_GXM_TEXTURE_SWIZZLE2_RGGG = 0x00003000u, + SCE_GXM_TEXTURE_SWIZZLE2_GRGR = 0x00004000u, + SCE_GXM_TEXTURE_SWIZZLE2_00RG = 0x00005000u +}; + +enum SceGxmTextureSwizzle2ModeAlt : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE2_SD = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE2_DS = 0x00001000u +}; + +enum SceGxmTextureSwizzle1Mode : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE1_R = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE1_000R = 0x00001000u, + SCE_GXM_TEXTURE_SWIZZLE1_111R = 0x00002000u, + SCE_GXM_TEXTURE_SWIZZLE1_RRRR = 0x00003000u, + SCE_GXM_TEXTURE_SWIZZLE1_0RRR = 0x00004000u, + SCE_GXM_TEXTURE_SWIZZLE1_1RRR = 0x00005000u, + SCE_GXM_TEXTURE_SWIZZLE1_R000 = 0x00006000u, + SCE_GXM_TEXTURE_SWIZZLE1_R111 = 0x00007000u +}; + +enum SceGxmTextureSwizzleYUV422Mode : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE_YUYV_CSC0 = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE_YVYU_CSC0 = 0x00001000u, + SCE_GXM_TEXTURE_SWIZZLE_UYVY_CSC0 = 0x00002000u, + SCE_GXM_TEXTURE_SWIZZLE_VYUY_CSC0 = 0x00003000u, + SCE_GXM_TEXTURE_SWIZZLE_YUYV_CSC1 = 0x00004000u, + SCE_GXM_TEXTURE_SWIZZLE_YVYU_CSC1 = 0x00005000u, + SCE_GXM_TEXTURE_SWIZZLE_UYVY_CSC1 = 0x00006000u, + SCE_GXM_TEXTURE_SWIZZLE_VYUY_CSC1 = 0x00007000u +}; + +enum SceGxmTextureSwizzleYUV420Mode : u32 +{ + SCE_GXM_TEXTURE_SWIZZLE_YUV_CSC0 = 0x00000000u, + SCE_GXM_TEXTURE_SWIZZLE_YVU_CSC0 = 0x00001000u, + SCE_GXM_TEXTURE_SWIZZLE_YUV_CSC1 = 0x00002000u, + SCE_GXM_TEXTURE_SWIZZLE_YVU_CSC1 = 0x00003000u +}; + +enum SceGxmTextureBaseFormat : u32 +{ + SCE_GXM_TEXTURE_BASE_FORMAT_U8 = 0x00000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S8 = 0x01000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 = 0x02000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2 = 0x03000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 = 0x04000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5 = 0x05000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6 = 0x06000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 = 0x07000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 = 0x08000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U16 = 0x09000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S16 = 0x0a000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F16 = 0x0b000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 = 0x0c000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 = 0x0d000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 = 0x0e000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 = 0x0f000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 = 0x10000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 = 0x11000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F32 = 0x12000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F32M = 0x13000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_X8S8S8U8 = 0x14000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_X8U24 = 0x15000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U32 = 0x17000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S32 = 0x18000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_SE5M9M9M9 = 0x19000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F11F11F10 = 0x1a000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 = 0x1b000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 = 0x1c000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 = 0x1d000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 = 0x1e000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 = 0x1f000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_PVRT2BPP = 0x80000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_PVRT4BPP = 0x81000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_PVRTII2BPP = 0x82000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_PVRTII4BPP = 0x83000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_UBC1 = 0x85000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_UBC2 = 0x86000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_UBC3 = 0x87000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2 = 0x90000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 = 0x91000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 = 0x92000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_P4 = 0x94000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_P8 = 0x95000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8 = 0x98000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8 = 0x99000000u, + SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 = 0x9a000000u +}; + +enum SceGxmTextureFormat : u32 +{ + // Supported formats + + SCE_GXM_TEXTURE_FORMAT_U8_000R = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_U8_111R = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_U8_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_U8_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_U8_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_U8_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_U8_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_U8_R = SCE_GXM_TEXTURE_BASE_FORMAT_U8 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_S8_000R = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_S8_111R = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_S8_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_S8_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_S8_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_S8_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_S8_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_S8_R = SCE_GXM_TEXTURE_BASE_FORMAT_S8 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_U4U4U4U4_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_U4U4U4U4_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_U4U4U4U4_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_U4U4U4U4_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X4U4U4U4_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X4U4U4U4_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_U4U4U4X4_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_U4U4U4X4_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_U8U3U3U2_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2, + + SCE_GXM_TEXTURE_FORMAT_U1U5U5U5_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_U1U5U5U5_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_U5U5U5U1_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_U5U5U5U1_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X1U5U5U5_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X1U5U5U5_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_U5U5U5X1_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_U5U5U5X1_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_U6S5S5_BGR = SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_S5S5U6_RGB = SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_U8U8_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_U8U8_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_U8U8_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_U8U8_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_U8U8_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_U8U8_GR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_S8S8_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_S8S8_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_S8S8_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_S8S8_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_S8S8_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_S8S8_GR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_U16_000R = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_U16_111R = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_U16_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_U16_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_U16_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_U16_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_U16_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_U16_R = SCE_GXM_TEXTURE_BASE_FORMAT_U16 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_S16_000R = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_S16_111R = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_S16_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_S16_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_S16_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_S16_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_S16_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_S16_R = SCE_GXM_TEXTURE_BASE_FORMAT_S16 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_F16_000R = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_F16_111R = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_F16_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_F16_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_F16_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_F16_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_F16_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_F16_R = SCE_GXM_TEXTURE_BASE_FORMAT_F16 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_U8U8U8X8_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_U8U8U8X8_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_S8S8S8S8_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_S8S8S8S8_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_S8S8S8S8_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_S8S8S8S8_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X8S8S8S8_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X8S8S8S8_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_S8S8S8X8_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_S8S8S8X8_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_U2U10U10U10_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_U2U10U10U10_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_U10U10U10U2_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_U10U10U10U2_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X2U10U10U10_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X2U10U10U10_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_U10U10U10X2_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_U10U10U10X2_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_U2U10U10U10 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_U16U16_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_U16U16_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_U16U16_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_U16U16_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_U16U16_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_U16U16_GR = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_S16S16_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_S16S16_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_S16S16_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_S16S16_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_S16S16_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_S16S16_GR = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_F16F16_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_F16F16_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_F16F16_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_F16F16_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_F16F16_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_F16F16_GR = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_F32_000R = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_F32_111R = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_F32_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_F32_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_F32_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_F32_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_F32_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_F32_R = SCE_GXM_TEXTURE_BASE_FORMAT_F32 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_F32M_000R = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_F32M_111R = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_F32M_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_F32M_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_F32M_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_F32M_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_F32M_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_F32M_R = SCE_GXM_TEXTURE_BASE_FORMAT_F32M | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_X8S8S8U8_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_X8S8S8U8 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_X8U8S8S8_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_X8S8S8U8 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_X8U24_SD = SCE_GXM_TEXTURE_BASE_FORMAT_X8U24 | SCE_GXM_TEXTURE_SWIZZLE2_SD, + SCE_GXM_TEXTURE_FORMAT_U24X8_DS = SCE_GXM_TEXTURE_BASE_FORMAT_X8U24 | SCE_GXM_TEXTURE_SWIZZLE2_DS, + + SCE_GXM_TEXTURE_FORMAT_U32_000R = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_U32_111R = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_U32_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_U32_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_U32_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_U32_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_U32_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_U32_R = SCE_GXM_TEXTURE_BASE_FORMAT_U32 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_S32_000R = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_000R, + SCE_GXM_TEXTURE_FORMAT_S32_111R = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_111R, + SCE_GXM_TEXTURE_FORMAT_S32_RRRR = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_RRRR, + SCE_GXM_TEXTURE_FORMAT_S32_0RRR = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_0RRR, + SCE_GXM_TEXTURE_FORMAT_S32_1RRR = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_1RRR, + SCE_GXM_TEXTURE_FORMAT_S32_R000 = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_R000, + SCE_GXM_TEXTURE_FORMAT_S32_R111 = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_R111, + SCE_GXM_TEXTURE_FORMAT_S32_R = SCE_GXM_TEXTURE_BASE_FORMAT_S32 | SCE_GXM_TEXTURE_SWIZZLE1_R, + + SCE_GXM_TEXTURE_FORMAT_SE5M9M9M9_BGR = SCE_GXM_TEXTURE_BASE_FORMAT_SE5M9M9M9 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_SE5M9M9M9_RGB = SCE_GXM_TEXTURE_BASE_FORMAT_SE5M9M9M9 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_F10F11F11_BGR = SCE_GXM_TEXTURE_BASE_FORMAT_F11F11F10 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_F11F11F10_RGB = SCE_GXM_TEXTURE_BASE_FORMAT_F11F11F10 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_F16F16F16F16_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_F16F16F16F16_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_F16F16F16F16_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_F16F16F16F16_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X16F16F16F16_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X16F16F16F16_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_F16F16F16X16_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_F16F16F16X16_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_F16F16F16F16 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_U16U16U16U16_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_U16U16U16U16_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_U16U16U16U16_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_U16U16U16U16_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X16U16U16U16_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X16U16U16U16_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_U16U16U16X16_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_U16U16U16X16_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_U16U16U16U16 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_S16S16S16S16_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_S16S16S16S16_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_S16S16S16S16_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_S16S16S16S16_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X16S16S16S16_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X16S16S16S16_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_S16S16S16X16_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_S16S16S16X16_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_S16S16S16S16 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_F32F32_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_F32F32_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_F32F32_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_F32F32_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_F32F32_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_F32F32_GR = SCE_GXM_TEXTURE_BASE_FORMAT_F32F32 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_U32U32_00GR = SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 | SCE_GXM_TEXTURE_SWIZZLE2_00GR, + SCE_GXM_TEXTURE_FORMAT_U32U32_GRRR = SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 | SCE_GXM_TEXTURE_SWIZZLE2_GRRR, + SCE_GXM_TEXTURE_FORMAT_U32U32_RGGG = SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 | SCE_GXM_TEXTURE_SWIZZLE2_RGGG, + SCE_GXM_TEXTURE_FORMAT_U32U32_GRGR = SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 | SCE_GXM_TEXTURE_SWIZZLE2_GRGR, + SCE_GXM_TEXTURE_FORMAT_U32U32_00RG = SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 | SCE_GXM_TEXTURE_SWIZZLE2_00RG, + SCE_GXM_TEXTURE_FORMAT_U32U32_GR = SCE_GXM_TEXTURE_BASE_FORMAT_U32U32 | SCE_GXM_TEXTURE_SWIZZLE2_GR, + + SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRT2BPP | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRT2BPP | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + + SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRT4BPP | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRT4BPP | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + + SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRTII2BPP | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRTII2BPP | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + + SCE_GXM_TEXTURE_FORMAT_PVRTII4BPP_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRTII4BPP | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRTII4BPP_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_PVRTII4BPP | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + + SCE_GXM_TEXTURE_FORMAT_UBC1_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_UBC1 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + + SCE_GXM_TEXTURE_FORMAT_UBC2_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_UBC2 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + + SCE_GXM_TEXTURE_FORMAT_UBC3_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_UBC3 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + + SCE_GXM_TEXTURE_FORMAT_YUV420P2_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2 | SCE_GXM_TEXTURE_SWIZZLE_YUV_CSC0, + SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2 | SCE_GXM_TEXTURE_SWIZZLE_YVU_CSC0, + SCE_GXM_TEXTURE_FORMAT_YUV420P2_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2 | SCE_GXM_TEXTURE_SWIZZLE_YUV_CSC1, + SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2 | SCE_GXM_TEXTURE_SWIZZLE_YVU_CSC1, + + SCE_GXM_TEXTURE_FORMAT_YUV420P3_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 | SCE_GXM_TEXTURE_SWIZZLE_YUV_CSC0, + SCE_GXM_TEXTURE_FORMAT_YVU420P3_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 | SCE_GXM_TEXTURE_SWIZZLE_YVU_CSC0, + SCE_GXM_TEXTURE_FORMAT_YUV420P3_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 | SCE_GXM_TEXTURE_SWIZZLE_YUV_CSC1, + SCE_GXM_TEXTURE_FORMAT_YVU420P3_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 | SCE_GXM_TEXTURE_SWIZZLE_YVU_CSC1, + + SCE_GXM_TEXTURE_FORMAT_YUYV422_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_YUYV_CSC0, + SCE_GXM_TEXTURE_FORMAT_YVYU422_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_YVYU_CSC0, + SCE_GXM_TEXTURE_FORMAT_UYVY422_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_UYVY_CSC0, + SCE_GXM_TEXTURE_FORMAT_VYUY422_CSC0 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_VYUY_CSC0, + SCE_GXM_TEXTURE_FORMAT_YUYV422_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_YUYV_CSC1, + SCE_GXM_TEXTURE_FORMAT_YVYU422_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_YVYU_CSC1, + SCE_GXM_TEXTURE_FORMAT_UYVY422_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_UYVY_CSC1, + SCE_GXM_TEXTURE_FORMAT_VYUY422_CSC1 = SCE_GXM_TEXTURE_BASE_FORMAT_YUV422 | SCE_GXM_TEXTURE_SWIZZLE_VYUY_CSC1, + + SCE_GXM_TEXTURE_FORMAT_P4_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_P4_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_P4_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_P4_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_P4_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_P4_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_P4_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_P4_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_P4 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_P8_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_P8_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_P8_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_P8_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_P8_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_P8_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_P8_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_P8_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_P8 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + SCE_GXM_TEXTURE_FORMAT_U8U8U8_BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_U8U8U8_RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_S8S8S8_BGR = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE3_BGR, + SCE_GXM_TEXTURE_FORMAT_S8S8S8_RGB = SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8 | SCE_GXM_TEXTURE_SWIZZLE3_RGB, + + SCE_GXM_TEXTURE_FORMAT_U2F10F10F10_ABGR = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_ABGR, + SCE_GXM_TEXTURE_FORMAT_U2F10F10F10_ARGB = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_ARGB, + SCE_GXM_TEXTURE_FORMAT_F10F10F10U2_RGBA = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_RGBA, + SCE_GXM_TEXTURE_FORMAT_F10F10F10U2_BGRA = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_BGRA, + SCE_GXM_TEXTURE_FORMAT_X2F10F10F10_1BGR = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_1BGR, + SCE_GXM_TEXTURE_FORMAT_X2F10F10F10_1RGB = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_1RGB, + SCE_GXM_TEXTURE_FORMAT_F10F10F10X2_RGB1 = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_RGB1, + SCE_GXM_TEXTURE_FORMAT_F10F10F10X2_BGR1 = SCE_GXM_TEXTURE_BASE_FORMAT_U2F10F10F10 | SCE_GXM_TEXTURE_SWIZZLE4_BGR1, + + // Legacy formats + + SCE_GXM_TEXTURE_FORMAT_L8 = SCE_GXM_TEXTURE_FORMAT_U8_1RRR, + SCE_GXM_TEXTURE_FORMAT_A8 = SCE_GXM_TEXTURE_FORMAT_U8_R000, + SCE_GXM_TEXTURE_FORMAT_R8 = SCE_GXM_TEXTURE_FORMAT_U8_000R, + SCE_GXM_TEXTURE_FORMAT_A4R4G4B4 = SCE_GXM_TEXTURE_FORMAT_U4U4U4U4_ARGB, + SCE_GXM_TEXTURE_FORMAT_A1R5G5B5 = SCE_GXM_TEXTURE_FORMAT_U1U5U5U5_ARGB, + SCE_GXM_TEXTURE_FORMAT_R5G6B5 = SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB, + SCE_GXM_TEXTURE_FORMAT_A8L8 = SCE_GXM_TEXTURE_FORMAT_U8U8_GRRR, + SCE_GXM_TEXTURE_FORMAT_L8A8 = SCE_GXM_TEXTURE_FORMAT_U8U8_RGGG, + SCE_GXM_TEXTURE_FORMAT_G8R8 = SCE_GXM_TEXTURE_FORMAT_U8U8_00GR, + SCE_GXM_TEXTURE_FORMAT_L16 = SCE_GXM_TEXTURE_FORMAT_U16_1RRR, + SCE_GXM_TEXTURE_FORMAT_A16 = SCE_GXM_TEXTURE_FORMAT_U16_R000, + SCE_GXM_TEXTURE_FORMAT_R16 = SCE_GXM_TEXTURE_FORMAT_U16_000R, + SCE_GXM_TEXTURE_FORMAT_D16 = SCE_GXM_TEXTURE_FORMAT_U16_R, + SCE_GXM_TEXTURE_FORMAT_LF16 = SCE_GXM_TEXTURE_FORMAT_F16_1RRR, + SCE_GXM_TEXTURE_FORMAT_AF16 = SCE_GXM_TEXTURE_FORMAT_F16_R000, + SCE_GXM_TEXTURE_FORMAT_RF16 = SCE_GXM_TEXTURE_FORMAT_F16_000R, + SCE_GXM_TEXTURE_FORMAT_A8R8G8B8 = SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB, + SCE_GXM_TEXTURE_FORMAT_A8B8G8R8 = SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR, + SCE_GXM_TEXTURE_FORMAT_AF16LF16 = SCE_GXM_TEXTURE_FORMAT_F16F16_GRRR, + SCE_GXM_TEXTURE_FORMAT_LF16AF16 = SCE_GXM_TEXTURE_FORMAT_F16F16_RGGG, + SCE_GXM_TEXTURE_FORMAT_GF16RF16 = SCE_GXM_TEXTURE_FORMAT_F16F16_00GR, + SCE_GXM_TEXTURE_FORMAT_LF32M = SCE_GXM_TEXTURE_FORMAT_F32M_1RRR, + SCE_GXM_TEXTURE_FORMAT_AF32M = SCE_GXM_TEXTURE_FORMAT_F32M_R000, + SCE_GXM_TEXTURE_FORMAT_RF32M = SCE_GXM_TEXTURE_FORMAT_F32M_000R, + SCE_GXM_TEXTURE_FORMAT_DF32M = SCE_GXM_TEXTURE_FORMAT_F32M_R, + SCE_GXM_TEXTURE_FORMAT_VYUY = SCE_GXM_TEXTURE_FORMAT_VYUY422_CSC0, + SCE_GXM_TEXTURE_FORMAT_YVYU = SCE_GXM_TEXTURE_FORMAT_YVYU422_CSC0, + SCE_GXM_TEXTURE_FORMAT_UBC1 = SCE_GXM_TEXTURE_FORMAT_UBC1_ABGR, + SCE_GXM_TEXTURE_FORMAT_UBC2 = SCE_GXM_TEXTURE_FORMAT_UBC2_ABGR, + SCE_GXM_TEXTURE_FORMAT_UBC3 = SCE_GXM_TEXTURE_FORMAT_UBC3_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRT2BPP = SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRT4BPP = SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP = SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP_ABGR, + SCE_GXM_TEXTURE_FORMAT_PVRTII4BPP = SCE_GXM_TEXTURE_FORMAT_PVRTII4BPP_ABGR +}; + +enum SceGxmTextureAnisoMode : u32 +{ + SCE_GXM_TEXTURE_ANISO_DISABLED = 0x00000000u, + SCE_GXM_TEXTURE_ANISO_ENABLED = 0x00004000u +}; + +enum SceGxmTextureType : u32 +{ + SCE_GXM_TEXTURE_SWIZZLED = 0x00000000u, + SCE_GXM_TEXTURE_CUBE = 0x40000000u, + SCE_GXM_TEXTURE_LINEAR = 0x60000000u, + SCE_GXM_TEXTURE_TILED = 0x80000000u, + SCE_GXM_TEXTURE_LINEAR_STRIDED = 0xc0000000u +}; + +enum SceGxmTextureFilter : u32 +{ + SCE_GXM_TEXTURE_FILTER_POINT = 0x00000000u, + SCE_GXM_TEXTURE_FILTER_LINEAR = 0x00000001u, + SCE_GXM_TEXTURE_FILTER_ANISO_LINEAR = 0x00000002u, + SCE_GXM_TEXTURE_FILTER_ANISO_POINT = 0x00000003u +}; + +enum SceGxmTextureMipFilter : u32 +{ + SCE_GXM_TEXTURE_MIP_FILTER_DISABLED = 0x00000000u, + SCE_GXM_TEXTURE_MIP_FILTER_ENABLED = 0x00000200u +}; + +enum SceGxmTextureAddrMode : u32 +{ + SCE_GXM_TEXTURE_ADDR_REPEAT = 0x00000000u, + SCE_GXM_TEXTURE_ADDR_MIRROR = 0x00000001u, + SCE_GXM_TEXTURE_ADDR_CLAMP = 0x00000002u, + SCE_GXM_TEXTURE_ADDR_MIRROR_CLAMP = 0x00000003u, + SCE_GXM_TEXTURE_ADDR_REPEAT_IGNORE_BORDER = 0x00000004u, + SCE_GXM_TEXTURE_ADDR_CLAMP_FULL_BORDER = 0x00000005u, + SCE_GXM_TEXTURE_ADDR_CLAMP_IGNORE_BORDER = 0x00000006u, + SCE_GXM_TEXTURE_ADDR_CLAMP_HALF_BORDER = 0x00000007u +}; + +enum SceGxmTextureGammaMode : u32 +{ + SCE_GXM_TEXTURE_GAMMA_NONE = 0x00000000u, + SCE_GXM_TEXTURE_GAMMA_R = 0x08000000u, + SCE_GXM_TEXTURE_GAMMA_GR = 0x18000000u, + SCE_GXM_TEXTURE_GAMMA_BGR = 0x08000000u +}; + +enum SceGxmIndexFormat : u32 +{ + SCE_GXM_INDEX_FORMAT_U16 = 0x00000000u, + SCE_GXM_INDEX_FORMAT_U32 = 0x01000000u +}; + +enum SceGxmIndexSource : u16 +{ + SCE_GXM_INDEX_SOURCE_INDEX_16BIT = 0x00000000u, + SCE_GXM_INDEX_SOURCE_INDEX_32BIT = 0x00000001u, + SCE_GXM_INDEX_SOURCE_INSTANCE_16BIT = 0x00000002u, + SCE_GXM_INDEX_SOURCE_INSTANCE_32BIT = 0x00000003u +}; + +enum SceGxmFragmentProgramMode : u32 +{ + SCE_GXM_FRAGMENT_PROGRAM_DISABLED = 0x00200000u, + SCE_GXM_FRAGMENT_PROGRAM_ENABLED = 0x00000000u +}; + +enum SceGxmDepthWriteMode : u32 +{ + SCE_GXM_DEPTH_WRITE_DISABLED = 0x00100000u, + SCE_GXM_DEPTH_WRITE_ENABLED = 0x00000000u +}; + +enum SceGxmLineFillLastPixelMode : u32 +{ + SCE_GXM_LINE_FILL_LAST_PIXEL_DISABLED = 0x00000000u, + SCE_GXM_LINE_FILL_LAST_PIXEL_ENABLED = 0x00080000u +}; + +enum SceGxmTwoSidedMode : u32 +{ + SCE_GXM_TWO_SIDED_DISABLED = 0x00000000u, + SCE_GXM_TWO_SIDED_ENABLED = 0x00000800u +}; + +enum SceGxmWClampMode : u32 +{ + SCE_GXM_WCLAMP_MODE_DISABLED = 0x00000000u, + SCE_GXM_WCLAMP_MODE_ENABLED = 0x00008000u +}; + +enum SceGxmViewportMode : u32 +{ + SCE_GXM_VIEWPORT_DISABLED = 0x00010000u, + SCE_GXM_VIEWPORT_ENABLED = 0x00000000u +}; + +enum SceGxmWBufferMode : u32 +{ + SCE_GXM_WBUFFER_DISABLED = 0x00000000u, + SCE_GXM_WBUFFER_ENABLED = 0x00004000u +}; + +enum SceGxmDepthStencilForceLoadMode : u32 +{ + SCE_GXM_DEPTH_STENCIL_FORCE_LOAD_DISABLED = 0x00000000u, + SCE_GXM_DEPTH_STENCIL_FORCE_LOAD_ENABLED = 0x00000002u +}; + +enum SceGxmDepthStencilForceStoreMode : u32 +{ + SCE_GXM_DEPTH_STENCIL_FORCE_STORE_DISABLED = 0x00000000u, + SCE_GXM_DEPTH_STENCIL_FORCE_STORE_ENABLED = 0x00000004u +}; + +enum SceGxmSceneFlags : u32 +{ + SCE_GXM_SCENE_FRAGMENT_SET_DEPENDENCY = 0x00000001u, + SCE_GXM_SCENE_VERTEX_WAIT_FOR_DEPENDENCY = 0x00000002u +}; + +enum SceGxmMidSceneFlags : u32 +{ + SCE_GXM_MIDSCENE_PRESERVE_DEFAULT_UNIFORM_BUFFERS = 0x00000001u +}; + +enum SceGxmColorSurfaceScaleMode : u32 +{ + SCE_GXM_COLOR_SURFACE_SCALE_NONE = 0x00000000u, + SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE = 0x00000001u +}; + +enum SceGxmOutputRegisterSize : u32 +{ + SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT = 0x00000000u, + SCE_GXM_OUTPUT_REGISTER_SIZE_64BIT = 0x00000001u +}; + +enum SceGxmVisibilityTestMode : u32 +{ + SCE_GXM_VISIBILITY_TEST_DISABLED = 0x00000000u, + SCE_GXM_VISIBILITY_TEST_ENABLED = 0x00004000u +}; + +enum SceGxmVisibilityTestOp : u32 +{ + SCE_GXM_VISIBILITY_TEST_OP_INCREMENT = 0x00000000u, + SCE_GXM_VISIBILITY_TEST_OP_SET = 0x00040000u +}; + +enum SceGxmBlendFunc : u8 +{ + SCE_GXM_BLEND_FUNC_NONE, + SCE_GXM_BLEND_FUNC_ADD, + SCE_GXM_BLEND_FUNC_SUBTRACT, + SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT +}; + +enum SceGxmBlendFactor : u8 +{ + SCE_GXM_BLEND_FACTOR_ZERO, + SCE_GXM_BLEND_FACTOR_ONE, + SCE_GXM_BLEND_FACTOR_SRC_COLOR, + SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + SCE_GXM_BLEND_FACTOR_SRC_ALPHA, + SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + SCE_GXM_BLEND_FACTOR_DST_COLOR, + SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR, + SCE_GXM_BLEND_FACTOR_DST_ALPHA, + SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, + SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE, + SCE_GXM_BLEND_FACTOR_DST_ALPHA_SATURATE +}; + +enum SceGxmColorMask : u8 +{ + SCE_GXM_COLOR_MASK_NONE = 0, + SCE_GXM_COLOR_MASK_A = (1 << 0), + SCE_GXM_COLOR_MASK_R = (1 << 1), + SCE_GXM_COLOR_MASK_G = (1 << 2), + SCE_GXM_COLOR_MASK_B = (1 << 3), + SCE_GXM_COLOR_MASK_ALL = (SCE_GXM_COLOR_MASK_A | SCE_GXM_COLOR_MASK_B | SCE_GXM_COLOR_MASK_G | SCE_GXM_COLOR_MASK_R) +}; + +struct SceGxmBlendInfo +{ + SceGxmColorMask colorMask; + SceGxmBlendFunc colorFunc : 4; + SceGxmBlendFunc alphaFunc : 4; + SceGxmBlendFactor colorSrc : 4; + SceGxmBlendFactor colorDst : 4; + SceGxmBlendFactor alphaSrc : 4; + SceGxmBlendFactor alphaDst : 4; +}; + +struct SceGxmRenderTarget; + +struct SceGxmSyncObject; + +struct SceGxmVertexAttribute +{ + u16 streamIndex; + u16 offset; + SceGxmAttributeFormat format; + u8 componentCount; + u16 regIndex; +}; + +struct SceGxmVertexStream +{ + u16 stride; + u16 indexSource; +}; + +struct SceGxmTexture +{ + u32 controlWords[4]; +}; + +struct SceGxmColorSurface +{ + u32 pbeSidebandWord; + u32 pbeEmitWords[6]; + u32 outputRegisterSize; + SceGxmTexture backgroundTex; +}; + +struct SceGxmDepthStencilSurface +{ + u32 zlsControl; + vm::psv::ptr depthData; + vm::psv::ptr stencilData; + float backgroundDepth; + u32 backgroundControl; +}; + +struct SceGxmAuxiliarySurface +{ + SceGxmColorFormat colorFormat; + SceGxmColorSurfaceType type; + u32 width; + u32 height; + u32 stride; + vm::psv::ptr data; +}; + +struct SceGxmNotification +{ + vm::psv::ptr address; + u32 value; +}; + +struct SceGxmValidRegion +{ + u32 xMin; + u32 yMin; + u32 xMax; + u32 yMax; +}; + +struct SceGxmContext; + +enum +{ + SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE = 2048, + SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE = (128 * 1024), + SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE = (2 * 1024 * 1024), + SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE = (512 * 1024), + SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE = (16 * 1024), +}; + +struct SceGxmContextParams +{ + vm::psv::ptr hostMem; + u32 hostMemSize; + vm::psv::ptr vdmRingBufferMem; + u32 vdmRingBufferMemSize; + vm::psv::ptr vertexRingBufferMem; + u32 vertexRingBufferMemSize; + vm::psv::ptr fragmentRingBufferMem; + u32 fragmentRingBufferMemSize; + vm::psv::ptr fragmentUsseRingBufferMem; + u32 fragmentUsseRingBufferMemSize; + u32 fragmentUsseRingBufferOffset; +}; + +struct SceGxmVertexProgram; + +struct SceGxmFragmentProgram; + +enum +{ + SCE_GXM_PRECOMPUTED_VERTEX_STATE_WORD_COUNT = 7, + SCE_GXM_PRECOMPUTED_FRAGMENT_STATE_WORD_COUNT = 9, + SCE_GXM_PRECOMPUTED_DRAW_WORD_COUNT = 11, +}; + +struct SceGxmPrecomputedVertexState +{ + u32 data[SCE_GXM_PRECOMPUTED_VERTEX_STATE_WORD_COUNT]; +}; + +struct SceGxmPrecomputedFragmentState +{ + u32 data[SCE_GXM_PRECOMPUTED_FRAGMENT_STATE_WORD_COUNT]; +}; + +struct SceGxmPrecomputedDraw +{ + u32 data[SCE_GXM_PRECOMPUTED_DRAW_WORD_COUNT]; +}; + +enum : u32 +{ + SCE_GXM_MAX_VERTEX_ATTRIBUTES = 16, + SCE_GXM_MAX_VERTEX_STREAMS = 4, + SCE_GXM_MAX_TEXTURE_UNITS = 16, + SCE_GXM_MAX_UNIFORM_BUFFERS = 8, + SCE_GXM_MAX_AUXILIARY_SURFACES = 3, +}; + +struct SceGxmProgram; + +struct SceGxmProgramParameter; + +enum SceGxmProgramType : s32 +{ + SCE_GXM_VERTEX_PROGRAM, + SCE_GXM_FRAGMENT_PROGRAM +}; + +enum SceGxmParameterCategory : s32 +{ + SCE_GXM_PARAMETER_CATEGORY_ATTRIBUTE, + SCE_GXM_PARAMETER_CATEGORY_UNIFORM, + SCE_GXM_PARAMETER_CATEGORY_SAMPLER, + SCE_GXM_PARAMETER_CATEGORY_AUXILIARY_SURFACE, + SCE_GXM_PARAMETER_CATEGORY_UNIFORM_BUFFER +}; + +enum SceGxmParameterType : s32 +{ + SCE_GXM_PARAMETER_TYPE_F32, + SCE_GXM_PARAMETER_TYPE_F16, + SCE_GXM_PARAMETER_TYPE_C10, + SCE_GXM_PARAMETER_TYPE_U32, + SCE_GXM_PARAMETER_TYPE_S32, + SCE_GXM_PARAMETER_TYPE_U16, + SCE_GXM_PARAMETER_TYPE_S16, + SCE_GXM_PARAMETER_TYPE_U8, + SCE_GXM_PARAMETER_TYPE_S8, + SCE_GXM_PARAMETER_TYPE_AGGREGATE +}; + +enum SceGxmParameterSemantic : s32 +{ + SCE_GXM_PARAMETER_SEMANTIC_NONE, + SCE_GXM_PARAMETER_SEMANTIC_ATTR, + SCE_GXM_PARAMETER_SEMANTIC_BCOL, + SCE_GXM_PARAMETER_SEMANTIC_BINORMAL, + SCE_GXM_PARAMETER_SEMANTIC_BLENDINDICES, + SCE_GXM_PARAMETER_SEMANTIC_BLENDWEIGHT, + SCE_GXM_PARAMETER_SEMANTIC_COLOR, + SCE_GXM_PARAMETER_SEMANTIC_DIFFUSE, + SCE_GXM_PARAMETER_SEMANTIC_FOGCOORD, + SCE_GXM_PARAMETER_SEMANTIC_NORMAL, + SCE_GXM_PARAMETER_SEMANTIC_POINTSIZE, + SCE_GXM_PARAMETER_SEMANTIC_POSITION, + SCE_GXM_PARAMETER_SEMANTIC_SPECULAR, + SCE_GXM_PARAMETER_SEMANTIC_TANGENT, + SCE_GXM_PARAMETER_SEMANTIC_TEXCOORD +}; + +struct SceGxmShaderPatcher; + +struct SceGxmRegisteredProgram; + +typedef vm::psv::ptr SceGxmShaderPatcherId; + +typedef vm::psv::ptr(SceGxmShaderPatcherHostAllocCallback)(vm::psv::ptr userData, u32 size); +typedef void(SceGxmShaderPatcherHostFreeCallback)(vm::psv::ptr userData, vm::psv::ptr mem); +typedef vm::psv::ptr(SceGxmShaderPatcherBufferAllocCallback)(vm::psv::ptr userData, u32 size); +typedef void(SceGxmShaderPatcherBufferFreeCallback)(vm::psv::ptr userData, vm::psv::ptr mem); +typedef vm::psv::ptr(SceGxmShaderPatcherUsseAllocCallback)(vm::psv::ptr userData, u32 size, vm::psv::ptr usseOffset); +typedef void(SceGxmShaderPatcherUsseFreeCallback)(vm::psv::ptr userData, vm::psv::ptr mem); + +struct SceGxmShaderPatcherParams +{ + vm::psv::ptr userData; + vm::psv::ptr hostAllocCallback; + vm::psv::ptr hostFreeCallback; + vm::psv::ptr bufferAllocCallback; + vm::psv::ptr bufferFreeCallback; + vm::psv::ptr bufferMem; + u32 bufferMemSize; + vm::psv::ptr vertexUsseAllocCallback; + vm::psv::ptr vertexUsseFreeCallback; + vm::psv::ptr vertexUsseMem; + u32 vertexUsseMemSize; + u32 vertexUsseOffset; + vm::psv::ptr fragmentUsseAllocCallback; + vm::psv::ptr fragmentUsseFreeCallback; + vm::psv::ptr fragmentUsseMem; + u32 fragmentUsseMemSize; + u32 fragmentUsseOffset; +}; + +enum SceGxmRenderTargetFlags : u32 +{ + SCE_GXM_RENDER_TARGET_CUSTOM_MULTISAMPLE_LOCATIONS = 1 << 0, +}; + +struct SceGxmRenderTargetParams +{ + SceGxmRenderTargetFlags flags; + u16 width; + u16 height; + u16 scenesPerFrame; + SceGxmMultisampleMode multisampleMode; + u32 multisampleLocations; + vm::psv::ptr hostMem; + u32 hostMemSize; + s32 driverMemBlock; +}; + +extern psv_log_base sceGxm; diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index b011da905b..4ca94b42a6 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -51,6 +51,9 @@ extern psv_log_base sceLibKernel; extern psv_log_base sceSysmodule; extern psv_log_base scePerf; extern psv_log_base sceCtrl; +extern psv_log_base sceDeci4p; +extern psv_log_base sceDisplay; +extern psv_log_base sceGxm; void initialize_psv_modules() { @@ -64,6 +67,9 @@ void initialize_psv_modules() g_psv_modules.push_back(&sceSysmodule); g_psv_modules.push_back(&scePerf); g_psv_modules.push_back(&sceCtrl); + g_psv_modules.push_back(&sceDeci4p); + g_psv_modules.push_back(&sceDisplay); + g_psv_modules.push_back(&sceGxm); // setup special functions (without NIDs) psv_func unimplemented; From a7728c9067165c23d0e70000a72fefc11a84612a Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Wed, 28 Jan 2015 23:48:06 +0530 Subject: [PATCH 32/94] SPURS: Document some parts of taskset policy module --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 40 +++++++++--- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 68 ++++++++++++++++++--- 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 99d2d35eea..c9795203f8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2821,7 +2821,7 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: } taskset->m.task_info[tmp_task_id].elf_addr.set(elf_addr.addr()); - taskset->m.task_info[tmp_task_id].context_save_storage.set((context_addr.addr() & 0xFFFFFFF8) | alloc_ls_blocks); + taskset->m.task_info[tmp_task_id].context_save_storage_and_alloc_ls_blocks = (context_addr.addr() | alloc_ls_blocks); for (u32 i = 0; i < 2; i++) { taskset->m.task_info[tmp_task_id].args.u64[i] = arg != 0 ? arg->u64[i] : 0; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 196fedd3a8..4ccf224ec7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -181,6 +181,12 @@ enum SpursTraceConstants CELL_SPURS_TRACE_SERVICE_WAIT = 0x02, CELL_SPURS_TRACE_SERVICE_EXIT = 0x03, + // Task incident + CELL_SPURS_TRACE_TASK_DISPATCH = 0x01, + CELL_SPURS_TRACE_TASK_YIELD = 0x03, + CELL_SPURS_TRACE_TASK_WAIT = 0x04, + CELL_SPURS_TRACE_TASK_EXIT = 0x05, + // Trace mode flags CELL_SPURS_TRACE_MODE_FLAG_WRAP_BUFFER = 0x1, CELL_SPURS_TRACE_MODE_FLAG_SYNCHRONOUS_START_STOP = 0x2, @@ -335,6 +341,12 @@ struct CellSpursTracePacket be_t ls; } start; + struct + { + be_t incident; + be_t taskId; + } task; + be_t user; be_t guid; be_t stop; @@ -607,7 +619,7 @@ struct CellSpursTaskset { CellSpursTaskArgument args; vm::bptr elf_addr; - vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) + be_t context_save_storage_and_alloc_ls_blocks; // This is (context_save_storage_addr | allocated_ls_blocks) CellSpursTaskLsPattern ls_pattern; }; @@ -716,7 +728,7 @@ struct CellSpursTaskset2 { CellSpursTaskArgument args; vm::bptr elf_addr; - vm::bptr context_save_storage; // This is ((context_save_storage_addr & 0xFFFFFFF8) | allocated_ls_blocks) + vm::bptr context_save_storage; // This is (context_save_storage_addr | allocated_ls_blocks) CellSpursTaskLsPattern ls_pattern; }; @@ -885,10 +897,11 @@ static_assert(sizeof(SpursKernelMgmtData) == 0x130, "Incorrect size for SpursKer // The SPURS taskset policy module data store. This resides at 0x2700 of the LS. struct SpursTasksetPmMgmtData { - u8 tempArea[0x80]; // 0x2700 - u8 x2780[0x27B8 - 0x2780]; // 0x2780 + u8 tempAreaTaskset[0x80]; // 0x2700 + u8 tempAreaTaskInfo[0x30]; // 0x2780 + be_t x27B0; // 0x27B0 vm::bptr taskset; // 0x27B8 - be_t kernelMgmt; // 0x27C0 + be_t kernelMgmtAddr; // 0x27C0 be_t yieldAddr; // 0x27C4 be_t x27C8; // 0x27C8 be_t spuNum; // 0x27CC @@ -896,9 +909,20 @@ struct SpursTasksetPmMgmtData be_t taskId; // 0x27D4 u8 x27D8[0x2840 - 0x27D8]; // 0x27D8 u8 moduleId[16]; // 0x2840 - u8 x2850[0x2C80 - 0x2850]; // 0x2850 - be_t contextSaveArea[50]; // 0x2C80 - u8 x2FA0[0x3000 - 0x2FA0]; // 0x2FA0 + u8 stackArea[0x2C80 - 0x2850]; // 0x2850 + be_t savedContextLr; // 0x2C80 + be_t savedContextSp; // 0x2C90 + be_t savedContextR80ToR127[48]; // 0x2CA0 + be_t savedContextFpscr; // 0x2FA0 + be_t savedWriteTagGroupQueryMask; // 0x2FB0 + be_t savedSpuWriteEventMask; // 0x2FB4 + be_t tasksetMgmtAddr; // 0x2FB8 + be_t lowestLoadSegmentAddr; // 0x2FBC + be_t x2FC0; // 0x2FC0 + be_t x2FC8; // 0x2FC8 + be_t x2FD0; // 0x2FD0 + be_t taskExitCode; // 0x2FD4 + u8 x2FD8[0x3000 - 0x2FD8]; // 0x2FD8 }; static_assert(sizeof(SpursTasksetPmMgmtData) == 0x900, "Incorrect size for SpursTasksetPmMgmtData"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 624be7e805..e4ebca84a5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -865,7 +865,57 @@ bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 return false; } -void spursTasksetDispatch() { +void spursTasksetDispatch(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); + + u32 taskId; + u32 isWaiting; + spursTasksetProcessRequest(spu, 5, &taskId, &isWaiting); + if (taskId >= CELL_SPURS_MAX_TASK) { + // TODO: spursTasksetExit(spu); + } + + mgmt->taskId = taskId; + u64 elfAddr = mgmt->taskset->m.task_info[taskId].elf_addr.addr() & 0xFFFFFFFFFFFFFFF8ull; + + // Trace - Task: Incident=dispatch + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; + pkt.data.task.incident = CELL_SPURS_TRACE_TASK_DISPATCH; + pkt.data.task.taskId = taskId; + cellSpursModulePutTrace(&pkt, 0x1F); + + if (isWaiting == 0) { + } + + if (mgmt->taskset->m.enable_clear_ls) { + memset(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); + } + + // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area + if (mgmt->taskset->m.task_info[taskId].ls_pattern.u64[0] != 0xFFFFFFFFFFFFFFFFull || + (mgmt->taskset->m.task_info[taskId].ls_pattern.u64[0] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { + // Load the ELF + // TODO: Load ELF + } + + // Load save context from main memory to LS + u64 context_save_storage = mgmt->taskset->m.task_info[taskId].context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; + for (auto i = 6; i < 128; i++) { + bool shouldLoad = mgmt->taskset->m.task_info[taskId].ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; + if (shouldLoad) { + memcpy(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), + vm::get_ptr((u32)context_save_storage + 0x400 + ((i - 6) << 11)), 0x800); + } + } + + // Trace - GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; + pkt.data.guid = 0; // TODO: Put GUID of taskId here + cellSpursModulePutTrace(&pkt, 0x1F); } void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { @@ -917,20 +967,20 @@ void spursTasksetEntry(SPUThread & spu) { memset(mgmt, 0, sizeof(*mgmt)); mgmt->taskset.set(arg); memcpy(mgmt->moduleId, "SPURSTASK MODULE", 16); - mgmt->kernelMgmt = spu.GPR[3]._u32[3]; - mgmt->yieldAddr = 0xA70; - mgmt->spuNum = kernelMgmt->spuNum; - mgmt->dmaTagId = kernelMgmt->dmaTagId; - mgmt->taskId = 0xFFFFFFFF; + mgmt->kernelMgmtAddr = spu.GPR[3]._u32[3]; + mgmt->yieldAddr = 0xA70; + mgmt->spuNum = kernelMgmt->spuNum; + mgmt->dmaTagId = kernelMgmt->dmaTagId; + mgmt->taskId = 0xFFFFFFFF; spursTasksetInit(spu, pollStatus); // TODO: Dispatch } - mgmt->contextSaveArea[0] = spu.GPR[0]; - mgmt->contextSaveArea[1] = spu.GPR[1]; + mgmt->savedContextLr = spu.GPR[0]; + mgmt->savedContextSp = spu.GPR[1]; for (auto i = 0; i < 48; i++) { - mgmt->contextSaveArea[i + 2] = spu.GPR[80 + i]; + mgmt->savedContextR80ToR127[i] = spu.GPR[80 + i]; } // TODO: Process syscall From 62e2d8d9a7b8aaa110673862b80733b4e93b42c7 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Thu, 29 Jan 2015 20:20:34 +0530 Subject: [PATCH 33/94] SPURS: Update kernel to use lock line reservations --- rpcs3/Emu/Cell/MFC.h | 8 + rpcs3/Emu/Cell/SPUThread.cpp | 9 +- rpcs3/Emu/Cell/SPUThread.h | 31 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 19 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 19 +- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 623 +++++++++++--------- rpcs3/stdafx.h | 2 + 7 files changed, 414 insertions(+), 297 deletions(-) diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index a6c731d3da..0b669deb97 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -35,6 +35,14 @@ enum MFC_GETLLAR_SUCCESS = 4, }; +// MFC Write Tag Status Update Request Channel (ch23) operations +enum +{ + MFC_TAG_UPDATE_IMMEDIATE = 0, + MFC_TAG_UPDATE_ANY = 1, + MFC_TAG_UPDATE_ALL = 2, +}; + enum { MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF, diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 95f678bf02..fcb9b012e9 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1060,7 +1060,14 @@ void SPUThread::StopAndSignal(u32 code) case 0x003: { - m_code3_func(*this); + auto iter = m_addr_to_hle_function_map.find(PC); + assert(iter != m_addr_to_hle_function_map.end()); + + auto return_to_caller = iter->second(*this); + if (return_to_caller) + { + SetBranch(GPR[0]._u32[3] & 0x3fffc); + } break; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index f880e5ca6e..d6ecbe64b0 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -290,6 +290,8 @@ public: u32 m_event_mask; u32 m_events; + std::unordered_map> m_addr_to_hle_function_map; + struct IntrTag { u32 enabled; // 1 == true @@ -509,8 +511,35 @@ public: void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); } void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); } + void RegisterHleFuncion(u32 addr, std::function function) + { + m_addr_to_hle_function_map[addr] = function; + WriteLS32(addr, 0x00000003); // STOP 3 + } + + void UnregisterHleFunction(u32 addr) + { + WriteLS32(addr, 0x00200000); // NOP + m_addr_to_hle_function_map.erase(addr); + } + + void UnregisterHleFunctions(u32 start_addr, u32 end_addr) + { + for (auto iter = m_addr_to_hle_function_map.begin(); iter != m_addr_to_hle_function_map.end();) + { + if (iter->first >= start_addr && iter->first <= end_addr) + { + WriteLS32(iter->first, 0x00200000); // NOP + m_addr_to_hle_function_map.erase(iter++); + } + else + { + iter++; + } + } + } + std::function m_custom_task; - std::function m_code3_func; public: SPUThread(CPUThreadType type = CPU_THREAD_SPU); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index c9795203f8..62349f276d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -26,7 +26,7 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif -void spursKernelMain(SPUThread & spu); +bool spursKernelMain(SPUThread & spu); s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id); s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID); @@ -155,7 +155,8 @@ s64 spursInit( assert(!"spu_image_import() failed"); } #else - spurs->m.spuImg.addr = (u32)Memory.Alloc(0x40000, 4096); + spurs->m.spuImg.addr = (u32)Memory.Alloc(0x40000, 4096); + spurs->m.spuImg.entry_point = isSecond ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR; #endif s32 tgt = SYS_SPU_THREAD_GROUP_TYPE_NORMAL; @@ -179,17 +180,11 @@ s64 spursInit( name += "CellSpursKernel0"; for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) { - spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num](SPUThread& SPU) - { - SPU.GPR[3]._u32[3] = num; - SPU.GPR[4]._u64[1] = spurs.addr(); - -#ifdef PRX_DEBUG_XXX - return SPU.FastCall(SPU.PC); + auto spu = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, num, spurs.addr(), 0, 0); +#ifndef PRX_DEBUG_XXX + spu->RegisterHleFuncion(spurs->m.spuImg.entry_point, spursKernelMain); #endif - - spursKernelMain(SPU); - })->GetId(); + spurs->m.spus[num] = spu->GetId(); } if (flags & SAF_SPU_PRINTF_ENABLED) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 4ccf224ec7..4d77a06402 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -102,6 +102,12 @@ enum SPURSKernelInterfaces CELL_SPURS_INTERRUPT_VECTOR = 0x0, CELL_SPURS_LOCK_LINE = 0x80, CELL_SPURS_KERNEL_DMA_TAG_ID = 31, + CELL_SPURS_KERNEL1_ENTRY_ADDR = 0x818, + CELL_SPURS_KERNEL2_ENTRY_ADDR = 0x848, + CELL_SPURS_KERNEL1_YIELD_ADDR = 0x808, + CELL_SPURS_KERNEL2_YIELD_ADDR = 0x838, + CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR = 0x290, + CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR = 0x290, }; enum RangeofEventQueuePortNumbers @@ -885,14 +891,23 @@ struct SpursKernelMgmtData u8 spuIdling; // 0x1EB be_t wklRunnable1; // 0x1EC be_t wklRunnable2; // 0x1EE - u8 x1F0[0x210 - 0x1F0]; // 0x1F0 + be_t x1F0; // 0x1F0 + be_t x1F4; // 0x1F4 + be_t x1F8; // 0x1F8 + be_t x1FC; // 0x1FC + be_t x200; // 0x200 + be_t x204; // 0x204 + be_t x208; // 0x208 + be_t x20C; // 0x20C be_t traceBuffer; // 0x210 be_t traceMsgCount; // 0x218 be_t traceMaxCount; // 0x21C u8 wklUniqueId[0x10]; // 0x220 + u8 x230[0x280 - 0x230]; // 0x230 + be_t guid[4]; // 0x280 }; -static_assert(sizeof(SpursKernelMgmtData) == 0x130, "Incorrect size for SpursKernelMgmtData"); +static_assert(sizeof(SpursKernelMgmtData) == 0x190, "Incorrect size for SpursKernelMgmtData"); // The SPURS taskset policy module data store. This resides at 0x2700 of the LS. struct SpursTasksetPmMgmtData diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index e4ebca84a5..898638894c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -14,11 +14,15 @@ void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag); u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status); +bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag); +u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask); +u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll = true); + // // SPURS Kernel functions // -void spursKernelSelectWorkload(SPUThread & spu); -void spursKernelSelectWorkload2(SPUThread & spu); +bool spursKernel1SelectWorkload(SPUThread & spu); +bool spursKernel2SelectWorkload(SPUThread & spu); // // SPURS system service workload functions @@ -31,7 +35,7 @@ void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt); void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt); void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt); void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus); -void spursSysServiceWorkloadEntry(SPUThread & spu); +bool spursSysServiceWorkloadEntry(SPUThread & spu); // // SPURS taskset polict module functions @@ -54,9 +58,9 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { spu.GPR[3]._u32[3] = 1; if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { - spursKernelSelectWorkload2(spu); + spursKernel2SelectWorkload(spu); } else { - spursKernelSelectWorkload(spu); + spursKernel1SelectWorkload(spu); } auto result = spu.GPR[3]._u64[1]; @@ -68,14 +72,51 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { return wklId == mgmt->wklCurrentId ? 0 : 1; } +/// Execute a DMA operation +bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag) { + spu.WriteChannel(MFC_LSA, u128::from32r(lsa)); + spu.WriteChannel(MFC_EAH, u128::from32r((u32)(ea >> 32))); + spu.WriteChannel(MFC_EAL, u128::from32r((u32)ea)); + spu.WriteChannel(MFC_Size, u128::from32r(size)); + spu.WriteChannel(MFC_TagID, u128::from32r(tag)); + spu.WriteChannel(MFC_Cmd, u128::from32r(cmd)); + + if (cmd == MFC_GETLLAR_CMD || cmd == MFC_PUTLLC_CMD || cmd == MFC_PUTLLUC_CMD) { + u128 rv; + + spu.ReadChannel(rv, MFC_RdAtomicStat); + return rv._u32[3] ? true : false; + } + + return true; +} + +/// Get the status of DMA operations +u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask) { + u128 rv; + + spu.WriteChannel(MFC_WrTagMask, u128::from32r(tagMask)); + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(MFC_TAG_UPDATE_IMMEDIATE)); + spu.ReadChannel(rv, MFC_RdTagStat); + return rv._u32[3]; +} + +/// Wait for DMA operations to complete +u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll) { + u128 rv; + + spu.WriteChannel(MFC_WrTagMask, u128::from32r(tagMask)); + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(waitForAll ? MFC_TAG_UPDATE_ALL : MFC_TAG_UPDATE_ANY)); + spu.ReadChannel(rv, MFC_RdTagStat); + return rv._u32[3]; +} + ////////////////////////////////////////////////////////////////////////////// // SPURS kernel functions ////////////////////////////////////////////////////////////////////////////// /// Select a workload to run -void spursKernelSelectWorkload(SPUThread & spu) { - LV2_LOCK(0); // TODO: lock-free implementation if possible - +bool spursKernel1SelectWorkload(SPUThread & spu) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); // The first and only argument to this function is a boolean that is set to false if the function @@ -83,140 +124,148 @@ void spursKernelSelectWorkload(SPUThread & spu) { // If the first argument is true then the shared data is not updated with the result. const auto isPoll = spu.GPR[3]._u32[3]; - // Calculate the contention (number of SPUs used) for each workload - u8 contention[CELL_SPURS_MAX_WORKLOAD]; - u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - contention[i] = mgmt->spurs->m.wklCurrentContention[i] - mgmt->wklLocContention[i]; + u32 wklSelectedId; + u32 pollStatus; - // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably - // to prevent unnecessary jumps to the kernel - if (isPoll) { - pendingContention[i] = mgmt->spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; - if (i != mgmt->wklCurrentId) { - contention[i] += pendingContention[i]; - } - } - } + do { + // DMA and lock the first 0x80 bytes of spurs + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + CellSpurs * spurs = (CellSpurs *)mgmt->tempArea; - u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - u32 pollStatus = 0; - - // The system service workload has the highest priority. Select the system service workload if - // the system service message bit for this SPU is set. - if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - mgmt->spuIdling = 0; - if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - // Clear the message bit - mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); - } - } else { - // Caclulate the scheduling weight for each workload - u16 maxWeight = 0; + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u16 runnable = mgmt->wklRunnable1 & (0x8000 >> i); - u16 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); - u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); - u8 idleSpuCount = mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); - u8 requestCount = readyCount + idleSpuCount; + contention[i] = spurs->m.wklCurrentContention[i] - mgmt->wklLocContention[i]; - // For a workload to be considered for scheduling: - // 1. Its priority must not be 0 - // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The workload should be in runnable state - // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // OR the workload must be signalled - // OR the workload flag is 0 and the workload is configured as the wokload flag receiver - if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) { - if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { - // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: - // 1. Wokload signal set or workload flag or ready count > contention - // 2. Priority of the workload on the SPU - // 3. Is the workload the last selected workload - // 4. Minimum contention of the workload - // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) - // 6. Is the workload executable same as the currently loaded executable - // 7. The workload id (lesser the number, more the weight) - u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; - weight |= (u16)(mgmt->priority[i] & 0x7F) << 16; - weight |= i == mgmt->wklCurrentId ? 0x80 : 0x00; - weight |= (contention[i] > 0 && mgmt->spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00; - weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; - weight |= mgmt->wklUniqueId[i] == mgmt->wklCurrentId ? 0x02 : 0x00; - weight |= 0x01; - - // In case of a tie the lower numbered workload is chosen - if (weight > maxWeight) { - wklSelectedId = i; - maxWeight = weight; - pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; - pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; - pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; - } + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) { + pendingContention[i] = spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; + if (i != mgmt->wklCurrentId) { + contention[i] += pendingContention[i]; } } } - // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + pollStatus = 0; - if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { - // Clear workload signal for the selected workload - mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); - mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + // The system service workload has the highest priority. Select the system service workload if + // the system service message bit for this SPU is set. + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + mgmt->spuIdling = 0; + if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + // Clear the message bit + spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + } + } else { + // Caclulate the scheduling weight for each workload + u16 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + u16 runnable = mgmt->wklRunnable1 & (0x8000 >> i); + u16 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed(); + u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); + u8 requestCount = readyCount + idleSpuCount; - // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s - if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) { - mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + // For a workload to be considered for scheduling: + // 1. Its priority must not be 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The workload should be in runnable state + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload flag receiver + if (runnable && mgmt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { + // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: + // 1. Wokload signal set or workload flag or ready count > contention + // 2. Priority of the workload on the SPU + // 3. Is the workload the last selected workload + // 4. Minimum contention of the workload + // 5. Number of SPUs that are being used by the workload (lesser the number, more the weight) + // 6. Is the workload executable same as the currently loaded executable + // 7. The workload id (lesser the number, more the weight) + u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; + weight |= (u16)(mgmt->priority[i] & 0x7F) << 16; + weight |= i == mgmt->wklCurrentId ? 0x80 : 0x00; + weight |= (contention[i] > 0 && spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00; + weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; + weight |= mgmt->wklUniqueId[i] == mgmt->wklCurrentId ? 0x02 : 0x00; + weight |= 0x01; + + // In case of a tie the lower numbered workload is chosen + if (weight > maxWeight) { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { + // Clear workload signal for the selected workload + spurs->m.wklSignal1.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); + spurs->m.wklSignal2.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == spurs->m.wklFlagReceiver.read_relaxed()) { + spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + } } } - } - if (!isPoll) { - // Called by kernel - // Increment the contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - contention[wklSelectedId]++; - } + if (!isPoll) { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + contention[wklSelectedId]++; + } - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - mgmt->spurs->m.wklCurrentContention[i] = contention[i]; - mgmt->wklLocContention[i] = 0; - mgmt->wklLocPendingContention[i] = 0; - } + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + spurs->m.wklCurrentContention[i] = contention[i]; + mgmt->wklLocContention[i] = 0; + mgmt->wklLocPendingContention[i] = 0; + } - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - mgmt->wklLocContention[wklSelectedId] = 1; - } + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + mgmt->wklLocContention[wklSelectedId] = 1; + } - mgmt->wklCurrentId = wklSelectedId; - } else if (wklSelectedId != mgmt->wklCurrentId) { - // Not called by kernel but a context switch is required - // Increment the pending contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - pendingContention[wklSelectedId]++; - } + mgmt->wklCurrentId = wklSelectedId; + } else if (wklSelectedId != mgmt->wklCurrentId) { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + pendingContention[wklSelectedId]++; + } - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - mgmt->spurs->m.wklPendingContention[i] = pendingContention[i]; - mgmt->wklLocPendingContention[i] = 0; - } + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + spurs->m.wklPendingContention[i] = pendingContention[i]; + mgmt->wklLocPendingContention[i] = 0; + } - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - mgmt->wklLocPendingContention[wklSelectedId] = 1; + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + mgmt->wklLocPendingContention[wklSelectedId] = 1; + } } - } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); u64 result = (u64)wklSelectedId << 32; result |= pollStatus; spu.GPR[3]._u64[1] = result; + return true; } /// Select a workload to run -void spursKernelSelectWorkload2(SPUThread & spu) { - LV2_LOCK(0); // TODO: lock-free implementation if possible - +bool spursKernel2SelectWorkload(SPUThread & spu) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); // The first and only argument to this function is a boolean that is set to false if the function @@ -224,202 +273,214 @@ void spursKernelSelectWorkload2(SPUThread & spu) { // If the first argument is true then the shared data is not updated with the result. const auto isPoll = spu.GPR[3]._u32[3]; - // Calculate the contention (number of SPUs used) for each workload - u8 contention[CELL_SPURS_MAX_WORKLOAD2]; - u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; - for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - contention[i] = mgmt->spurs->m.wklCurrentContention[i & 0x0F] - mgmt->wklLocContention[i & 0x0F]; - contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; + u32 wklSelectedId; + u32 pollStatus; - // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably - // to prevent unnecessary jumps to the kernel - if (isPoll) { - pendingContention[i] = mgmt->spurs->m.wklPendingContention[i & 0x0F] - mgmt->wklLocPendingContention[i & 0x0F]; - pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; - if (i != mgmt->wklCurrentId) { - contention[i] += pendingContention[i]; - } - } - } + do { + // DMA and lock the first 0x80 bytes of spurs + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + CellSpurs * spurs = (CellSpurs *)mgmt->tempArea; - u32 wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - u32 pollStatus = 0; - - // The system service workload has the highest priority. Select the system service workload if - // the system service message bit for this SPU is set. - if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - // Not sure what this does. Possibly Mark the SPU as in use. - mgmt->spuIdling = 0; - if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - // Clear the message bit - mgmt->spurs->m.sysSrvMessage.write_relaxed(mgmt->spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); - } - } else { - // Caclulate the scheduling weight for each workload - u8 maxWeight = 0; + // Calculate the contention (number of SPUs used) for each workload + u8 contention[CELL_SPURS_MAX_WORKLOAD2]; + u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - auto j = i & 0x0F; - u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); - u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; - u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; - u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); - u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklReadyCount1[j].read_relaxed() : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); + contention[i] = spurs->m.wklCurrentContention[i & 0x0F] - mgmt->wklLocContention[i & 0x0F]; + contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; - // For a workload to be considered for scheduling: - // 1. Its priority must be greater than 0 - // 2. The number of SPUs used by it must be less than the max contention for that workload - // 3. The workload should be in runnable state - // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) - // OR the workload must be signalled - // OR the workload flag is 0 and the workload is configured as the wokload receiver - if (runnable && priority > 0 && maxContention > contention[i]) { - if (wklFlag || wklSignal || readyCount > contention[i]) { - // The scheduling weight of the workload is equal to the priority of the workload for the SPU. - // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. - // In case of a tie the lower numbered workload is chosen. - u8 weight = priority << 4; - if (mgmt->wklCurrentId == i) { - weight |= 0x04; - } - - if (weight > maxWeight) { - wklSelectedId = i; - maxWeight = weight; - pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; - pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; - pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; - } + // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably + // to prevent unnecessary jumps to the kernel + if (isPoll) { + pendingContention[i] = spurs->m.wklPendingContention[i & 0x0F] - mgmt->wklLocPendingContention[i & 0x0F]; + pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; + if (i != mgmt->wklCurrentId) { + contention[i] += pendingContention[i]; } } } - // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + pollStatus = 0; - if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { - // Clear workload signal for the selected workload - mgmt->spurs->m.wklSignal1.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); - mgmt->spurs->m.wklSignal2.write_relaxed(be_t::make(mgmt->spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + // The system service workload has the highest priority. Select the system service workload if + // the system service message bit for this SPU is set. + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + // Not sure what this does. Possibly Mark the SPU as in use. + mgmt->spuIdling = 0; + if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + // Clear the message bit + spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + } + } else { + // Caclulate the scheduling weight for each workload + u8 maxWeight = 0; + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { + auto j = i & 0x0F; + u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4; + u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); - // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s - if (wklSelectedId == mgmt->spurs->m.wklFlagReceiver.read_relaxed()) { - mgmt->spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + // For a workload to be considered for scheduling: + // 1. Its priority must be greater than 0 + // 2. The number of SPUs used by it must be less than the max contention for that workload + // 3. The workload should be in runnable state + // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) + // OR the workload must be signalled + // OR the workload flag is 0 and the workload is configured as the wokload receiver + if (runnable && priority > 0 && maxContention > contention[i]) { + if (wklFlag || wklSignal || readyCount > contention[i]) { + // The scheduling weight of the workload is equal to the priority of the workload for the SPU. + // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. + // In case of a tie the lower numbered workload is chosen. + u8 weight = priority << 4; + if (mgmt->wklCurrentId == i) { + weight |= 0x04; + } + + if (weight > maxWeight) { + wklSelectedId = i; + maxWeight = weight; + pollStatus = readyCount > contention[i] ? CELL_SPURS_MODULE_POLL_STATUS_READYCOUNT : 0; + pollStatus |= wklSignal ? CELL_SPURS_MODULE_POLL_STATUS_SIGNAL : 0; + pollStatus |= wklFlag ? CELL_SPURS_MODULE_POLL_STATUS_FLAG : 0; + } + } + } + } + + // Not sure what this does. Possibly mark the SPU as idle/in use. + mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + + if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { + // Clear workload signal for the selected workload + spurs->m.wklSignal1.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); + spurs->m.wklSignal2.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); + + // If the selected workload is the wklFlag workload then pull the wklFlag to all 1s + if (wklSelectedId == spurs->m.wklFlagReceiver.read_relaxed()) { + spurs->m.wklFlag.flag.write_relaxed(be_t::make(0xFFFFFFFF)); + } } } - } - if (!isPoll) { - // Called by kernel - // Increment the contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - contention[wklSelectedId]++; + if (!isPoll) { + // Called by kernel + // Increment the contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + contention[wklSelectedId]++; + } + + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { + spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); + mgmt->wklLocContention[i] = 0; + mgmt->wklLocPendingContention[i] = 0; + } + + mgmt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + mgmt->wklCurrentId = wklSelectedId; + } else if (wklSelectedId != mgmt->wklCurrentId) { + // Not called by kernel but a context switch is required + // Increment the pending contention for the selected workload + if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + pendingContention[wklSelectedId]++; + } + + for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { + spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); + mgmt->wklLocPendingContention[i] = 0; + } + + mgmt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; } - - for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { - mgmt->spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); - mgmt->wklLocContention[i] = 0; - mgmt->wklLocPendingContention[i] = 0; - } - - mgmt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - mgmt->wklCurrentId = wklSelectedId; - } else if (wklSelectedId != mgmt->wklCurrentId) { - // Not called by kernel but a context switch is required - // Increment the pending contention for the selected workload - if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - pendingContention[wklSelectedId]++; - } - - for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { - mgmt->spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); - mgmt->wklLocPendingContention[i] = 0; - } - - mgmt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); u64 result = (u64)wklSelectedId << 32; result |= pollStatus; spu.GPR[3]._u64[1] = result; + return true; } -/// Entry point of the SPURS kernel -void spursKernelMain(SPUThread & spu) { +/// SPURS kernel main +bool spursKernelMain(SPUThread & spu) { SpursKernelMgmtData * mgmt = vm::get_ptr(spu.ls_offset + 0x100); - mgmt->spuNum = spu.GPR[3]._u32[3]; - mgmt->dmaTagId = 0x1F; - mgmt->spurs.set(spu.GPR[4]._u64[1]); - mgmt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - mgmt->wklCurrentUniqueId = 0x20; - bool isSecond = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - mgmt->yieldToKernelAddr = isSecond ? 0x838 : 0x808; - mgmt->selectWorkloadAddr = 0x290; - spu.WriteLS32(mgmt->yieldToKernelAddr, 2); // hack for cellSpursModuleExit - spu.WriteLS32(mgmt->selectWorkloadAddr, 3); // hack for cellSpursModulePollStatus - spu.WriteLS32(mgmt->selectWorkloadAddr + 4, 0x35000000); // bi $0 - spu.m_code3_func = isSecond ? spursKernelSelectWorkload2 : spursKernelSelectWorkload; + bool isKernel2; + u32 pollStatus; + const CellSpurs::WorkloadInfo * wklInfo; + if (spu.PC == CELL_SPURS_KERNEL1_ENTRY_ADDR || spu.PC == CELL_SPURS_KERNEL2_ENTRY_ADDR) { + // Entry point of SPURS kernel + // Save arguments + mgmt->spuNum = spu.GPR[3]._u32[3]; + mgmt->spurs.set(spu.GPR[4]._u64[1]); - u32 wid = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - u32 pollStatus = 0; - while (true) { - if (Emu.IsStopped()) { - cellSpurs->Warning("Spurs Kernel aborted"); - return; - } + isKernel2 = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - // Get current workload info - auto & wkl = wid < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isSecond ? mgmt->spurs->m.wklInfo2[wid & 0xf] : mgmt->spurs->m.wklInfoSysSrv); + memset(mgmt, 0, sizeof(SpursKernelMgmtData)); - if (mgmt->wklCurrentAddr != wkl.addr) { - if (wkl.addr.addr() != SPURS_IMG_ADDR_SYS_SRV_WORKLOAD) { - // Load executable code - memcpy(vm::get_ptr(spu.ls_offset + 0xA00), wkl.addr.get_ptr(), wkl.size); - } - mgmt->wklCurrentAddr = wkl.addr; - mgmt->wklCurrentUniqueId = wkl.uniqueId.read_relaxed(); - } - - if (!isSecond) { - mgmt->moduleId[0] = 0; - mgmt->moduleId[1] = 0; - } - - // Run workload - spu.GPR[1]._u32[3] = 0x3FFB0; - spu.GPR[3]._u32[3] = 0x100; - spu.GPR[4]._u64[1] = wkl.arg; - spu.GPR[5]._u32[3] = pollStatus; - spu.SetPc(0xA00); - switch (mgmt->wklCurrentAddr.addr()) { - case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: - spursSysServiceWorkloadEntry(spu); - break; - default: - spu.FastCall(0xA00); - break; - } - - // Check status - auto status = spu.SPU.Status.GetValue(); - if (status == SPU_STATUS_STOPPED_BY_STOP) { - return; + // Initialise the SPURS management area to its initial values + mgmt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID; + mgmt->wklCurrentUniqueId = 0x20; + mgmt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + mgmt->yieldToKernelAddr = isKernel2 ? CELL_SPURS_KERNEL2_YIELD_ADDR : CELL_SPURS_KERNEL1_YIELD_ADDR; + mgmt->selectWorkloadAddr = isKernel2 ? CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR : CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR; + if (!isKernel2) { + mgmt->x1F0 = 0xF0020000; + mgmt->x200 = 0x20000; + mgmt->guid[0] = 0x423A3A02; + mgmt->guid[1] = 0x43F43A82; + mgmt->guid[2] = 0x43F26502; + mgmt->guid[3] = 0x420EB382; } else { - assert(status == SPU_STATUS_RUNNING); + mgmt->guid[0] = 0x43A08402; + mgmt->guid[1] = 0x43FB0A82; + mgmt->guid[2] = 0x435E9302; + mgmt->guid[3] = 0x43A3C982; } + spu.UnregisterHleFunctions(0, 0x40000); // TODO: use a symbolic constant + spu.RegisterHleFuncion(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelMain); + spu.RegisterHleFuncion(mgmt->yieldToKernelAddr, spursKernelMain); + spu.RegisterHleFuncion(mgmt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); + + // Start the system service workload + spu.RegisterHleFuncion(0xA00, spursSysServiceWorkloadEntry); + wklInfo = &mgmt->spurs->m.wklInfoSysSrv; + pollStatus = 0; + } else if (spu.PC == mgmt->yieldToKernelAddr) { + isKernel2 = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; + // Select next workload to run spu.GPR[3].clear(); - if (isSecond) { - spursKernelSelectWorkload2(spu); + if (isKernel2) { + spursKernel2SelectWorkload(spu); } else { - spursKernelSelectWorkload(spu); + spursKernel1SelectWorkload(spu); } - u64 res = spu.GPR[3]._u64[1]; - pollStatus = (u32)(res); - wid = (u32)(res >> 32); + + pollStatus = (u32)(spu.GPR[3]._u64[1]); + auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); + wklInfo = wid < CELL_SPURS_MAX_WORKLOAD ? &mgmt->spurs->m.wklInfo1[wid] : + (wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &mgmt->spurs->m.wklInfo2[wid & 0xf] : &mgmt->spurs->m.wklInfoSysSrv); + } else { + assert(0); } + + if (!isKernel2) { + mgmt->moduleId[0] = 0; + mgmt->moduleId[1] = 0; + } + + // Run workload + spu.GPR[0]._u32[3] = mgmt->yieldToKernelAddr; + spu.GPR[1]._u32[3] = 0x3FFB0; + spu.GPR[3]._u32[3] = 0x100; + spu.GPR[4]._u64[1] = wklInfo->arg; + spu.GPR[5]._u32[3] = pollStatus; + spu.SetBranch(0xA00); + return false; } ////////////////////////////////////////////////////////////////////////////// @@ -783,7 +844,7 @@ poll: } /// Entry point of the system service workload -void spursSysServiceWorkloadEntry(SPUThread & spu) { +bool spursSysServiceWorkloadEntry(SPUThread & spu) { auto mgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); auto arg = spu.GPR[4]._u64[1]; auto pollStatus = spu.GPR[5]._u32[3]; @@ -800,7 +861,7 @@ void spursSysServiceWorkloadEntry(SPUThread & spu) { } // TODO: Ensure that this function always returns to the SPURS kernel - return; + return false; } ////////////////////////////////////////////////////////////////////////////// diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 825c1c4007..4581c27650 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include "Utilities/GNU.h" From 62c8f2ac342527d75c64c123ead8186e2fafbe1a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 29 Jan 2015 18:48:05 +0300 Subject: [PATCH 34/94] ARMv7: stubs for other modules, loader improved --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 2 - rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 5 - rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 3 - rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp | 20 ++ rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp | 28 +++ rpcs3/Emu/ARMv7/Modules/sceAudio.cpp | 24 +++ rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp | 19 ++ rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp | 22 ++ rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp | 23 +++ rpcs3/Emu/ARMv7/Modules/sceCamera.cpp | 56 ++++++ rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp | 19 ++ rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp | 55 +++++ rpcs3/Emu/ARMv7/Modules/sceDbg.cpp | 19 ++ rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp | 2 +- rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp | 27 +++ rpcs3/Emu/ARMv7/Modules/sceFiber.cpp | 26 +++ rpcs3/Emu/ARMv7/Modules/sceFios.cpp | 147 ++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceFpu.cpp | 29 +++ rpcs3/Emu/ARMv7/Modules/sceHttp.cpp | 82 ++++++++ rpcs3/Emu/ARMv7/Modules/sceIme.cpp | 20 ++ rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp | 24 +++ rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp | 24 +++ rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 2 +- rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp | 17 ++ rpcs3/Emu/ARMv7/Modules/sceLocation.cpp | 34 ++++ rpcs3/Emu/ARMv7/Modules/sceMd5.cpp | 19 ++ rpcs3/Emu/ARMv7/Modules/sceMotion.cpp | 31 +++ rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp | 17 ++ rpcs3/Emu/ARMv7/Modules/sceNet.cpp | 73 +++++++ rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp | 31 +++ rpcs3/Emu/ARMv7/Modules/sceNgs.cpp | 78 +++++++ rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp | 33 +++ rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp | 26 +++ rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp | 25 +++ rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp | 46 +++++ rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp | 44 ++++ rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp | 35 ++++ rpcs3/Emu/ARMv7/Modules/scePgf.cpp | 38 ++++ rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp | 17 ++ rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp | 18 ++ rpcs3/Emu/ARMv7/Modules/sceRtc.cpp | 52 +++++ rpcs3/Emu/ARMv7/Modules/sceSas.cpp | 64 ++++++ rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp | 19 ++ rpcs3/Emu/ARMv7/Modules/sceSfmt.cpp | 84 ++++++++ rpcs3/Emu/ARMv7/Modules/sceSha.cpp | 44 ++++ rpcs3/Emu/ARMv7/Modules/sceSqlite.cpp | 187 +++++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceSsl.cpp | 26 +++ rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp | 38 ++++ rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp | 32 +++ rpcs3/Emu/ARMv7/Modules/sceTouch.cpp | 20 ++ rpcs3/Emu/ARMv7/Modules/sceUlt.cpp | 68 +++++++ rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp | 34 ++++ rpcs3/Emu/ARMv7/Modules/sceVoice.cpp | 40 ++++ rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp | 32 +++ rpcs3/Emu/ARMv7/Modules/sceXml.cpp | 201 +++++++++++++++++++ rpcs3/Emu/ARMv7/PSVFuncList.cpp | 124 ++++++++++-- rpcs3/Emu/FS/vfsDirBase.h | 11 +- rpcs3/Emu/Memory/Memory.cpp | 9 +- rpcs3/Emu/Memory/Memory.h | 2 - rpcs3/Emu/Memory/vm.cpp | 5 + rpcs3/Emu/Memory/vm.h | 4 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.h | 4 +- rpcs3/Loader/ELF32.cpp | 114 +++++++++-- rpcs3/Loader/ELF64.cpp | 1 + rpcs3/emucore.vcxproj | 50 +++++ rpcs3/emucore.vcxproj.filters | 150 ++++++++++++++ 66 files changed, 2616 insertions(+), 59 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAudio.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceCamera.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceDbg.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceFiber.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceFios.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceFpu.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceHttp.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceIme.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceLocation.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceMd5.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceMotion.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNet.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNgs.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/scePgf.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceRtc.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSas.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSfmt.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSha.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSqlite.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSsl.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceTouch.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceUlt.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceVoice.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/sceXml.cpp diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index e5a7b4b87f..fac6873a33 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -29,8 +29,6 @@ struct ARMv7_opcode_t const ARMv7_opcode_t ARMv7_opcode_table[] = { - ARMv7_OP2(0xffff, 0x0000, T1, NULL_OP), // ??? - ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK), // "Undefined" Thumb opcode used ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode used diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 954e07dfcc..ea01bcecc9 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -283,11 +283,6 @@ void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); } -void ARMv7_instrs::NULL_OP(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) -{ - throw fmt::format("Null opcode found: 0x%04x 0x%04x", code.code1, code.code0); -} - void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { u32 cond, func; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 4e4b8b6dc1..2a18646d42 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -30,10 +30,7 @@ namespace ARMv7_instrs { void UNK(ARMv7Context& context, const ARMv7Code code); - void NULL_OP(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); - void HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); - void MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void ADC_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp b/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp new file mode 100644 index 0000000000..0d9aa8a072 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceAppMgr; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAppMgr, #name, name) + +psv_log_base sceAppMgr("SceAppMgr", []() +{ + sceAppMgr.on_load = nullptr; + sceAppMgr.on_unload = nullptr; + sceAppMgr.on_stop = nullptr; + + //REG_FUNC(0x47E5DD7D, sceAppMgrReceiveEventNum); + //REG_FUNC(0xCFAD5A3A, sceAppMgrReceiveEvent); + //REG_FUNC(0xF3D65520, sceAppMgrAcquireBgmPort); + //REG_FUNC(0x96CBE713, sceAppMgrReleaseBgmPort); + //REG_FUNC(0x49255C91, sceAppMgrGetRunStatus); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp new file mode 100644 index 0000000000..567f6c4f3e --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp @@ -0,0 +1,28 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceAppUtil; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAppUtil, #name, name) + +psv_log_base sceAppUtil("SceAppUtil", []() +{ + sceAppUtil.on_load = nullptr; + sceAppUtil.on_unload = nullptr; + sceAppUtil.on_stop = nullptr; + + //REG_FUNC(0xDAFFE671, sceAppUtilInit); + //REG_FUNC(0xB220B00B, sceAppUtilShutdown); + //REG_FUNC(0x7E8FE96A, sceAppUtilSaveDataSlotCreate); + //REG_FUNC(0x266A7646, sceAppUtilSaveDataSlotDelete); + //REG_FUNC(0x98630136, sceAppUtilSaveDataSlotSetParam); + //REG_FUNC(0x93F0D89F, sceAppUtilSaveDataSlotGetParam); + //REG_FUNC(0x1E2A6158, sceAppUtilSaveDataFileSave); + //REG_FUNC(0xEE85804D, sceAppUtilPhotoMount); + //REG_FUNC(0x9651B941, sceAppUtilPhotoUmount); + //REG_FUNC(0x5DFB9CA0, sceAppUtilSystemParamGetInt); + //REG_FUNC(0x6E6AA267, sceAppUtilSystemParamGetString); + //REG_FUNC(0x9D8AC677, sceAppUtilSaveSafeMemory); + //REG_FUNC(0x3424D772, sceAppUtilLoadSafeMemory); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp new file mode 100644 index 0000000000..36920a8e59 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceAudio; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudio, #name, name) + +psv_log_base sceAudio("SceAudio", []() +{ + sceAudio.on_load = nullptr; + sceAudio.on_unload = nullptr; + sceAudio.on_stop = nullptr; + + //REG_FUNC(0x5BC341E4, sceAudioOutOpenPort); + //REG_FUNC(0x69E2E6B5, sceAudioOutReleasePort); + //REG_FUNC(0x02DB3F5F, sceAudioOutOutput); + //REG_FUNC(0x64167F11, sceAudioOutSetVolume); + //REG_FUNC(0xB8BA0D07, sceAudioOutSetConfig); + //REG_FUNC(0x9C8EDAEA, sceAudioOutGetConfig); + //REG_FUNC(0x9A5370C4, sceAudioOutGetRestSample); + //REG_FUNC(0x12FB1767, sceAudioOutGetAdopt); + //REG_FUNC(0xC6D8D775, sceAudioInRaw); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp new file mode 100644 index 0000000000..0ae64a168d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceAudioIn; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudioIn, #name, name) + +psv_log_base sceAudioIn("SceAudioIn", []() +{ + sceAudioIn.on_load = nullptr; + sceAudioIn.on_unload = nullptr; + sceAudioIn.on_stop = nullptr; + + //REG_FUNC(0x638ADD2D, sceAudioInInput); + //REG_FUNC(0x39B50DC1, sceAudioInOpenPort); + //REG_FUNC(0x3A61B8C4, sceAudioInReleasePort); + //REG_FUNC(0x566AC433, sceAudioInGetAdopt); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp new file mode 100644 index 0000000000..f8e3952dec --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp @@ -0,0 +1,22 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceAudiodec; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudiodec, #name, name) + +psv_log_base sceAudiodec("SceAudiodec", []() +{ + sceAudiodec.on_load = nullptr; + sceAudiodec.on_unload = nullptr; + sceAudiodec.on_stop = nullptr; + + //REG_FUNC(0x445C2CEF, sceAudiodecInitLibrary); + //REG_FUNC(0x45719B9D, sceAudiodecTermLibrary); + //REG_FUNC(0x4DFD3AAA, sceAudiodecCreateDecoder); + //REG_FUNC(0xE7A24E16, sceAudiodecDeleteDecoder); + //REG_FUNC(0xCCDABA04, sceAudiodecDecode); + //REG_FUNC(0xF72F9B64, sceAudiodecClearContext); + //REG_FUNC(0x883B0CF5, sceAudiodecGetInternalError); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp new file mode 100644 index 0000000000..a3bf58617c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp @@ -0,0 +1,23 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceAudioenc; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudioenc, #name, name) + +psv_log_base sceAudioenc("SceAudioenc", []() +{ + sceAudioenc.on_load = nullptr; + sceAudioenc.on_unload = nullptr; + sceAudioenc.on_stop = nullptr; + + //REG_FUNC(0x76EE4DC6, sceAudioencInitLibrary); + //REG_FUNC(0xAB32D022, sceAudioencTermLibrary); + //REG_FUNC(0x64C04AE8, sceAudioencCreateEncoder); + //REG_FUNC(0xC6BA5EE6, sceAudioencDeleteEncoder); + //REG_FUNC(0xD85DB29C, sceAudioencEncode); + //REG_FUNC(0x9386F42D, sceAudioencClearContext); + //REG_FUNC(0xD01C63A3, sceAudioencGetOptInfo); + //REG_FUNC(0x452246D0, sceAudioencGetInternalError); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp b/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp new file mode 100644 index 0000000000..79c219443c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp @@ -0,0 +1,56 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceCamera; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCamera, #name, name) + +psv_log_base sceCamera("SceCamera", []() +{ + sceCamera.on_load = nullptr; + sceCamera.on_unload = nullptr; + sceCamera.on_stop = nullptr; + + //REG_FUNC(0xA462F801, sceCameraOpen); + //REG_FUNC(0xCD6E1CFC, sceCameraClose); + //REG_FUNC(0xA8FEAE35, sceCameraStart); + //REG_FUNC(0x1DD9C9CE, sceCameraStop); + //REG_FUNC(0x79B5C2DE, sceCameraRead); + //REG_FUNC(0x103A75B8, sceCameraIsActive); + //REG_FUNC(0x624F7653, sceCameraGetSaturation); + //REG_FUNC(0xF9F7CA3D, sceCameraSetSaturation); + //REG_FUNC(0x85D5951D, sceCameraGetBrightness); + //REG_FUNC(0x98D71588, sceCameraSetBrightness); + //REG_FUNC(0x8FBE84BE, sceCameraGetContrast); + //REG_FUNC(0x06FB2900, sceCameraSetContrast); + //REG_FUNC(0xAA72C3DC, sceCameraGetSharpness); + //REG_FUNC(0xD1A5BB0B, sceCameraSetSharpness); + //REG_FUNC(0x44F6043F, sceCameraGetReverse); + //REG_FUNC(0x1175F477, sceCameraSetReverse); + //REG_FUNC(0x7E8EF3B2, sceCameraGetEffect); + //REG_FUNC(0xE9D2CFB1, sceCameraSetEffect); + //REG_FUNC(0x8B5E6147, sceCameraGetEV); + //REG_FUNC(0x62AFF0B8, sceCameraSetEV); + //REG_FUNC(0x06D3816C, sceCameraGetZoom); + //REG_FUNC(0xF7464216, sceCameraSetZoom); + //REG_FUNC(0x9FDACB99, sceCameraGetAntiFlicker); + //REG_FUNC(0xE312958A, sceCameraSetAntiFlicker); + //REG_FUNC(0x4EBD5C68, sceCameraGetISO); + //REG_FUNC(0x3CF630A1, sceCameraSetISO); + //REG_FUNC(0x2C36D6F3, sceCameraGetGain); + //REG_FUNC(0xE65CFE86, sceCameraSetGain); + //REG_FUNC(0xDBFFA1DA, sceCameraGetWhiteBalance); + //REG_FUNC(0x4D4514AC, sceCameraSetWhiteBalance); + //REG_FUNC(0x8DD1292B, sceCameraGetBacklight); + //REG_FUNC(0xAE071044, sceCameraSetBacklight); + //REG_FUNC(0x12B6FF26, sceCameraGetNightmode); + //REG_FUNC(0x3F26233E, sceCameraSetNightmode); + //REG_FUNC(0xD02CFA5C, sceCameraLedSwitch); + //REG_FUNC(0x89B16030, sceCameraLedBlink); + //REG_FUNC(0x7670474C, sceCameraUseCacheMemoryForTrial); + //REG_FUNC(0x27BB0528, sceCameraGetNoiseReductionForDebug); + //REG_FUNC(0x233C9E27, sceCameraSetNoiseReductionForDebug); + //REG_FUNC(0xC387F4DC, sceCameraGetSharpnessOffForDebug); + //REG_FUNC(0xE22C2375, sceCameraSetSharpnessOffForDebug); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp b/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp new file mode 100644 index 0000000000..013f4ff52b --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceCodecEngine; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCodecEngine, #name, name) + +psv_log_base sceCodecEngine("SceCodecEngine", []() +{ + sceCodecEngine.on_load = nullptr; + sceCodecEngine.on_unload = nullptr; + sceCodecEngine.on_stop = nullptr; + + //REG_FUNC(0x3E718890, sceCodecEnginePmonStart); + //REG_FUNC(0x268B1EF5, sceCodecEnginePmonStop); + //REG_FUNC(0x859E4A68, sceCodecEnginePmonGetProcessorLoad); + //REG_FUNC(0xA097E4C8, sceCodecEnginePmonReset); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp b/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp new file mode 100644 index 0000000000..1f5a4863a3 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp @@ -0,0 +1,55 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceCommonDialog; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceCommonDialog, #name, name) + +psv_log_base sceCommonDialog("SceCommonDialog", []() +{ + sceCommonDialog.on_load = nullptr; + sceCommonDialog.on_unload = nullptr; + sceCommonDialog.on_stop = nullptr; + + //REG_FUNC(0x90530F2F, sceCommonDialogUpdate); + //REG_FUNC(0x755FF270, sceMsgDialogInit); + //REG_FUNC(0x4107019E, sceMsgDialogGetStatus); + //REG_FUNC(0xC296D396, sceMsgDialogClose); + //REG_FUNC(0x0CC66115, sceMsgDialogAbort); + //REG_FUNC(0xBB3BFC89, sceMsgDialogGetResult); + //REG_FUNC(0x81ACF695, sceMsgDialogTerm); + //REG_FUNC(0x7BE0E08B, sceMsgDialogProgressBarInc); + //REG_FUNC(0x9CDA5E0D, sceMsgDialogProgressBarSetValue); + //REG_FUNC(0xA38A4A0D, sceNetCheckDialogInit); + //REG_FUNC(0x8027292A, sceNetCheckDialogGetStatus); + //REG_FUNC(0x2D8EDF09, sceNetCheckDialogAbort); + //REG_FUNC(0xB05FCE9E, sceNetCheckDialogGetResult); + //REG_FUNC(0x8BE51C15, sceNetCheckDialogTerm); + //REG_FUNC(0xBF5248FA, sceSaveDataDialogInit); + //REG_FUNC(0x6E258046, sceSaveDataDialogGetStatus); + //REG_FUNC(0x013E7F74, sceSaveDataDialogAbort); + //REG_FUNC(0xB2FF576E, sceSaveDataDialogGetResult); + //REG_FUNC(0x2192A10A, sceSaveDataDialogTerm); + //REG_FUNC(0x19192C8B, sceSaveDataDialogContinue); + //REG_FUNC(0xBA0542CA, sceSaveDataDialogGetSubStatus); + //REG_FUNC(0x415D6068, sceSaveDataDialogSubClose); + //REG_FUNC(0x6C49924B, sceSaveDataDialogFinish); + //REG_FUNC(0xBDE00A83, sceSaveDataDialogProgressBarInc); + //REG_FUNC(0x5C322D1E, sceSaveDataDialogProgressBarSetValue); + //REG_FUNC(0x1E7043BF, sceImeDialogInit); + //REG_FUNC(0xCF0431FD, sceImeDialogGetStatus); + //REG_FUNC(0x594A220E, sceImeDialogAbort); + //REG_FUNC(0x2EB3D046, sceImeDialogGetResult); + //REG_FUNC(0x838A3AF4, sceImeDialogTerm); + //REG_FUNC(0x73EE7C9C, scePhotoImportDialogInit); + //REG_FUNC(0x032206D8, scePhotoImportDialogGetStatus); + //REG_FUNC(0xD855414C, scePhotoImportDialogGetResult); + //REG_FUNC(0x7FE5BD77, scePhotoImportDialogTerm); + //REG_FUNC(0x4B125581, scePhotoImportDialogAbort); + //REG_FUNC(0xCD990375, scePhotoReviewDialogInit); + //REG_FUNC(0xF4F600CA, scePhotoReviewDialogGetStatus); + //REG_FUNC(0xFFA35858, scePhotoReviewDialogGetResult); + //REG_FUNC(0xC700B2DF, scePhotoReviewDialogTerm); + //REG_FUNC(0x74FF2A8B, scePhotoReviewDialogAbort); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp b/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp new file mode 100644 index 0000000000..6fe3856b9c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceDbg; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceDbg, #name, name) + +psv_log_base sceDbg("SceDbg", []() +{ + sceDbg.on_load = nullptr; + sceDbg.on_unload = nullptr; + sceDbg.on_stop = nullptr; + + //REG_FUNC(0x941622FA, sceDbgSetMinimumLogLevel); + //REG_FUNC(0x1AF3678B, sceDbgAssertionHandler); + //REG_FUNC(0x6605AB19, sceDbgLoggingHandler); + //REG_FUNC(0xED4A00BA, sceDbgSetBreakOnErrorState); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp b/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp index bdd5e58e5d..d90fcca74f 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp @@ -45,4 +45,4 @@ psv_log_base sceDeci4p("SceDeci4pUserp", []() REG_FUNC(0x971E1C66, sceKernelDeci4pRead); REG_FUNC(0xCDA3AAAC, sceKernelDeci4pWrite); REG_FUNC(0x73371F35, sceKernelDeci4pRegisterCallback); -}); \ No newline at end of file +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp b/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp new file mode 100644 index 0000000000..6d7e440c2f --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp @@ -0,0 +1,27 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceDeflt; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceDeflt, #name, name) + +psv_log_base sceDeflt("SceDeflt", []() +{ + sceDeflt.on_load = nullptr; + sceDeflt.on_unload = nullptr; + sceDeflt.on_stop = nullptr; + + //REG_FUNC(0xCD83A464, sceZlibAdler32); + //REG_FUNC(0x110D5050, sceDeflateDecompress); + //REG_FUNC(0xE3CB51A3, sceGzipDecompress); + //REG_FUNC(0xBABCF5CF, sceGzipGetComment); + //REG_FUNC(0xE1844802, sceGzipGetCompressedData); + //REG_FUNC(0x1B8E5862, sceGzipGetInfo); + //REG_FUNC(0xAEBAABE6, sceGzipGetName); + //REG_FUNC(0xDEDADC31, sceGzipIsValid); + //REG_FUNC(0xE38F754D, sceZlibDecompress); + //REG_FUNC(0xE680A65A, sceZlibGetCompressedData); + //REG_FUNC(0x4C0A685D, sceZlibGetInfo); + //REG_FUNC(0x14A0698D, sceZlibIsValid); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp b/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp new file mode 100644 index 0000000000..73678a396c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp @@ -0,0 +1,26 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceFiber; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceFiber, #name, name) + +psv_log_base sceFiber("SceFiber", []() +{ + sceFiber.on_load = nullptr; + sceFiber.on_unload = nullptr; + sceFiber.on_stop = nullptr; + + //REG_FUNC(0xF24A298C, _sceFiberInitializeImpl); + //REG_FUNC(0xC6A3F9BB, _sceFiberInitializeWithInternalOptionImpl); + //REG_FUNC(0x7D0C7DDB, _sceFiberAttachContextAndRun); + //REG_FUNC(0xE00B9AFE, _sceFiberAttachContextAndSwitch); + //REG_FUNC(0x801AB334, sceFiberOptParamInitialize); + //REG_FUNC(0xE160F844, sceFiberFinalize); + //REG_FUNC(0x7DF23243, sceFiberRun); + //REG_FUNC(0xE4283144, sceFiberSwitch); + //REG_FUNC(0x414D8CA5, sceFiberGetSelf); + //REG_FUNC(0x3B42921F, sceFiberReturnToThread); + //REG_FUNC(0x189599B4, sceFiberGetInfo); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceFios.cpp b/rpcs3/Emu/ARMv7/Modules/sceFios.cpp new file mode 100644 index 0000000000..d04af5b3cd --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceFios.cpp @@ -0,0 +1,147 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceFios; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceFios, #name, name) + +psv_log_base sceFios("SceFios2", []() +{ + sceFios.on_load = nullptr; + sceFios.on_unload = nullptr; + sceFios.on_stop = nullptr; + + //REG_FUNC(0x15857180, sceFiosArchiveGetMountBufferSize); + //REG_FUNC(0xDF3352FC, sceFiosArchiveGetMountBufferSizeSync); + //REG_FUNC(0x92E76BBD, sceFiosArchiveMount); + //REG_FUNC(0xC4822276, sceFiosArchiveMountSync); + //REG_FUNC(0xFE1E1D28, sceFiosArchiveUnmount); + //REG_FUNC(0xB26DC24D, sceFiosArchiveUnmountSync); + //REG_FUNC(0x1E920B1D, sceFiosCancelAllOps); + //REG_FUNC(0xF85C208B, sceFiosCloseAllFiles); + //REG_FUNC(0xF6CACFC7, sceFiosDHClose); + //REG_FUNC(0x1F3CC428, sceFiosDHCloseSync); + //REG_FUNC(0x2B406DEB, sceFiosDHGetPath); + //REG_FUNC(0xEA9855BA, sceFiosDHOpen); + //REG_FUNC(0x34BC3713, sceFiosDHOpenSync); + //REG_FUNC(0x72A0A851, sceFiosDHRead); + //REG_FUNC(0xB7E79CAD, sceFiosDHReadSync); + //REG_FUNC(0x280D284A, sceFiosDateFromComponents); + //REG_FUNC(0x5C593C1E, sceFiosDateGetCurrent); + //REG_FUNC(0x5CFF6EA0, sceFiosDateToComponents); + //REG_FUNC(0x44B9F8EB, sceFiosDebugDumpDH); + //REG_FUNC(0x159B1FA8, sceFiosDebugDumpDate); + //REG_FUNC(0x51E677DF, sceFiosDebugDumpError); + //REG_FUNC(0x5506ACAB, sceFiosDebugDumpFH); + //REG_FUNC(0xE438D4F0, sceFiosDebugDumpOp); + //REG_FUNC(0x764DFA7A, sceFiosDelete); + //REG_FUNC(0xAAC54B44, sceFiosDeleteSync); + //REG_FUNC(0x9198ED8B, sceFiosDirectoryCreate); + //REG_FUNC(0xE037B076, sceFiosDirectoryCreateSync); + //REG_FUNC(0xDA93677C, sceFiosDirectoryDelete); + //REG_FUNC(0xB9573146, sceFiosDirectoryDeleteSync); + //REG_FUNC(0x48D50D97, sceFiosDirectoryExists); + //REG_FUNC(0x726E01BE, sceFiosDirectoryExistsSync); + //REG_FUNC(0x6F12D8A5, sceFiosExists); + //REG_FUNC(0x125EFD34, sceFiosExistsSync); + //REG_FUNC(0xA88EDCA8, sceFiosFHClose); + //REG_FUNC(0x45182328, sceFiosFHCloseSync); + //REG_FUNC(0xC55DB73B, sceFiosFHGetOpenParams); + //REG_FUNC(0x37143AE3, sceFiosFHGetPath); + //REG_FUNC(0xC5C26581, sceFiosFHGetSize); + //REG_FUNC(0xBF699BD4, sceFiosFHOpen); + //REG_FUNC(0xC3E7C3DB, sceFiosFHOpenSync); + //REG_FUNC(0x6A51E688, sceFiosFHPread); + //REG_FUNC(0xE2805059, sceFiosFHPreadSync); + //REG_FUNC(0x7C4E0C42, sceFiosFHPreadv); + //REG_FUNC(0x4D42F95C, sceFiosFHPreadvSync); + //REG_FUNC(0xCF1FAA6F, sceFiosFHPwrite); + //REG_FUNC(0x1E962F57, sceFiosFHPwriteSync); + //REG_FUNC(0xBBC9AFD5, sceFiosFHPwritev); + //REG_FUNC(0x742ADDC4, sceFiosFHPwritevSync); + //REG_FUNC(0xB09AFBDF, sceFiosFHRead); + //REG_FUNC(0x76945919, sceFiosFHReadSync); + //REG_FUNC(0x7DB0AFAF, sceFiosFHReadv); + //REG_FUNC(0x1BC977FA, sceFiosFHReadvSync); + //REG_FUNC(0xA75F3C4A, sceFiosFHSeek); + //REG_FUNC(0xD97C4DF7, sceFiosFHStat); + //REG_FUNC(0xF8BEAC88, sceFiosFHStatSync); + //REG_FUNC(0xE485F35E, sceFiosFHSync); + //REG_FUNC(0xA909CCE3, sceFiosFHSyncSync); + //REG_FUNC(0xD7F33130, sceFiosFHTell); + //REG_FUNC(0x2B39453B, sceFiosFHTruncate); + //REG_FUNC(0xFEF940B7, sceFiosFHTruncateSync); + //REG_FUNC(0xE663138E, sceFiosFHWrite); + //REG_FUNC(0x984024E5, sceFiosFHWriteSync); + //REG_FUNC(0x988DD7FF, sceFiosFHWritev); + //REG_FUNC(0x267E6CE3, sceFiosFHWritevSync); + //REG_FUNC(0xB647278B, sceFiosFileDelete); + //REG_FUNC(0xB5302E30, sceFiosFileDeleteSync); + //REG_FUNC(0x8758E62F, sceFiosFileExists); + //REG_FUNC(0x233B070C, sceFiosFileExistsSync); + //REG_FUNC(0x79D9BB50, sceFiosFileGetSize); + //REG_FUNC(0x789215C3, sceFiosFileGetSizeSync); + //REG_FUNC(0x84080161, sceFiosFileRead); + //REG_FUNC(0x1C488B32, sceFiosFileReadSync); + //REG_FUNC(0xC5513E13, sceFiosFileTruncate); + //REG_FUNC(0x6E1252B8, sceFiosFileTruncateSync); + //REG_FUNC(0x42C278E5, sceFiosFileWrite); + //REG_FUNC(0x132B6DE6, sceFiosFileWriteSync); + //REG_FUNC(0x681184A2, sceFiosGetAllDHs); + //REG_FUNC(0x90AB9195, sceFiosGetAllFHs); + //REG_FUNC(0x8F62832C, sceFiosGetAllOps); + //REG_FUNC(0xC897F6A7, sceFiosGetDefaultOpAttr); + //REG_FUNC(0x30583FCB, sceFiosGetGlobalDefaultOpAttr); + //REG_FUNC(0x156EAFDC, sceFiosGetSuspendCount); + //REG_FUNC(0xD55B8555, sceFiosIOFilterAdd); + //REG_FUNC(0x7C9B14EB, sceFiosIOFilterGetInfo); + //REG_FUNC(0x057252F2, sceFiosIOFilterPsarcDearchiver); + //REG_FUNC(0x22E35018, sceFiosIOFilterRemove); + //REG_FUNC(0x774C2C05, sceFiosInitialize); + //REG_FUNC(0x29104BF3, sceFiosIsIdle); + //REG_FUNC(0xF4F54E09, sceFiosIsInitialized); + //REG_FUNC(0xD2466EA5, sceFiosIsSuspended); + //REG_FUNC(0xB309E327, sceFiosIsValidHandle); + //REG_FUNC(0x3904F205, sceFiosOpCancel); + //REG_FUNC(0xE4EA92FA, sceFiosOpDelete); + //REG_FUNC(0x218A43EE, sceFiosOpGetActualCount); + //REG_FUNC(0xABFEE706, sceFiosOpGetAttr); + //REG_FUNC(0x68C436E4, sceFiosOpGetBuffer); + //REG_FUNC(0xBF099E16, sceFiosOpGetError); + //REG_FUNC(0xF21213B9, sceFiosOpGetOffset); + //REG_FUNC(0x157515CB, sceFiosOpGetPath); + //REG_FUNC(0x9C1084C5, sceFiosOpGetRequestCount); + //REG_FUNC(0x0C81D80E, sceFiosOpIsCancelled); + //REG_FUNC(0x1B9A575E, sceFiosOpIsDone); + //REG_FUNC(0x968CADBD, sceFiosOpReschedule); + //REG_FUNC(0xE6A66C70, sceFiosOpSyncWait); + //REG_FUNC(0x202079F9, sceFiosOpSyncWaitForIO); + //REG_FUNC(0x2AC79DFC, sceFiosOpWait); + //REG_FUNC(0xCC823B47, sceFiosOpWaitUntil); + //REG_FUNC(0x27AE468B, sceFiosOverlayAdd); + //REG_FUNC(0xF4C6B72A, sceFiosOverlayGetInfo); + //REG_FUNC(0x1C0BCAD5, sceFiosOverlayGetList); + //REG_FUNC(0x30F56704, sceFiosOverlayModify); + //REG_FUNC(0xF3C84D0F, sceFiosOverlayRemove); + //REG_FUNC(0x8A243E74, sceFiosOverlayResolveSync); + //REG_FUNC(0x5E75937A, sceFiosPathcmp); + //REG_FUNC(0xCC21C849, sceFiosPathncmp); + //REG_FUNC(0xAF7FAADF, sceFiosPrintf); + //REG_FUNC(0x25E399E5, sceFiosRename); + //REG_FUNC(0x030306F4, sceFiosRenameSync); + //REG_FUNC(0xD0B19C9F, sceFiosResolve); + //REG_FUNC(0x7FF33797, sceFiosResolveSync); + //REG_FUNC(0xBF2D3CC1, sceFiosResume); + //REG_FUNC(0x4E2FD311, sceFiosSetGlobalDefaultOpAttr); + //REG_FUNC(0x5B8D48C4, sceFiosShutdownAndCancelOps); + //REG_FUNC(0xFF04AF72, sceFiosStat); + //REG_FUNC(0xACBAF3E0, sceFiosStatSync); + //REG_FUNC(0x510953DC, sceFiosSuspend); + //REG_FUNC(0x2904B539, sceFiosTerminate); + //REG_FUNC(0xE76C8EC3, sceFiosTimeGetCurrent); + //REG_FUNC(0x35A82737, sceFiosTimeIntervalFromNanoseconds); + //REG_FUNC(0x397BF626, sceFiosTimeIntervalToNanoseconds); + //REG_FUNC(0x1915052A, sceFiosUpdateParameters); + //REG_FUNC(0x5BA4BD6D, sceFiosVprintf); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceFpu.cpp b/rpcs3/Emu/ARMv7/Modules/sceFpu.cpp new file mode 100644 index 0000000000..2992c6fc58 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceFpu.cpp @@ -0,0 +1,29 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceFpu; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceFpu, #name, name) + +psv_log_base sceFpu("SceFpu", []() +{ + sceFpu.on_load = nullptr; + sceFpu.on_unload = nullptr; + sceFpu.on_stop = nullptr; + + //REG_FUNC(0x33E1AC14, sceFpuSinf); + //REG_FUNC(0xDB66BA89, sceFpuCosf); + //REG_FUNC(0x6FBDA1C9, sceFpuTanf); + //REG_FUNC(0x53FF26AF, sceFpuAtanf); + //REG_FUNC(0xC8A4989B, sceFpuAtan2f); + //REG_FUNC(0x4D1AE0F1, sceFpuAsinf); + //REG_FUNC(0x64A8F9FE, sceFpuAcosf); + //REG_FUNC(0x936F0D27, sceFpuLogf); + //REG_FUNC(0x19881EC8, sceFpuLog2f); + //REG_FUNC(0xABBB6168, sceFpuLog10f); + //REG_FUNC(0xEFA16C6E, sceFpuExpf); + //REG_FUNC(0xA3A88AD0, sceFpuExp2f); + //REG_FUNC(0x35652326, sceFpuExp10f); + //REG_FUNC(0xDF622E56, sceFpuPowf); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp b/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp new file mode 100644 index 0000000000..4f23c935cd --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp @@ -0,0 +1,82 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceHttp; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceHttp, #name, name) + +psv_log_base sceHttp("SceHttp", []() +{ + sceHttp.on_load = nullptr; + sceHttp.on_unload = nullptr; + sceHttp.on_stop = nullptr; + + //REG_FUNC(0x214926D9, sceHttpInit); + //REG_FUNC(0xC9076666, sceHttpTerm); + //REG_FUNC(0xF98CDFA9, sceHttpGetMemoryPoolStats); + //REG_FUNC(0x62241DAB, sceHttpCreateTemplate); + //REG_FUNC(0xEC85ECFB, sceHttpDeleteTemplate); + //REG_FUNC(0xC616C200, sceHttpCreateConnectionWithURL); + //REG_FUNC(0xAEB3307E, sceHttpCreateConnection); + //REG_FUNC(0xF0F65C15, sceHttpDeleteConnection); + //REG_FUNC(0xBD5DA1D0, sceHttpCreateRequestWithURL); + //REG_FUNC(0xB0284270, sceHttpCreateRequest); + //REG_FUNC(0x3D3D29AD, sceHttpDeleteRequest); + //REG_FUNC(0x9CA58B99, sceHttpSendRequest); + //REG_FUNC(0x7EDE3979, sceHttpReadData); + //REG_FUNC(0xF580D304, sceHttpGetResponseContentLength); + //REG_FUNC(0x27071691, sceHttpGetStatusCode); + //REG_FUNC(0xEA61662F, sceHttpAbortRequest); + //REG_FUNC(0x7B51B122, sceHttpAddRequestHeader); + //REG_FUNC(0x5EB5F548, sceHttpRemoveRequestHeader); + //REG_FUNC(0x11F6C27F, sceHttpGetAllResponseHeaders); + //REG_FUNC(0x03A6C89E, sceHttpParseResponseHeader); + //REG_FUNC(0x179C56DB, sceHttpParseStatusLine); + //REG_FUNC(0x1DA2A673, sceHttpUriEscape); + //REG_FUNC(0x1274D318, sceHttpUriUnescape); + //REG_FUNC(0x1D45F24E, sceHttpUriParse); + //REG_FUNC(0x47664424, sceHttpUriBuild); + //REG_FUNC(0x75027D1D, sceHttpUriMerge); + //REG_FUNC(0x50737A3F, sceHttpUriSweepPath); + //REG_FUNC(0x37C30C90, sceHttpSetRequestContentLength); + //REG_FUNC(0x11EC42D0, sceHttpSetAuthEnabled); + //REG_FUNC(0x6727874C, sceHttpGetAuthEnabled); + //REG_FUNC(0x34891C3F, sceHttpSetAutoRedirect); + //REG_FUNC(0x6EAD73EB, sceHttpGetAutoRedirect); + //REG_FUNC(0xE0A3A88D, sceHttpSetAuthInfoCallback); + //REG_FUNC(0x4E08167D, sceHttpSetRedirectCallback); + //REG_FUNC(0x8455B5B3, sceHttpSetResolveTimeOut); + //REG_FUNC(0x9AB56EA7, sceHttpSetResolveRetry); + //REG_FUNC(0x237CA86E, sceHttpSetConnectTimeOut); + //REG_FUNC(0x8AE3F008, sceHttpSetSendTimeOut); + //REG_FUNC(0x94BF196E, sceHttpSetRecvTimeOut); + //REG_FUNC(0x27A98BDA, sceHttpSetNonblock); + //REG_FUNC(0xD65746BC, sceHttpGetNonblock); + //REG_FUNC(0x5CEB6554, sceHttpSetEpollId); + //REG_FUNC(0x9E031D7C, sceHttpGetEpollId); + //REG_FUNC(0x94F7256A, sceHttpWaitRequest); + //REG_FUNC(0x7C99AF67, sceHttpCreateEpoll); + //REG_FUNC(0x0F1FD1B3, sceHttpSetEpoll); + //REG_FUNC(0xCFB1DA4B, sceHttpUnsetEpoll); + //REG_FUNC(0x65FE983F, sceHttpGetEpoll); + //REG_FUNC(0x07D9F8BB, sceHttpDestroyEpoll); + //REG_FUNC(0xAEE573A3, sceHttpSetCookieEnabled); + //REG_FUNC(0x1B6EF66E, sceHttpGetCookieEnabled); + //REG_FUNC(0x70220BFA, sceHttpGetCookie); + //REG_FUNC(0xBEDB988D, sceHttpAddCookie); + //REG_FUNC(0x4259FB9E, sceHttpCookieExport); + //REG_FUNC(0x9DF48282, sceHttpCookieImport); + //REG_FUNC(0xD4F32A23, sceHttpSetCookieRecvCallback); + //REG_FUNC(0x11C03867, sceHttpSetCookieSendCallback); + //REG_FUNC(0xAE8D7C33, sceHttpsLoadCert); + //REG_FUNC(0x8577833F, sceHttpsUnloadCert); + //REG_FUNC(0x9FBE2869, sceHttpsEnableOption); + //REG_FUNC(0xC6D60403, sceHttpsDisableOption); + //REG_FUNC(0x72CB0741, sceHttpsEnableOptionPrivate); + //REG_FUNC(0x00659635, sceHttpsDisableOptionPrivate); + //REG_FUNC(0x2B79BDE0, sceHttpsGetSslError); + //REG_FUNC(0xA0926037, sceHttpsSetSslCallback); + //REG_FUNC(0xF71AA58D, sceHttpsGetCaList); + //REG_FUNC(0x56C95D94, sceHttpsFreeCaList); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceIme.cpp b/rpcs3/Emu/ARMv7/Modules/sceIme.cpp new file mode 100644 index 0000000000..d0e90298d9 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceIme.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceIme; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceIme, #name, name) + +psv_log_base sceIme("SceIme", []() +{ + sceIme.on_load = nullptr; + sceIme.on_unload = nullptr; + sceIme.on_stop = nullptr; + + //REG_FUNC(0x0E050613, sceImeOpen); + //REG_FUNC(0x71D6898A, sceImeUpdate); + //REG_FUNC(0x889A8421, sceImeClose); + //REG_FUNC(0xD8342D2A, sceImeSetCaret); + //REG_FUNC(0x7B1EFAA5, sceImeSetPreeditGeometry); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp b/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp new file mode 100644 index 0000000000..5ec6f79614 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceJpeg; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceJpeg, #name, name) + +psv_log_base sceJpeg("SceJpeg", []() +{ + sceJpeg.on_load = nullptr; + sceJpeg.on_unload = nullptr; + sceJpeg.on_stop = nullptr; + + //REG_FUNC(0xB030773B, sceJpegInitMJpeg); + //REG_FUNC(0x62842598, sceJpegFinishMJpeg); + //REG_FUNC(0x6215B095, sceJpegDecodeMJpeg); + //REG_FUNC(0x2A769BD8, sceJpegDecodeMJpegYCbCr); + //REG_FUNC(0xC2380E3A, sceJpegMJpegCsc); + //REG_FUNC(0x353BA9B0, sceJpegGetOutputInfo); + //REG_FUNC(0x123B4734, sceJpegCreateSplitDecoder); + //REG_FUNC(0xDE8D5FA1, sceJpegDeleteSplitDecoder); + //REG_FUNC(0x4598EC9C, sceJpegSplitDecodeMJpeg); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp b/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp new file mode 100644 index 0000000000..1567f5487d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp @@ -0,0 +1,24 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceJpegEnc; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceJpegEnc, #name, name) + +psv_log_base sceJpegEnc("SceJpegEnc", []() +{ + sceJpegEnc.on_load = nullptr; + sceJpegEnc.on_unload = nullptr; + sceJpegEnc.on_stop = nullptr; + + //REG_FUNC(0x2B55844D, sceJpegEncoderGetContextSize); + //REG_FUNC(0x88DA92B4, sceJpegEncoderInit); + //REG_FUNC(0xC60DE94C, sceJpegEncoderEncode); + //REG_FUNC(0xC87AA849, sceJpegEncoderEnd); + //REG_FUNC(0x9511F3BC, sceJpegEncoderSetValidRegion); + //REG_FUNC(0xB2B828EC, sceJpegEncoderSetCompressionRatio); + //REG_FUNC(0x2F58B12C, sceJpegEncoderSetHeaderMode); + //REG_FUNC(0x25D52D97, sceJpegEncoderSetOutputAddr); + //REG_FUNC(0x824A7D4F, sceJpegEncoderCsc); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index 611be74629..abb831ae32 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -156,7 +156,7 @@ namespace sce_libc_func { sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func); - LOG_ERROR(TTY, "%s : %s", func.get_ptr(), text.get_ptr()); + LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr()); Emu.Pause(); } } diff --git a/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp b/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp new file mode 100644 index 0000000000..4511ca2ae7 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceLiveArea; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceLiveArea, #name, name) + +psv_log_base sceLiveArea("SceLiveArea", []() +{ + sceLiveArea.on_load = nullptr; + sceLiveArea.on_unload = nullptr; + sceLiveArea.on_stop = nullptr; + + //REG_FUNC(0xA4B506F9, sceLiveAreaResourceReplaceAll); + //REG_FUNC(0x54A395FB, sceLiveAreaResourceGetStatus); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp b/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp new file mode 100644 index 0000000000..734f7f62e1 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp @@ -0,0 +1,34 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceLocation; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceLocation, #name, name) + +psv_log_base sceLocation("SceLibLocation", []() +{ + sceLocation.on_load = nullptr; + sceLocation.on_unload = nullptr; + sceLocation.on_stop = nullptr; + + //REG_FUNC(0xDD271661, sceLocationOpen); + //REG_FUNC(0x14FE76E8, sceLocationClose); + //REG_FUNC(0xB1F55065, sceLocationReopen); + //REG_FUNC(0x188CE004, sceLocationGetMethod); + //REG_FUNC(0x15BC27C8, sceLocationGetLocation); + //REG_FUNC(0x71503251, sceLocationCancelGetLocation); + //REG_FUNC(0x12D1F0EA, sceLocationStartLocationCallback); + //REG_FUNC(0xED378700, sceLocationStopLocationCallback); + //REG_FUNC(0x4E9E5ED9, sceLocationGetHeading); + //REG_FUNC(0x07D4DFE0, sceLocationStartHeadingCallback); + //REG_FUNC(0x92E53F94, sceLocationStopHeadingCallback); + //REG_FUNC(0xE055BCF5, sceLocationSetHeapAllocator); + //REG_FUNC(0xC895E567, sceLocationConfirm); + //REG_FUNC(0x730FF842, sceLocationConfirmGetStatus); + //REG_FUNC(0xFF016C13, sceLocationConfirmGetResult); + //REG_FUNC(0xE3CBF875, sceLocationConfirmAbort); + //REG_FUNC(0x482622C6, sceLocationGetPermission); + //REG_FUNC(0xDE0A9EA4, sceLocationSetGpsEmulationFile); + //REG_FUNC(0x760D08FF, sceLocationConfirmSetMessage); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp b/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp new file mode 100644 index 0000000000..aed0422ed4 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceMd5; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceMd5, #name, name) + +psv_log_base sceMd5("SceMd5", []() +{ + sceMd5.on_load = nullptr; + sceMd5.on_unload = nullptr; + sceMd5.on_stop = nullptr; + + //REG_FUNC(0xB845BCCB, sceMd5Digest); + //REG_FUNC(0x4D6436F9, sceMd5BlockInit); + //REG_FUNC(0x094A4902, sceMd5BlockUpdate); + //REG_FUNC(0xB94ABF83, sceMd5BlockResult); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp b/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp new file mode 100644 index 0000000000..bc86726bb2 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp @@ -0,0 +1,31 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceMotion; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceMotion, #name, name) + +psv_log_base sceMotion("SceMotion", []() +{ + sceMotion.on_load = nullptr; + sceMotion.on_unload = nullptr; + sceMotion.on_stop = nullptr; + + //REG_FUNC(0xBDB32767, sceMotionGetState); + //REG_FUNC(0x47D679EA, sceMotionGetSensorState); + //REG_FUNC(0xC1652201, sceMotionGetTiltCorrection); + //REG_FUNC(0xAF09FCDB, sceMotionSetTiltCorrection); + //REG_FUNC(0x112E0EAE, sceMotionGetDeadband); + //REG_FUNC(0x917EA390, sceMotionSetDeadband); + //REG_FUNC(0x20F00078, sceMotionRotateYaw); + //REG_FUNC(0x0FD2CDA2, sceMotionReset); + //REG_FUNC(0x28034AC9, sceMotionStartSampling); + //REG_FUNC(0xAF32CB1D, sceMotionStopSampling); + //REG_FUNC(0xDACB2A41, sceMotionSetAngleThreshold); + //REG_FUNC(0x499B6C87, sceMotionGetAngleThreshold); + //REG_FUNC(0x4F28BFE0, sceMotionGetBasicOrientation); + //REG_FUNC(0x122A79F8, sceMotionMagnetometerOn); + //REG_FUNC(0xC1A7395A, sceMotionMagnetometerOff); + //REG_FUNC(0x3D4813AE, sceMotionGetMagnetometerState); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp b/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp new file mode 100644 index 0000000000..3893d344bf --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceMt19937; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceMt19937, #name, name) + +psv_log_base sceMt19937("SceMt19937", []() +{ + sceMt19937.on_load = nullptr; + sceMt19937.on_unload = nullptr; + sceMt19937.on_stop = nullptr; + + //REG_FUNC(0xEE5BA27C, sceMt19937Init); + //REG_FUNC(0x29E43BB5, sceMt19937UInt); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNet.cpp b/rpcs3/Emu/ARMv7/Modules/sceNet.cpp new file mode 100644 index 0000000000..f68a283618 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNet.cpp @@ -0,0 +1,73 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNet; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNet, #name, name) + +psv_log_base sceNet("SceNet", []() +{ + sceNet.on_load = nullptr; + sceNet.on_unload = nullptr; + sceNet.on_stop = nullptr; + + //REG_FUNC(0xD62EF218, sceNetSetDnsInfo); + //REG_FUNC(0xFEC1166D, sceNetClearDnsCache); + //REG_FUNC(0xAFF9FA4D, sceNetDumpCreate); + //REG_FUNC(0x04042925, sceNetDumpRead); + //REG_FUNC(0x82DDCF63, sceNetDumpDestroy); + //REG_FUNC(0x3B24E75F, sceNetDumpAbort); + //REG_FUNC(0xF9D102AE, sceNetEpollCreate); + //REG_FUNC(0x4C8764AC, sceNetEpollControl); + //REG_FUNC(0x45CE337D, sceNetEpollWait); + //REG_FUNC(0x92D3E767, sceNetEpollWaitCB); + //REG_FUNC(0x7915CAF3, sceNetEpollDestroy); + //REG_FUNC(0x93FCC4E8, sceNetEpollAbort); + //REG_FUNC(0xE37F34AA, sceNetErrnoLoc); + //REG_FUNC(0xEEC6D75F, sceNetEtherStrton); + //REG_FUNC(0x84334EB2, sceNetEtherNtostr); + //REG_FUNC(0x06C05518, sceNetGetMacAddress); + //REG_FUNC(0x98839B74, sceNetInetNtop); + //REG_FUNC(0xD5EEB048, sceNetInetPton); + //REG_FUNC(0x12C19209, sceNetHtonll); + //REG_FUNC(0x4C30B03C, sceNetHtonl); + //REG_FUNC(0x9FA3207B, sceNetHtons); + //REG_FUNC(0xFB3336A6, sceNetNtohll); + //REG_FUNC(0xD2EAA645, sceNetNtohl); + //REG_FUNC(0x07845128, sceNetNtohs); + //REG_FUNC(0xEB03E265, sceNetInit); + //REG_FUNC(0xEA3CC286, sceNetTerm); + //REG_FUNC(0x658B903B, sceNetShowIfconfig); + //REG_FUNC(0x6AB3B74B, sceNetShowRoute); + //REG_FUNC(0x338EDC2E, sceNetShowNetstat); + //REG_FUNC(0x561DFD03, sceNetEmulationSet); + //REG_FUNC(0xAE3F4AC6, sceNetEmulationGet); + //REG_FUNC(0x6DA29319, sceNetResolverCreate); + //REG_FUNC(0x1EB11857, sceNetResolverStartNtoa); + //REG_FUNC(0x0424AE26, sceNetResolverStartAton); + //REG_FUNC(0x874EF500, sceNetResolverGetError); + //REG_FUNC(0x3559F098, sceNetResolverDestroy); + //REG_FUNC(0x38EBBD57, sceNetResolverAbort); + //REG_FUNC(0xF084FCE3, sceNetSocket); + //REG_FUNC(0x1ADF9BB1, sceNetAccept); + //REG_FUNC(0x1296A94B, sceNetBind); + //REG_FUNC(0x11E5B6F6, sceNetConnect); + //REG_FUNC(0x2348D353, sceNetGetpeername); + //REG_FUNC(0x1C66A6DB, sceNetGetsockname); + //REG_FUNC(0xBA652062, sceNetGetsockopt); + //REG_FUNC(0x7A8DA094, sceNetListen); + //REG_FUNC(0x023643B7, sceNetRecv); + //REG_FUNC(0xB226138B, sceNetRecvfrom); + //REG_FUNC(0xDE94C6FE, sceNetRecvmsg); + //REG_FUNC(0xE3DD8CD9, sceNetSend); + //REG_FUNC(0x52DB31D5, sceNetSendto); + //REG_FUNC(0x99C579AE, sceNetSendmsg); + //REG_FUNC(0x065505CA, sceNetSetsockopt); + //REG_FUNC(0x69E50BB5, sceNetShutdown); + //REG_FUNC(0x29822B4D, sceNetSocketClose); + //REG_FUNC(0x891C1B9B, sceNetSocketAbort); + //REG_FUNC(0xB1AF6840, sceNetGetSockInfo); + //REG_FUNC(0x138CF1D6, sceNetGetSockIdInfo); + //REG_FUNC(0xA86F8FE5, sceNetGetStatisticsInfo); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp b/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp new file mode 100644 index 0000000000..cde7d28916 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp @@ -0,0 +1,31 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNetCtl; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNetCtl, #name, name) + +psv_log_base sceNetCtl("SceNetCtl", []() +{ + sceNetCtl.on_load = nullptr; + sceNetCtl.on_unload = nullptr; + sceNetCtl.on_stop = nullptr; + + //REG_FUNC(0x495CA1DB, sceNetCtlInit); + //REG_FUNC(0xCD188648, sceNetCtlTerm); + //REG_FUNC(0xDFFC3ED4, sceNetCtlCheckCallback); + //REG_FUNC(0x6B20EC02, sceNetCtlInetGetResult); + //REG_FUNC(0x7AE0ED19, sceNetCtlAdhocGetResult); + //REG_FUNC(0xB26D07F3, sceNetCtlInetGetInfo); + //REG_FUNC(0x6D26AC68, sceNetCtlInetGetState); + //REG_FUNC(0xEAEE6185, sceNetCtlInetRegisterCallback); + //REG_FUNC(0xD0C3BF3F, sceNetCtlInetUnregisterCallback); + //REG_FUNC(0x4DDD6149, sceNetCtlGetNatInfo); + //REG_FUNC(0x0961A561, sceNetCtlAdhocGetState); + //REG_FUNC(0xFFA9D594, sceNetCtlAdhocRegisterCallback); + //REG_FUNC(0xA4471E10, sceNetCtlAdhocUnregisterCallback); + //REG_FUNC(0xED43B79A, sceNetCtlAdhocDisconnect); + //REG_FUNC(0x77586C59, sceNetCtlAdhocGetPeerList); + //REG_FUNC(0x7118C99D, sceNetCtlAdhocGetInAddr); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp b/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp new file mode 100644 index 0000000000..5798792b12 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp @@ -0,0 +1,78 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNgs; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNgs, #name, name) + +psv_log_base sceNgs("SceNgs", []() +{ + sceNgs.on_load = nullptr; + sceNgs.on_unload = nullptr; + sceNgs.on_stop = nullptr; + + //REG_FUNC(0x6CE8B36F, sceNgsSystemGetRequiredMemorySize); + //REG_FUNC(0xED14CF4A, sceNgsSystemInit); + //REG_FUNC(0x684F080C, sceNgsSystemUpdate); + //REG_FUNC(0x4A25BEBC, sceNgsSystemRelease); + //REG_FUNC(0xB9D971F2, sceNgsSystemLock); + //REG_FUNC(0x0A93EA96, sceNgsSystemUnlock); + //REG_FUNC(0x5ADD22DC, sceNgsSystemSetParamErrorCallback); + //REG_FUNC(0x64D80013, sceNgsSystemSetFlags); + //REG_FUNC(0x477318C0, sceNgsRackGetRequiredMemorySize); + //REG_FUNC(0x0A92E4EC, sceNgsRackInit); + //REG_FUNC(0xFE1A98E9, sceNgsRackGetVoiceHandle); + //REG_FUNC(0xDD5CA10B, sceNgsRackRelease); + //REG_FUNC(0x534B6E3F, sceNgsRackSetParamErrorCallback); + //REG_FUNC(0x1DDBEBEB, sceNgsVoiceInit); + //REG_FUNC(0xFA0A0F34, sceNgsVoicePlay); + //REG_FUNC(0xBB13373D, sceNgsVoiceKeyOff); + //REG_FUNC(0x0E291AAD, sceNgsVoiceKill); + //REG_FUNC(0xD7786E99, sceNgsVoicePause); + //REG_FUNC(0x54CFB981, sceNgsVoiceResume); + //REG_FUNC(0x8A88E665, sceNgsVoiceSetPreset); + //REG_FUNC(0xAB6BEF8F, sceNgsVoiceLockParams); + //REG_FUNC(0x3D46D8A7, sceNgsVoiceUnlockParams); + //REG_FUNC(0xFB8174B1, sceNgsVoiceSetParamsBlock); + //REG_FUNC(0x9AB87E71, sceNgsVoiceBypassModule); + //REG_FUNC(0x24E909A8, sceNgsVoiceSetModuleCallback); + //REG_FUNC(0x17A6F564, sceNgsVoiceSetFinishedCallback); + //REG_FUNC(0xC9B8C0B4, sceNgsVoiceGetStateData); + //REG_FUNC(0x5551410D, sceNgsVoiceGetInfo); + //REG_FUNC(0xB307185E, sceNgsVoiceGetModuleType); + //REG_FUNC(0x431BF3AB, sceNgsVoiceGetModuleBypass); + //REG_FUNC(0xD668B49C, sceNgsPatchCreateRouting); + //REG_FUNC(0x98703DBC, sceNgsPatchGetInfo); + //REG_FUNC(0x01A52E3A, sceNgsVoiceGetOutputPatch); + //REG_FUNC(0xD0C9AE5A, sceNgsPatchRemoveRouting); + //REG_FUNC(0xA3C807BC, sceNgsVoicePatchSetVolume); + //REG_FUNC(0xBD6F57F0, sceNgsVoicePatchSetVolumes); + //REG_FUNC(0xA0F5402D, sceNgsVoicePatchSetVolumesMatrix); + //REG_FUNC(0xF6B68C31, sceNgsVoiceDefGetEnvelopeBuss); + //REG_FUNC(0x9DCF50F5, sceNgsVoiceDefGetReverbBuss); + //REG_FUNC(0x214485D6, sceNgsVoiceDefGetPauserBuss); + //REG_FUNC(0xE0AC8776, sceNgsVoiceDefGetMixerBuss); + //REG_FUNC(0x79A121D1, sceNgsVoiceDefGetMasterBuss); + //REG_FUNC(0x0E0ACB68, sceNgsVoiceDefGetCompressorBuss); + //REG_FUNC(0x1AF83512, sceNgsVoiceDefGetCompressorSideChainBuss); + //REG_FUNC(0xAAD90DEB, sceNgsVoiceDefGetDistortionBuss); + //REG_FUNC(0xF964120E, sceNgsVoiceDefGetEqBuss); + //REG_FUNC(0xE9B572B7, sceNgsVoiceDefGetTemplate1); + //REG_FUNC(0x0D5399CF, sceNgsVoiceDefGetSimpleVoice); + //REG_FUNC(0x1F51C2BA, sceNgsVoiceDefGetSasEmuVoice); + //REG_FUNC(0x4CBE08F3, sceNgsVoiceGetParamsOutOfRange); + //REG_FUNC(0x14EF65A0, sceNgsVoiceDefGetAtrac9Voice); + //REG_FUNC(0x4D705E3E, sceNgsVoiceDefGetDelayBuss); + //REG_FUNC(0x5FD8AEDB, sceSulphaNgsGetDefaultConfig); + //REG_FUNC(0x793E3E8C, sceSulphaNgsGetNeededMemory); + //REG_FUNC(0xAFCD824F, sceSulphaNgsInit); + //REG_FUNC(0xD124BFB1, sceSulphaNgsShutdown); + //REG_FUNC(0x2F3F7515, sceSulphaNgsSetSynthName); + //REG_FUNC(0x251AF6A9, sceSulphaNgsSetRackName); + //REG_FUNC(0x508975BD, sceSulphaNgsSetVoiceName); + //REG_FUNC(0x54EC5B8D, sceSulphaNgsSetSampleName); + //REG_FUNC(0xDC7C0F05, sceSulphaNgsTrace); + //REG_FUNC(0x5C71FE09, sceNgsModuleGetNumPresets); + //REG_FUNC(0xC58298A7, sceNgsModuleGetPreset); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp new file mode 100644 index 0000000000..1afa85a9cc --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp @@ -0,0 +1,33 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNpBasic; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpBasic, #name, name) + +psv_log_base sceNpBasic("SceNpBasic", []() +{ + sceNpBasic.on_load = nullptr; + sceNpBasic.on_unload = nullptr; + sceNpBasic.on_stop = nullptr; + + //REG_FUNC(0xEFB91A99, sceNpBasicInit); + //REG_FUNC(0x389BCB3B, sceNpBasicTerm); + //REG_FUNC(0x26E6E048, sceNpBasicRegisterHandler); + //REG_FUNC(0x050AE072, sceNpBasicUnregisterHandler); + //REG_FUNC(0x20146AEC, sceNpBasicCheckCallback); + //REG_FUNC(0x5183A4B5, sceNpBasicGetFriendOnlineStatus); + //REG_FUNC(0xEF8A91BC, sceNpBasicGetGamePresenceOfFriend); + //REG_FUNC(0xDF41F308, sceNpBasicGetFriendListEntryCount); + //REG_FUNC(0xFF07E787, sceNpBasicGetFriendListEntries); + //REG_FUNC(0x407E1E6F, sceNpBasicGetBlockListEntryCount); + //REG_FUNC(0x1211AE8E, sceNpBasicGetBlockListEntries); + //REG_FUNC(0xF51545D8, sceNpBasicCheckIfPlayerIsBlocked); + //REG_FUNC(0x51D75562, sceNpBasicSetInGamePresence); + //REG_FUNC(0xD20C2370, sceNpBasicUnsetInGamePresence); + //REG_FUNC(0x7A5020A5, sceNpBasicSendInGameDataMessage); + //REG_FUNC(0x3B0A7F47, sceNpBasicRecordPlaySessionLog); + //REG_FUNC(0xFB0F7FDF, sceNpBasicGetPlaySessionLogSize); + //REG_FUNC(0x364531A8, sceNpBasicGetPlaySessionLog); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp new file mode 100644 index 0000000000..4422bee950 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp @@ -0,0 +1,26 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNpCommon; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpCommon, #name, name) + +psv_log_base sceNpCommon("SceNpCommon", []() +{ + sceNpCommon.on_load = nullptr; + sceNpCommon.on_unload = nullptr; + sceNpCommon.on_stop = nullptr; + + //REG_FUNC(0x441D8B4E, sceNpAuthInit); + //REG_FUNC(0x6093B689, sceNpAuthTerm); + //REG_FUNC(0xED42079F, sceNpAuthCreateStartRequest); + //REG_FUNC(0x14FC18AF, sceNpAuthDestroyRequest); + //REG_FUNC(0xE2582575, sceNpAuthAbortRequest); + //REG_FUNC(0x59608D1C, sceNpAuthGetTicket); + //REG_FUNC(0xC1E23E01, sceNpAuthGetTicketParam); + //REG_FUNC(0x3377CD37, sceNpAuthGetEntitlementIdList); + //REG_FUNC(0xF93842F0, sceNpAuthGetEntitlementById); + //REG_FUNC(0xFB8D82E5, sceNpCmpNpId); + //REG_FUNC(0x6BC8150A, sceNpCmpNpIdInOrder); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp new file mode 100644 index 0000000000..4771107b92 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp @@ -0,0 +1,25 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNpManager; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpManager, #name, name) + +psv_log_base sceNpManager("SceNpManager", []() +{ + sceNpManager.on_load = nullptr; + sceNpManager.on_unload = nullptr; + sceNpManager.on_stop = nullptr; + + //REG_FUNC(0x04D9F484, sceNpInit); + //REG_FUNC(0x19E40AE1, sceNpTerm); + //REG_FUNC(0x3C94B4B4, sceNpManagerGetNpId); + //REG_FUNC(0x54060DF6, sceNpGetServiceState); + //REG_FUNC(0x44239C35, sceNpRegisterServiceStateCallback); + //REG_FUNC(0xD9E6E56C, sceNpUnregisterServiceStateCallback); + //REG_FUNC(0x3B0AE9A9, sceNpCheckCallback); + //REG_FUNC(0xFE835967, sceNpManagerGetAccountRegion); + //REG_FUNC(0xAF0073B2, sceNpManagerGetContentRatingFlag); + //REG_FUNC(0x60C575B1, sceNpManagerGetChatRestrictionFlag); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp new file mode 100644 index 0000000000..ffc7d962a7 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp @@ -0,0 +1,46 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNpMatching; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpMatching, #name, name) + +psv_log_base sceNpMatching("SceNpMatching2", []() +{ + sceNpMatching.on_load = nullptr; + sceNpMatching.on_unload = nullptr; + sceNpMatching.on_stop = nullptr; + + //REG_FUNC(0xEBB1FE74, sceNpMatching2Init); + //REG_FUNC(0x0124641C, sceNpMatching2Term); + //REG_FUNC(0xADF578E1, sceNpMatching2CreateContext); + //REG_FUNC(0x368AA759, sceNpMatching2DestroyContext); + //REG_FUNC(0xBB2E7559, sceNpMatching2ContextStart); + //REG_FUNC(0xF2847E3B, sceNpMatching2AbortContextStart); + //REG_FUNC(0x506454DE, sceNpMatching2ContextStop); + //REG_FUNC(0xF3A43C50, sceNpMatching2SetDefaultRequestOptParam); + //REG_FUNC(0xF486991B, sceNpMatching2RegisterRoomEventCallback); + //REG_FUNC(0xFA51949B, sceNpMatching2RegisterRoomMessageCallback); + //REG_FUNC(0xF9E35566, sceNpMatching2RegisterContextCallback); + //REG_FUNC(0x74EB6CE9, sceNpMatching2AbortRequest); + //REG_FUNC(0x7BD39E50, sceNpMatching2GetMemoryInfo); + //REG_FUNC(0x65C0FEED, sceNpMatching2GetServerLocal); + //REG_FUNC(0xC086B560, sceNpMatching2GetWorldInfoList); + //REG_FUNC(0x818A9499, sceNpMatching2CreateJoinRoom); + //REG_FUNC(0xD48BAF13, sceNpMatching2SearchRoom); + //REG_FUNC(0x33F7D5AE, sceNpMatching2JoinRoom); + //REG_FUNC(0xC8B0C9EE, sceNpMatching2LeaveRoom); + //REG_FUNC(0x495D2B46, sceNpMatching2GetSignalingOptParamLocal); + //REG_FUNC(0xE0BE0510, sceNpMatching2SendRoomChatMessage); + //REG_FUNC(0x7B908D99, sceNpMatching2SendRoomMessage); + //REG_FUNC(0x4E4C55BD, sceNpMatching2SignalingGetConnectionStatus); + //REG_FUNC(0x20598618, sceNpMatching2SignalingGetConnectionInfo); + //REG_FUNC(0x79310806, sceNpMatching2SignalingGetLocalNetInfo); + //REG_FUNC(0xF0CB1DD3, sceNpMatching2SignalingGetPeerNetInfo); + //REG_FUNC(0xADCD102C, sceNpMatching2SignalingCancelPeerNetInfo); + //REG_FUNC(0xFDC7B2C9, sceNpMatching2SignalingGetPeerNetInfoResult); + //REG_FUNC(0x1C60BC5B, sceNpMatching2RegisterSignalingCallback); + //REG_FUNC(0x8F88AC7E, sceNpMatching2SetRoomDataExternal); + //REG_FUNC(0xA8021394, sceNpMatching2KickoutRoomMember); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp new file mode 100644 index 0000000000..612114af70 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp @@ -0,0 +1,44 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNpScore; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpScore, #name, name) + +psv_log_base sceNpScore("SceNpScore", []() +{ + sceNpScore.on_load = nullptr; + sceNpScore.on_unload = nullptr; + sceNpScore.on_stop = nullptr; + + //REG_FUNC(0x0433069F, sceNpScoreInit); + //REG_FUNC(0x2050F98F, sceNpScoreTerm); + //REG_FUNC(0x5685F225, sceNpScoreCreateTitleCtx); + //REG_FUNC(0xD30D1993, sceNpScoreCreateRequest); + //REG_FUNC(0xF52EA88A, sceNpScoreDeleteTitleCtx); + //REG_FUNC(0xFFF24BB1, sceNpScoreDeleteRequest); + //REG_FUNC(0x320C0277, sceNpScoreRecordScore); + //REG_FUNC(0x24B09634, sceNpScoreRecordScoreAsync); + //REG_FUNC(0xC2862B67, sceNpScoreRecordGameData); + //REG_FUNC(0x40573917, sceNpScoreRecordGameDataAsync); + //REG_FUNC(0xDFAD64D3, sceNpScoreGetGameData); + //REG_FUNC(0xCE416993, sceNpScoreGetGameDataAsync); + //REG_FUNC(0x427D3412, sceNpScoreGetRankingByRange); + //REG_FUNC(0xC45E3FCD, sceNpScoreGetRankingByRangeAsync); + //REG_FUNC(0xBAE55B34, sceNpScoreGetRankingByNpId); + //REG_FUNC(0x45CD1D00, sceNpScoreGetRankingByNpIdAsync); + //REG_FUNC(0x871F28AA, sceNpScoreGetRankingByNpIdPcId); + //REG_FUNC(0xCE3A9544, sceNpScoreGetRankingByNpIdPcIdAsync); + //REG_FUNC(0xA7E93CE1, sceNpScoreAbortRequest); + //REG_FUNC(0x31733BF3, sceNpScoreWaitAsync); + //REG_FUNC(0x9F2A7AC9, sceNpScorePollAsync); + //REG_FUNC(0x00F90E7B, sceNpScoreGetBoardInfo); + //REG_FUNC(0x3CD9974E, sceNpScoreGetBoardInfoAsync); + //REG_FUNC(0xA0C94D46, sceNpScoreCensorComment); + //REG_FUNC(0xAA0BBF8E, sceNpScoreCensorCommentAsync); + //REG_FUNC(0x6FD2041A, sceNpScoreSanitizeComment); + //REG_FUNC(0x15981858, sceNpScoreSanitizeCommentAsync); + //REG_FUNC(0x5EF44841, sceNpScoreSetTimeout); + //REG_FUNC(0x53D77883, sceNpScoreSetPlayerCharacterId); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp new file mode 100644 index 0000000000..5ce2ca80ad --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp @@ -0,0 +1,35 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceNpUtility; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpUtility, #name, name) + +psv_log_base sceNpUtility("SceNpUtility", []() +{ + sceNpUtility.on_load = nullptr; + sceNpUtility.on_unload = nullptr; + sceNpUtility.on_stop = nullptr; + + //REG_FUNC(0x9246A673, sceNpLookupInit); + //REG_FUNC(0x0158B61B, sceNpLookupTerm); + //REG_FUNC(0x5110E17E, sceNpLookupCreateTitleCtx); + //REG_FUNC(0x33B64699, sceNpLookupDeleteTitleCtx); + //REG_FUNC(0x9E42E922, sceNpLookupCreateRequest); + //REG_FUNC(0x8B608BF6, sceNpLookupDeleteRequest); + //REG_FUNC(0x027587C4, sceNpLookupAbortRequest); + //REG_FUNC(0xB0C9DC45, sceNpLookupSetTimeout); + //REG_FUNC(0xCF956F23, sceNpLookupWaitAsync); + //REG_FUNC(0xFCDBA234, sceNpLookupPollAsync); + //REG_FUNC(0xB1A14879, sceNpLookupNpId); + //REG_FUNC(0x5387BABB, sceNpLookupNpIdAsync); + //REG_FUNC(0x6A1BF429, sceNpLookupUserProfile); + //REG_FUNC(0xE5285E0F, sceNpLookupUserProfileAsync); + //REG_FUNC(0xFDB0AE47, sceNpLookupAvatarImage); + //REG_FUNC(0x282BD43C, sceNpLookupAvatarImageAsync); + //REG_FUNC(0x081FA13C, sceNpBandwidthTestInitStart); + //REG_FUNC(0xE0EBFBF6, sceNpBandwidthTestGetStatus); + //REG_FUNC(0x58D92EFD, sceNpBandwidthTestShutdown); + //REG_FUNC(0x32B068C4, sceNpBandwidthTestAbort); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/scePgf.cpp b/rpcs3/Emu/ARMv7/Modules/scePgf.cpp new file mode 100644 index 0000000000..c4a1f21065 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/scePgf.cpp @@ -0,0 +1,38 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base scePgf; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &scePgf, #name, name) + +psv_log_base scePgf("ScePgf", []() +{ + scePgf.on_load = nullptr; + scePgf.on_unload = nullptr; + scePgf.on_stop = nullptr; + + //REG_FUNC(0x1055ABA3, sceFontNewLib); + //REG_FUNC(0x07EE1733, sceFontDoneLib); + //REG_FUNC(0xDE47674C, sceFontSetResolution); + //REG_FUNC(0x9F842307, sceFontGetNumFontList); + //REG_FUNC(0xD56DCCEA, sceFontGetFontList); + //REG_FUNC(0x8DFBAE1B, sceFontFindOptimumFont); + //REG_FUNC(0x51061D87, sceFontFindFont); + //REG_FUNC(0xAB034738, sceFontGetFontInfoByIndexNumber); + //REG_FUNC(0xBD2DFCFF, sceFontOpen); + //REG_FUNC(0xE260E740, sceFontOpenUserFile); + //REG_FUNC(0xB23ED47C, sceFontOpenUserMemory); + //REG_FUNC(0x4A7293E9, sceFontClose); + //REG_FUNC(0xF9414FA2, sceFontGetFontInfo); + //REG_FUNC(0x6FD1BA65, sceFontGetCharInfo); + //REG_FUNC(0x70C86B3E, sceFontGetCharImageRect); + //REG_FUNC(0xAB45AAD3, sceFontGetCharGlyphImage); + //REG_FUNC(0xEB589530, sceFontGetCharGlyphImage_Clip); + //REG_FUNC(0x9E38F4D6, sceFontPixelToPointH); + //REG_FUNC(0x7B45E2D1, sceFontPixelToPointV); + //REG_FUNC(0x39B9AEFF, sceFontPointToPixelH); + //REG_FUNC(0x03F10EC8, sceFontPointToPixelV); + //REG_FUNC(0x8D5B44DF, sceFontSetAltCharacterCode); + //REG_FUNC(0x7D8CB13B, sceFontFlush); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp b/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp new file mode 100644 index 0000000000..2fab7c29d4 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp @@ -0,0 +1,17 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base scePhotoExport; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &scePhotoExport, #name, name) + +psv_log_base scePhotoExport("ScePhotoExport", []() +{ + scePhotoExport.on_load = nullptr; + scePhotoExport.on_unload = nullptr; + scePhotoExport.on_stop = nullptr; + + //REG_FUNC(0x70512321, scePhotoExportFromData); + //REG_FUNC(0x84FD9FC5, scePhotoExportFromFile); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp b/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp new file mode 100644 index 0000000000..4eaeb11070 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp @@ -0,0 +1,18 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceRazorCapture; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceRazorCapture, #name, name) + +psv_log_base sceRazorCapture("SceRazorCapture", []() +{ + sceRazorCapture.on_load = nullptr; + sceRazorCapture.on_unload = nullptr; + sceRazorCapture.on_stop = nullptr; + + //REG_FUNC(0x911E0AA0, sceRazorCaptureIsInProgress); + //REG_FUNC(0xE916B538, sceRazorCaptureSetTrigger); + //REG_FUNC(0x3D4B7E68, sceRazorCaptureSetTriggerNextFrame); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp new file mode 100644 index 0000000000..72d81d8e15 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp @@ -0,0 +1,52 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceRtc; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceRtc, #name, name) + +psv_log_base sceRtc("SceRtc", []() +{ + sceRtc.on_load = nullptr; + sceRtc.on_unload = nullptr; + sceRtc.on_stop = nullptr; + + //REG_FUNC(0x23F79274, sceRtcGetCurrentTick); + //REG_FUNC(0xCDDD25FE, sceRtcGetCurrentNetworkTick); + //REG_FUNC(0x70FDE8F1, sceRtcGetCurrentClock); + //REG_FUNC(0x0572EDDC, sceRtcGetCurrentClockLocalTime); + //REG_FUNC(0x1282C436, sceRtcConvertUtcToLocalTime); + //REG_FUNC(0x0A05E201, sceRtcConvertLocalTimeToUtc); + //REG_FUNC(0x42CA8EB5, sceRtcFormatRFC2822LocalTime); + //REG_FUNC(0x147F2138, sceRtcFormatRFC2822); + //REG_FUNC(0x742250A9, sceRtcFormatRFC3339LocalTime); + //REG_FUNC(0xCCEA2B54, sceRtcFormatRFC3339); + //REG_FUNC(0xF17FD8B5, sceRtcIsLeapYear); + //REG_FUNC(0x49EB4556, sceRtcGetDaysInMonth); + //REG_FUNC(0x2F3531EB, sceRtcGetDayOfWeek); + //REG_FUNC(0xD7622935, sceRtcCheckValid); + //REG_FUNC(0x3A332F81, sceRtcSetTime_t); + //REG_FUNC(0xA6C36B6A, sceRtcSetTime64_t); + //REG_FUNC(0x8DE6FEB7, sceRtcGetTime_t); + //REG_FUNC(0xC995DE02, sceRtcGetTime64_t); + //REG_FUNC(0xF8B22B07, sceRtcSetDosTime); + //REG_FUNC(0x92ABEBAF, sceRtcGetDosTime); + //REG_FUNC(0xA79A8846, sceRtcSetWin32FileTime); + //REG_FUNC(0x8A95E119, sceRtcGetWin32FileTime); + //REG_FUNC(0x811313B3, sceRtcGetTickResolution); + //REG_FUNC(0xCD89F464, sceRtcSetTick); + //REG_FUNC(0xF2B238E2, sceRtcGetTick); + //REG_FUNC(0xC7385158, sceRtcCompareTick); + //REG_FUNC(0x4559E2DB, sceRtcTickAddTicks); + //REG_FUNC(0xAE26D920, sceRtcTickAddMicroseconds); + //REG_FUNC(0x979AFD79, sceRtcTickAddSeconds); + //REG_FUNC(0x4C358871, sceRtcTickAddMinutes); + //REG_FUNC(0x6F193F55, sceRtcTickAddHours); + //REG_FUNC(0x58DE3C70, sceRtcTickAddDays); + //REG_FUNC(0xE713C640, sceRtcTickAddWeeks); + //REG_FUNC(0x6321B4AA, sceRtcTickAddMonths); + //REG_FUNC(0xDF6C3E1B, sceRtcTickAddYears); + //REG_FUNC(0x2347CE12, sceRtcParseDateTime); + //REG_FUNC(0x2D18AEEC, sceRtcParseRFC3339); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSas.cpp b/rpcs3/Emu/ARMv7/Modules/sceSas.cpp new file mode 100644 index 0000000000..0db6b65e16 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSas.cpp @@ -0,0 +1,64 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSas; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSas, #name, name) + +psv_log_base sceSas("SceSas", []() +{ + sceSas.on_load = nullptr; + sceSas.on_unload = nullptr; + sceSas.on_stop = nullptr; + + //REG_FUNC(0xA2209C58, sceAsSetRegisterReportHandler); + //REG_FUNC(0xBB635544, sceAsSetUnregisterReportHandler); + //REG_FUNC(0xF578F0EF, sceAsGetSystemNeededMemory); + //REG_FUNC(0xAA8D4541, sceAsCreateSystem); + //REG_FUNC(0x139D29C0, sceAsDestroySystem); + //REG_FUNC(0xBE843EEC, sceAsLockParam); + //REG_FUNC(0xFF2380C4, sceAsUnlockParam); + //REG_FUNC(0x2549F436, sceAsSetEvent); + //REG_FUNC(0xDC26B9F2, sceAsGetState); + //REG_FUNC(0xB6220E73, sceAsSetBuss); + //REG_FUNC(0x1E608068, sceAsSetRacks); + //REG_FUNC(0x5835B473, sceAsSetGranularity); + //REG_FUNC(0xDFE6502F, sceAsGetGranularity); + //REG_FUNC(0xC72F1EEF, sceAsRender); + //REG_FUNC(0xCE23F057, sceAsLockUpdate); + //REG_FUNC(0x8BEF3C92, sceAsUnlockUpdate); + //REG_FUNC(0x180C6824, sceSasGetNeededMemorySize); + //REG_FUNC(0x449B5974, sceSasInit); + //REG_FUNC(0x820D5F82, sceSasInitWithGrain); + //REG_FUNC(0xBB7D6790, sceSasExit); + //REG_FUNC(0x2B4A207C, sceSasSetGrain); + //REG_FUNC(0x2BEA45BC, sceSasGetGrain); + //REG_FUNC(0x44DDB3C4, sceSasSetOutputmode); + //REG_FUNC(0x2C36E150, sceSasGetOutputmode); + //REG_FUNC(0x7A4672B2, sceSasCore); + //REG_FUNC(0xBD496983, sceSasCoreWithMix); + //REG_FUNC(0x2B75F9BC, sceSasSetVoice); + //REG_FUNC(0xB1756EFC, sceSasSetVoicePCM); + //REG_FUNC(0xF1C63CB9, sceSasSetNoise); + //REG_FUNC(0x0BE8204D, sceSasSetVolume); + //REG_FUNC(0x011788BE, sceSasSetDistortion); + //REG_FUNC(0x2C48A08C, sceSasSetPitch); + //REG_FUNC(0x18A5EFA2, sceSasSetADSR); + //REG_FUNC(0x5207F9D2, sceSasSetADSRmode); + //REG_FUNC(0xDE6227B8, sceSasSetSL); + //REG_FUNC(0xECCE0DB8, sceSasSetSimpleADSR); + //REG_FUNC(0xC838DB6F, sceSasSetKeyOn); + //REG_FUNC(0x5E42ADAB, sceSasSetKeyOff); + //REG_FUNC(0x59C7A9DF, sceSasSetPause); + //REG_FUNC(0x007E63E6, sceSasGetEndState); + //REG_FUNC(0xFD1A0CBF, sceSasGetPauseState); + //REG_FUNC(0x296A9910, sceSasGetEnvelope); + //REG_FUNC(0xB0444E69, sceSasSetEffect); + //REG_FUNC(0xCDF2DDD5, sceSasSetEffectType); + //REG_FUNC(0x55EDDBFA, sceSasSetEffectVolume); + //REG_FUNC(0xBAD546A0, sceSasSetEffectParam); + //REG_FUNC(0xB6642276, sceSasGetDryPeak); + //REG_FUNC(0x4314F0E9, sceSasGetWetPeak); + //REG_FUNC(0x1568017A, sceSasGetPreMasterPeak); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp b/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp new file mode 100644 index 0000000000..47ab0d614c --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp @@ -0,0 +1,19 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceScreenShot; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceScreenShot, #name, name) + +psv_log_base sceScreenShot("SceScreenShot", []() +{ + sceScreenShot.on_load = nullptr; + sceScreenShot.on_unload = nullptr; + sceScreenShot.on_stop = nullptr; + + //REG_FUNC(0x05DB59C7, sceScreenShotSetParam); + //REG_FUNC(0x7061665B, sceScreenShotSetOverlayImage); + //REG_FUNC(0x50AE9FF9, sceScreenShotDisable); + //REG_FUNC(0x76E674D1, sceScreenShotEnable); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSfmt.cpp b/rpcs3/Emu/ARMv7/Modules/sceSfmt.cpp new file mode 100644 index 0000000000..e6d2f2a4be --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSfmt.cpp @@ -0,0 +1,84 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSfmt; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSfmt, #name, name) + +psv_log_base sceSfmt("SceSfmt", []() +{ + sceSfmt.on_load = nullptr; + sceSfmt.on_unload = nullptr; + sceSfmt.on_stop = nullptr; + + //REG_FUNC(0x8FF464C9, sceSfmt11213InitGenRand); + //REG_FUNC(0xBAF5F058, sceSfmt11213InitByArray); + //REG_FUNC(0xFB281CD7, sceSfmt11213GenRand32); + //REG_FUNC(0xAFEDD6E1, sceSfmt11213GenRand64); + //REG_FUNC(0xFD696585, sceSfmt11213FillArray32); + //REG_FUNC(0x7A412A29, sceSfmt11213FillArray64); + + //REG_FUNC(0x02E8D906, sceSfmt1279InitGenRand); + //REG_FUNC(0xC25D9ACE, sceSfmt1279InitByArray); + //REG_FUNC(0x9B4A48DF, sceSfmt1279GenRand32); + //REG_FUNC(0xA2C5EE14, sceSfmt1279GenRand64); + //REG_FUNC(0xE7F63838, sceSfmt1279FillArray32); + //REG_FUNC(0xDB3832EB, sceSfmt1279FillArray64); + + //REG_FUNC(0xDC6B23B0, sceSfmt132049InitGenRand); + //REG_FUNC(0xDC69294A, sceSfmt132049InitByArray); + //REG_FUNC(0x795F9644, sceSfmt132049GenRand32); + //REG_FUNC(0xBBD80AC4, sceSfmt132049GenRand64); + //REG_FUNC(0xD891A99F, sceSfmt132049FillArray32); + //REG_FUNC(0x68AD7866, sceSfmt132049FillArray64); + + //REG_FUNC(0x2AFACB0B, sceSfmt19937InitGenRand); + //REG_FUNC(0xAC496C8C, sceSfmt19937InitByArray); + //REG_FUNC(0xF0557157, sceSfmt19937GenRand32); + //REG_FUNC(0xE66F2502, sceSfmt19937GenRand64); + //REG_FUNC(0xA1C654D8, sceSfmt19937FillArray32); + //REG_FUNC(0xE74BA81C, sceSfmt19937FillArray64); + + //REG_FUNC(0x86DDE4A7, sceSfmt216091InitGenRand); + //REG_FUNC(0xA9CF6616, sceSfmt216091InitByArray); + //REG_FUNC(0x4A972DCD, sceSfmt216091GenRand32); + //REG_FUNC(0x23369ABF, sceSfmt216091GenRand64); + //REG_FUNC(0xDD4256F0, sceSfmt216091FillArray32); + //REG_FUNC(0xA1CE5628, sceSfmt216091FillArray64); + + //REG_FUNC(0xB8E5A0BB, sceSfmt2281InitGenRand); + //REG_FUNC(0xAB3AD459, sceSfmt2281InitByArray); + //REG_FUNC(0x84BB4ADB, sceSfmt2281GenRand32); + //REG_FUNC(0x3CC47146, sceSfmt2281GenRand64); + //REG_FUNC(0xBB89D8F0, sceSfmt2281FillArray32); + //REG_FUNC(0x17C10E2D, sceSfmt2281FillArray64); + + //REG_FUNC(0xE9F8CB9A, sceSfmt4253InitGenRand); + //REG_FUNC(0xC4D7AA2D, sceSfmt4253InitByArray); + //REG_FUNC(0x8791E2EF, sceSfmt4253GenRand32); + //REG_FUNC(0x6C0E5E3C, sceSfmt4253GenRand64); + //REG_FUNC(0x59A1B9FC, sceSfmt4253FillArray32); + //REG_FUNC(0x01683CDD, sceSfmt4253FillArray64); + + //REG_FUNC(0xCF1C8C38, sceSfmt44497InitGenRand); + //REG_FUNC(0x16D8AA5E, sceSfmt44497InitByArray); + //REG_FUNC(0xF869DFDC, sceSfmt44497GenRand32); + //REG_FUNC(0xD411A9A6, sceSfmt44497GenRand64); + //REG_FUNC(0x1C38322A, sceSfmt44497FillArray32); + //REG_FUNC(0x908F1122, sceSfmt44497FillArray64); + + //REG_FUNC(0x76A5D8CA, sceSfmt607InitGenRand); + //REG_FUNC(0xCC6DABA0, sceSfmt607InitByArray); + //REG_FUNC(0x8A0BF859, sceSfmt607GenRand32); + //REG_FUNC(0x5E880862, sceSfmt607GenRand64); + //REG_FUNC(0xA288ADB9, sceSfmt607FillArray32); + //REG_FUNC(0x1520D408, sceSfmt607FillArray64); + + //REG_FUNC(0x2FF42588, sceSfmt86243InitGenRand); + //REG_FUNC(0x81B67AB5, sceSfmt86243InitByArray); + //REG_FUNC(0x569BF903, sceSfmt86243GenRand32); + //REG_FUNC(0x8E25CBA8, sceSfmt86243GenRand64); + //REG_FUNC(0xC297E6B1, sceSfmt86243FillArray32); + //REG_FUNC(0xF7FFE87C, sceSfmt86243FillArray64); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSha.cpp b/rpcs3/Emu/ARMv7/Modules/sceSha.cpp new file mode 100644 index 0000000000..5ec792b06d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSha.cpp @@ -0,0 +1,44 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSha; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSha, #name, name) + +psv_log_base sceSha("SceSha", []() +{ + sceSha.on_load = nullptr; + sceSha.on_unload = nullptr; + sceSha.on_stop = nullptr; + + //REG_FUNC(0xD19A9AA8, sceSha0Digest); + //REG_FUNC(0xBCF6DB3A, sceSha0BlockInit); + //REG_FUNC(0x37EF2AFC, sceSha0BlockUpdate); + //REG_FUNC(0xBF0158C4, sceSha0BlockResult); + + //REG_FUNC(0xE1215C9D, sceSha1Digest); + //REG_FUNC(0xB13D65AA, sceSha1BlockInit); + //REG_FUNC(0x9007205E, sceSha1BlockUpdate); + //REG_FUNC(0x0195DADF, sceSha1BlockResult); + + //REG_FUNC(0x1346D270, sceSha224Digest); + //REG_FUNC(0x538F04CE, sceSha224BlockInit); + //REG_FUNC(0xB5FD0160, sceSha224BlockUpdate); + //REG_FUNC(0xA36ECF65, sceSha224BlockResult); + + //REG_FUNC(0xA337079C, sceSha256Digest); + //REG_FUNC(0xE281374F, sceSha256BlockInit); + //REG_FUNC(0xDAECA1F8, sceSha256BlockUpdate); + //REG_FUNC(0x9B5BB4BA, sceSha256BlockResult); + + //REG_FUNC(0xA602C694, sceSha384Digest); + //REG_FUNC(0x037AABE7, sceSha384BlockInit); + //REG_FUNC(0x4B99DBB8, sceSha384BlockUpdate); + //REG_FUNC(0x30D5C919, sceSha384BlockResult); + + //REG_FUNC(0x5DC0B916, sceSha512Digest); + //REG_FUNC(0xE017A9CD, sceSha512BlockInit); + //REG_FUNC(0x669281E8, sceSha512BlockUpdate); + //REG_FUNC(0x26146A16, sceSha512BlockResult); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSqlite.cpp b/rpcs3/Emu/ARMv7/Modules/sceSqlite.cpp new file mode 100644 index 0000000000..19f560c963 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSqlite.cpp @@ -0,0 +1,187 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSqlite; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSqlite, #name, name) + +psv_log_base sceSqlite("SceSqlite", []() +{ + sceSqlite.on_load = nullptr; + sceSqlite.on_unload = nullptr; + sceSqlite.on_stop = nullptr; + + //REG_FUNC(0x26E46324, sqlite3_libversion); + //REG_FUNC(0x4CCB58A2, sqlite3_sourceid); + //REG_FUNC(0x5982F404, sqlite3_libversion_number); + //REG_FUNC(0xA3B818DA, sqlite3_threadsafe); + //REG_FUNC(0x7DF94B79, sqlite3_close); + //REG_FUNC(0x2371E86A, sqlite3_exec); + //REG_FUNC(0xC22AF627, sqlite3_initialize); + //REG_FUNC(0x99B5A4A3, sqlite3_shutdown); + //REG_FUNC(0xBD304836, sqlite3_os_init); + //REG_FUNC(0x9CE7C4C3, sqlite3_os_end); + //REG_FUNC(0x96C5D388, sqlite3_config); + //REG_FUNC(0xADFB25C0, sqlite3_db_config); + //REG_FUNC(0x3892C4B8, sqlite3_extended_result_codes); + //REG_FUNC(0x301851A1, sqlite3_last_insert_rowid); + //REG_FUNC(0xF206FBA1, sqlite3_changes); + //REG_FUNC(0x02ADA92D, sqlite3_total_changes); + //REG_FUNC(0x3CB771AC, sqlite3_interrupt); + //REG_FUNC(0x2E28B2A7, sqlite3_complete); + //REG_FUNC(0x4EAB317B, sqlite3_complete16); + //REG_FUNC(0xB5B5D287, sqlite3_busy_handler); + //REG_FUNC(0xAE8E3630, sqlite3_busy_timeout); + //REG_FUNC(0xF2AB9C89, sqlite3_get_table); + //REG_FUNC(0x1FEC6959, sqlite3_free_table); + //REG_FUNC(0xE630216C, sqlite3_mprintf); + //REG_FUNC(0xC6372184, sqlite3_vmprintf); + //REG_FUNC(0xCC189941, sqlite3_snprintf); + //REG_FUNC(0xF01DEB95, sqlite3_malloc); + //REG_FUNC(0xD1CF5631, sqlite3_realloc); + //REG_FUNC(0xCBF0CA8A, sqlite3_free); + //REG_FUNC(0x8E4F6ED5, sqlite3_memory_used); + //REG_FUNC(0x2F33DAD6, sqlite3_memory_highwater); + //REG_FUNC(0x5A2590BF, sqlite3_randomness); + //REG_FUNC(0x77FB3458, sqlite3_set_authorizer); + //REG_FUNC(0xFC127A83, sqlite3_trace); + //REG_FUNC(0x48B789A1, sqlite3_profile); + //REG_FUNC(0x19165D04, sqlite3_progress_handler); + //REG_FUNC(0x8E506859, sqlite3_open); + //REG_FUNC(0x881EEDD8, sqlite3_open16); + //REG_FUNC(0xA1E98A41, sqlite3_open_v2); + //REG_FUNC(0xA7AAE2E7, sqlite3_errcode); + //REG_FUNC(0x91187282, sqlite3_extended_errcode); + //REG_FUNC(0xABFB8B6E, sqlite3_errmsg); + //REG_FUNC(0xF0DE1A97, sqlite3_errmsg16); + //REG_FUNC(0xDED2D517, sqlite3_limit); + //REG_FUNC(0x0C1B5509, sqlite3_prepare); + //REG_FUNC(0xBC4BDCF4, sqlite3_prepare_v2); + //REG_FUNC(0xC657CFB8, sqlite3_prepare16); + //REG_FUNC(0x426D81D2, sqlite3_prepare16_v2); + //REG_FUNC(0x082C36D4, sqlite3_sql); + //REG_FUNC(0x3F225D62, sqlite3_bind_blob); + //REG_FUNC(0xDE007F1B, sqlite3_bind_double); + //REG_FUNC(0x14ABCBCC, sqlite3_bind_int); + //REG_FUNC(0x43D967EF, sqlite3_bind_int64); + //REG_FUNC(0xFF8A9974, sqlite3_bind_null); + //REG_FUNC(0x613AB709, sqlite3_bind_text); + //REG_FUNC(0x9D0FEAEF, sqlite3_bind_text16); + //REG_FUNC(0x8A667D2A, sqlite3_bind_value); + //REG_FUNC(0x78FBA2D0, sqlite3_bind_zeroblob); + //REG_FUNC(0x17D4F00B, sqlite3_bind_parameter_count); + //REG_FUNC(0x96D3B5F9, sqlite3_bind_parameter_name); + //REG_FUNC(0xD4D2A5D8, sqlite3_bind_parameter_index); + //REG_FUNC(0x690947E2, sqlite3_clear_bindings); + //REG_FUNC(0x8567A8DE, sqlite3_column_count); + //REG_FUNC(0xBC422DF6, sqlite3_column_name); + //REG_FUNC(0x6EF9A642, sqlite3_column_name16); + //REG_FUNC(0x5AE92D67, sqlite3_column_decltype); + //REG_FUNC(0xE058DE60, sqlite3_column_decltype16); + //REG_FUNC(0xCA8755B7, sqlite3_step); + //REG_FUNC(0x61911935, sqlite3_data_count); + //REG_FUNC(0xFE237ED7, sqlite3_column_blob); + //REG_FUNC(0x36013FE4, sqlite3_column_bytes); + //REG_FUNC(0x439F160B, sqlite3_column_bytes16); + //REG_FUNC(0xC4866097, sqlite3_column_double); + //REG_FUNC(0xE5B6BA01, sqlite3_column_int); + //REG_FUNC(0x90BA0B88, sqlite3_column_int64); + //REG_FUNC(0x8E68D270, sqlite3_column_text); + //REG_FUNC(0xD7BD6B76, sqlite3_column_text16); + //REG_FUNC(0xDBB25C43, sqlite3_column_type); + //REG_FUNC(0x2227F21D, sqlite3_column_value); + //REG_FUNC(0xB656B7E2, sqlite3_finalize); + //REG_FUNC(0xA6ECC214, sqlite3_reset); + //REG_FUNC(0xB0543897, sqlite3_create_function); + //REG_FUNC(0x7655FA45, sqlite3_create_function16); + //REG_FUNC(0x6AB02532, sqlite3_aggregate_count); + //REG_FUNC(0xF8AA518B, sqlite3_expired); + //REG_FUNC(0x6EC012E5, sqlite3_transfer_bindings); + //REG_FUNC(0xF48E021B, sqlite3_global_recover); + //REG_FUNC(0x173C9C0B, sqlite3_thread_cleanup); + //REG_FUNC(0x56EDF517, sqlite3_memory_alarm); + //REG_FUNC(0xC9962B31, sqlite3_value_blob); + //REG_FUNC(0x5368EF1F, sqlite3_value_bytes); + //REG_FUNC(0x4D10900D, sqlite3_value_bytes16); + //REG_FUNC(0xF1F2C9BE, sqlite3_value_double); + //REG_FUNC(0x4809A520, sqlite3_value_int); + //REG_FUNC(0xA6581C04, sqlite3_value_int64); + //REG_FUNC(0x7EB97356, sqlite3_value_text); + //REG_FUNC(0x5BBE38C2, sqlite3_value_text16); + //REG_FUNC(0x014863A6, sqlite3_value_text16le); + //REG_FUNC(0x3B89AA8D, sqlite3_value_text16be); + //REG_FUNC(0xC5EEBB5D, sqlite3_value_type); + //REG_FUNC(0x81B7D43D, sqlite3_value_numeric_type); + //REG_FUNC(0xAA8BE477, sqlite3_aggregate_context); + //REG_FUNC(0x78FF81FB, sqlite3_user_data); + //REG_FUNC(0x74259C09, sqlite3_context_db_handle); + //REG_FUNC(0x394FC1CB, sqlite3_get_auxdata); + //REG_FUNC(0x129E01C9, sqlite3_set_auxdata); + //REG_FUNC(0x90CDF8C1, sqlite3_result_blob); + //REG_FUNC(0xC2A5C2F8, sqlite3_result_double); + //REG_FUNC(0x063BFACA, sqlite3_result_error); + //REG_FUNC(0xAB2AEB4A, sqlite3_result_error16); + //REG_FUNC(0xAB9EFF96, sqlite3_result_error_toobig); + //REG_FUNC(0x944E747A, sqlite3_result_error_nomem); + //REG_FUNC(0x1165223C, sqlite3_result_error_code); + //REG_FUNC(0x5C9CD9D4, sqlite3_result_int); + //REG_FUNC(0x0EF1AA07, sqlite3_result_int64); + //REG_FUNC(0x6DE09482, sqlite3_result_null); + //REG_FUNC(0x696B5E6A, sqlite3_result_text); + //REG_FUNC(0x3AF5D206, sqlite3_result_text16); + //REG_FUNC(0x845B4FC2, sqlite3_result_text16le); + //REG_FUNC(0xEE3E906A, sqlite3_result_text16be); + //REG_FUNC(0x09664492, sqlite3_result_value); + //REG_FUNC(0x3D463CF7, sqlite3_result_zeroblob); + //REG_FUNC(0xC61B63FB, sqlite3_create_collation); + //REG_FUNC(0x4B110AF2, sqlite3_create_collation_v2); + //REG_FUNC(0xF7FE99C8, sqlite3_create_collation16); + //REG_FUNC(0x836C99A3, sqlite3_collation_needed); + //REG_FUNC(0x537066CE, sqlite3_collation_needed16); + //REG_FUNC(0x6B88D1D4, sqlite3_sleep); + //REG_FUNC(0x0910C3CB, sqlite3_get_autocommit); + //REG_FUNC(0x2C62429E, sqlite3_db_handle); + //REG_FUNC(0xD257592A, sqlite3_next_stmt); + //REG_FUNC(0x4BAE6E3B, sqlite3_commit_hook); + //REG_FUNC(0x67F53D6B, sqlite3_rollback_hook); + //REG_FUNC(0xEB05FE87, sqlite3_update_hook); + //REG_FUNC(0xF0094BED, sqlite3_enable_shared_cache); + //REG_FUNC(0x8F99FBE5, sqlite3_release_memory); + //REG_FUNC(0xD1458BA7, sqlite3_soft_heap_limit); + //REG_FUNC(0xC9EA8E1F, sqlite3_load_extension); + //REG_FUNC(0x9BFC6F07, sqlite3_enable_load_extension); + //REG_FUNC(0x24738263, sqlite3_auto_extension); + //REG_FUNC(0xC4296FFD, sqlite3_reset_auto_extension); + //REG_FUNC(0x8970C45F, sqlite3_create_module); + //REG_FUNC(0x1AA3BC1A, sqlite3_create_module_v2); + //REG_FUNC(0x7E2A5E8F, sqlite3_declare_vtab); + //REG_FUNC(0xAF680D40, sqlite3_overload_function); + //REG_FUNC(0xD35B3E55, sqlite3_blob_open); + //REG_FUNC(0xC085A15D, sqlite3_blob_close); + //REG_FUNC(0xA07AEEE3, sqlite3_blob_bytes); + //REG_FUNC(0x71393AA4, sqlite3_blob_read); + //REG_FUNC(0xBDB46BCF, sqlite3_blob_write); + //REG_FUNC(0x0C6DD8C3, sqlite3_vfs_find); + //REG_FUNC(0x65F53B9C, sqlite3_vfs_register); + //REG_FUNC(0x69CF4171, sqlite3_vfs_unregister); + //REG_FUNC(0xEEB7839F, sqlite3_mutex_alloc); + //REG_FUNC(0x38E933E2, sqlite3_mutex_free); + //REG_FUNC(0x60DB89C0, sqlite3_mutex_enter); + //REG_FUNC(0x218D700E, sqlite3_mutex_try); + //REG_FUNC(0x545ABDDB, sqlite3_mutex_leave); + //REG_FUNC(0xA8E53D26, sqlite3_db_mutex); + //REG_FUNC(0xBB096FBD, sqlite3_file_control); + //REG_FUNC(0x324D4EFD, sqlite3_test_control); + //REG_FUNC(0xD8C435AA, sqlite3_status); + //REG_FUNC(0xB5DFAF6A, sqlite3_db_status); + //REG_FUNC(0xF7ABF5FA, sqlite3_stmt_status); + //REG_FUNC(0x91DDB12A, sqlite3_backup_init); + //REG_FUNC(0x2A15E081, sqlite3_backup_step); + //REG_FUNC(0x93A6B7EF, sqlite3_backup_finish); + //REG_FUNC(0x9962540B, sqlite3_backup_remaining); + //REG_FUNC(0x20D054CF, sqlite3_backup_pagecount); + //REG_FUNC(0x12E2FC18, sqlite3_strnicmp); + //REG_FUNC(0xB80D43C7, sqlite3_version); + //REG_FUNC(0x1AEC1F74, sqlite3_temp_directory); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp b/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp new file mode 100644 index 0000000000..51032ab5fd --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp @@ -0,0 +1,26 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSsl; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSsl, #name, name) + +psv_log_base sceSsl("SceSsl", []() +{ + sceSsl.on_load = nullptr; + sceSsl.on_unload = nullptr; + sceSsl.on_stop = nullptr; + + //REG_FUNC(0x3C733316, sceSslInit); + //REG_FUNC(0x03CE6E3A, sceSslTerm); + //REG_FUNC(0xBD203262, sceSslGetMemoryPoolStats); + //REG_FUNC(0x901C5C15, sceSslGetSerialNumber); + //REG_FUNC(0x9B2F1BC1, sceSslGetSubjectName); + //REG_FUNC(0x412711E5, sceSslGetIssuerName); + //REG_FUNC(0x70DEA174, sceSslGetNotBefore); + //REG_FUNC(0xF5ED7B68, sceSslGetNotAfter); + //REG_FUNC(0x95E14CA6, sceSslGetNameEntryCount); + //REG_FUNC(0x2A857867, sceSslGetNameEntryInfo); + //REG_FUNC(0xC73687E4, sceSslFreeSslCertName); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp b/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp new file mode 100644 index 0000000000..09c50ce4e9 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp @@ -0,0 +1,38 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSulpha; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSulpha, #name, name) + +psv_log_base sceSulpha("SceSulpha", []() +{ + sceSulpha.on_load = nullptr; + sceSulpha.on_unload = nullptr; + sceSulpha.on_stop = nullptr; + + //REG_FUNC(0xB4668AEA, sceSulphaNetworkInit); + //REG_FUNC(0x0FC71B72, sceSulphaNetworkShutdown); + //REG_FUNC(0xA6A05C50, sceSulphaGetDefaultConfig); + //REG_FUNC(0xD52E5A5A, sceSulphaGetNeededMemory); + //REG_FUNC(0x324F158F, sceSulphaInit); + //REG_FUNC(0x10770BA7, sceSulphaShutdown); + //REG_FUNC(0x920EC7BF, sceSulphaUpdate); + //REG_FUNC(0x7968A138, sceSulphaFileConnect); + //REG_FUNC(0xB16E7B88, sceSulphaFileDisconnect); + //REG_FUNC(0x5E15E164, sceSulphaSetBookmark); + //REG_FUNC(0xC5752B6B, sceSulphaAgentsGetNeededMemory); + //REG_FUNC(0x7ADB454D, sceSulphaAgentsRegister); + //REG_FUNC(0x2A8B74D7, sceSulphaAgentsUnregister); + //REG_FUNC(0xDE7E2911, sceSulphaGetAgent); + //REG_FUNC(0xA41B7402, sceSulphaNodeNew); + //REG_FUNC(0xD44C9F86, sceSulphaNodeDelete); + //REG_FUNC(0xBF61F3B8, sceSulphaEventNew); + //REG_FUNC(0xD5D995A9, sceSulphaEventDelete); + //REG_FUNC(0xB0C2B9CE, sceSulphaEventAdd); + //REG_FUNC(0xBC6A2833, sceSulphaEventReport); + //REG_FUNC(0x29F0DA12, sceSulphaGetTimestamp); + //REG_FUNC(0x951D159D, sceSulphaLogSetLevel); + //REG_FUNC(0x5C6815C6, sceSulphaLogHandler); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp b/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp new file mode 100644 index 0000000000..b70a5a27c4 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceSystemGesture; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceSystemGesture, #name, name) + +psv_log_base sceSystemGesture("SceSystemGesture", []() +{ + sceSystemGesture.on_load = nullptr; + sceSystemGesture.on_unload = nullptr; + sceSystemGesture.on_stop = nullptr; + + //REG_FUNC(0x6078A08B, sceSystemGestureInitializePrimitiveTouchRecognizer); + //REG_FUNC(0xFD5A6504, sceSystemGestureResetPrimitiveTouchRecognizer); + //REG_FUNC(0xB3875104, sceSystemGestureFinalizePrimitiveTouchRecognizer); + //REG_FUNC(0xDF4C665A, sceSystemGestureUpdatePrimitiveTouchRecognizer); + //REG_FUNC(0xC750D3DA, sceSystemGestureGetPrimitiveTouchEvents); + //REG_FUNC(0xBAB8ECCB, sceSystemGestureGetPrimitiveTouchEventsCount); + //REG_FUNC(0xE0577765, sceSystemGestureGetPrimitiveTouchEventByIndex); + //REG_FUNC(0x480564C9, sceSystemGestureGetPrimitiveTouchEventByPrimitiveID); + //REG_FUNC(0xC3367370, sceSystemGestureCreateTouchRecognizer); + //REG_FUNC(0xF0DB1AE5, sceSystemGestureGetTouchRecognizerInformation); + //REG_FUNC(0x0D941B90, sceSystemGestureResetTouchRecognizer); + //REG_FUNC(0x851FB144, sceSystemGestureUpdateTouchRecognizer); + //REG_FUNC(0xA9DB29F6, sceSystemGestureUpdateTouchRecognizerRectangle); + //REG_FUNC(0x789D867C, sceSystemGestureGetTouchEvents); + //REG_FUNC(0x13AD2218, sceSystemGestureGetTouchEventsCount); + //REG_FUNC(0x74724147, sceSystemGestureGetTouchEventByIndex); + //REG_FUNC(0x5570B83E, sceSystemGestureGetTouchEventByEventID); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp b/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp new file mode 100644 index 0000000000..6636644e0d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceTouch; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceTouch, #name, name) + +psv_log_base sceTouch("SceTouch", []() +{ + sceTouch.on_load = nullptr; + sceTouch.on_unload = nullptr; + sceTouch.on_stop = nullptr; + + //REG_FUNC(0x169A1D58, sceTouchRead); + //REG_FUNC(0xFF082DF0, sceTouchPeek); + //REG_FUNC(0x1B9C5D14, sceTouchSetSamplingState); + //REG_FUNC(0x26531526, sceTouchGetSamplingState); + //REG_FUNC(0x10A2CA25, sceTouchGetPanelInfo); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp b/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp new file mode 100644 index 0000000000..6fb390fbd8 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp @@ -0,0 +1,68 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceUlt; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceUlt, #name, name) + +psv_log_base sceUlt("SceUlt", []() +{ + sceUlt.on_load = nullptr; + sceUlt.on_unload = nullptr; + sceUlt.on_stop = nullptr; + + //REG_FUNC(0xEF094E35, _sceUltWaitingQueueResourcePoolOptParamInitialize); + //REG_FUNC(0x644DA029, sceUltWaitingQueueResourcePoolGetWorkAreaSize); + //REG_FUNC(0x62F9493E, _sceUltWaitingQueueResourcePoolCreate); + //REG_FUNC(0xC9E96714, sceUltWaitingQueueResourcePoolDestroy); + //REG_FUNC(0x8A4F88A2, _sceUltQueueDataResourcePoolOptParamInitialize); + //REG_FUNC(0xECDA7FEE, sceUltQueueDataResourcePoolGetWorkAreaSize); + //REG_FUNC(0x40856827, _sceUltQueueDataResourcePoolCreate); + //REG_FUNC(0x2B8D33F1, sceUltQueueDataResourcePoolDestroy); + //REG_FUNC(0x24D87E05, _sceUltMutexOptParamInitialize); + //REG_FUNC(0x5AFEC7A1, _sceUltMutexCreate); + //REG_FUNC(0x001EAC8A, sceUltMutexLock); + //REG_FUNC(0xE5936A69, sceUltMutexTryLock); + //REG_FUNC(0x897C9097, sceUltMutexUnlock); + //REG_FUNC(0xEEBD9052, sceUltMutexDestroy); + //REG_FUNC(0x0603FCC1, _sceUltConditionVariableOptParamInitialize); + //REG_FUNC(0xD76A156C, _sceUltConditionVariableCreate); + //REG_FUNC(0x9FE7CB9F, sceUltConditionVariableSignal); + //REG_FUNC(0xEBB6FC1E, sceUltConditionVariableSignalAll); + //REG_FUNC(0x2CD0F57C, sceUltConditionVariableWait); + //REG_FUNC(0x53420ED2, sceUltConditionVariableDestroy); + //REG_FUNC(0xF7A83023, _sceUltQueueOptParamInitialize); + //REG_FUNC(0x14DA1BB4, _sceUltQueueCreate); + //REG_FUNC(0xA7E78FF9, sceUltQueuePush); + //REG_FUNC(0x6D356B29, sceUltQueueTryPush); + //REG_FUNC(0x1AD58A53, sceUltQueuePop); + //REG_FUNC(0x2A1A8EA6, sceUltQueueTryPop); + //REG_FUNC(0xF37862DE, sceUltQueueDestroy); + //REG_FUNC(0xD8334A1F, _sceUltReaderWriterLockOptParamInitialize); + //REG_FUNC(0x2FB0EB32, _sceUltReaderWriterLockCreate); + //REG_FUNC(0x9AD07630, sceUltReaderWriterLockLockRead); + //REG_FUNC(0x2629C055, sceUltReaderWriterLockTryLockRead); + //REG_FUNC(0x218D4743, sceUltReaderWriterLockUnlockRead); + //REG_FUNC(0xF5F63E2C, sceUltReaderWriterLockLockWrite); + //REG_FUNC(0x944FB222, sceUltReaderWriterLockTryLockWrite); + //REG_FUNC(0x2A5741F5, sceUltReaderWriterLockUnlockWrite); + //REG_FUNC(0xB1FEB79B, sceUltReaderWriterLockDestroy); + //REG_FUNC(0x8E31B9FE, _sceUltSemaphoreOptParamInitialize); + //REG_FUNC(0xDD59562C, _sceUltSemaphoreCreate); + //REG_FUNC(0xF220D3AE, sceUltSemaphoreAcquire); + //REG_FUNC(0xAF15606D, sceUltSemaphoreTryAcquire); + //REG_FUNC(0x65376E2D, sceUltSemaphoreRelease); + //REG_FUNC(0x8EC57420, sceUltSemaphoreDestroy); + //REG_FUNC(0x8486DDE6, _sceUltUlthreadRuntimeOptParamInitialize); + //REG_FUNC(0x5435C586, sceUltUlthreadRuntimeGetWorkAreaSize); + //REG_FUNC(0x86DDA3AE, _sceUltUlthreadRuntimeCreate); + //REG_FUNC(0x4E9A745C, sceUltUlthreadRuntimeDestroy); + //REG_FUNC(0x7F373376, _sceUltUlthreadOptParamInitialize); + //REG_FUNC(0xB1290375, _sceUltUlthreadCreate); + //REG_FUNC(0xCAD57BAD, sceUltUlthreadYield); + //REG_FUNC(0x1E401DF8, sceUltUlthreadExit); + //REG_FUNC(0x63483381, sceUltUlthreadJoin); + //REG_FUNC(0xB4CF88AC, sceUltUlthreadTryJoin); + //REG_FUNC(0xA798C5D7, sceUltUlthreadGetSelf); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp b/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp new file mode 100644 index 0000000000..472c7bbfb3 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp @@ -0,0 +1,34 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceVideodec; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceVideodec, #name, name) + +psv_log_base sceVideodec("SceVideodec", []() +{ + sceVideodec.on_load = nullptr; + sceVideodec.on_unload = nullptr; + sceVideodec.on_stop = nullptr; + + //REG_FUNC(0xF1AF65A3, sceVideodecInitLibrary); + //REG_FUNC(0x3A5F4924, sceVideodecTermLibrary); + //REG_FUNC(0x97E95EDB, sceAvcdecQueryDecoderMemSize); + //REG_FUNC(0xE82BB69B, sceAvcdecCreateDecoder); + //REG_FUNC(0x8A0E359E, sceAvcdecDeleteDecoder); + //REG_FUNC(0x441673E3, sceAvcdecDecodeAvailableSize); + //REG_FUNC(0xD6190A06, sceAvcdecDecode); + //REG_FUNC(0x9648D853, sceAvcdecDecodeStop); + //REG_FUNC(0x25F31020, sceAvcdecDecodeFlush); + //REG_FUNC(0xB2A428DB, sceAvcdecCsc); + //REG_FUNC(0x6C68A38F, sceAvcdecDecodeNalAu); + //REG_FUNC(0xC67C1A80, sceM4vdecQueryDecoderMemSize); + //REG_FUNC(0x17C6AC9E, sceM4vdecCreateDecoder); + //REG_FUNC(0x0EB2E4E7, sceM4vdecDeleteDecoder); + //REG_FUNC(0xA8CF1942, sceM4vdecDecodeAvailableSize); + //REG_FUNC(0x624664DB, sceM4vdecDecode); + //REG_FUNC(0x87CFD23B, sceM4vdecDecodeStop); + //REG_FUNC(0x7C460D75, sceM4vdecDecodeFlush); + //REG_FUNC(0xB4BC325B, sceM4vdecCsc); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp b/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp new file mode 100644 index 0000000000..072f3d3303 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp @@ -0,0 +1,40 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceVoice; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceVoice, #name, name) + +psv_log_base sceVoice("SceVoice", []() +{ + sceVoice.on_load = nullptr; + sceVoice.on_unload = nullptr; + sceVoice.on_stop = nullptr; + + //REG_FUNC(0xD02C00B4, sceVoiceGetBitRate); + //REG_FUNC(0xC913F7E9, sceVoiceGetMuteFlag); + //REG_FUNC(0x875CC80D, sceVoiceGetVolume); + //REG_FUNC(0x02F58D6F, sceVoiceSetBitRate); + //REG_FUNC(0x0B9E4AE2, sceVoiceSetMuteFlag); + //REG_FUNC(0xDB90EAC4, sceVoiceSetMuteFlagAll); + //REG_FUNC(0xD93769E6, sceVoiceSetVolume); + //REG_FUNC(0x6E46950E, sceVoiceGetResourceInfo); + //REG_FUNC(0xAC98853E, sceVoiceEnd); + //REG_FUNC(0x805CC20F, sceVoiceInit); + //REG_FUNC(0xB2ED725B, sceVoiceStart); + //REG_FUNC(0xC3868DF6, sceVoiceStop); + //REG_FUNC(0x698BDAAE, sceVoiceConnectIPortToOPort); + //REG_FUNC(0xFA4E57B1, sceVoiceCreatePort); + //REG_FUNC(0xAE46564D, sceVoiceDeletePort); + //REG_FUNC(0x5F0260F4, sceVoiceDisconnectIPortFromOPort); + //REG_FUNC(0x5933CCFB, sceVoiceGetPortInfo); + //REG_FUNC(0x23C6B16B, sceVoicePausePort); + //REG_FUNC(0x39AA3884, sceVoicePausePortAll); + //REG_FUNC(0x09E4D18C, sceVoiceReadFromOPort); + //REG_FUNC(0x5E1CE910, sceVoiceResetPort); + //REG_FUNC(0x2DE35411, sceVoiceResumePort); + //REG_FUNC(0x1F93FC0C, sceVoiceResumePortAll); + //REG_FUNC(0xCE855C50, sceVoiceUpdatePort); + //REG_FUNC(0x0A22EC0E, sceVoiceWriteToIPort); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp b/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp new file mode 100644 index 0000000000..bc5fb062a3 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceVoiceQoS; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceVoiceQoS, #name, name) + +psv_log_base sceVoiceQoS("SceVoiceQos", []() +{ + sceVoiceQoS.on_load = nullptr; + sceVoiceQoS.on_unload = nullptr; + sceVoiceQoS.on_stop = nullptr; + + //REG_FUNC(0x4B5FFF1C, sceVoiceQoSInit); + //REG_FUNC(0xFB0B747B, sceVoiceQoSEnd); + //REG_FUNC(0xAAB54BE4, sceVoiceQoSCreateLocalEndpoint); + //REG_FUNC(0x68FABF6F, sceVoiceQoSDeleteLocalEndpoint); + //REG_FUNC(0xBAB98727, sceVoiceQoSCreateRemoteEndpoint); + //REG_FUNC(0xC2F2C771, sceVoiceQoSDeleteRemoteEndpoint); + //REG_FUNC(0xE0C5CEEE, sceVoiceQoSConnect); + //REG_FUNC(0x3C7A08B0, sceVoiceQoSDisconnect); + //REG_FUNC(0xE5B4527D, sceVoiceQoSGetLocalEndpoint); + //REG_FUNC(0x876A9B9C, sceVoiceQoSGetRemoteEndpoint); + //REG_FUNC(0x540CEBA5, sceVoiceQoSSetLocalEndpointAttribute); + //REG_FUNC(0xC981AB3B, sceVoiceQoSGetLocalEndpointAttribute); + //REG_FUNC(0xE757806F, sceVoiceQoSSetConnectionAttribute); + //REG_FUNC(0xE81B8D44, sceVoiceQoSGetConnectionAttribute); + //REG_FUNC(0xC9DC1425, sceVoiceQoSGetStatus); + //REG_FUNC(0x2FE1F28F, sceVoiceQoSWritePacket); + //REG_FUNC(0x2D613549, sceVoiceQoSReadPacket); +}); diff --git a/rpcs3/Emu/ARMv7/Modules/sceXml.cpp b/rpcs3/Emu/ARMv7/Modules/sceXml.cpp new file mode 100644 index 0000000000..525ce21565 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceXml.cpp @@ -0,0 +1,201 @@ +#include "stdafx.h" +#include "Emu/System.h" +#include "Emu/ARMv7/PSVFuncList.h" + +extern psv_log_base sceXml; + +#define REG_FUNC(nid, name) reg_psv_func(nid, &sceXml, #name, name) + +psv_log_base sceXml("SceXml", []() +{ + sceXml.on_load = nullptr; + sceXml.on_unload = nullptr; + sceXml.on_stop = nullptr; + + //REG_FUNC(0x57400A1A, _ZN3sce3Xml10SimpleDataC1EPKcj); + //REG_FUNC(0x7E582075, _ZN3sce3Xml10SimpleDataC1Ev); + //REG_FUNC(0x4CF0656B, _ZN3sce3Xml10SimpleDataC2EPKcj); + //REG_FUNC(0x95077028, _ZN3sce3Xml10SimpleDataC2Ev); + //REG_FUNC(0xECFA6A2A, _ZN3sce3Xml11Initializer10initializeEPKNS0_13InitParameterE); + //REG_FUNC(0x29824CD5, _ZN3sce3Xml11Initializer9terminateEv); + //REG_FUNC(0xBF13FDE6, _ZN3sce3Xml11InitializerC1Ev); + //REG_FUNC(0x94AAA71D, _ZN3sce3Xml11InitializerC2Ev); + //REG_FUNC(0xB4547C88, _ZN3sce3Xml11InitializerD1Ev); + //REG_FUNC(0xAAA08FA8, _ZN3sce3Xml11InitializerD2Ev); + //REG_FUNC(0x8D387E01, _ZN3sce3Xml12MemAllocatorC1Ev); + //REG_FUNC(0xE982E681, _ZN3sce3Xml12MemAllocatorC2Ev); + //REG_FUNC(0x90B82579, _ZN3sce3Xml12MemAllocatorD0Ev); + //REG_FUNC(0x56002B9D, _ZN3sce3Xml12MemAllocatorD1Ev); + //REG_FUNC(0x1BE022EA, _ZN3sce3Xml12MemAllocatorD2Ev); + //REG_FUNC(0x89AA847E, _ZN3sce3Xml13AttributeList10initializeEPKNS0_11InitializerE); + //REG_FUNC(0xD08EE434, _ZN3sce3Xml13AttributeList12addAttributeEPKNS0_6StringES4_); + //REG_FUNC(0xCCEE4E7C, _ZN3sce3Xml13AttributeList5clearEv); + //REG_FUNC(0x11FE5A65, _ZN3sce3Xml13AttributeList9terminateEv); + //REG_FUNC(0x9CBD82D4, _ZN3sce3Xml13AttributeListC1ERKS1_); + //REG_FUNC(0x542076D8, _ZN3sce3Xml13AttributeListC1Ev); + //REG_FUNC(0x87C89447, _ZN3sce3Xml13AttributeListC2ERKS1_); + //REG_FUNC(0x5D49542A, _ZN3sce3Xml13AttributeListC2Ev); + //REG_FUNC(0x38861841, _ZN3sce3Xml13AttributeListD1Ev); + //REG_FUNC(0x1B0B3976, _ZN3sce3Xml13AttributeListD2Ev); + //REG_FUNC(0x30520B78, _ZN3sce3Xml14VarAllocBuffer4copyEPKhjb); + //REG_FUNC(0x7D5A0041, _ZN3sce3Xml14VarAllocBuffer5clearEv); + //REG_FUNC(0xD95D3824, _ZN3sce3Xml14VarAllocBuffer7copyStrEPKcj); + //REG_FUNC(0xFE99676E, _ZN3sce3Xml14VarAllocBuffer7copyStrERKNS0_6StringE); + //REG_FUNC(0x82747F92, _ZN3sce3Xml14VarAllocBuffer7reserveEj); + //REG_FUNC(0xE93EACFC, _ZN3sce3Xml14VarAllocBuffer9terminateEv); + //REG_FUNC(0x8045D9C2, _ZN3sce3Xml14VarAllocBufferC1EPKNS0_11InitializerE); + //REG_FUNC(0xEF4FA027, _ZN3sce3Xml14VarAllocBufferC2EPKNS0_11InitializerE); + //REG_FUNC(0xD61CAAFC, _ZN3sce3Xml14VarAllocBufferD0Ev); + //REG_FUNC(0xD9217FC8, _ZN3sce3Xml14VarAllocBufferD1Ev); + //REG_FUNC(0x8A4B9379, _ZN3sce3Xml14VarAllocBufferD2Ev); + //REG_FUNC(0xB7770E5E, _ZN3sce3Xml18SerializeParameterC1Ev); + //REG_FUNC(0xF65270FC, _ZN3sce3Xml18SerializeParameterC2Ev); + //REG_FUNC(0x2CB61A7C, _ZN3sce3Xml20bXResultToResultTypeEi); + //REG_FUNC(0x59C5E9B2, _ZN3sce3Xml23getMemManagerDebugLevelEv); + //REG_FUNC(0xBA8B7374, _ZN3sce3Xml23setMemManagerDebugLevelEi); + //REG_FUNC(0xBBACFE87, _ZN3sce3Xml3Dom15DocumentBuilder10initializeEPKNS0_11InitializerE); + //REG_FUNC(0x1A29526B, _ZN3sce3Xml3Dom15DocumentBuilder11getDocumentEv); + //REG_FUNC(0xA2431C2B, _ZN3sce3Xml3Dom15DocumentBuilder16setResolveEntityEb); + //REG_FUNC(0xB8C4D13C, _ZN3sce3Xml3Dom15DocumentBuilder20setSkipIgnorableTextEb); + //REG_FUNC(0xF351D753, _ZN3sce3Xml3Dom15DocumentBuilder26setSkipIgnorableWhiteSpaceEb); + //REG_FUNC(0x7744DD14, _ZN3sce3Xml3Dom15DocumentBuilder5parseEPKNS0_6StringEb); + //REG_FUNC(0x42D59053, _ZN3sce3Xml3Dom15DocumentBuilder9terminateEv); + //REG_FUNC(0x702492EA, _ZN3sce3Xml3Dom15DocumentBuilderC1Ev); + //REG_FUNC(0x36F6BDF2, _ZN3sce3Xml3Dom15DocumentBuilderC2Ev); + //REG_FUNC(0x79C9322E, _ZN3sce3Xml3Dom15DocumentBuilderD0Ev); + //REG_FUNC(0x19D0E024, _ZN3sce3Xml3Dom15DocumentBuilderD1Ev); + //REG_FUNC(0x99C58389, _ZN3sce3Xml3Dom15DocumentBuilderD2Ev); + //REG_FUNC(0x3CA958D3, _ZN3sce3Xml3Dom4Node11removeChildEy); + //REG_FUNC(0x1B98BDBE, _ZN3sce3Xml3Dom4Node12insertBeforeEyy); + //REG_FUNC(0x26BA1E6E, _ZNK3sce3Xml3Dom4Node13hasAttributesEv); + //REG_FUNC(0xC6F4F6A8, _ZN3sce3Xml3Dom4Node13hasChildNodesEv); + //REG_FUNC(0x088C100E, _ZN3sce3Xml3Dom4NodeC1Ey); + //REG_FUNC(0x44CAF9E1, _ZN3sce3Xml3Dom4NodeC2Ey); + //REG_FUNC(0x8F2EB967, _ZN3sce3Xml3Dom4NodeD1Ev); + //REG_FUNC(0x241EFC0E, _ZN3sce3Xml3Dom4NodeD2Ev); + //REG_FUNC(0x6A16C2FF, _ZN3sce3Xml3Dom8Document10importNodeEyyPKS2_y); + //REG_FUNC(0xB4A33B78, _ZN3sce3Xml3Dom8Document10initializeEPKNS0_11InitializerE); + //REG_FUNC(0x18686B94, _ZN3sce3Xml3Dom8Document10insertNodeEyyy); + //REG_FUNC(0x49263CE5, _ZN3sce3Xml3Dom8Document11removeChildEyy); + //REG_FUNC(0xD945184A, _ZN3sce3Xml3Dom8Document11resetStatusEv); + //REG_FUNC(0x7B0A8F6C, _ZN3sce3Xml3Dom8Document11setWritableEv); + //REG_FUNC(0x0CBC1C3F, _ZN3sce3Xml3Dom8Document12importParentEPKS2_y); + //REG_FUNC(0x016A9ADB, _ZN3sce3Xml3Dom8Document12setAttrValueEyPKNS0_6StringES5_); + //REG_FUNC(0xEA19C7CF, _ZN3sce3Xml3Dom8Document12setAttributeEyPKNS0_6StringES5_); + //REG_FUNC(0x35C50B8B, _ZN3sce3Xml3Dom8Document13createElementEPKNS0_6StringEPKNS0_13AttributeListES5_); + //REG_FUNC(0xBCA5E62A, _ZN3sce3Xml3Dom8Document13recurseDeleteEy); + //REG_FUNC(0x8D19723F, _ZN3sce3Xml3Dom8Document14createTextNodeEPKNS0_6StringE); + //REG_FUNC(0x6220E98B, _ZN3sce3Xml3Dom8Document15addElementChildEyPKNS0_6StringEPKNS0_13AttributeListES5_); + //REG_FUNC(0xF1DB18B1, _ZN3sce3Xml3Dom8Document15removeAttributeEyPKNS0_6StringE); + //REG_FUNC(0x779036AB, _ZN3sce3Xml3Dom8Document16removeAttributesEy); + //REG_FUNC(0x0667B08D, _ZN3sce3Xml3Dom8Document16setAttributeListEyPKNS0_13AttributeListE); + //REG_FUNC(0xD2BFBC47, _ZNK3sce3Xml3Dom8Document20getElementsByTagNameEyPKNS0_6StringEPNS1_8NodeListE); + //REG_FUNC(0xDEFEAFD2, _ZN3sce3Xml3Dom8Document7setTextEyPKNS0_6StringE); + //REG_FUNC(0x87F8B4DA, _ZN3sce3Xml3Dom8Document9serializeEPKNS0_18SerializeParameterEPNS0_6StringE); + //REG_FUNC(0x4B7321FB, _ZN3sce3Xml3Dom8Document9terminateEv); + //REG_FUNC(0x1DD41C7A, _ZN3sce3Xml3Dom8DocumentC1ERKS2_); + //REG_FUNC(0x7B7107AD, _ZN3sce3Xml3Dom8DocumentC1Ev); + //REG_FUNC(0xF399F763, _ZN3sce3Xml3Dom8DocumentC2ERKS2_); + //REG_FUNC(0xE6BA9C73, _ZN3sce3Xml3Dom8DocumentC2Ev); + //REG_FUNC(0xFB207925, _ZN3sce3Xml3Dom8DocumentD1Ev); + //REG_FUNC(0x11A5F0A3, _ZN3sce3Xml3Dom8DocumentD2Ev); + //REG_FUNC(0xD622A7FE, _ZN3sce3Xml3Dom8DocumentaSERKS2_); + //REG_FUNC(0x860CC706, _ZN3sce3Xml3Dom8NodeList10initializeEPKNS0_11InitializerE); + //REG_FUNC(0x7A889374, _ZN3sce3Xml3Dom8NodeList10insertLastEy); + //REG_FUNC(0xE9995F58, _ZN3sce3Xml3Dom8NodeList10removeItemEy); + //REG_FUNC(0xFA921C6E, _ZN3sce3Xml3Dom8NodeList11insertFirstEy); + //REG_FUNC(0xCDD1D418, _ZNK3sce3Xml3Dom8NodeList4itemEj); + //REG_FUNC(0x508E9150, _ZN3sce3Xml3Dom8NodeList5clearEv); + //REG_FUNC(0xA41ED241, _ZNK3sce3Xml3Dom8NodeList8findItemEPKNS0_6StringE); + //REG_FUNC(0xE1AB441D, _ZNK3sce3Xml3Dom8NodeList8findItemEy); + //REG_FUNC(0xFB9EDBF9, _ZNK3sce3Xml3Dom8NodeList9getLengthEv); + //REG_FUNC(0x32B396AD, _ZN3sce3Xml3Dom8NodeList9terminateEv); + //REG_FUNC(0xB1CA0E34, _ZN3sce3Xml3Dom8NodeListC1ERKS2_); + //REG_FUNC(0x0580C02E, _ZN3sce3Xml3Dom8NodeListC1Ev); + //REG_FUNC(0xB97BF737, _ZN3sce3Xml3Dom8NodeListC2ERKS2_); + //REG_FUNC(0x684E57B9, _ZN3sce3Xml3Dom8NodeListC2Ev); + //REG_FUNC(0x92EBC9F8, _ZN3sce3Xml3Dom8NodeListD1Ev); + //REG_FUNC(0x2DF80037, _ZN3sce3Xml3Dom8NodeListD2Ev); + //REG_FUNC(0xBAD4AAFA, _ZNK3sce3Xml3Dom8NodeListixEj); + //REG_FUNC(0x874C8331, _ZN3sce3Xml3Sax6Parser10initializeEPKNS0_11InitializerE); + //REG_FUNC(0x4DB998E6, _ZN3sce3Xml3Sax6Parser11setUserDataEPv); + //REG_FUNC(0xB77BF8A0, _ZN3sce3Xml3Sax6Parser16setResolveEntityEb); + //REG_FUNC(0x1B2442A0, _ZN3sce3Xml3Sax6Parser18setDocumentHandlerEPNS1_15DocumentHandlerE); + //REG_FUNC(0xCE1DAE23, _ZN3sce3Xml3Sax6Parser26setSkipIgnorableWhiteSpaceEb); + //REG_FUNC(0x70D9FC8E, _ZN3sce3Xml3Sax6Parser5parseEPKNS0_6StringEb); + //REG_FUNC(0xA2B40FA7, _ZN3sce3Xml3Sax6Parser5resetEv); + //REG_FUNC(0xF2C8950D, _ZN3sce3Xml3Sax6Parser9terminateEv); + //REG_FUNC(0x60BF9988, _ZN3sce3Xml3Sax6ParserC1Ev); + //REG_FUNC(0x56390CA0, _ZN3sce3Xml3Sax6ParserC2Ev); + //REG_FUNC(0xA11C2AED, _ZN3sce3Xml3Sax6ParserD1Ev); + //REG_FUNC(0x02E8F7FA, _ZN3sce3Xml3Sax6ParserD2Ev); + //REG_FUNC(0xE5314387, _ZN3sce3Xml4Attr10initializeEPKNS0_11InitializerE); + //REG_FUNC(0x66D1B605, _ZN3sce3Xml4Attr7setNameEPKNS0_6StringE); + //REG_FUNC(0x7DD3059D, _ZN3sce3Xml4Attr8setValueEPKNS0_6StringE); + //REG_FUNC(0x67E0DF2B, _ZN3sce3Xml4Attr9terminateEv); + //REG_FUNC(0xC09ABF87, _ZN3sce3Xml4AttrC1ERKS1_); + //REG_FUNC(0xD016F1BC, _ZN3sce3Xml4AttrC1Ev); + //REG_FUNC(0xB4851BEC, _ZN3sce3Xml4AttrC2ERKS1_); + //REG_FUNC(0x0B3AE81B, _ZN3sce3Xml4AttrC2Ev); + //REG_FUNC(0x58E349A5, _ZN3sce3Xml4AttrD1Ev); + //REG_FUNC(0xB9E6F81A, _ZN3sce3Xml4AttrD2Ev); + //REG_FUNC(0xA5B902D4, _ZN3sce3Xml4AttraSERKS1_); + //REG_FUNC(0xA7E983E2, _ZN3sce3Xml4Util9strResultEi); + //REG_FUNC(0x035F013B, _ZN3sce3Xml6StringC1EPKc); + //REG_FUNC(0x0B5461E0, _ZN3sce3Xml6StringC1EPKcj); + //REG_FUNC(0x67191CC6, _ZN3sce3Xml6StringC1ERKS1_); + //REG_FUNC(0xA17502C1, _ZN3sce3Xml6StringC1Ev); + //REG_FUNC(0xECC1F1A4, _ZN3sce3Xml6StringC2EPKc); + //REG_FUNC(0x457CCE55, _ZN3sce3Xml6StringC2EPKcj); + //REG_FUNC(0xD785BA85, _ZN3sce3Xml6StringC2ERKS1_); + //REG_FUNC(0x8816F7EF, _ZN3sce3Xml6StringC2Ev); + //REG_FUNC(0x18758863, _ZN3sce3Xml6StringaSERKS1_); + //REG_FUNC(0x4F30F0CC, _ZNK3sce3Xml13AttributeList12getAttributeEPKNS0_6StringE); + //REG_FUNC(0x5ED0B2F9, _ZNK3sce3Xml13AttributeList12getAttributeEj); + //REG_FUNC(0x38AEB52E, _ZNK3sce3Xml13AttributeList9getLengthEv); + //REG_FUNC(0xEC96BFC6, _ZNK3sce3Xml3Dom13DocumentDebug13getStructSizeEv); + //REG_FUNC(0xE1100FC0, _ZNK3sce3Xml3Dom13DocumentDebug16getAttrTableSizeEv); + //REG_FUNC(0x6E1F1FFB, _ZNK3sce3Xml3Dom13DocumentDebug16getCharTableSizeEv); + //REG_FUNC(0x8F9CEE10, _ZNK3sce3Xml3Dom13DocumentDebug19getElementTableSizeEv); + //REG_FUNC(0xE1269956, _ZNK3sce3Xml3Dom4Node11getNodeNameEv); + //REG_FUNC(0xCED5E0FF, _ZNK3sce3Xml3Dom4Node11getNodeTypeEv); + //REG_FUNC(0x4F2D5541, _ZNK3sce3Xml3Dom4Node12getNodeValueEv); + //REG_FUNC(0xB405A149, _ZNK3sce3Xml3Dom4Node13getAttributesEv); + //REG_FUNC(0x117BEA8A, _ZNK3sce3Xml3Dom4Node13getChildNodesEv); + //REG_FUNC(0x639D219C, _ZNK3sce3Xml3Dom4Node13getFirstChildEv); + //REG_FUNC(0x3FD63FB8, _ZNK3sce3Xml3Dom4Node12getLastChildEv); + //REG_FUNC(0x1A46C0E1, _ZNK3sce3Xml3Dom4Node14getNextSiblingEv); + //REG_FUNC(0xD9757BC8, _ZNK3sce3Xml3Dom4Node14getParenetNodeEv); + //REG_FUNC(0x3E8122AB, _ZNK3sce3Xml3Dom4Node16getOwnerDocumentEv); + //REG_FUNC(0x22DBB221, _ZNK3sce3Xml3Dom8Document10getDocRootEv); + //REG_FUNC(0xE3D0A78A, _ZNK3sce3Xml3Dom8Document10getSiblingEy); + //REG_FUNC(0x2D370226, _ZNK3sce3Xml3Dom8Document10getXmlMetaEv); + //REG_FUNC(0xA4D99D40, _ZNK3sce3Xml3Dom8Document10isReadOnlyEv); + //REG_FUNC(0xCD65B91F, _ZNK3sce3Xml3Dom8Document11getAttrNameEy); + //REG_FUNC(0x883E1BFC, _ZNK3sce3Xml3Dom8Document11getNextAttrEy); + //REG_FUNC(0x471A22E8, _ZNK3sce3Xml3Dom8Document11getNodeNameEy); + //REG_FUNC(0x62D3CB44, _ZNK3sce3Xml3Dom8Document11getNodeTypeEy); + //REG_FUNC(0x28FD79E3, _ZNK3sce3Xml3Dom8Document11isAvailableEv); + //REG_FUNC(0x7C6A03FD, _ZNK3sce3Xml3Dom8Document12getAttrValueEy); + //REG_FUNC(0x9531C3CD, _ZNK3sce3Xml3Dom8Document12getAttributeEyPKNS0_6StringE); + //REG_FUNC(0xEC856072, _ZNK3sce3Xml3Dom8Document12getFirstAttrEy); + //REG_FUNC(0xFBCF0D3E, _ZNK3sce3Xml3Dom8Document12getLastChildEy); + //REG_FUNC(0xCDEC3F43, _ZNK3sce3Xml3Dom8Document13getAttributesEyPNS1_8NodeListE); + //REG_FUNC(0xFC61FDF1, _ZNK3sce3Xml3Dom8Document13getChildNodesEyPNS1_8NodeListE); + //REG_FUNC(0xDAC75E49, _ZNK3sce3Xml3Dom8Document13getEntityTypeEy); + //REG_FUNC(0xEA805296, _ZNK3sce3Xml3Dom8Document13hasAttributesEy); + //REG_FUNC(0xC5E7431A, _ZNK3sce3Xml3Dom8Document13hasChildNodesEy); + //REG_FUNC(0x0C1DDEC5, _ZNK3sce3Xml3Dom8Document14getSkippedTextEy); + //REG_FUNC(0xB34D9672, _ZNK3sce3Xml3Dom8Document7getRootEv); + //REG_FUNC(0x36ACFF5E, _ZNK3sce3Xml3Dom8Document7getTextEy); + //REG_FUNC(0x3028E05D, _ZNK3sce3Xml3Dom8Document13getFirstChildEy); + //REG_FUNC(0x161BA85E, _ZNK3sce3Xml3Dom8Document9getEntityEy); + //REG_FUNC(0xA98B5758, _ZNK3sce3Xml3Dom8Document9getParentEy); + //REG_FUNC(0xD428753A, _ZNK3sce3Xml3Dom8Document9getStatusEv); + //REG_FUNC(0x10530611, _ZNK3sce3Xml3Dom8NodeList11isAvailableEv); + //REG_FUNC(0x35134B85, _ZNK3sce3Xml4Attr7getNameEv); + //REG_FUNC(0x7834A2F7, _ZNK3sce3Xml4Attr8getValueEv); + //REG_FUNC(0x0D119AB3, _ZNK3sce3Xml3Dom4Node11isAvailableEv); + //REG_FUNC(0x1633846D, _ZNK3sce3Xml4Attr11isAvailableEv); + //REG_FUNC(0x58854322, _ZNK3sce3Xml13AttributeList11isAvailableEv); +}); diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index 4ca94b42a6..29990a3208 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -44,32 +44,132 @@ void execute_psv_func_by_index(ARMv7Context& context, u32 index) context.thread.m_last_syscall = old_last_syscall; } +extern psv_log_base sceAppMgr; +extern psv_log_base sceAppUtil; +extern psv_log_base sceAudio; +extern psv_log_base sceAudiodec; +extern psv_log_base sceAudioenc; +extern psv_log_base sceAudioIn; +extern psv_log_base sceCamera; +extern psv_log_base sceCodecEngine; +extern psv_log_base sceCommonDialog; +extern psv_log_base sceCtrl; +extern psv_log_base sceDbg; +extern psv_log_base sceDeci4p; +extern psv_log_base sceDeflt; +extern psv_log_base sceDisplay; +extern psv_log_base sceFiber; +extern psv_log_base sceFios; +extern psv_log_base sceFpu; +extern psv_log_base sceGxm; +extern psv_log_base sceHttp; +extern psv_log_base sceIme; +extern psv_log_base sceJpeg; +extern psv_log_base sceJpegEnc; extern psv_log_base sceLibc; +extern psv_log_base sceLibKernel; extern psv_log_base sceLibm; extern psv_log_base sceLibstdcxx; -extern psv_log_base sceLibKernel; -extern psv_log_base sceSysmodule; +extern psv_log_base sceLiveArea; +extern psv_log_base sceLocation; +extern psv_log_base sceMd5; +extern psv_log_base sceMotion; +extern psv_log_base sceMt19937; +extern psv_log_base sceNet; +extern psv_log_base sceNetCtl; +extern psv_log_base sceNgs; +extern psv_log_base sceNpBasic; +extern psv_log_base sceNpCommon; +extern psv_log_base sceNpManager; +extern psv_log_base sceNpMatching; +extern psv_log_base sceNpScore; +extern psv_log_base sceNpUtility; extern psv_log_base scePerf; -extern psv_log_base sceCtrl; -extern psv_log_base sceDeci4p; -extern psv_log_base sceDisplay; -extern psv_log_base sceGxm; +extern psv_log_base scePgf; +extern psv_log_base scePhotoExport; +extern psv_log_base sceRazorCapture; +extern psv_log_base sceRtc; +extern psv_log_base sceSas; +extern psv_log_base sceScreenShot; +extern psv_log_base sceSfmt; +extern psv_log_base sceSha; +extern psv_log_base sceSqlite; +extern psv_log_base sceSsl; +extern psv_log_base sceSulpha; +extern psv_log_base sceSysmodule; +extern psv_log_base sceSystemGesture; +extern psv_log_base sceTouch; +extern psv_log_base sceUlt; +extern psv_log_base sceVideodec; +extern psv_log_base sceVoice; +extern psv_log_base sceVoiceQoS; +extern psv_log_base sceXml; void initialize_psv_modules() { assert(!g_psv_func_list.size() && !g_psv_modules.size()); // fill module list + g_psv_modules.push_back(&sceAppMgr); + g_psv_modules.push_back(&sceAppUtil); + g_psv_modules.push_back(&sceAudio); + g_psv_modules.push_back(&sceAudiodec); + g_psv_modules.push_back(&sceAudioenc); + g_psv_modules.push_back(&sceAudioIn); + g_psv_modules.push_back(&sceCamera); + g_psv_modules.push_back(&sceCodecEngine); + g_psv_modules.push_back(&sceCommonDialog); + g_psv_modules.push_back(&sceCtrl); + g_psv_modules.push_back(&sceDbg); + g_psv_modules.push_back(&sceDeci4p); + g_psv_modules.push_back(&sceDeflt); + g_psv_modules.push_back(&sceDisplay); + g_psv_modules.push_back(&sceFiber); + g_psv_modules.push_back(&sceFios); + g_psv_modules.push_back(&sceFpu); + g_psv_modules.push_back(&sceGxm); + g_psv_modules.push_back(&sceHttp); + g_psv_modules.push_back(&sceIme); + g_psv_modules.push_back(&sceJpeg); + g_psv_modules.push_back(&sceJpegEnc); g_psv_modules.push_back(&sceLibc); + g_psv_modules.push_back(&sceLibKernel); g_psv_modules.push_back(&sceLibm); g_psv_modules.push_back(&sceLibstdcxx); - g_psv_modules.push_back(&sceLibKernel); - g_psv_modules.push_back(&sceSysmodule); + g_psv_modules.push_back(&sceLiveArea); + g_psv_modules.push_back(&sceLocation); + g_psv_modules.push_back(&sceMd5); + g_psv_modules.push_back(&sceMotion); + g_psv_modules.push_back(&sceMt19937); + g_psv_modules.push_back(&sceNet); + g_psv_modules.push_back(&sceNetCtl); + g_psv_modules.push_back(&sceNgs); + g_psv_modules.push_back(&sceNpBasic); + g_psv_modules.push_back(&sceNpCommon); + g_psv_modules.push_back(&sceNpManager); + g_psv_modules.push_back(&sceNpMatching); + g_psv_modules.push_back(&sceNpScore); + g_psv_modules.push_back(&sceNpUtility); g_psv_modules.push_back(&scePerf); - g_psv_modules.push_back(&sceCtrl); - g_psv_modules.push_back(&sceDeci4p); - g_psv_modules.push_back(&sceDisplay); - g_psv_modules.push_back(&sceGxm); + g_psv_modules.push_back(&scePgf); + g_psv_modules.push_back(&scePhotoExport); + g_psv_modules.push_back(&sceRazorCapture); + g_psv_modules.push_back(&sceRtc); + g_psv_modules.push_back(&sceSas); + g_psv_modules.push_back(&sceScreenShot); + g_psv_modules.push_back(&sceSfmt); + g_psv_modules.push_back(&sceSha); + g_psv_modules.push_back(&sceSqlite); + g_psv_modules.push_back(&sceSsl); + g_psv_modules.push_back(&sceSulpha); + g_psv_modules.push_back(&sceSysmodule); + g_psv_modules.push_back(&sceSystemGesture); + g_psv_modules.push_back(&sceTouch); + g_psv_modules.push_back(&sceUlt); + g_psv_modules.push_back(&sceVideodec); + g_psv_modules.push_back(&sceVoice); + g_psv_modules.push_back(&sceVoiceQoS); + g_psv_modules.push_back(&sceXml); // setup special functions (without NIDs) psv_func unimplemented; diff --git a/rpcs3/Emu/FS/vfsDirBase.h b/rpcs3/Emu/FS/vfsDirBase.h index c4d515899c..654cc72d01 100644 --- a/rpcs3/Emu/FS/vfsDirBase.h +++ b/rpcs3/Emu/FS/vfsDirBase.h @@ -67,8 +67,9 @@ public: { } - iterator(const DirEntryInfo* data) - : data(data) + iterator(vfsDirBase* parent, const DirEntryInfo* data) + : parent(parent) + , data(data) { } @@ -82,7 +83,7 @@ public: { const DirEntryInfo* olddata = data; data = parent->Read(); - return iterator(olddata); + return iterator(parent, olddata); } const DirEntryInfo* operator *() @@ -90,7 +91,7 @@ public: return data; } - bool operator!=(iterator other) const + bool operator !=(iterator other) const { return data != other.data; } @@ -103,6 +104,6 @@ public: iterator end() { - return iterator((const DirEntryInfo*)nullptr); + return iterator(this, nullptr); } }; diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 6c5d405eab..84f75c6fff 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -17,11 +17,6 @@ MemoryBase Memory; -void MemoryBase::InvalidAddress(const char* func, const u64 addr) -{ - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", func, addr); -} - void MemoryBase::RegisterPages(u64 addr, u32 size) { LV2_LOCK(0); @@ -31,7 +26,7 @@ void MemoryBase::RegisterPages(u64 addr, u32 size) { if (i >= sizeof(m_pages) / sizeof(m_pages[0])) { - InvalidAddress(__FUNCTION__, i * 4096); + LOG_ERROR(MEMORY, "%s(): invalid address 0x%llx", __FUNCTION__, i * 4096); break; } if (m_pages[i]) @@ -52,7 +47,7 @@ void MemoryBase::UnregisterPages(u64 addr, u32 size) { if (i >= sizeof(m_pages) / sizeof(m_pages[0])) { - InvalidAddress(__FUNCTION__, i * 4096); + LOG_ERROR(MEMORY, "%s(): invalid address 0x%llx", __FUNCTION__, i * 4096); break; } if (!m_pages[i]) diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 5ba0e1dd7b..3f9a981041 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -77,8 +77,6 @@ public: return vm::g_base_addr; } - __noinline void InvalidAddress(const char* func, const u64 addr); - void RegisterPages(u64 addr, u32 size); void UnregisterPages(u64 addr, u32 size); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 25a4d8c0e7..2c23ecdb66 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -66,6 +66,11 @@ namespace vm return 0; } + void error(const u64 addr, const char* func) + { + throw fmt::format("%s(): invalid address 0x%llx", func, addr); + } + namespace ps3 { u32 main_alloc(u32 size) diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 38735da8ba..7cc958c3ba 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -42,6 +42,8 @@ namespace vm u32 get_addr(const void* real_pointer); + __noinline void error(const u64 addr, const char* func); + template struct cast_ptr { @@ -70,7 +72,7 @@ namespace vm const u32 res = static_cast(addr); if (res != addr) { - throw fmt::format("%s(): invalid address 0x%llx", func, addr); + vm::error(addr, func); } return res; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h index 7554b95bf1..1e919b12f9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h @@ -251,8 +251,8 @@ typedef void(CellWebBrowserUsrdata)(vm::ptr usrdata); struct CellWebBrowserMimeSet { - vm::bptr const type; - vm::bptr const directory; + const vm::bptr type; + const vm::bptr directory; }; struct CellWebBrowserPos diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 80cac220ad..6a4884798b 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Ini.h" #include "Utilities/Log.h" #include "Utilities/rFile.h" #include "Emu/FS/vfsStream.h" @@ -102,6 +103,9 @@ namespace loader u32 code_start = 0; u32 code_end = 0; + u32 vnid_addr = 0; + std::unordered_map vnid_list; + for (auto& shdr : m_shdrs) { // get secton name @@ -165,15 +169,19 @@ namespace loader for (u32 j = 0; j < shdr.data_le.sh_size / 4; j++) { - u32 nid = fnid[j]; - u32 addr = fstub[j]; + const u32 nid = fnid[j]; + const u32 addr = fstub[j]; if (auto func = get_psv_func_by_nid(nid)) { if (func->module) + { func->module->Notice("Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + } else + { LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + } // writing Thumb code (temporarily, because it should be ARM) vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) @@ -183,7 +191,7 @@ namespace loader } else { - LOG_ERROR(LOADER, "Unimplemented function 0x%08x (addr=0x%x)", nid, addr); + LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr); vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) vm::psv::write16(addr + 2, 0); // index 0 (unimplemented stub) @@ -193,6 +201,44 @@ namespace loader code_end = std::min(addr, code_end); } } + else if (!strcmp(name.c_str(), ".sceVNID.rodata")) + { + LOG_NOTICE(LOADER, ".sceVNID.rodata analysis..."); + + vnid_addr = shdr.data_le.sh_addr; + } + else if (!strcmp(name.c_str(), ".sceVStub.rodata")) + { + LOG_NOTICE(LOADER, ".sceVStub.rodata analysis..."); + + if (!vnid_addr) + { + if (shdr.data_le.sh_size) + { + LOG_ERROR(LOADER, ".sceVNID.rodata address not found, unable to process imports"); + } + continue; + } + + auto vnid = vm::psv::ptr::make(vnid_addr); + auto vstub = vm::psv::ptr::make(shdr.data_le.sh_addr); + + for (u32 j = 0; j < shdr.data_le.sh_size / 4; j++) + { + const u32 nid = vnid[j]; + const u32 addr = vstub[j]; + + LOG_ERROR(LOADER, "Unknown object 0x%08x (ref_addr=0x%x)", nid, addr); + + // TODO: find imported object (vtable, typeinfo or something), assign it to vnid_list[addr] + } + } + else if (!strcmp(name.c_str(), ".tbss")) + { + LOG_NOTICE(LOADER, ".tbss analysis"); + + LOG_ERROR(LOADER, "TLS: size=0x%08x", shdr.data_le.sh_size); + } else if (!strcmp(name.c_str(), ".sceRefs.rodata")) { LOG_NOTICE(LOADER, ".sceRefs.rodata analysis..."); @@ -203,39 +249,71 @@ namespace loader { switch (*code) { - case 0x000000ff: + case 0x000000ff: // save address for future use { - // save address for future use data = *++code; break; } - case 0x0000002f: + case 0x0000002f: // movw r*,# instruction is replaced { - // movw r12,# instruction will be replaced const u32 addr = *++code; - vm::psv::write16(addr + 0, 0xf240 | (data & 0x800) >> 1 | (data & 0xf000) >> 12); // MOVW - vm::psv::write16(addr + 2, 0x0c00 | (data & 0x700) << 4 | (data & 0xff)); - //LOG_NOTICE(LOADER, "sceRefs: movw written at 0x%x (data=0x%x)", addr, data); + + if (!data) + { + auto found = vnid_list.find(code.addr()); + if (found != vnid_list.end()) + { + data = found->second; + } + } + + if (!data) + { + LOG_ERROR(LOADER, ".sceRefs: movw writing failed (code=0x%x, addr=0x%x)", code, addr); + break; + } + + vm::psv::write16(addr + 0, vm::psv::read16(addr + 0) | (data & 0x800) >> 1 | (data & 0xf000) >> 12); + vm::psv::write16(addr + 2, vm::psv::read16(addr + 2) | (data & 0x700) << 4 | (data & 0xff)); + + //if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(LOADER, ".sceRefs: movw written at 0x%x (data=0x%x)", addr, data); + } break; } - case 0x00000030: + case 0x00000030: // movt r*,# instruction is replaced { - // movt r12,# instruction will be replaced const u32 addr = *++code; - vm::psv::write16(addr + 0, 0xf2c0 | (data & 0x8000000) >> 17 | (data & 0xf0000000) >> 28); // MOVT - vm::psv::write16(addr + 2, 0x0c00 | (data & 0x7000000) >> 12 | (data & 0xff0000) >> 16); - //LOG_NOTICE(LOADER, "sceRefs: movt written at 0x%x (data=0x%x)", addr, data); + + if (!data) + { + LOG_ERROR(LOADER, ".sceRefs: movt writing failed (code=0x%x, addr=0x%x)", code, addr); + break; + } + + vm::psv::write16(addr + 0, vm::psv::read16(addr + 0) | (data & 0x8000000) >> 17 | (data & 0xf0000000) >> 28); + vm::psv::write16(addr + 2, vm::psv::read16(addr + 2) | (data & 0x7000000) >> 12 | (data & 0xff0000) >> 16); + + //if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(LOADER, ".sceRefs: movt written at 0x%x (data=0x%x)", addr, data); + } break; } case 0x00000000: { - // probably, no operation - //LOG_NOTICE(LOADER, "sceRefs: zero code"); + data = 0; + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(LOADER, ".sceRefs: zero code found"); + } break; } default: { - LOG_ERROR(LOADER, "sceRefs: unknown code found (0x%08x)", *code); + LOG_ERROR(LOADER, "Unknown code in .sceRefs section (0x%08x)", *code); } } } diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index b5d9850335..c71e8cb5f7 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -423,6 +423,7 @@ namespace loader case 0x00000007: //TLS Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value()); + LOG_ERROR(LOADER, "TLS: addr=0x%x, filesz=0x%x, memsz=0x%x", Emu.GetTLSAddr(), Emu.GetTLSFilesz(), Emu.GetTLSMemsz()); break; case 0x60000001: //LOOS+1 diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 9b3c761dde..ca94bcbcc5 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -58,16 +58,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 9b46ecec23..ba692d9a05 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -695,6 +695,156 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + From 6c40dc0631e83ce819eef6c3305b9221fd8ffae6 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 29 Jan 2015 20:42:51 +0300 Subject: [PATCH 35/94] Some functions added --- rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp | 36 +++++- rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp | 158 ++++++++++++++++++++++-- rpcs3/Emu/ARMv7/Modules/sceAudio.cpp | 57 +++++++-- rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp | 22 +++- rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp | 130 +++++++++++++++++-- rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp | 114 +++++++++++++++-- 6 files changed, 474 insertions(+), 43 deletions(-) diff --git a/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp b/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp index 0d9aa8a072..5b39017a62 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAppMgr.cpp @@ -4,6 +4,34 @@ extern psv_log_base sceAppMgr; +struct SceAppMgrEvent +{ + s32 event; + s32 appId; + char param[56]; +}; + +s32 sceAppMgrReceiveEventNum(vm::psv::ptr eventNum) +{ + throw __FUNCTION__; +} + +s32 sceAppMgrReceiveEvent(vm::psv::ptr appEvent) +{ + throw __FUNCTION__; +} + +s32 sceAppMgrAcquireBgmPort() +{ + throw __FUNCTION__; +} + +s32 sceAppMgrReleaseBgmPort() +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceAppMgr, #name, name) psv_log_base sceAppMgr("SceAppMgr", []() @@ -12,9 +40,9 @@ psv_log_base sceAppMgr("SceAppMgr", []() sceAppMgr.on_unload = nullptr; sceAppMgr.on_stop = nullptr; - //REG_FUNC(0x47E5DD7D, sceAppMgrReceiveEventNum); - //REG_FUNC(0xCFAD5A3A, sceAppMgrReceiveEvent); - //REG_FUNC(0xF3D65520, sceAppMgrAcquireBgmPort); - //REG_FUNC(0x96CBE713, sceAppMgrReleaseBgmPort); + REG_FUNC(0x47E5DD7D, sceAppMgrReceiveEventNum); + REG_FUNC(0xCFAD5A3A, sceAppMgrReceiveEvent); + REG_FUNC(0xF3D65520, sceAppMgrAcquireBgmPort); + REG_FUNC(0x96CBE713, sceAppMgrReleaseBgmPort); //REG_FUNC(0x49255C91, sceAppMgrGetRunStatus); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp index 567f6c4f3e..6d1739d789 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp @@ -4,6 +4,138 @@ extern psv_log_base sceAppUtil; +struct SceAppUtilInitParam +{ + u32 workBufSize; + char reserved[60]; +}; + +struct SceAppUtilBootParam +{ + u32 attr; + u32 appVersion; + char reserved[32]; +}; + +struct SceAppUtilSaveDataMountPoint +{ + char data[16]; +}; + +struct SceAppUtilSaveDataSlotParam +{ + u32 status; + char title[64]; + char subTitle[128]; + char detail[512]; + char iconPath[64]; + s32 userParam; + u32 sizeKB; + SceDateTime modifiedTime; + char reserved[48]; +}; + +struct SceAppUtilSaveDataSlotEmptyParam +{ + vm::psv::ptr title; + vm::psv::ptr iconPath; + vm::psv::ptr iconBuf; + u32 iconBufSize; + char reserved[32]; +}; + +struct SceAppUtilSaveDataSlot +{ + u32 id; + u32 status; + s32 userParam; + vm::psv::ptr emptyParam; +}; + +struct SceAppUtilSaveDataFile +{ + vm::psv::ptr filePath; + vm::psv::ptr buf; + u32 bufSize; + s64 offset; + u32 mode; + u32 progDelta; + char reserved[32]; +}; + +struct SceAppUtilSaveDataFileSlot +{ + u32 id; + vm::psv::ptr slotParam; + char reserved[32]; +}; + +s32 sceAppUtilInit(vm::psv::ptr initParam, vm::psv::ptr bootParam) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilShutdown() +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSaveDataSlotCreate(u32 slotId, vm::psv::ptr param, vm::psv::ptr mountPoint) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSaveDataSlotDelete(u32 slotId, vm::psv::ptr mountPoint) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSaveDataSlotSetParam(u32 slotId, vm::psv::ptr param, vm::psv::ptr mountPoint) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSaveDataSlotGetParam(u32 slotId, vm::psv::ptr param, vm::psv::ptr mountPoint) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSaveDataFileSave(vm::psv::ptr slot, vm::psv::ptr files, u32 fileNum, vm::psv::ptr mountPoint, vm::psv::ptr requiredSizeKB) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilPhotoMount() +{ + throw __FUNCTION__; +} + +s32 sceAppUtilPhotoUmount() +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSystemParamGetInt(u32 paramId, vm::psv::ptr value) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSystemParamGetString(u32 paramId, vm::psv::ptr buf, u32 bufSize) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilSaveSafeMemory(vm::psv::ptr buf, u32 bufSize, s64 offset) +{ + throw __FUNCTION__; +} + +s32 sceAppUtilLoadSafeMemory(vm::psv::ptr buf, u32 bufSize, s64 offset) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceAppUtil, #name, name) psv_log_base sceAppUtil("SceAppUtil", []() @@ -12,17 +144,17 @@ psv_log_base sceAppUtil("SceAppUtil", []() sceAppUtil.on_unload = nullptr; sceAppUtil.on_stop = nullptr; - //REG_FUNC(0xDAFFE671, sceAppUtilInit); - //REG_FUNC(0xB220B00B, sceAppUtilShutdown); - //REG_FUNC(0x7E8FE96A, sceAppUtilSaveDataSlotCreate); - //REG_FUNC(0x266A7646, sceAppUtilSaveDataSlotDelete); - //REG_FUNC(0x98630136, sceAppUtilSaveDataSlotSetParam); - //REG_FUNC(0x93F0D89F, sceAppUtilSaveDataSlotGetParam); - //REG_FUNC(0x1E2A6158, sceAppUtilSaveDataFileSave); - //REG_FUNC(0xEE85804D, sceAppUtilPhotoMount); - //REG_FUNC(0x9651B941, sceAppUtilPhotoUmount); - //REG_FUNC(0x5DFB9CA0, sceAppUtilSystemParamGetInt); - //REG_FUNC(0x6E6AA267, sceAppUtilSystemParamGetString); - //REG_FUNC(0x9D8AC677, sceAppUtilSaveSafeMemory); - //REG_FUNC(0x3424D772, sceAppUtilLoadSafeMemory); + REG_FUNC(0xDAFFE671, sceAppUtilInit); + REG_FUNC(0xB220B00B, sceAppUtilShutdown); + REG_FUNC(0x7E8FE96A, sceAppUtilSaveDataSlotCreate); + REG_FUNC(0x266A7646, sceAppUtilSaveDataSlotDelete); + REG_FUNC(0x98630136, sceAppUtilSaveDataSlotSetParam); + REG_FUNC(0x93F0D89F, sceAppUtilSaveDataSlotGetParam); + REG_FUNC(0x1E2A6158, sceAppUtilSaveDataFileSave); + REG_FUNC(0xEE85804D, sceAppUtilPhotoMount); + REG_FUNC(0x9651B941, sceAppUtilPhotoUmount); + REG_FUNC(0x5DFB9CA0, sceAppUtilSystemParamGetInt); + REG_FUNC(0x6E6AA267, sceAppUtilSystemParamGetString); + REG_FUNC(0x9D8AC677, sceAppUtilSaveSafeMemory); + REG_FUNC(0x3424D772, sceAppUtilLoadSafeMemory); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp index 36920a8e59..ad0ab8d9af 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAudio.cpp @@ -4,6 +4,47 @@ extern psv_log_base sceAudio; +s32 sceAudioOutOpenPort(s32 portType, s32 len, s32 freq, s32 param) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutReleasePort(s32 port) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutOutput(s32 port, vm::psv::ptr ptr) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutSetVolume(s32 port, s32 flag, vm::psv::ptr vol) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutSetConfig(s32 port, s32 len, s32 freq, s32 param) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutGetConfig(s32 port, s32 configType) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutGetRestSample(s32 port) +{ + throw __FUNCTION__; +} + +s32 sceAudioOutGetAdopt(s32 portType) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudio, #name, name) psv_log_base sceAudio("SceAudio", []() @@ -12,13 +53,13 @@ psv_log_base sceAudio("SceAudio", []() sceAudio.on_unload = nullptr; sceAudio.on_stop = nullptr; - //REG_FUNC(0x5BC341E4, sceAudioOutOpenPort); - //REG_FUNC(0x69E2E6B5, sceAudioOutReleasePort); - //REG_FUNC(0x02DB3F5F, sceAudioOutOutput); - //REG_FUNC(0x64167F11, sceAudioOutSetVolume); - //REG_FUNC(0xB8BA0D07, sceAudioOutSetConfig); - //REG_FUNC(0x9C8EDAEA, sceAudioOutGetConfig); - //REG_FUNC(0x9A5370C4, sceAudioOutGetRestSample); - //REG_FUNC(0x12FB1767, sceAudioOutGetAdopt); + REG_FUNC(0x5BC341E4, sceAudioOutOpenPort); + REG_FUNC(0x69E2E6B5, sceAudioOutReleasePort); + REG_FUNC(0x02DB3F5F, sceAudioOutOutput); + REG_FUNC(0x64167F11, sceAudioOutSetVolume); + REG_FUNC(0xB8BA0D07, sceAudioOutSetConfig); + REG_FUNC(0x9C8EDAEA, sceAudioOutGetConfig); + REG_FUNC(0x9A5370C4, sceAudioOutGetRestSample); + REG_FUNC(0x12FB1767, sceAudioOutGetAdopt); //REG_FUNC(0xC6D8D775, sceAudioInRaw); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp index 0ae64a168d..29c7378b33 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAudioIn.cpp @@ -4,6 +4,22 @@ extern psv_log_base sceAudioIn; +s32 sceAudioInOpenPort(s32 portType, s32 grain, s32 freq, s32 param) +{ + throw __FUNCTION__; +} + +s32 sceAudioInReleasePort(s32 port) +{ + throw __FUNCTION__; +} + +s32 sceAudioInInput(s32 port, vm::psv::ptr destPtr) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudioIn, #name, name) psv_log_base sceAudioIn("SceAudioIn", []() @@ -12,8 +28,8 @@ psv_log_base sceAudioIn("SceAudioIn", []() sceAudioIn.on_unload = nullptr; sceAudioIn.on_stop = nullptr; - //REG_FUNC(0x638ADD2D, sceAudioInInput); - //REG_FUNC(0x39B50DC1, sceAudioInOpenPort); - //REG_FUNC(0x3A61B8C4, sceAudioInReleasePort); + REG_FUNC(0x638ADD2D, sceAudioInInput); + REG_FUNC(0x39B50DC1, sceAudioInOpenPort); + REG_FUNC(0x3A61B8C4, sceAudioInReleasePort); //REG_FUNC(0x566AC433, sceAudioInGetAdopt); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp index f8e3952dec..bf0d1a6bf9 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAudiodec.cpp @@ -4,6 +4,122 @@ extern psv_log_base sceAudiodec; +struct SceAudiodecInitStreamParam +{ + u32 size; + u32 totalStreams; +}; + +struct SceAudiodecInitChParam +{ + u32 size; + u32 totalCh; +}; + +union SceAudiodecInitParam +{ + u32 size; + SceAudiodecInitChParam at9; + SceAudiodecInitStreamParam mp3; + SceAudiodecInitStreamParam aac; + SceAudiodecInitStreamParam celp; +}; + +struct SceAudiodecInfoAt9 +{ + u32 size; + u8 configData[4]; + u32 ch; + u32 bitRate; + u32 samplingRate; + u32 superFrameSize; + u32 framesInSuperFrame; +}; + +struct SceAudiodecInfoMp3 +{ + u32 size; + u32 ch; + u32 version; +}; + +struct SceAudiodecInfoAac +{ + u32 size; + u32 isAdts; + u32 ch; + u32 samplingRate; + u32 isSbr; +}; + +struct SceAudiodecInfoCelp +{ + u32 size; + u32 excitationMode; + u32 samplingRate; + u32 bitRate; + u32 lostCount; +}; + +union SceAudiodecInfo +{ + u32 size; + SceAudiodecInfoAt9 at9; + SceAudiodecInfoMp3 mp3; + SceAudiodecInfoAac aac; + SceAudiodecInfoCelp celp; +}; + +struct SceAudiodecCtrl +{ + u32 size; + s32 handle; + vm::psv::ptr pEs; + u32 inputEsSize; + u32 maxEsSize; + vm::psv::ptr pPcm; + u32 outputPcmSize; + u32 maxPcmSize; + u32 wordLength; + vm::psv::ptr pInfo; +}; + +s32 sceAudiodecInitLibrary(u32 codecType, vm::psv::ptr pInitParam) +{ + throw __FUNCTION__; +} + +s32 sceAudiodecTermLibrary(u32 codecType) +{ + throw __FUNCTION__; +} + +s32 sceAudiodecCreateDecoder(vm::psv::ptr pCtrl, u32 codecType) +{ + throw __FUNCTION__; +} + +s32 sceAudiodecDeleteDecoder(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudiodecDecode(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudiodecClearContext(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudiodecGetInternalError(vm::psv::ptr pCtrl, vm::psv::ptr pInternalError) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudiodec, #name, name) psv_log_base sceAudiodec("SceAudiodec", []() @@ -12,11 +128,11 @@ psv_log_base sceAudiodec("SceAudiodec", []() sceAudiodec.on_unload = nullptr; sceAudiodec.on_stop = nullptr; - //REG_FUNC(0x445C2CEF, sceAudiodecInitLibrary); - //REG_FUNC(0x45719B9D, sceAudiodecTermLibrary); - //REG_FUNC(0x4DFD3AAA, sceAudiodecCreateDecoder); - //REG_FUNC(0xE7A24E16, sceAudiodecDeleteDecoder); - //REG_FUNC(0xCCDABA04, sceAudiodecDecode); - //REG_FUNC(0xF72F9B64, sceAudiodecClearContext); - //REG_FUNC(0x883B0CF5, sceAudiodecGetInternalError); + REG_FUNC(0x445C2CEF, sceAudiodecInitLibrary); + REG_FUNC(0x45719B9D, sceAudiodecTermLibrary); + REG_FUNC(0x4DFD3AAA, sceAudiodecCreateDecoder); + REG_FUNC(0xE7A24E16, sceAudiodecDeleteDecoder); + REG_FUNC(0xCCDABA04, sceAudiodecDecode); + REG_FUNC(0xF72F9B64, sceAudiodecClearContext); + REG_FUNC(0x883B0CF5, sceAudiodecGetInternalError); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp b/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp index a3bf58617c..d507170248 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAudioenc.cpp @@ -4,6 +4,104 @@ extern psv_log_base sceAudioenc; +struct SceAudioencInitStreamParam +{ + u32 size; + u32 totalStreams; +}; + +struct SceAudioencInfoCelp +{ + u32 size; + u32 excitationMode; + u32 samplingRate; + u32 bitRate; +}; + +struct SceAudioencOptInfoCelp +{ + u32 size; + u8 header[32]; + u32 headerSize; + u32 encoderVersion; +}; + + +union SceAudioencInitParam +{ + u32 size; + SceAudioencInitStreamParam celp; +}; + +union SceAudioencInfo +{ + u32 size; + SceAudioencInfoCelp celp; +}; + +union SceAudioencOptInfo +{ + u32 size; + SceAudioencOptInfoCelp celp; +}; + +struct SceAudioencCtrl +{ + u32 size; + s32 handle; + vm::psv::ptr pInputPcm; + u32 inputPcmSize; + u32 maxPcmSize; + vm::psv::ptr pOutputEs; + u32 outputEsSize; + u32 maxEsSize; + u32 wordLength; + vm::psv::ptr pInfo; + vm::psv::ptr pOptInfo; +}; + + +s32 sceAudioencInitLibrary(u32 codecType, vm::psv::ptr pInitParam) +{ + throw __FUNCTION__; +} + +s32 sceAudioencTermLibrary(u32 codecType) +{ + throw __FUNCTION__; +} + +s32 sceAudioencCreateEncoder(vm::psv::ptr pCtrl, u32 codecType) +{ + throw __FUNCTION__; +} + +s32 sceAudioencDeleteEncoder(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudioencEncode(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudioencClearContext(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudioencGetOptInfo(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAudioencGetInternalError(vm::psv::ptr pCtrl, vm::psv::ptr pInternalError) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceAudioenc, #name, name) psv_log_base sceAudioenc("SceAudioenc", []() @@ -12,12 +110,12 @@ psv_log_base sceAudioenc("SceAudioenc", []() sceAudioenc.on_unload = nullptr; sceAudioenc.on_stop = nullptr; - //REG_FUNC(0x76EE4DC6, sceAudioencInitLibrary); - //REG_FUNC(0xAB32D022, sceAudioencTermLibrary); - //REG_FUNC(0x64C04AE8, sceAudioencCreateEncoder); - //REG_FUNC(0xC6BA5EE6, sceAudioencDeleteEncoder); - //REG_FUNC(0xD85DB29C, sceAudioencEncode); - //REG_FUNC(0x9386F42D, sceAudioencClearContext); - //REG_FUNC(0xD01C63A3, sceAudioencGetOptInfo); - //REG_FUNC(0x452246D0, sceAudioencGetInternalError); + REG_FUNC(0x76EE4DC6, sceAudioencInitLibrary); + REG_FUNC(0xAB32D022, sceAudioencTermLibrary); + REG_FUNC(0x64C04AE8, sceAudioencCreateEncoder); + REG_FUNC(0xC6BA5EE6, sceAudioencDeleteEncoder); + REG_FUNC(0xD85DB29C, sceAudioencEncode); + REG_FUNC(0x9386F42D, sceAudioencClearContext); + REG_FUNC(0xD01C63A3, sceAudioencGetOptInfo); + REG_FUNC(0x452246D0, sceAudioencGetInternalError); }); From 74b6d5c2eda6255ce346debb3cdedd54aa65287b Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 00:42:53 +0300 Subject: [PATCH 36/94] Some functions added --- rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp | 68 +- rpcs3/Emu/ARMv7/Modules/sceAppUtil.h | 69 ++ rpcs3/Emu/ARMv7/Modules/sceCamera.cpp | 325 +++++- rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp | 35 +- rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp | 581 +++++++++- rpcs3/Emu/ARMv7/Modules/sceDbg.cpp | 35 +- rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp | 2 +- rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp | 90 +- rpcs3/Emu/ARMv7/Modules/sceFiber.cpp | 89 +- rpcs3/Emu/ARMv7/Modules/sceFios.cpp | 1054 ++++++++++++++++--- rpcs3/Emu/ARMv7/Modules/sceIme.cpp | 38 +- rpcs3/Emu/ARMv7/Modules/sceIme.h | 70 ++ rpcs3/Loader/ELF32.cpp | 34 +- rpcs3/emucore.vcxproj | 2 + rpcs3/emucore.vcxproj.filters | 6 + 15 files changed, 2167 insertions(+), 331 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceAppUtil.h create mode 100644 rpcs3/Emu/ARMv7/Modules/sceIme.h diff --git a/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp index 6d1739d789..815efa0461 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.cpp @@ -2,73 +2,7 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" -extern psv_log_base sceAppUtil; - -struct SceAppUtilInitParam -{ - u32 workBufSize; - char reserved[60]; -}; - -struct SceAppUtilBootParam -{ - u32 attr; - u32 appVersion; - char reserved[32]; -}; - -struct SceAppUtilSaveDataMountPoint -{ - char data[16]; -}; - -struct SceAppUtilSaveDataSlotParam -{ - u32 status; - char title[64]; - char subTitle[128]; - char detail[512]; - char iconPath[64]; - s32 userParam; - u32 sizeKB; - SceDateTime modifiedTime; - char reserved[48]; -}; - -struct SceAppUtilSaveDataSlotEmptyParam -{ - vm::psv::ptr title; - vm::psv::ptr iconPath; - vm::psv::ptr iconBuf; - u32 iconBufSize; - char reserved[32]; -}; - -struct SceAppUtilSaveDataSlot -{ - u32 id; - u32 status; - s32 userParam; - vm::psv::ptr emptyParam; -}; - -struct SceAppUtilSaveDataFile -{ - vm::psv::ptr filePath; - vm::psv::ptr buf; - u32 bufSize; - s64 offset; - u32 mode; - u32 progDelta; - char reserved[32]; -}; - -struct SceAppUtilSaveDataFileSlot -{ - u32 id; - vm::psv::ptr slotParam; - char reserved[32]; -}; +#include "sceAppUtil.h" s32 sceAppUtilInit(vm::psv::ptr initParam, vm::psv::ptr bootParam) { diff --git a/rpcs3/Emu/ARMv7/Modules/sceAppUtil.h b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.h new file mode 100644 index 0000000000..2e489cab22 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceAppUtil.h @@ -0,0 +1,69 @@ +#pragma once + +struct SceAppUtilInitParam +{ + u32 workBufSize; + char reserved[60]; +}; + +struct SceAppUtilBootParam +{ + u32 attr; + u32 appVersion; + char reserved[32]; +}; + +struct SceAppUtilSaveDataMountPoint +{ + char data[16]; +}; + +struct SceAppUtilSaveDataSlotParam +{ + u32 status; + char title[64]; + char subTitle[128]; + char detail[512]; + char iconPath[64]; + s32 userParam; + u32 sizeKB; + SceDateTime modifiedTime; + char reserved[48]; +}; + +struct SceAppUtilSaveDataSlotEmptyParam +{ + vm::psv::ptr title; + vm::psv::ptr iconPath; + vm::psv::ptr iconBuf; + u32 iconBufSize; + char reserved[32]; +}; + +struct SceAppUtilSaveDataSlot +{ + u32 id; + u32 status; + s32 userParam; + vm::psv::ptr emptyParam; +}; + +struct SceAppUtilSaveDataFile +{ + vm::psv::ptr filePath; + vm::psv::ptr buf; + u32 bufSize; + s64 offset; + u32 mode; + u32 progDelta; + char reserved[32]; +}; + +struct SceAppUtilSaveDataFileSlot +{ + u32 id; + vm::psv::ptr slotParam; + char reserved[32]; +}; + +extern psv_log_base sceAppUtil; diff --git a/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp b/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp index 79c219443c..e341d6d75f 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceCamera.cpp @@ -4,6 +4,249 @@ extern psv_log_base sceCamera; +struct SceCameraInfo +{ + u32 sizeThis; + u32 wPriority; + u32 wFormat; + u32 wResolution; + u32 wFramerate; + u32 wWidth; + u32 wHeight; + u32 wRange; + u32 _padding_0; + u32 sizeIBase; + u32 sizeUBase; + u32 sizeVBase; + vm::psv::ptr pvIBase; + vm::psv::ptr pvUBase; + vm::psv::ptr pvVBase; + u32 wPitch; + u32 wBuffer; +}; + +struct SceCameraRead +{ + u32 sizeThis; + s32 dwMode; + s32 _padding_0; + s32 dwStatus; + u32 qwFrame; + u32 qwTimestamp; + u32 sizeIBase; + u32 sizeUBase; + u32 sizeVBase; + vm::psv::ptr pvIBase; + vm::psv::ptr pvUBase; + vm::psv::ptr pvVBase; +}; + +s32 sceCameraOpen(s32 devnum, vm::psv::ptr pInfo) +{ + throw __FUNCTION__; +} + +s32 sceCameraClose(s32 devnum) +{ + throw __FUNCTION__; +} + +s32 sceCameraStart(s32 devnum) +{ + throw __FUNCTION__; +} + +s32 sceCameraStop(s32 devnum) +{ + throw __FUNCTION__; +} + +s32 sceCameraRead(s32 devnum, vm::psv::ptr pRead) +{ + throw __FUNCTION__; +} + +s32 sceCameraIsActive(s32 devnum) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetSaturation(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetSaturation(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetBrightness(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetBrightness(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetContrast(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetContrast(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetSharpness(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetSharpness(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetReverse(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetReverse(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetEffect(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetEffect(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetEV(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetEV(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetZoom(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetZoom(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetAntiFlicker(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetAntiFlicker(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetISO(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetISO(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetGain(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetGain(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetWhiteBalance(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetWhiteBalance(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetBacklight(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetBacklight(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetNightmode(s32 devnum, vm::psv::ptr pMode) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetNightmode(s32 devnum, s32 mode) +{ + throw __FUNCTION__; +} + +s32 sceCameraLedSwitch(s32 devnum, s32 iSwitch) +{ + throw __FUNCTION__; +} + +s32 sceCameraLedBlink(s32 devnum, s32 iOnCount, s32 iOffCount, s32 iBlinkCount) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetNoiseReductionForDebug(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetNoiseReductionForDebug(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +s32 sceCameraGetSharpnessOffForDebug(s32 devnum, vm::psv::ptr pLevel) +{ + throw __FUNCTION__; +} + +s32 sceCameraSetSharpnessOffForDebug(s32 devnum, s32 level) +{ + throw __FUNCTION__; +} + +void sceCameraUseCacheMemoryForTrial(s32 isCache) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceCamera, #name, name) psv_log_base sceCamera("SceCamera", []() @@ -12,45 +255,45 @@ psv_log_base sceCamera("SceCamera", []() sceCamera.on_unload = nullptr; sceCamera.on_stop = nullptr; - //REG_FUNC(0xA462F801, sceCameraOpen); - //REG_FUNC(0xCD6E1CFC, sceCameraClose); - //REG_FUNC(0xA8FEAE35, sceCameraStart); - //REG_FUNC(0x1DD9C9CE, sceCameraStop); - //REG_FUNC(0x79B5C2DE, sceCameraRead); - //REG_FUNC(0x103A75B8, sceCameraIsActive); - //REG_FUNC(0x624F7653, sceCameraGetSaturation); - //REG_FUNC(0xF9F7CA3D, sceCameraSetSaturation); - //REG_FUNC(0x85D5951D, sceCameraGetBrightness); - //REG_FUNC(0x98D71588, sceCameraSetBrightness); - //REG_FUNC(0x8FBE84BE, sceCameraGetContrast); - //REG_FUNC(0x06FB2900, sceCameraSetContrast); - //REG_FUNC(0xAA72C3DC, sceCameraGetSharpness); - //REG_FUNC(0xD1A5BB0B, sceCameraSetSharpness); - //REG_FUNC(0x44F6043F, sceCameraGetReverse); - //REG_FUNC(0x1175F477, sceCameraSetReverse); - //REG_FUNC(0x7E8EF3B2, sceCameraGetEffect); - //REG_FUNC(0xE9D2CFB1, sceCameraSetEffect); - //REG_FUNC(0x8B5E6147, sceCameraGetEV); - //REG_FUNC(0x62AFF0B8, sceCameraSetEV); - //REG_FUNC(0x06D3816C, sceCameraGetZoom); - //REG_FUNC(0xF7464216, sceCameraSetZoom); - //REG_FUNC(0x9FDACB99, sceCameraGetAntiFlicker); - //REG_FUNC(0xE312958A, sceCameraSetAntiFlicker); - //REG_FUNC(0x4EBD5C68, sceCameraGetISO); - //REG_FUNC(0x3CF630A1, sceCameraSetISO); - //REG_FUNC(0x2C36D6F3, sceCameraGetGain); - //REG_FUNC(0xE65CFE86, sceCameraSetGain); - //REG_FUNC(0xDBFFA1DA, sceCameraGetWhiteBalance); - //REG_FUNC(0x4D4514AC, sceCameraSetWhiteBalance); - //REG_FUNC(0x8DD1292B, sceCameraGetBacklight); - //REG_FUNC(0xAE071044, sceCameraSetBacklight); - //REG_FUNC(0x12B6FF26, sceCameraGetNightmode); - //REG_FUNC(0x3F26233E, sceCameraSetNightmode); - //REG_FUNC(0xD02CFA5C, sceCameraLedSwitch); - //REG_FUNC(0x89B16030, sceCameraLedBlink); - //REG_FUNC(0x7670474C, sceCameraUseCacheMemoryForTrial); - //REG_FUNC(0x27BB0528, sceCameraGetNoiseReductionForDebug); - //REG_FUNC(0x233C9E27, sceCameraSetNoiseReductionForDebug); - //REG_FUNC(0xC387F4DC, sceCameraGetSharpnessOffForDebug); - //REG_FUNC(0xE22C2375, sceCameraSetSharpnessOffForDebug); + REG_FUNC(0xA462F801, sceCameraOpen); + REG_FUNC(0xCD6E1CFC, sceCameraClose); + REG_FUNC(0xA8FEAE35, sceCameraStart); + REG_FUNC(0x1DD9C9CE, sceCameraStop); + REG_FUNC(0x79B5C2DE, sceCameraRead); + REG_FUNC(0x103A75B8, sceCameraIsActive); + REG_FUNC(0x624F7653, sceCameraGetSaturation); + REG_FUNC(0xF9F7CA3D, sceCameraSetSaturation); + REG_FUNC(0x85D5951D, sceCameraGetBrightness); + REG_FUNC(0x98D71588, sceCameraSetBrightness); + REG_FUNC(0x8FBE84BE, sceCameraGetContrast); + REG_FUNC(0x06FB2900, sceCameraSetContrast); + REG_FUNC(0xAA72C3DC, sceCameraGetSharpness); + REG_FUNC(0xD1A5BB0B, sceCameraSetSharpness); + REG_FUNC(0x44F6043F, sceCameraGetReverse); + REG_FUNC(0x1175F477, sceCameraSetReverse); + REG_FUNC(0x7E8EF3B2, sceCameraGetEffect); + REG_FUNC(0xE9D2CFB1, sceCameraSetEffect); + REG_FUNC(0x8B5E6147, sceCameraGetEV); + REG_FUNC(0x62AFF0B8, sceCameraSetEV); + REG_FUNC(0x06D3816C, sceCameraGetZoom); + REG_FUNC(0xF7464216, sceCameraSetZoom); + REG_FUNC(0x9FDACB99, sceCameraGetAntiFlicker); + REG_FUNC(0xE312958A, sceCameraSetAntiFlicker); + REG_FUNC(0x4EBD5C68, sceCameraGetISO); + REG_FUNC(0x3CF630A1, sceCameraSetISO); + REG_FUNC(0x2C36D6F3, sceCameraGetGain); + REG_FUNC(0xE65CFE86, sceCameraSetGain); + REG_FUNC(0xDBFFA1DA, sceCameraGetWhiteBalance); + REG_FUNC(0x4D4514AC, sceCameraSetWhiteBalance); + REG_FUNC(0x8DD1292B, sceCameraGetBacklight); + REG_FUNC(0xAE071044, sceCameraSetBacklight); + REG_FUNC(0x12B6FF26, sceCameraGetNightmode); + REG_FUNC(0x3F26233E, sceCameraSetNightmode); + REG_FUNC(0xD02CFA5C, sceCameraLedSwitch); + REG_FUNC(0x89B16030, sceCameraLedBlink); + REG_FUNC(0x7670474C, sceCameraUseCacheMemoryForTrial); + REG_FUNC(0x27BB0528, sceCameraGetNoiseReductionForDebug); + REG_FUNC(0x233C9E27, sceCameraSetNoiseReductionForDebug); + REG_FUNC(0xC387F4DC, sceCameraGetSharpnessOffForDebug); + REG_FUNC(0xE22C2375, sceCameraSetSharpnessOffForDebug); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp b/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp index 013f4ff52b..cda018a995 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceCodecEngine.cpp @@ -4,6 +4,33 @@ extern psv_log_base sceCodecEngine; +struct SceCodecEnginePmonProcessorLoad +{ + u32 size; + u32 average; +}; + +s32 sceCodecEnginePmonStart() +{ + throw __FUNCTION__; +} + +s32 sceCodecEnginePmonStop() +{ + throw __FUNCTION__; +} + +s32 sceCodecEnginePmonGetProcessorLoad(vm::psv::ptr pProcessorLoad) +{ + throw __FUNCTION__; +} + +s32 sceCodecEnginePmonReset() +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceCodecEngine, #name, name) psv_log_base sceCodecEngine("SceCodecEngine", []() @@ -12,8 +39,8 @@ psv_log_base sceCodecEngine("SceCodecEngine", []() sceCodecEngine.on_unload = nullptr; sceCodecEngine.on_stop = nullptr; - //REG_FUNC(0x3E718890, sceCodecEnginePmonStart); - //REG_FUNC(0x268B1EF5, sceCodecEnginePmonStop); - //REG_FUNC(0x859E4A68, sceCodecEnginePmonGetProcessorLoad); - //REG_FUNC(0xA097E4C8, sceCodecEnginePmonReset); + REG_FUNC(0x3E718890, sceCodecEnginePmonStart); + REG_FUNC(0x268B1EF5, sceCodecEnginePmonStop); + REG_FUNC(0x859E4A68, sceCodecEnginePmonGetProcessorLoad); + REG_FUNC(0xA097E4C8, sceCodecEnginePmonReset); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp b/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp index 1f5a4863a3..3e7b998f63 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceCommonDialog.cpp @@ -2,8 +2,509 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceGxm.h" +#include "sceAppUtil.h" +#include "sceIme.h" + extern psv_log_base sceCommonDialog; +enum SceCommonDialogStatus : s32 +{ + SCE_COMMON_DIALOG_STATUS_NONE = 0, + SCE_COMMON_DIALOG_STATUS_RUNNING = 1, + SCE_COMMON_DIALOG_STATUS_FINISHED = 2 +}; + +enum SceCommonDialogResult : s32 +{ + SCE_COMMON_DIALOG_RESULT_OK, + SCE_COMMON_DIALOG_RESULT_USER_CANCELED, + SCE_COMMON_DIALOG_RESULT_ABORTED +}; + +struct SceCommonDialogRenderTargetInfo +{ + vm::psv::ptr depthSurfaceData; + vm::psv::ptr colorSurfaceData; + SceGxmColorSurfaceType surfaceType; + SceGxmColorFormat colorFormat; + u32 width; + u32 height; + u32 strideInPixels; + u8 reserved[32]; +}; + +struct SceCommonDialogUpdateParam +{ + SceCommonDialogRenderTargetInfo renderTarget; + vm::psv::ptr displaySyncObject; + u8 reserved[32]; +}; + +struct SceMsgDialogUserMessageParam +{ + s32 buttonType; + vm::psv::ptr msg; + char reserved[32]; +}; + +struct SceMsgDialogSystemMessageParam +{ + s32 sysMsgType; + s32 value; + char reserved[32]; +}; + +struct SceMsgDialogErrorCodeParam +{ + s32 errorCode; + char reserved[32]; +}; + +struct SceMsgDialogProgressBarParam +{ + s32 barType; + SceMsgDialogSystemMessageParam sysMsgParam; + vm::psv::ptr msg; + char reserved[32]; +}; + +struct SceMsgDialogParam +{ + u32 sdkVersion; + s32 mode; + vm::psv::ptr userMsgParam; + vm::psv::ptr sysMsgParam; + vm::psv::ptr errorCodeParam; + vm::psv::ptr progBarParam; + u32 flag; + char reserved[32]; +}; + +struct SceMsgDialogResult +{ + s32 mode; + s32 result; + s32 buttonId; + u8 reserved[32]; +}; + + +struct SceNetCheckDialogParam +{ + u32 sdkVersion; + s32 mode; + u8 reserved[128]; +}; + +struct SceNetCheckDialogResult +{ + s32 result; + u8 reserved[128]; +}; + +struct SceSaveDataDialogFixedParam +{ + u32 targetSlot; + char reserved[32]; +}; + +struct SceSaveDataDialogListParam +{ + vm::psv::ptr slotList; + u32 slotListSize; + s32 focusPos; + u32 focusId; + vm::psv::ptr listTitle; + char reserved[32]; +}; + +struct SceSaveDataDialogUserMessageParam +{ + s32 buttonType; + vm::psv::ptr msg; + u32 targetSlot; + char reserved[32]; +}; + +struct SceSaveDataDialogSystemMessageParam +{ + s32 sysMsgType; + s32 value; + u32 targetSlot; + char reserved[32]; +}; + +struct SceSaveDataDialogErrorCodeParam +{ + s32 errorCode; + u32 targetSlot; + char reserved[32]; +}; + +struct SceSaveDataDialogProgressBarParam +{ + s32 barType; + SceSaveDataDialogSystemMessageParam sysMsgParam; + vm::psv::ptr msg; + u32 targetSlot; + char reserved[32]; +}; + +struct SceSaveDataDialogSlotConfigParam +{ + vm::psv::ptr mountPoint; + vm::psv::ptr appSubDir; + char reserved[32]; +}; + +struct SceSaveDataDialogParam +{ + u32 sdkVersion; + s32 mode; + s32 dispType; + vm::psv::ptr fixedParam; + vm::psv::ptr listParam; + vm::psv::ptr userMsgParam; + vm::psv::ptr sysMsgParam; + vm::psv::ptr errorCodeParam; + vm::psv::ptr progBarParam; + vm::psv::ptr slotConfParam; + u32 flag; + vm::psv::ptr userdata; + char reserved[32]; +}; + +struct SceSaveDataDialogFinishParam +{ + u32 flag; + char reserved[32]; +}; + +struct SceSaveDataDialogSlotInfo +{ + u32 isExist; + vm::psv::ptr slotParam; + u8 reserved[32]; +}; + +struct SceSaveDataDialogResult +{ + s32 mode; + s32 result; + s32 buttonId; + u32 slotId; + vm::psv::ptr slotInfo; + vm::psv::ptr userdata; + char reserved[32]; +}; + + +struct SceImeDialogParam +{ + u32 sdkVersion; + u32 inputMethod; + u64 supportedLanguages; + s32 languagesForced; + u32 type; + u32 option; + vm::psv::ptr filter; + u32 dialogMode; + u32 textBoxMode; + vm::psv::ptr title; + u32 maxTextLength; + vm::psv::ptr initialText; + vm::psv::ptr inputTextBuffer; + char reserved[32]; +}; + +struct SceImeDialogResult +{ + s32 result; + char reserved[32]; +}; + +enum ScePhotoImportDialogFormatType : s32 +{ + SCE_PHOTOIMPORT_DIALOG_FORMAT_TYPE_UNKNOWN = 0, + SCE_PHOTOIMPORT_DIALOG_FORMAT_TYPE_JPEG, + SCE_PHOTOIMPORT_DIALOG_FORMAT_TYPE_PNG, + SCE_PHOTOIMPORT_DIALOG_FORMAT_TYPE_GIF, + SCE_PHOTOIMPORT_DIALOG_FORMAT_TYPE_BMP, + SCE_PHOTOIMPORT_DIALOG_FORMAT_TYPE_TIFF +}; + +enum ScePhotoImportDialogOrientation : s32 +{ + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_UNKNOWN = 0, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_TOP_LEFT, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_TOP_RIGHT, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_BOTTOM_RIGHT, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_BOTTOM_LEFT, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_LEFT_TOP, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_RIGHT_TOP, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_RIGHT_BOTTOM, + SCE_PHOTOIMPORT_DIALOG_ORIENTATION_LEFT_BOTTOM +}; + +struct ScePhotoImportDialogFileDataSub +{ + u32 width; + u32 height; + ScePhotoImportDialogFormatType format; + ScePhotoImportDialogOrientation orientation; + char reserved[32]; +}; + +struct ScePhotoImportDialogFileData +{ + char fileName[1024]; + char photoTitle[256]; + char reserved[32]; +}; + +struct ScePhotoImportDialogItemData +{ + ScePhotoImportDialogFileData fileData; + ScePhotoImportDialogFileDataSub dataSub; + char reserved[32]; +}; + +struct ScePhotoImportDialogResult +{ + s32 result; + u32 importedItemNum; + char reserved[32]; +}; + +struct ScePhotoImportDialogParam +{ + u32 sdkVersion; + s32 mode; + u32 visibleCategory; + u32 itemCount; + vm::psv::ptr itemData; + char reserved[32]; +}; + +struct ScePhotoReviewDialogParam +{ + u32 sdkVersion; + s32 mode; + char fileName[1024]; + vm::psv::ptr workMemory; + u32 workMemorySize; + char reserved[32]; +}; + +struct ScePhotoReviewDialogResult +{ + s32 result; + char reserved[32]; +}; + + +s32 sceCommonDialogUpdate(vm::psv::ptr updateParam) +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus sceMsgDialogGetStatus() +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogAbort() +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogGetResult(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogTerm() +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogClose() +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogProgressBarInc(s32 target, u32 delta) +{ + throw __FUNCTION__; +} + +s32 sceMsgDialogProgressBarSetValue(s32 target, u32 rate) +{ + throw __FUNCTION__; +} + +s32 sceNetCheckDialogInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus sceNetCheckDialogGetStatus() +{ + throw __FUNCTION__; +} + +s32 sceNetCheckDialogAbort() +{ + throw __FUNCTION__; +} + +s32 sceNetCheckDialogGetResult(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNetCheckDialogTerm() +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus sceSaveDataDialogGetStatus() +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogAbort() +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogGetResult(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogTerm() +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus sceSaveDataDialogGetSubStatus() +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogSubClose() +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogContinue(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogFinish(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogProgressBarInc(s32 target, u32 delta) +{ + throw __FUNCTION__; +} + +s32 sceSaveDataDialogProgressBarSetValue(s32 target, u32 rate) +{ + throw __FUNCTION__; +} + +s32 sceImeDialogInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus sceImeDialogGetStatus() +{ + throw __FUNCTION__; +} + +s32 sceImeDialogAbort() +{ + throw __FUNCTION__; +} + +s32 sceImeDialogGetResult(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceImeDialogTerm() +{ + throw __FUNCTION__; +} + +s32 scePhotoImportDialogInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus scePhotoImportDialogGetStatus() +{ + throw __FUNCTION__; +} + +s32 scePhotoImportDialogGetResult(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 scePhotoImportDialogTerm() +{ + throw __FUNCTION__; +} + +s32 scePhotoImportDialogAbort() +{ + throw __FUNCTION__; +} + +s32 scePhotoReviewDialogInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +SceCommonDialogStatus scePhotoReviewDialogGetStatus() +{ + throw __FUNCTION__; +} + +s32 scePhotoReviewDialogGetResult(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 scePhotoReviewDialogTerm() +{ + throw __FUNCTION__; +} + +s32 scePhotoReviewDialogAbort() +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceCommonDialog, #name, name) psv_log_base sceCommonDialog("SceCommonDialog", []() @@ -12,44 +513,44 @@ psv_log_base sceCommonDialog("SceCommonDialog", []() sceCommonDialog.on_unload = nullptr; sceCommonDialog.on_stop = nullptr; - //REG_FUNC(0x90530F2F, sceCommonDialogUpdate); - //REG_FUNC(0x755FF270, sceMsgDialogInit); - //REG_FUNC(0x4107019E, sceMsgDialogGetStatus); - //REG_FUNC(0xC296D396, sceMsgDialogClose); - //REG_FUNC(0x0CC66115, sceMsgDialogAbort); - //REG_FUNC(0xBB3BFC89, sceMsgDialogGetResult); - //REG_FUNC(0x81ACF695, sceMsgDialogTerm); - //REG_FUNC(0x7BE0E08B, sceMsgDialogProgressBarInc); - //REG_FUNC(0x9CDA5E0D, sceMsgDialogProgressBarSetValue); - //REG_FUNC(0xA38A4A0D, sceNetCheckDialogInit); - //REG_FUNC(0x8027292A, sceNetCheckDialogGetStatus); - //REG_FUNC(0x2D8EDF09, sceNetCheckDialogAbort); - //REG_FUNC(0xB05FCE9E, sceNetCheckDialogGetResult); - //REG_FUNC(0x8BE51C15, sceNetCheckDialogTerm); - //REG_FUNC(0xBF5248FA, sceSaveDataDialogInit); - //REG_FUNC(0x6E258046, sceSaveDataDialogGetStatus); - //REG_FUNC(0x013E7F74, sceSaveDataDialogAbort); - //REG_FUNC(0xB2FF576E, sceSaveDataDialogGetResult); - //REG_FUNC(0x2192A10A, sceSaveDataDialogTerm); - //REG_FUNC(0x19192C8B, sceSaveDataDialogContinue); - //REG_FUNC(0xBA0542CA, sceSaveDataDialogGetSubStatus); - //REG_FUNC(0x415D6068, sceSaveDataDialogSubClose); - //REG_FUNC(0x6C49924B, sceSaveDataDialogFinish); - //REG_FUNC(0xBDE00A83, sceSaveDataDialogProgressBarInc); - //REG_FUNC(0x5C322D1E, sceSaveDataDialogProgressBarSetValue); - //REG_FUNC(0x1E7043BF, sceImeDialogInit); - //REG_FUNC(0xCF0431FD, sceImeDialogGetStatus); - //REG_FUNC(0x594A220E, sceImeDialogAbort); - //REG_FUNC(0x2EB3D046, sceImeDialogGetResult); - //REG_FUNC(0x838A3AF4, sceImeDialogTerm); - //REG_FUNC(0x73EE7C9C, scePhotoImportDialogInit); - //REG_FUNC(0x032206D8, scePhotoImportDialogGetStatus); - //REG_FUNC(0xD855414C, scePhotoImportDialogGetResult); - //REG_FUNC(0x7FE5BD77, scePhotoImportDialogTerm); - //REG_FUNC(0x4B125581, scePhotoImportDialogAbort); - //REG_FUNC(0xCD990375, scePhotoReviewDialogInit); - //REG_FUNC(0xF4F600CA, scePhotoReviewDialogGetStatus); - //REG_FUNC(0xFFA35858, scePhotoReviewDialogGetResult); - //REG_FUNC(0xC700B2DF, scePhotoReviewDialogTerm); - //REG_FUNC(0x74FF2A8B, scePhotoReviewDialogAbort); + REG_FUNC(0x90530F2F, sceCommonDialogUpdate); + REG_FUNC(0x755FF270, sceMsgDialogInit); + REG_FUNC(0x4107019E, sceMsgDialogGetStatus); + REG_FUNC(0xC296D396, sceMsgDialogClose); + REG_FUNC(0x0CC66115, sceMsgDialogAbort); + REG_FUNC(0xBB3BFC89, sceMsgDialogGetResult); + REG_FUNC(0x81ACF695, sceMsgDialogTerm); + REG_FUNC(0x7BE0E08B, sceMsgDialogProgressBarInc); + REG_FUNC(0x9CDA5E0D, sceMsgDialogProgressBarSetValue); + REG_FUNC(0xA38A4A0D, sceNetCheckDialogInit); + REG_FUNC(0x8027292A, sceNetCheckDialogGetStatus); + REG_FUNC(0x2D8EDF09, sceNetCheckDialogAbort); + REG_FUNC(0xB05FCE9E, sceNetCheckDialogGetResult); + REG_FUNC(0x8BE51C15, sceNetCheckDialogTerm); + REG_FUNC(0xBF5248FA, sceSaveDataDialogInit); + REG_FUNC(0x6E258046, sceSaveDataDialogGetStatus); + REG_FUNC(0x013E7F74, sceSaveDataDialogAbort); + REG_FUNC(0xB2FF576E, sceSaveDataDialogGetResult); + REG_FUNC(0x2192A10A, sceSaveDataDialogTerm); + REG_FUNC(0x19192C8B, sceSaveDataDialogContinue); + REG_FUNC(0xBA0542CA, sceSaveDataDialogGetSubStatus); + REG_FUNC(0x415D6068, sceSaveDataDialogSubClose); + REG_FUNC(0x6C49924B, sceSaveDataDialogFinish); + REG_FUNC(0xBDE00A83, sceSaveDataDialogProgressBarInc); + REG_FUNC(0x5C322D1E, sceSaveDataDialogProgressBarSetValue); + REG_FUNC(0x1E7043BF, sceImeDialogInit); + REG_FUNC(0xCF0431FD, sceImeDialogGetStatus); + REG_FUNC(0x594A220E, sceImeDialogAbort); + REG_FUNC(0x2EB3D046, sceImeDialogGetResult); + REG_FUNC(0x838A3AF4, sceImeDialogTerm); + REG_FUNC(0x73EE7C9C, scePhotoImportDialogInit); + REG_FUNC(0x032206D8, scePhotoImportDialogGetStatus); + REG_FUNC(0xD855414C, scePhotoImportDialogGetResult); + REG_FUNC(0x7FE5BD77, scePhotoImportDialogTerm); + REG_FUNC(0x4B125581, scePhotoImportDialogAbort); + REG_FUNC(0xCD990375, scePhotoReviewDialogInit); + REG_FUNC(0xF4F600CA, scePhotoReviewDialogGetStatus); + REG_FUNC(0xFFA35858, scePhotoReviewDialogGetResult); + REG_FUNC(0xC700B2DF, scePhotoReviewDialogTerm); + REG_FUNC(0x74FF2A8B, scePhotoReviewDialogAbort); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp b/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp index 6fe3856b9c..6a2cc4c9a2 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceDbg.cpp @@ -4,6 +4,33 @@ extern psv_log_base sceDbg; +enum SceDbgBreakOnErrorState : s32 +{ + SCE_DBG_DISABLE_BREAK_ON_ERROR = 0, + SCE_DBG_ENABLE_BREAK_ON_ERROR +}; + +s32 sceDbgSetMinimumLogLevel(s32 minimumLogLevel) +{ + throw __FUNCTION__; +} + +s32 sceDbgSetBreakOnErrorState(SceDbgBreakOnErrorState state) +{ + throw __FUNCTION__; +} + +s32 sceDbgAssertionHandler(vm::psv::ptr pFile, s32 line, bool stop, vm::psv::ptr pComponent, vm::psv::ptr pMessage) // va_args... +{ + throw __FUNCTION__; +} + +s32 sceDbgLoggingHandler(vm::psv::ptr pFile, s32 line, s32 severity, vm::psv::ptr pComponent, vm::psv::ptr pMessage) // va_args... +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceDbg, #name, name) psv_log_base sceDbg("SceDbg", []() @@ -12,8 +39,8 @@ psv_log_base sceDbg("SceDbg", []() sceDbg.on_unload = nullptr; sceDbg.on_stop = nullptr; - //REG_FUNC(0x941622FA, sceDbgSetMinimumLogLevel); - //REG_FUNC(0x1AF3678B, sceDbgAssertionHandler); - //REG_FUNC(0x6605AB19, sceDbgLoggingHandler); - //REG_FUNC(0xED4A00BA, sceDbgSetBreakOnErrorState); + REG_FUNC(0x941622FA, sceDbgSetMinimumLogLevel); + REG_FUNC(0x1AF3678B, sceDbgAssertionHandler); + REG_FUNC(0x6605AB19, sceDbgLoggingHandler); + REG_FUNC(0xED4A00BA, sceDbgSetBreakOnErrorState); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp b/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp index d90fcca74f..f0cf7e3c8e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceDeci4p.cpp @@ -4,7 +4,7 @@ extern psv_log_base sceDeci4p; -typedef s32(*SceKernelDeci4pCallback)(s32 notifyId, s32 notifyCount, s32 notifyArg, vm::psv::ptr pCommon); +typedef vm::psv::ptr pCommon)> SceKernelDeci4pCallback; s32 sceKernelDeci4pOpen(vm::psv::ptr protoname, u32 protonum, u32 bufsize) { diff --git a/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp b/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp index 6d7e440c2f..8e31b95c72 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceDeflt.cpp @@ -4,6 +4,72 @@ extern psv_log_base sceDeflt; +s32 sceGzipIsValid(vm::psv::ptr pSrcGzip) +{ + throw __FUNCTION__; +} + +s32 sceGzipGetInfo(vm::psv::ptr pSrcGzip, vm::psv::ptr> ppvExtra, vm::psv::ptr> ppszName, vm::psv::ptr> ppszComment, vm::psv::ptr pusCrc, vm::psv::ptr> ppvData) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGzipGetName(vm::psv::ptr pSrcGzip) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGzipGetComment(vm::psv::ptr pSrcGzip) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceGzipGetCompressedData(vm::psv::ptr pSrcGzip) +{ + throw __FUNCTION__; +} + +s32 sceGzipDecompress(vm::psv::ptr pDst, u32 uiBufSize, vm::psv::ptr pSrcGzip, vm::psv::ptr puiCrc32) +{ + throw __FUNCTION__; +} + +s32 sceZlibIsValid(vm::psv::ptr pSrcZlib) +{ + throw __FUNCTION__; +} + +s32 sceZlibGetInfo(vm::psv::ptr pSrcZlib, vm::psv::ptr pbCmf, vm::psv::ptr pbFlg, vm::psv::ptr puiDictId, vm::psv::ptr> ppvData) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceZlibGetCompressedData(vm::psv::ptr pSrcZlib) +{ + throw __FUNCTION__; +} + +s32 sceZlibDecompress(vm::psv::ptr pDst, u32 uiBufSize, vm::psv::ptr pSrcZlib, vm::psv::ptr puiAdler32) +{ + throw __FUNCTION__; +} + +u32 sceZlibAdler32(u32 uiAdler, vm::psv::ptr pSrc, u32 uiSize) +{ + throw __FUNCTION__; +} + +s32 sceDeflateDecompress(vm::psv::ptr pDst, u32 uiBufSize, vm::psv::ptr pSrcDeflate, vm::psv::ptr> ppNext) +{ + throw __FUNCTION__; +} + +s32 sceZipGetInfo(vm::psv::ptr pSrc, vm::psv::ptr> ppvExtra, vm::psv::ptr puiCrc, vm::psv::ptr> ppvData) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceDeflt, #name, name) psv_log_base sceDeflt("SceDeflt", []() @@ -12,16 +78,16 @@ psv_log_base sceDeflt("SceDeflt", []() sceDeflt.on_unload = nullptr; sceDeflt.on_stop = nullptr; - //REG_FUNC(0xCD83A464, sceZlibAdler32); - //REG_FUNC(0x110D5050, sceDeflateDecompress); - //REG_FUNC(0xE3CB51A3, sceGzipDecompress); - //REG_FUNC(0xBABCF5CF, sceGzipGetComment); - //REG_FUNC(0xE1844802, sceGzipGetCompressedData); - //REG_FUNC(0x1B8E5862, sceGzipGetInfo); - //REG_FUNC(0xAEBAABE6, sceGzipGetName); - //REG_FUNC(0xDEDADC31, sceGzipIsValid); - //REG_FUNC(0xE38F754D, sceZlibDecompress); - //REG_FUNC(0xE680A65A, sceZlibGetCompressedData); - //REG_FUNC(0x4C0A685D, sceZlibGetInfo); - //REG_FUNC(0x14A0698D, sceZlibIsValid); + REG_FUNC(0xCD83A464, sceZlibAdler32); + REG_FUNC(0x110D5050, sceDeflateDecompress); + REG_FUNC(0xE3CB51A3, sceGzipDecompress); + REG_FUNC(0xBABCF5CF, sceGzipGetComment); + REG_FUNC(0xE1844802, sceGzipGetCompressedData); + REG_FUNC(0x1B8E5862, sceGzipGetInfo); + REG_FUNC(0xAEBAABE6, sceGzipGetName); + REG_FUNC(0xDEDADC31, sceGzipIsValid); + REG_FUNC(0xE38F754D, sceZlibDecompress); + REG_FUNC(0xE680A65A, sceZlibGetCompressedData); + REG_FUNC(0x4C0A685D, sceZlibGetInfo); + REG_FUNC(0x14A0698D, sceZlibIsValid); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp b/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp index 73678a396c..8d21dc8f66 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp @@ -4,6 +4,79 @@ extern psv_log_base sceFiber; +typedef vm::psv::ptr SceFiberEntry; + +union SceFiber +{ + static const uint size = 128; + static const uint align = 8; + u64 padding[size / sizeof(u64)]; +}; + +union SceFiberOptParam +{ + static const uint size = 128; + static const uint align = 8; + u64 padding[size / sizeof(u64)]; +}; + +union SceFiberInfo +{ + static const uint size = 128; + static const uint align = 8; + u64 padding[size / sizeof(u64)]; + + struct + { + SceFiberEntry entry; + u32 argOnInitialize; + vm::psv::ptr addrContext; + s32 sizeContext; + char name[32]; + }; +}; + +s32 _sceFiberInitializeImpl(vm::psv::ptr fiber, vm::psv::ptr name, SceFiberEntry entry, u32 argOnInitialize, vm::psv::ptr addrContext, u32 sizeContext, vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceFiberOptParamInitialize(vm::psv::ptr optParam) +{ + throw __FUNCTION__; +} + +s32 sceFiberFinalize(vm::psv::ptr fiber) +{ + throw __FUNCTION__; +} + +s32 sceFiberRun(vm::psv::ptr fiber, u32 argOnRunTo, vm::psv::ptr argOnReturn) +{ + throw __FUNCTION__; +} + +s32 sceFiberSwitch(vm::psv::ptr fiber, u32 argOnRunTo, vm::psv::ptr argOnRun) +{ + throw __FUNCTION__; +} + +s32 sceFiberGetSelf(vm::psv::ptr> fiber) +{ + throw __FUNCTION__; +} + +s32 sceFiberReturnToThread(u32 argOnReturn, vm::psv::ptr argOnRun) +{ + throw __FUNCTION__; +} + +s32 sceFiberGetInfo(vm::psv::ptr fiber, vm::psv::ptr fiberInfo) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceFiber, #name, name) psv_log_base sceFiber("SceFiber", []() @@ -12,15 +85,15 @@ psv_log_base sceFiber("SceFiber", []() sceFiber.on_unload = nullptr; sceFiber.on_stop = nullptr; - //REG_FUNC(0xF24A298C, _sceFiberInitializeImpl); + REG_FUNC(0xF24A298C, _sceFiberInitializeImpl); //REG_FUNC(0xC6A3F9BB, _sceFiberInitializeWithInternalOptionImpl); //REG_FUNC(0x7D0C7DDB, _sceFiberAttachContextAndRun); //REG_FUNC(0xE00B9AFE, _sceFiberAttachContextAndSwitch); - //REG_FUNC(0x801AB334, sceFiberOptParamInitialize); - //REG_FUNC(0xE160F844, sceFiberFinalize); - //REG_FUNC(0x7DF23243, sceFiberRun); - //REG_FUNC(0xE4283144, sceFiberSwitch); - //REG_FUNC(0x414D8CA5, sceFiberGetSelf); - //REG_FUNC(0x3B42921F, sceFiberReturnToThread); - //REG_FUNC(0x189599B4, sceFiberGetInfo); + REG_FUNC(0x801AB334, sceFiberOptParamInitialize); + REG_FUNC(0xE160F844, sceFiberFinalize); + REG_FUNC(0x7DF23243, sceFiberRun); + REG_FUNC(0xE4283144, sceFiberSwitch); + REG_FUNC(0x414D8CA5, sceFiberGetSelf); + REG_FUNC(0x3B42921F, sceFiberReturnToThread); + REG_FUNC(0x189599B4, sceFiberGetInfo); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceFios.cpp b/rpcs3/Emu/ARMv7/Modules/sceFios.cpp index d04af5b3cd..d542e97549 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceFios.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceFios.cpp @@ -4,6 +4,804 @@ extern psv_log_base sceFios; +typedef s64 SceFiosOffset; +typedef s64 SceFiosSize; +typedef u8 SceFiosOpEvent; +typedef s32 SceFiosHandle; +typedef SceFiosHandle SceFiosOp; +typedef SceFiosHandle SceFiosFH; +typedef SceFiosHandle SceFiosDH; +typedef s64 SceFiosTime; +typedef s8 SceFiosPriority; +typedef SceFiosTime SceFiosTimeInterval; +typedef u64 SceFiosDate; +typedef s32 SceFiosOverlayID; + +typedef vm::psv::ptr pContext, SceFiosOp op, SceFiosOpEvent event, s32 err)> SceFiosOpCallback; +typedef vm::psv::ptr fmt, va_list ap)> SceFiosVprintfCallback; +typedef vm::psv::ptr(vm::psv::ptr dst, vm::psv::ptr src, u32 len)> SceFiosMemcpyCallback; + +enum SceFiosWhence : s32 +{ + SCE_FIOS_SEEK_SET = 0, + SCE_FIOS_SEEK_CUR = 1, + SCE_FIOS_SEEK_END = 2 +}; + +struct SceFiosBuffer +{ + vm::psv::ptr pPtr; + u32 length; +}; + +struct SceFiosOpAttr +{ + SceFiosTime deadline; + SceFiosOpCallback pCallback; + vm::psv::ptr pCallbackContext; + s32 priority : 8; + u32 opflags : 24; + u32 userTag; + vm::psv::ptr userPtr; + vm::psv::ptr pReserved; +}; + +struct SceFiosDirEntry +{ + SceFiosOffset fileSize; + u32 statFlags; + u16 nameLength; + u16 fullPathLength; + u16 offsetToName; + u16 reserved[3]; + char fullPath[1024]; +}; + +struct SceFiosStat +{ + SceFiosOffset fileSize; + SceFiosDate accessDate; + SceFiosDate modificationDate; + SceFiosDate creationDate; + u32 statFlags; + u32 reserved; + s64 uid; + s64 gid; + s64 dev; + s64 ino; + s64 mode; +}; + +struct SceFiosOpenParams +{ + u32 openFlags; + u32 reserved; + SceFiosBuffer buffer; +}; + +struct SceFiosTuple +{ + SceFiosOffset offset; + SceFiosSize size; + char path[1024]; +}; + +struct SceFiosParams +{ + u32 initialized : 1; + u32 paramsSize : 14; + u32 pathMax : 16; + u32 profiling; + SceFiosBuffer opStorage; + SceFiosBuffer fhStorage; + SceFiosBuffer dhStorage; + SceFiosBuffer chunkStorage; + SceFiosVprintfCallback pVprintf; + SceFiosMemcpyCallback pMemcpy; + s32 threadPriority[2]; + s32 threadAffinity[2]; +}; + +struct SceFiosOverlay +{ + u8 type; + u8 order; + u8 reserved[10]; + SceFiosOverlayID id; + char dst[292]; + char src[292]; +}; + +typedef vm::psv::ptr SceFiosIOFilterCallback; + +struct SceFiosPsarcDearchiverContext +{ + u32 sizeOfContext; + u32 workBufferSize; + vm::psv::ptr pWorkBuffer; + s32 reserved[4]; +}; + +s32 sceFiosInitialize(vm::psv::ptr pParameters) +{ + throw __FUNCTION__; +} + +void sceFiosTerminate() +{ + throw __FUNCTION__; +} + +bool sceFiosIsInitialized(vm::psv::ptr pOutParameters) +{ + throw __FUNCTION__; +} + +void sceFiosUpdateParameters(vm::psv::ptr pParameters) +{ + throw __FUNCTION__; +} + +void sceFiosSetGlobalDefaultOpAttr(vm::psv::ptr pAttr) +{ + throw __FUNCTION__; +} + +bool sceFiosGetGlobalDefaultOpAttr(vm::psv::ptr pOutAttr) +{ + throw __FUNCTION__; +} + +void sceFiosSetThreadDefaultOpAttr(vm::psv::ptr pAttr) +{ + throw __FUNCTION__; +} + +bool sceFiosGetThreadDefaultOpAttr(vm::psv::ptr pOutAttr) +{ + throw __FUNCTION__; +} + +void sceFiosGetDefaultOpAttr(vm::psv::ptr pOutAttr) +{ + throw __FUNCTION__; +} + +void sceFiosSuspend() +{ + throw __FUNCTION__; +} + +u32 sceFiosGetSuspendCount() +{ + throw __FUNCTION__; +} + +bool sceFiosIsSuspended() +{ + throw __FUNCTION__; +} + +void sceFiosResume() +{ + throw __FUNCTION__; +} + +void sceFiosShutdownAndCancelOps() +{ + throw __FUNCTION__; +} + +void sceFiosCancelAllOps() +{ + throw __FUNCTION__; +} + +void sceFiosCloseAllFiles() +{ + throw __FUNCTION__; +} + +bool sceFiosIsIdle() +{ + throw __FUNCTION__; +} + +u32 sceFiosGetAllFHs(vm::psv::ptr pOutArray, u32 arraySize) +{ + throw __FUNCTION__; +} + +u32 sceFiosGetAllDHs(vm::psv::ptr pOutArray, u32 arraySize) +{ + throw __FUNCTION__; +} + +u32 sceFiosGetAllOps(vm::psv::ptr pOutArray, u32 arraySize) +{ + throw __FUNCTION__; +} + +bool sceFiosIsValidHandle(SceFiosHandle h) +{ + throw __FUNCTION__; +} + +s32 sceFiosPathcmp(vm::psv::ptr pA, vm::psv::ptr pB) +{ + throw __FUNCTION__; +} + +s32 sceFiosPathncmp(vm::psv::ptr pA, vm::psv::ptr pB, u32 n) +{ + throw __FUNCTION__; +} + +s32 sceFiosPrintf(vm::psv::ptr pFormat) // va_args... +{ + throw __FUNCTION__; +} + +s32 sceFiosVprintf(vm::psv::ptr pFormat) // va_list +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFileExists(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pOutExists) +{ + throw __FUNCTION__; +} + +bool sceFiosFileExistsSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFileGetSize(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pOutSize) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFileGetSizeSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFileDelete(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +s32 sceFiosFileDeleteSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosDirectoryExists(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pOutExists) +{ + throw __FUNCTION__; +} + +bool sceFiosDirectoryExistsSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosDirectoryCreate(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +s32 sceFiosDirectoryCreateSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosDirectoryDelete(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +s32 sceFiosDirectoryDeleteSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosExists(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pOutExists) +{ + throw __FUNCTION__; +} + +bool sceFiosExistsSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosStat(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pOutStatus) +{ + throw __FUNCTION__; +} + +s32 sceFiosStatSync(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pOutStatus) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosDelete(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +s32 sceFiosDeleteSync(vm::psv::ptr pAttr, vm::psv::ptr pPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosResolve(vm::psv::ptr pAttr, vm::psv::ptr pInTuple, vm::psv::ptr pOutTuple) +{ + throw __FUNCTION__; +} + +s32 sceFiosResolveSync(vm::psv::ptr pAttr, vm::psv::ptr pInTuple, vm::psv::ptr pOutTuple) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosRename(vm::psv::ptr pAttr, vm::psv::ptr pOldPath, vm::psv::ptr pNewPath) +{ + throw __FUNCTION__; +} + +s32 sceFiosRenameSync(vm::psv::ptr pAttr, vm::psv::ptr pOldPath, vm::psv::ptr pNewPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFileRead(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFileReadSync(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFileWrite(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFileWriteSync(vm::psv::ptr pAttr, vm::psv::ptr pPath, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFileTruncate(vm::psv::ptr pAttr, vm::psv::ptr pPath, SceFiosSize length) +{ + throw __FUNCTION__; +} + +s32 sceFiosFileTruncateSync(vm::psv::ptr pAttr, vm::psv::ptr pPath, SceFiosSize length) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHOpen(vm::psv::ptr pAttr, vm::psv::ptr pOutFH, vm::psv::ptr pPath, vm::psv::ptr pOpenParams) +{ + throw __FUNCTION__; +} + +s32 sceFiosFHOpenSync(vm::psv::ptr pAttr, vm::psv::ptr pOutFH, vm::psv::ptr pPath, vm::psv::ptr pOpenParams) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHStat(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pOutStatus) +{ + throw __FUNCTION__; +} + +s32 sceFiosFHStatSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pOutStatus) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHTruncate(vm::psv::ptr pAttr, SceFiosFH fh, SceFiosSize length) +{ + throw __FUNCTION__; +} + +s32 sceFiosFHTruncateSync(vm::psv::ptr pAttr, SceFiosFH fh, SceFiosSize length) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHSync(vm::psv::ptr pAttr, SceFiosFH fh) +{ + throw __FUNCTION__; +} + +s32 sceFiosFHSyncSync(vm::psv::ptr pAttr, SceFiosFH fh) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHRead(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHReadSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHWrite(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHWriteSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHReadv(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHReadvSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHWritev(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHWritevSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHPread(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHPreadSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHPwrite(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHPwriteSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr pBuf, SceFiosSize length, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHPreadv(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHPreadvSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHPwritev(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHPwritevSync(vm::psv::ptr pAttr, SceFiosFH fh, vm::psv::ptr iov, s32 iovcnt, SceFiosOffset offset) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosFHClose(vm::psv::ptr pAttr, SceFiosFH fh) +{ + throw __FUNCTION__; +} + +s32 sceFiosFHCloseSync(vm::psv::ptr pAttr, SceFiosFH fh) +{ + throw __FUNCTION__; +} + +SceFiosOffset sceFiosFHSeek(SceFiosFH fh, SceFiosOffset offset, SceFiosWhence whence) +{ + throw __FUNCTION__; +} + +SceFiosOffset sceFiosFHTell(SceFiosFH fh) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosFHGetPath(SceFiosFH fh) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosFHGetSize(SceFiosFH fh) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosFHGetOpenParams(SceFiosFH fh) +{ + throw __FUNCTION__; +} + +//SceFiosOp sceFiosDHOpen(vm::psv::ptr pAttr, vm::psv::ptr pOutDH, vm::psv::ptr pPath, SceFiosBuffer buf) +//{ +// throw __FUNCTION__; +//} +// +//s32 sceFiosDHOpenSync(vm::psv::ptr pAttr, vm::psv::ptr pOutDH, vm::psv::ptr pPath, SceFiosBuffer buf) +//{ +// throw __FUNCTION__; +//} + +SceFiosOp sceFiosDHRead(vm::psv::ptr pAttr, SceFiosDH dh, vm::psv::ptr pOutEntry) +{ + throw __FUNCTION__; +} + +s32 sceFiosDHReadSync(vm::psv::ptr pAttr, SceFiosDH dh, vm::psv::ptr pOutEntry) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosDHClose(vm::psv::ptr pAttr, SceFiosDH dh) +{ + throw __FUNCTION__; +} + +s32 sceFiosDHCloseSync(vm::psv::ptr pAttr, SceFiosDH dh) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDHGetPath(SceFiosDH dh) +{ + throw __FUNCTION__; +} + +bool sceFiosOpIsDone(SceFiosOp op) +{ + throw __FUNCTION__; +} + +s32 sceFiosOpWait(SceFiosOp op) +{ + throw __FUNCTION__; +} + +s32 sceFiosOpWaitUntil(SceFiosOp op, SceFiosTime deadline) +{ + throw __FUNCTION__; +} + +void sceFiosOpDelete(SceFiosOp op) +{ + throw __FUNCTION__; +} + +s32 sceFiosOpSyncWait(SceFiosOp op) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosOpSyncWaitForIO(SceFiosOp op) +{ + throw __FUNCTION__; +} + +s32 sceFiosOpGetError(SceFiosOp op) +{ + throw __FUNCTION__; +} + +void sceFiosOpCancel(SceFiosOp op) +{ + throw __FUNCTION__; +} + +bool sceFiosOpIsCancelled(SceFiosOp op) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosOpGetAttr(SceFiosOp op) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosOpGetPath(SceFiosOp op) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosOpGetBuffer(SceFiosOp op) +{ + throw __FUNCTION__; +} + +SceFiosOffset sceFiosOpGetOffset(SceFiosOp op) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosOpGetRequestCount(SceFiosOp op) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosOpGetActualCount(SceFiosOp op) +{ + throw __FUNCTION__; +} + +void sceFiosOpReschedule(SceFiosOp op, SceFiosTime newDeadline) +{ + throw __FUNCTION__; +} + +SceFiosTime sceFiosTimeGetCurrent() +{ + throw __FUNCTION__; +} + +s64 sceFiosTimeIntervalToNanoseconds(SceFiosTimeInterval interval) +{ + throw __FUNCTION__; +} + +SceFiosTimeInterval sceFiosTimeIntervalFromNanoseconds(s64 ns) +{ + throw __FUNCTION__; +} + +SceFiosDate sceFiosDateGetCurrent() +{ + throw __FUNCTION__; +} + +SceFiosDate sceFiosDateFromComponents(const struct vm::psv::ptr pComponents) +{ + throw __FUNCTION__; +} + +struct vm::psv::ptr sceFiosDateToComponents(SceFiosDate date, struct vm::psv::ptr pOutComponents) +{ + throw __FUNCTION__; +} + +SceFiosDate sceFiosDateFromSceDateTime(vm::psv::ptr pSceDateTime) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDateToSceDateTime(SceFiosDate date, vm::psv::ptr pSceDateTime) +{ + throw __FUNCTION__; +} + +s32 sceFiosOverlayAdd(vm::psv::ptr pOverlay, vm::psv::ptr pOutID) +{ + throw __FUNCTION__; +} + +s32 sceFiosOverlayRemove(SceFiosOverlayID id) +{ + throw __FUNCTION__; +} + +s32 sceFiosOverlayGetInfo(SceFiosOverlayID id, vm::psv::ptr pOutOverlay) +{ + throw __FUNCTION__; +} + +s32 sceFiosOverlayModify(SceFiosOverlayID id, vm::psv::ptr pNewValue) +{ + throw __FUNCTION__; +} + +s32 sceFiosOverlayGetList(vm::psv::ptr pOutIDs, u32 maxIDs, vm::psv::ptr pActualIDs) +{ + throw __FUNCTION__; +} + +s32 sceFiosOverlayResolveSync(s32 resolveFlag, vm::psv::ptr pInPath, vm::psv::ptr pOutPath, u32 maxPath) +{ + throw __FUNCTION__; +} + +SceFiosOp sceFiosArchiveGetMountBufferSize(vm::psv::ptr pAttr, vm::psv::ptr pArchivePath, vm::psv::ptr pOpenParams) +{ + throw __FUNCTION__; +} + +SceFiosSize sceFiosArchiveGetMountBufferSizeSync(vm::psv::ptr pAttr, vm::psv::ptr pArchivePath, vm::psv::ptr pOpenParams) +{ + throw __FUNCTION__; +} + +//SceFiosOp sceFiosArchiveMount(vm::psv::ptr pAttr, vm::psv::ptr pOutFH, vm::psv::ptr pArchivePath, vm::psv::ptr pMountPoint, SceFiosBuffer mountBuffer, vm::psv::ptr pOpenParams) +//{ +// throw __FUNCTION__; +//} +// +//s32 sceFiosArchiveMountSync(vm::psv::ptr pAttr, vm::psv::ptr pOutFH, vm::psv::ptr pArchivePath, vm::psv::ptr pMountPoint, SceFiosBuffer mountBuffer, vm::psv::ptr pOpenParams) +//{ +// throw __FUNCTION__; +//} + +SceFiosOp sceFiosArchiveUnmount(vm::psv::ptr pAttr, SceFiosFH fh) +{ + throw __FUNCTION__; +} + +s32 sceFiosArchiveUnmountSync(vm::psv::ptr pAttr, SceFiosFH fh) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDebugDumpError(s32 err, vm::psv::ptr pBuffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDebugDumpOp(SceFiosOp op, vm::psv::ptr pBuffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDebugDumpFH(SceFiosFH fh, vm::psv::ptr pBuffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDebugDumpDH(SceFiosDH dh, vm::psv::ptr pBuffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceFiosDebugDumpDate(SceFiosDate date, vm::psv::ptr pBuffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +s32 sceFiosIOFilterAdd(s32 index, SceFiosIOFilterCallback pFilterCallback, vm::psv::ptr pFilterContext) +{ + throw __FUNCTION__; +} + +s32 sceFiosIOFilterGetInfo(s32 index, vm::psv::ptr pOutFilterCallback, vm::psv::ptr> pOutFilterContext) +{ + throw __FUNCTION__; +} + +s32 sceFiosIOFilterRemove(s32 index) +{ + throw __FUNCTION__; +} + +void sceFiosIOFilterPsarcDearchiver() +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceFios, #name, name) psv_log_base sceFios("SceFios2", []() @@ -12,136 +810,136 @@ psv_log_base sceFios("SceFios2", []() sceFios.on_unload = nullptr; sceFios.on_stop = nullptr; - //REG_FUNC(0x15857180, sceFiosArchiveGetMountBufferSize); - //REG_FUNC(0xDF3352FC, sceFiosArchiveGetMountBufferSizeSync); + REG_FUNC(0x15857180, sceFiosArchiveGetMountBufferSize); + REG_FUNC(0xDF3352FC, sceFiosArchiveGetMountBufferSizeSync); //REG_FUNC(0x92E76BBD, sceFiosArchiveMount); //REG_FUNC(0xC4822276, sceFiosArchiveMountSync); - //REG_FUNC(0xFE1E1D28, sceFiosArchiveUnmount); - //REG_FUNC(0xB26DC24D, sceFiosArchiveUnmountSync); - //REG_FUNC(0x1E920B1D, sceFiosCancelAllOps); - //REG_FUNC(0xF85C208B, sceFiosCloseAllFiles); - //REG_FUNC(0xF6CACFC7, sceFiosDHClose); - //REG_FUNC(0x1F3CC428, sceFiosDHCloseSync); - //REG_FUNC(0x2B406DEB, sceFiosDHGetPath); + REG_FUNC(0xFE1E1D28, sceFiosArchiveUnmount); + REG_FUNC(0xB26DC24D, sceFiosArchiveUnmountSync); + REG_FUNC(0x1E920B1D, sceFiosCancelAllOps); + REG_FUNC(0xF85C208B, sceFiosCloseAllFiles); + REG_FUNC(0xF6CACFC7, sceFiosDHClose); + REG_FUNC(0x1F3CC428, sceFiosDHCloseSync); + REG_FUNC(0x2B406DEB, sceFiosDHGetPath); //REG_FUNC(0xEA9855BA, sceFiosDHOpen); //REG_FUNC(0x34BC3713, sceFiosDHOpenSync); - //REG_FUNC(0x72A0A851, sceFiosDHRead); - //REG_FUNC(0xB7E79CAD, sceFiosDHReadSync); - //REG_FUNC(0x280D284A, sceFiosDateFromComponents); - //REG_FUNC(0x5C593C1E, sceFiosDateGetCurrent); - //REG_FUNC(0x5CFF6EA0, sceFiosDateToComponents); - //REG_FUNC(0x44B9F8EB, sceFiosDebugDumpDH); - //REG_FUNC(0x159B1FA8, sceFiosDebugDumpDate); - //REG_FUNC(0x51E677DF, sceFiosDebugDumpError); - //REG_FUNC(0x5506ACAB, sceFiosDebugDumpFH); - //REG_FUNC(0xE438D4F0, sceFiosDebugDumpOp); - //REG_FUNC(0x764DFA7A, sceFiosDelete); - //REG_FUNC(0xAAC54B44, sceFiosDeleteSync); - //REG_FUNC(0x9198ED8B, sceFiosDirectoryCreate); - //REG_FUNC(0xE037B076, sceFiosDirectoryCreateSync); - //REG_FUNC(0xDA93677C, sceFiosDirectoryDelete); - //REG_FUNC(0xB9573146, sceFiosDirectoryDeleteSync); - //REG_FUNC(0x48D50D97, sceFiosDirectoryExists); - //REG_FUNC(0x726E01BE, sceFiosDirectoryExistsSync); - //REG_FUNC(0x6F12D8A5, sceFiosExists); - //REG_FUNC(0x125EFD34, sceFiosExistsSync); - //REG_FUNC(0xA88EDCA8, sceFiosFHClose); - //REG_FUNC(0x45182328, sceFiosFHCloseSync); - //REG_FUNC(0xC55DB73B, sceFiosFHGetOpenParams); - //REG_FUNC(0x37143AE3, sceFiosFHGetPath); - //REG_FUNC(0xC5C26581, sceFiosFHGetSize); - //REG_FUNC(0xBF699BD4, sceFiosFHOpen); - //REG_FUNC(0xC3E7C3DB, sceFiosFHOpenSync); - //REG_FUNC(0x6A51E688, sceFiosFHPread); - //REG_FUNC(0xE2805059, sceFiosFHPreadSync); - //REG_FUNC(0x7C4E0C42, sceFiosFHPreadv); - //REG_FUNC(0x4D42F95C, sceFiosFHPreadvSync); - //REG_FUNC(0xCF1FAA6F, sceFiosFHPwrite); - //REG_FUNC(0x1E962F57, sceFiosFHPwriteSync); - //REG_FUNC(0xBBC9AFD5, sceFiosFHPwritev); - //REG_FUNC(0x742ADDC4, sceFiosFHPwritevSync); - //REG_FUNC(0xB09AFBDF, sceFiosFHRead); - //REG_FUNC(0x76945919, sceFiosFHReadSync); - //REG_FUNC(0x7DB0AFAF, sceFiosFHReadv); - //REG_FUNC(0x1BC977FA, sceFiosFHReadvSync); - //REG_FUNC(0xA75F3C4A, sceFiosFHSeek); - //REG_FUNC(0xD97C4DF7, sceFiosFHStat); - //REG_FUNC(0xF8BEAC88, sceFiosFHStatSync); - //REG_FUNC(0xE485F35E, sceFiosFHSync); - //REG_FUNC(0xA909CCE3, sceFiosFHSyncSync); - //REG_FUNC(0xD7F33130, sceFiosFHTell); - //REG_FUNC(0x2B39453B, sceFiosFHTruncate); - //REG_FUNC(0xFEF940B7, sceFiosFHTruncateSync); - //REG_FUNC(0xE663138E, sceFiosFHWrite); - //REG_FUNC(0x984024E5, sceFiosFHWriteSync); - //REG_FUNC(0x988DD7FF, sceFiosFHWritev); - //REG_FUNC(0x267E6CE3, sceFiosFHWritevSync); - //REG_FUNC(0xB647278B, sceFiosFileDelete); - //REG_FUNC(0xB5302E30, sceFiosFileDeleteSync); - //REG_FUNC(0x8758E62F, sceFiosFileExists); - //REG_FUNC(0x233B070C, sceFiosFileExistsSync); - //REG_FUNC(0x79D9BB50, sceFiosFileGetSize); - //REG_FUNC(0x789215C3, sceFiosFileGetSizeSync); - //REG_FUNC(0x84080161, sceFiosFileRead); - //REG_FUNC(0x1C488B32, sceFiosFileReadSync); - //REG_FUNC(0xC5513E13, sceFiosFileTruncate); - //REG_FUNC(0x6E1252B8, sceFiosFileTruncateSync); - //REG_FUNC(0x42C278E5, sceFiosFileWrite); - //REG_FUNC(0x132B6DE6, sceFiosFileWriteSync); - //REG_FUNC(0x681184A2, sceFiosGetAllDHs); - //REG_FUNC(0x90AB9195, sceFiosGetAllFHs); - //REG_FUNC(0x8F62832C, sceFiosGetAllOps); - //REG_FUNC(0xC897F6A7, sceFiosGetDefaultOpAttr); - //REG_FUNC(0x30583FCB, sceFiosGetGlobalDefaultOpAttr); - //REG_FUNC(0x156EAFDC, sceFiosGetSuspendCount); - //REG_FUNC(0xD55B8555, sceFiosIOFilterAdd); - //REG_FUNC(0x7C9B14EB, sceFiosIOFilterGetInfo); - //REG_FUNC(0x057252F2, sceFiosIOFilterPsarcDearchiver); - //REG_FUNC(0x22E35018, sceFiosIOFilterRemove); - //REG_FUNC(0x774C2C05, sceFiosInitialize); - //REG_FUNC(0x29104BF3, sceFiosIsIdle); - //REG_FUNC(0xF4F54E09, sceFiosIsInitialized); - //REG_FUNC(0xD2466EA5, sceFiosIsSuspended); - //REG_FUNC(0xB309E327, sceFiosIsValidHandle); - //REG_FUNC(0x3904F205, sceFiosOpCancel); - //REG_FUNC(0xE4EA92FA, sceFiosOpDelete); - //REG_FUNC(0x218A43EE, sceFiosOpGetActualCount); - //REG_FUNC(0xABFEE706, sceFiosOpGetAttr); - //REG_FUNC(0x68C436E4, sceFiosOpGetBuffer); - //REG_FUNC(0xBF099E16, sceFiosOpGetError); - //REG_FUNC(0xF21213B9, sceFiosOpGetOffset); - //REG_FUNC(0x157515CB, sceFiosOpGetPath); - //REG_FUNC(0x9C1084C5, sceFiosOpGetRequestCount); - //REG_FUNC(0x0C81D80E, sceFiosOpIsCancelled); - //REG_FUNC(0x1B9A575E, sceFiosOpIsDone); - //REG_FUNC(0x968CADBD, sceFiosOpReschedule); - //REG_FUNC(0xE6A66C70, sceFiosOpSyncWait); - //REG_FUNC(0x202079F9, sceFiosOpSyncWaitForIO); - //REG_FUNC(0x2AC79DFC, sceFiosOpWait); - //REG_FUNC(0xCC823B47, sceFiosOpWaitUntil); - //REG_FUNC(0x27AE468B, sceFiosOverlayAdd); - //REG_FUNC(0xF4C6B72A, sceFiosOverlayGetInfo); - //REG_FUNC(0x1C0BCAD5, sceFiosOverlayGetList); - //REG_FUNC(0x30F56704, sceFiosOverlayModify); - //REG_FUNC(0xF3C84D0F, sceFiosOverlayRemove); - //REG_FUNC(0x8A243E74, sceFiosOverlayResolveSync); - //REG_FUNC(0x5E75937A, sceFiosPathcmp); - //REG_FUNC(0xCC21C849, sceFiosPathncmp); - //REG_FUNC(0xAF7FAADF, sceFiosPrintf); - //REG_FUNC(0x25E399E5, sceFiosRename); - //REG_FUNC(0x030306F4, sceFiosRenameSync); - //REG_FUNC(0xD0B19C9F, sceFiosResolve); - //REG_FUNC(0x7FF33797, sceFiosResolveSync); - //REG_FUNC(0xBF2D3CC1, sceFiosResume); - //REG_FUNC(0x4E2FD311, sceFiosSetGlobalDefaultOpAttr); - //REG_FUNC(0x5B8D48C4, sceFiosShutdownAndCancelOps); - //REG_FUNC(0xFF04AF72, sceFiosStat); - //REG_FUNC(0xACBAF3E0, sceFiosStatSync); - //REG_FUNC(0x510953DC, sceFiosSuspend); - //REG_FUNC(0x2904B539, sceFiosTerminate); - //REG_FUNC(0xE76C8EC3, sceFiosTimeGetCurrent); - //REG_FUNC(0x35A82737, sceFiosTimeIntervalFromNanoseconds); - //REG_FUNC(0x397BF626, sceFiosTimeIntervalToNanoseconds); - //REG_FUNC(0x1915052A, sceFiosUpdateParameters); - //REG_FUNC(0x5BA4BD6D, sceFiosVprintf); + REG_FUNC(0x72A0A851, sceFiosDHRead); + REG_FUNC(0xB7E79CAD, sceFiosDHReadSync); + REG_FUNC(0x280D284A, sceFiosDateFromComponents); + REG_FUNC(0x5C593C1E, sceFiosDateGetCurrent); + REG_FUNC(0x5CFF6EA0, sceFiosDateToComponents); + REG_FUNC(0x44B9F8EB, sceFiosDebugDumpDH); + REG_FUNC(0x159B1FA8, sceFiosDebugDumpDate); + REG_FUNC(0x51E677DF, sceFiosDebugDumpError); + REG_FUNC(0x5506ACAB, sceFiosDebugDumpFH); + REG_FUNC(0xE438D4F0, sceFiosDebugDumpOp); + REG_FUNC(0x764DFA7A, sceFiosDelete); + REG_FUNC(0xAAC54B44, sceFiosDeleteSync); + REG_FUNC(0x9198ED8B, sceFiosDirectoryCreate); + REG_FUNC(0xE037B076, sceFiosDirectoryCreateSync); + REG_FUNC(0xDA93677C, sceFiosDirectoryDelete); + REG_FUNC(0xB9573146, sceFiosDirectoryDeleteSync); + REG_FUNC(0x48D50D97, sceFiosDirectoryExists); + REG_FUNC(0x726E01BE, sceFiosDirectoryExistsSync); + REG_FUNC(0x6F12D8A5, sceFiosExists); + REG_FUNC(0x125EFD34, sceFiosExistsSync); + REG_FUNC(0xA88EDCA8, sceFiosFHClose); + REG_FUNC(0x45182328, sceFiosFHCloseSync); + REG_FUNC(0xC55DB73B, sceFiosFHGetOpenParams); + REG_FUNC(0x37143AE3, sceFiosFHGetPath); + REG_FUNC(0xC5C26581, sceFiosFHGetSize); + REG_FUNC(0xBF699BD4, sceFiosFHOpen); + REG_FUNC(0xC3E7C3DB, sceFiosFHOpenSync); + REG_FUNC(0x6A51E688, sceFiosFHPread); + REG_FUNC(0xE2805059, sceFiosFHPreadSync); + REG_FUNC(0x7C4E0C42, sceFiosFHPreadv); + REG_FUNC(0x4D42F95C, sceFiosFHPreadvSync); + REG_FUNC(0xCF1FAA6F, sceFiosFHPwrite); + REG_FUNC(0x1E962F57, sceFiosFHPwriteSync); + REG_FUNC(0xBBC9AFD5, sceFiosFHPwritev); + REG_FUNC(0x742ADDC4, sceFiosFHPwritevSync); + REG_FUNC(0xB09AFBDF, sceFiosFHRead); + REG_FUNC(0x76945919, sceFiosFHReadSync); + REG_FUNC(0x7DB0AFAF, sceFiosFHReadv); + REG_FUNC(0x1BC977FA, sceFiosFHReadvSync); + REG_FUNC(0xA75F3C4A, sceFiosFHSeek); + REG_FUNC(0xD97C4DF7, sceFiosFHStat); + REG_FUNC(0xF8BEAC88, sceFiosFHStatSync); + REG_FUNC(0xE485F35E, sceFiosFHSync); + REG_FUNC(0xA909CCE3, sceFiosFHSyncSync); + REG_FUNC(0xD7F33130, sceFiosFHTell); + REG_FUNC(0x2B39453B, sceFiosFHTruncate); + REG_FUNC(0xFEF940B7, sceFiosFHTruncateSync); + REG_FUNC(0xE663138E, sceFiosFHWrite); + REG_FUNC(0x984024E5, sceFiosFHWriteSync); + REG_FUNC(0x988DD7FF, sceFiosFHWritev); + REG_FUNC(0x267E6CE3, sceFiosFHWritevSync); + REG_FUNC(0xB647278B, sceFiosFileDelete); + REG_FUNC(0xB5302E30, sceFiosFileDeleteSync); + REG_FUNC(0x8758E62F, sceFiosFileExists); + REG_FUNC(0x233B070C, sceFiosFileExistsSync); + REG_FUNC(0x79D9BB50, sceFiosFileGetSize); + REG_FUNC(0x789215C3, sceFiosFileGetSizeSync); + REG_FUNC(0x84080161, sceFiosFileRead); + REG_FUNC(0x1C488B32, sceFiosFileReadSync); + REG_FUNC(0xC5513E13, sceFiosFileTruncate); + REG_FUNC(0x6E1252B8, sceFiosFileTruncateSync); + REG_FUNC(0x42C278E5, sceFiosFileWrite); + REG_FUNC(0x132B6DE6, sceFiosFileWriteSync); + REG_FUNC(0x681184A2, sceFiosGetAllDHs); + REG_FUNC(0x90AB9195, sceFiosGetAllFHs); + REG_FUNC(0x8F62832C, sceFiosGetAllOps); + REG_FUNC(0xC897F6A7, sceFiosGetDefaultOpAttr); + REG_FUNC(0x30583FCB, sceFiosGetGlobalDefaultOpAttr); + REG_FUNC(0x156EAFDC, sceFiosGetSuspendCount); + REG_FUNC(0xD55B8555, sceFiosIOFilterAdd); + REG_FUNC(0x7C9B14EB, sceFiosIOFilterGetInfo); + REG_FUNC(0x057252F2, sceFiosIOFilterPsarcDearchiver); + REG_FUNC(0x22E35018, sceFiosIOFilterRemove); + REG_FUNC(0x774C2C05, sceFiosInitialize); + REG_FUNC(0x29104BF3, sceFiosIsIdle); + REG_FUNC(0xF4F54E09, sceFiosIsInitialized); + REG_FUNC(0xD2466EA5, sceFiosIsSuspended); + REG_FUNC(0xB309E327, sceFiosIsValidHandle); + REG_FUNC(0x3904F205, sceFiosOpCancel); + REG_FUNC(0xE4EA92FA, sceFiosOpDelete); + REG_FUNC(0x218A43EE, sceFiosOpGetActualCount); + REG_FUNC(0xABFEE706, sceFiosOpGetAttr); + REG_FUNC(0x68C436E4, sceFiosOpGetBuffer); + REG_FUNC(0xBF099E16, sceFiosOpGetError); + REG_FUNC(0xF21213B9, sceFiosOpGetOffset); + REG_FUNC(0x157515CB, sceFiosOpGetPath); + REG_FUNC(0x9C1084C5, sceFiosOpGetRequestCount); + REG_FUNC(0x0C81D80E, sceFiosOpIsCancelled); + REG_FUNC(0x1B9A575E, sceFiosOpIsDone); + REG_FUNC(0x968CADBD, sceFiosOpReschedule); + REG_FUNC(0xE6A66C70, sceFiosOpSyncWait); + REG_FUNC(0x202079F9, sceFiosOpSyncWaitForIO); + REG_FUNC(0x2AC79DFC, sceFiosOpWait); + REG_FUNC(0xCC823B47, sceFiosOpWaitUntil); + REG_FUNC(0x27AE468B, sceFiosOverlayAdd); + REG_FUNC(0xF4C6B72A, sceFiosOverlayGetInfo); + REG_FUNC(0x1C0BCAD5, sceFiosOverlayGetList); + REG_FUNC(0x30F56704, sceFiosOverlayModify); + REG_FUNC(0xF3C84D0F, sceFiosOverlayRemove); + REG_FUNC(0x8A243E74, sceFiosOverlayResolveSync); + REG_FUNC(0x5E75937A, sceFiosPathcmp); + REG_FUNC(0xCC21C849, sceFiosPathncmp); + REG_FUNC(0xAF7FAADF, sceFiosPrintf); + REG_FUNC(0x25E399E5, sceFiosRename); + REG_FUNC(0x030306F4, sceFiosRenameSync); + REG_FUNC(0xD0B19C9F, sceFiosResolve); + REG_FUNC(0x7FF33797, sceFiosResolveSync); + REG_FUNC(0xBF2D3CC1, sceFiosResume); + REG_FUNC(0x4E2FD311, sceFiosSetGlobalDefaultOpAttr); + REG_FUNC(0x5B8D48C4, sceFiosShutdownAndCancelOps); + REG_FUNC(0xFF04AF72, sceFiosStat); + REG_FUNC(0xACBAF3E0, sceFiosStatSync); + REG_FUNC(0x510953DC, sceFiosSuspend); + REG_FUNC(0x2904B539, sceFiosTerminate); + REG_FUNC(0xE76C8EC3, sceFiosTimeGetCurrent); + REG_FUNC(0x35A82737, sceFiosTimeIntervalFromNanoseconds); + REG_FUNC(0x397BF626, sceFiosTimeIntervalToNanoseconds); + REG_FUNC(0x1915052A, sceFiosUpdateParameters); + REG_FUNC(0x5BA4BD6D, sceFiosVprintf); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceIme.cpp b/rpcs3/Emu/ARMv7/Modules/sceIme.cpp index d0e90298d9..797e282ace 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceIme.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceIme.cpp @@ -2,7 +2,33 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" -extern psv_log_base sceIme; +#include "sceIme.h" + +s32 sceImeOpen(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceImeUpdate() +{ + throw __FUNCTION__; +} + +s32 sceImeSetCaret(vm::psv::ptr caret) +{ + throw __FUNCTION__; +} + +s32 sceImeSetPreeditGeometry(vm::psv::ptr preedit) +{ + throw __FUNCTION__; +} + +s32 sceImeClose() +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceIme, #name, name) @@ -12,9 +38,9 @@ psv_log_base sceIme("SceIme", []() sceIme.on_unload = nullptr; sceIme.on_stop = nullptr; - //REG_FUNC(0x0E050613, sceImeOpen); - //REG_FUNC(0x71D6898A, sceImeUpdate); - //REG_FUNC(0x889A8421, sceImeClose); - //REG_FUNC(0xD8342D2A, sceImeSetCaret); - //REG_FUNC(0x7B1EFAA5, sceImeSetPreeditGeometry); + REG_FUNC(0x0E050613, sceImeOpen); + REG_FUNC(0x71D6898A, sceImeUpdate); + REG_FUNC(0x889A8421, sceImeClose); + REG_FUNC(0xD8342D2A, sceImeSetCaret); + REG_FUNC(0x7B1EFAA5, sceImeSetPreeditGeometry); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceIme.h b/rpcs3/Emu/ARMv7/Modules/sceIme.h new file mode 100644 index 0000000000..7e7fffb429 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceIme.h @@ -0,0 +1,70 @@ +#pragma once + +typedef s32(SceImeCharFilter)(u16 ch); + +struct SceImeRect +{ + u32 x; + u32 y; + u32 width; + u32 height; +}; + +struct SceImeEditText +{ + u32 preeditIndex; + u32 preeditLength; + u32 caretIndex; + vm::psv::ptr str; +}; + +union SceImeEventParam +{ + SceImeRect rect; + SceImeEditText text; + u32 caretIndex; +}; + +struct SceImeEvent +{ + u32 id; + SceImeEventParam param; +}; + +struct SceImeCaret +{ + u32 x; + u32 y; + u32 height; + u32 index; +}; + +struct SceImePreeditGeometry +{ + u32 x; + u32 y; + u32 height; +}; + +typedef void(SceImeEventHandler)(vm::psv::ptr arg, vm::psv::ptr e); + +struct SceImeParam +{ + u32 size; + u32 inputMethod; + u64 supportedLanguages; + s32 languagesForced; + u32 type; + u32 option; + vm::psv::ptr work; + vm::psv::ptr arg; + vm::psv::ptr handler; + vm::psv::ptr filter; + vm::psv::ptr initialText; + u32 maxTextLength; + vm::psv::ptr inputTextBuffer; + u32 reserved0; + u32 reserved1; +}; + +extern psv_log_base sceIme; diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 6a4884798b..01232eb579 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -256,9 +256,7 @@ namespace loader } case 0x0000002f: // movw r*,# instruction is replaced { - const u32 addr = *++code; - - if (!data) + if (!data) // probably, imported object { auto found = vnid_list.find(code.addr()); if (found != vnid_list.end()) @@ -269,36 +267,32 @@ namespace loader if (!data) { - LOG_ERROR(LOADER, ".sceRefs: movw writing failed (code=0x%x, addr=0x%x)", code, addr); - break; + LOG_ERROR(LOADER, ".sceRefs: movw writing failed (ref_addr=0x%x, addr=0x%x)", code, code[1]); + } + else //if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(LOADER, ".sceRefs: movw written at 0x%x (ref_addr=0x%x, data=0x%x)", code[1], code, data); } + const u32 addr = *++code; vm::psv::write16(addr + 0, vm::psv::read16(addr + 0) | (data & 0x800) >> 1 | (data & 0xf000) >> 12); vm::psv::write16(addr + 2, vm::psv::read16(addr + 2) | (data & 0x700) << 4 | (data & 0xff)); - - //if (Ini.HLELogging.GetValue()) - { - LOG_NOTICE(LOADER, ".sceRefs: movw written at 0x%x (data=0x%x)", addr, data); - } break; } case 0x00000030: // movt r*,# instruction is replaced { - const u32 addr = *++code; - if (!data) { - LOG_ERROR(LOADER, ".sceRefs: movt writing failed (code=0x%x, addr=0x%x)", code, addr); - break; + LOG_ERROR(LOADER, ".sceRefs: movt writing failed (ref_addr=0x%x, addr=0x%x)", code, code[1]); } - + else //if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(LOADER, ".sceRefs: movt written at 0x%x (ref_addr=0x%x, data=0x%x)", code[1], code, data); + } + + const u32 addr = *++code; vm::psv::write16(addr + 0, vm::psv::read16(addr + 0) | (data & 0x8000000) >> 17 | (data & 0xf0000000) >> 28); vm::psv::write16(addr + 2, vm::psv::read16(addr + 2) | (data & 0x7000000) >> 12 | (data & 0xff0000) >> 16); - - //if (Ini.HLELogging.GetValue()) - { - LOG_NOTICE(LOADER, ".sceRefs: movt written at 0x%x (data=0x%x)", addr, data); - } break; } case 0x00000000: diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index ca94bcbcc5..fb672d63a6 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -335,7 +335,9 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index ba692d9a05..6e45634fea 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1486,5 +1486,11 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + \ No newline at end of file From 35898a6cdf3d4afcff106342d31876eb305a3264 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 02:58:53 +0300 Subject: [PATCH 37/94] Some functions added --- rpcs3/Emu/ARMv7/Modules/sceFiber.cpp | 24 +- rpcs3/Emu/ARMv7/Modules/sceGxm.h | 6 +- rpcs3/Emu/ARMv7/Modules/sceHttp.cpp | 455 +++++++++++++++++++++--- rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp | 120 ++++++- rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp | 89 ++++- rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp | 14 +- rpcs3/Emu/ARMv7/Modules/sceLocation.cpp | 202 ++++++++++- rpcs3/Emu/ARMv7/Modules/sceMd5.cpp | 39 +- rpcs3/Emu/ARMv7/Modules/sceMotion.cpp | 133 ++++++- rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp | 21 +- rpcs3/Emu/ARMv7/PSVFuncList.h | 16 + 11 files changed, 997 insertions(+), 122 deletions(-) diff --git a/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp b/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp index 8d21dc8f66..ab35f7a9be 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceFiber.cpp @@ -6,33 +6,37 @@ extern psv_log_base sceFiber; typedef vm::psv::ptr SceFiberEntry; -union SceFiber +struct SceFiber { static const uint size = 128; static const uint align = 8; u64 padding[size / sizeof(u64)]; }; -union SceFiberOptParam +struct SceFiberOptParam { static const uint size = 128; static const uint align = 8; u64 padding[size / sizeof(u64)]; }; -union SceFiberInfo +struct SceFiberInfo { static const uint size = 128; static const uint align = 8; - u64 padding[size / sizeof(u64)]; - struct + union { - SceFiberEntry entry; - u32 argOnInitialize; - vm::psv::ptr addrContext; - s32 sizeContext; - char name[32]; + u64 padding[size / sizeof(u64)]; + + struct + { + SceFiberEntry entry; + u32 argOnInitialize; + vm::psv::ptr addrContext; + s32 sizeContext; + char name[32]; + }; }; }; diff --git a/rpcs3/Emu/ARMv7/Modules/sceGxm.h b/rpcs3/Emu/ARMv7/Modules/sceGxm.h index 28cdac4daf..390c7ed1e7 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceGxm.h +++ b/rpcs3/Emu/ARMv7/Modules/sceGxm.h @@ -1002,9 +1002,9 @@ enum SceGxmColorMask : u8 struct SceGxmBlendInfo { - SceGxmColorMask colorMask; - SceGxmBlendFunc colorFunc : 4; - SceGxmBlendFunc alphaFunc : 4; + SceGxmColorMask colorMask; + SceGxmBlendFunc colorFunc : 4; + SceGxmBlendFunc alphaFunc : 4; SceGxmBlendFactor colorSrc : 4; SceGxmBlendFactor colorDst : 4; SceGxmBlendFactor alphaSrc : 4; diff --git a/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp b/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp index 4f23c935cd..814159303e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp @@ -4,6 +4,355 @@ extern psv_log_base sceHttp; +enum SceHttpHttpVersion : s32 +{ + SCE_HTTP_VERSION_1_0 = 1, + SCE_HTTP_VERSION_1_1 +}; + +enum SceHttpProxyMode : s32 +{ + SCE_HTTP_PROXY_AUTO, + SCE_HTTP_PROXY_MANUAL +}; + +enum SceHttpAddHeaderMode : s32 +{ + SCE_HTTP_HEADER_OVERWRITE, + SCE_HTTP_HEADER_ADD +}; + +enum SceHttpAuthType : s32 +{ + SCE_HTTP_AUTH_BASIC, + SCE_HTTP_AUTH_DIGEST, + SCE_HTTP_AUTH_RESERVED0, + SCE_HTTP_AUTH_RESERVED1, + SCE_HTTP_AUTH_RESERVED2 +}; + +typedef vm::psv::ptr realm, vm::psv::ptr username, vm::psv::ptr password, s32 needEntity, vm::psv::ptr> entityBody, vm::psv::ptr entitySize, vm::psv::ptr save, vm::psv::ptr userArg)> SceHttpAuthInfoCallback; + +typedef vm::psv::ptr method, vm::psv::ptr location, vm::psv::ptr userArg)> SceHttpRedirectCallback; + +struct SceHttpMemoryPoolStats +{ + u32 poolSize; + u32 maxInuseSize; + u32 currentInuseSize; + s32 reserved; +}; + +struct SceHttpUriElement +{ + s32 opaque; + vm::psv::ptr scheme; + vm::psv::ptr username; + vm::psv::ptr password; + vm::psv::ptr hostname; + vm::psv::ptr path; + vm::psv::ptr query; + vm::psv::ptr fragment; + u16 port; + u8 reserved[10]; +}; + +typedef vm::psv::ptr url, vm::psv::ptr cookieHeader, u32 headerLen, vm::psv::ptr userArg)> SceHttpCookieRecvCallback; + +typedef vm::psv::ptr url, vm::psv::ptr cookieHeader, vm::psv::ptr userArg)> SceHttpCookieSendCallback; + +struct SceSslCert; + +struct SceHttpsData +{ + vm::psv::ptr ptr; + u32 size; +}; + +struct SceHttpsCaList +{ + vm::psv::ptr> caCerts; + s32 caNum; +}; + +typedef vm::psv::ptr> sslCert, s32 certNum, vm::psv::ptr userArg)> SceHttpsCallback; + +s32 sceHttpInit(u32 poolSize) +{ + throw __FUNCTION__; +} + +s32 sceHttpTerm() +{ + throw __FUNCTION__; +} + +s32 sceHttpGetMemoryPoolStats(vm::psv::ptr currentStat) +{ + throw __FUNCTION__; +} + +s32 sceHttpCreateTemplate(vm::psv::ptr userAgent, s32 httpVer, s32 autoProxyConf) +{ + throw __FUNCTION__; +} + +s32 sceHttpDeleteTemplate(s32 tmplId) +{ + throw __FUNCTION__; +} + +s32 sceHttpCreateConnection(s32 tmplId, vm::psv::ptr serverName, vm::psv::ptr scheme, u16 port, s32 enableKeepalive) +{ + throw __FUNCTION__; +} + +s32 sceHttpCreateConnectionWithURL(s32 tmplId, vm::psv::ptr url, s32 enableKeepalive) +{ + throw __FUNCTION__; +} + +s32 sceHttpDeleteConnection(s32 connId) +{ + throw __FUNCTION__; +} + +s32 sceHttpCreateRequest(s32 connId, s32 method, vm::psv::ptr path, u64 contentLength) +{ + throw __FUNCTION__; +} + +s32 sceHttpCreateRequestWithURL(s32 connId, s32 method, vm::psv::ptr url, u64 contentLength) +{ + throw __FUNCTION__; +} + +s32 sceHttpDeleteRequest(s32 reqId) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetResponseHeaderMaxSize(s32 id, u32 headerSize) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetRecvBlockSize(s32 id, u32 blockSize) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetRequestContentLength(s32 id, u64 contentLength) +{ + throw __FUNCTION__; +} + +s32 sceHttpSendRequest(s32 reqId, vm::psv::ptr postData, u32 size) +{ + throw __FUNCTION__; +} + +s32 sceHttpAbortRequest(s32 reqId) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetResponseContentLength(s32 reqId, vm::psv::ptr contentLength) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetStatusCode(s32 reqId, vm::psv::ptr statusCode) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetAllResponseHeaders(s32 reqId, vm::psv::ptr> header, vm::psv::ptr headerSize) +{ + throw __FUNCTION__; +} + +s32 sceHttpReadData(s32 reqId, vm::psv::ptr data, u32 size) +{ + throw __FUNCTION__; +} + +s32 sceHttpAddRequestHeader(s32 id, vm::psv::ptr name, vm::psv::ptr value, u32 mode) +{ + throw __FUNCTION__; +} + +s32 sceHttpRemoveRequestHeader(s32 id, vm::psv::ptr name) +{ + throw __FUNCTION__; +} + +s32 sceHttpParseResponseHeader(vm::psv::ptr header, u32 headerLen, vm::psv::ptr fieldStr, vm::psv::ptr> fieldValue, vm::psv::ptr valueLen) +{ + throw __FUNCTION__; +} + +s32 sceHttpParseStatusLine(vm::psv::ptr statusLine, u32 lineLen, vm::psv::ptr httpMajorVer, vm::psv::ptr httpMinorVer, vm::psv::ptr responseCode, vm::psv::ptr> reasonPhrase, vm::psv::ptr phraseLen) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetAuthInfoCallback(s32 id, SceHttpAuthInfoCallback cbfunc, vm::psv::ptr userArg) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetAuthEnabled(s32 id, s32 enable) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetAuthEnabled(s32 id, vm::psv::ptr enable) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetRedirectCallback(s32 id, SceHttpRedirectCallback cbfunc, vm::psv::ptr userArg) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetAutoRedirect(s32 id, s32 enable) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetAutoRedirect(s32 id, vm::psv::ptr enable) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetResolveTimeOut(s32 id, u32 usec) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetResolveRetry(s32 id, s32 retry) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetConnectTimeOut(s32 id, u32 usec) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetSendTimeOut(s32 id, u32 usec) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetRecvTimeOut(s32 id, u32 usec) +{ + throw __FUNCTION__; +} + +s32 sceHttpUriEscape(vm::psv::ptr out, vm::psv::ptr require, u32 prepare, vm::psv::ptr in) +{ + throw __FUNCTION__; +} + +s32 sceHttpUriUnescape(vm::psv::ptr out, vm::psv::ptr require, u32 prepare, vm::psv::ptr in) +{ + throw __FUNCTION__; +} + +s32 sceHttpUriParse(vm::psv::ptr out, vm::psv::ptr srcUrl, vm::psv::ptr pool, vm::psv::ptr require, u32 prepare) +{ + throw __FUNCTION__; +} + +s32 sceHttpUriBuild(vm::psv::ptr out, vm::psv::ptr require, u32 prepare, vm::psv::ptr srcElement, u32 option) +{ + throw __FUNCTION__; +} + +s32 sceHttpUriMerge(vm::psv::ptr mergedUrl, vm::psv::ptr url, vm::psv::ptr relativeUrl, vm::psv::ptr require, u32 prepare, u32 option) +{ + throw __FUNCTION__; +} + +s32 sceHttpUriSweepPath(vm::psv::ptr dst, vm::psv::ptr src, u32 srcSize) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetCookieEnabled(s32 id, s32 enable) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetCookieEnabled(s32 id, vm::psv::ptr enable) +{ + throw __FUNCTION__; +} + +s32 sceHttpGetCookie(vm::psv::ptr url, vm::psv::ptr cookie, vm::psv::ptr cookieLength, u32 prepare, s32 secure) +{ + throw __FUNCTION__; +} + +s32 sceHttpAddCookie(vm::psv::ptr url, vm::psv::ptr cookie, u32 cookieLength) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetCookieRecvCallback(s32 id, SceHttpCookieRecvCallback cbfunc, vm::psv::ptr userArg) +{ + throw __FUNCTION__; +} + +s32 sceHttpSetCookieSendCallback(s32 id, SceHttpCookieSendCallback cbfunc, vm::psv::ptr userArg) +{ + throw __FUNCTION__; +} + +s32 sceHttpsLoadCert(s32 caCertNum, vm::psv::ptr> caList, vm::psv::ptr cert, vm::psv::ptr privKey) +{ + throw __FUNCTION__; +} + +s32 sceHttpsUnloadCert() +{ + throw __FUNCTION__; +} + +s32 sceHttpsEnableOption(u32 sslFlags) +{ + throw __FUNCTION__; +} + +s32 sceHttpsDisableOption(u32 sslFlags) +{ + throw __FUNCTION__; +} + +s32 sceHttpsGetSslError(s32 id, vm::psv::ptr errNum, vm::psv::ptr detail) +{ + throw __FUNCTION__; +} + +s32 sceHttpsSetSslCallback(s32 id, SceHttpsCallback cbfunc, vm::psv::ptr userArg) +{ + throw __FUNCTION__; +} + +s32 sceHttpsGetCaList(vm::psv::ptr caList) +{ + throw __FUNCTION__; +} + +s32 sceHttpsFreeCaList(vm::psv::ptr caList) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceHttp, #name, name) psv_log_base sceHttp("SceHttp", []() @@ -12,45 +361,45 @@ psv_log_base sceHttp("SceHttp", []() sceHttp.on_unload = nullptr; sceHttp.on_stop = nullptr; - //REG_FUNC(0x214926D9, sceHttpInit); - //REG_FUNC(0xC9076666, sceHttpTerm); - //REG_FUNC(0xF98CDFA9, sceHttpGetMemoryPoolStats); - //REG_FUNC(0x62241DAB, sceHttpCreateTemplate); - //REG_FUNC(0xEC85ECFB, sceHttpDeleteTemplate); - //REG_FUNC(0xC616C200, sceHttpCreateConnectionWithURL); - //REG_FUNC(0xAEB3307E, sceHttpCreateConnection); - //REG_FUNC(0xF0F65C15, sceHttpDeleteConnection); - //REG_FUNC(0xBD5DA1D0, sceHttpCreateRequestWithURL); - //REG_FUNC(0xB0284270, sceHttpCreateRequest); - //REG_FUNC(0x3D3D29AD, sceHttpDeleteRequest); - //REG_FUNC(0x9CA58B99, sceHttpSendRequest); - //REG_FUNC(0x7EDE3979, sceHttpReadData); - //REG_FUNC(0xF580D304, sceHttpGetResponseContentLength); - //REG_FUNC(0x27071691, sceHttpGetStatusCode); - //REG_FUNC(0xEA61662F, sceHttpAbortRequest); - //REG_FUNC(0x7B51B122, sceHttpAddRequestHeader); - //REG_FUNC(0x5EB5F548, sceHttpRemoveRequestHeader); - //REG_FUNC(0x11F6C27F, sceHttpGetAllResponseHeaders); - //REG_FUNC(0x03A6C89E, sceHttpParseResponseHeader); - //REG_FUNC(0x179C56DB, sceHttpParseStatusLine); - //REG_FUNC(0x1DA2A673, sceHttpUriEscape); - //REG_FUNC(0x1274D318, sceHttpUriUnescape); - //REG_FUNC(0x1D45F24E, sceHttpUriParse); - //REG_FUNC(0x47664424, sceHttpUriBuild); - //REG_FUNC(0x75027D1D, sceHttpUriMerge); - //REG_FUNC(0x50737A3F, sceHttpUriSweepPath); - //REG_FUNC(0x37C30C90, sceHttpSetRequestContentLength); - //REG_FUNC(0x11EC42D0, sceHttpSetAuthEnabled); - //REG_FUNC(0x6727874C, sceHttpGetAuthEnabled); - //REG_FUNC(0x34891C3F, sceHttpSetAutoRedirect); - //REG_FUNC(0x6EAD73EB, sceHttpGetAutoRedirect); - //REG_FUNC(0xE0A3A88D, sceHttpSetAuthInfoCallback); - //REG_FUNC(0x4E08167D, sceHttpSetRedirectCallback); - //REG_FUNC(0x8455B5B3, sceHttpSetResolveTimeOut); - //REG_FUNC(0x9AB56EA7, sceHttpSetResolveRetry); - //REG_FUNC(0x237CA86E, sceHttpSetConnectTimeOut); - //REG_FUNC(0x8AE3F008, sceHttpSetSendTimeOut); - //REG_FUNC(0x94BF196E, sceHttpSetRecvTimeOut); + REG_FUNC(0x214926D9, sceHttpInit); + REG_FUNC(0xC9076666, sceHttpTerm); + REG_FUNC(0xF98CDFA9, sceHttpGetMemoryPoolStats); + REG_FUNC(0x62241DAB, sceHttpCreateTemplate); + REG_FUNC(0xEC85ECFB, sceHttpDeleteTemplate); + REG_FUNC(0xC616C200, sceHttpCreateConnectionWithURL); + REG_FUNC(0xAEB3307E, sceHttpCreateConnection); + REG_FUNC(0xF0F65C15, sceHttpDeleteConnection); + REG_FUNC(0xBD5DA1D0, sceHttpCreateRequestWithURL); + REG_FUNC(0xB0284270, sceHttpCreateRequest); + REG_FUNC(0x3D3D29AD, sceHttpDeleteRequest); + REG_FUNC(0x9CA58B99, sceHttpSendRequest); + REG_FUNC(0x7EDE3979, sceHttpReadData); + REG_FUNC(0xF580D304, sceHttpGetResponseContentLength); + REG_FUNC(0x27071691, sceHttpGetStatusCode); + REG_FUNC(0xEA61662F, sceHttpAbortRequest); + REG_FUNC(0x7B51B122, sceHttpAddRequestHeader); + REG_FUNC(0x5EB5F548, sceHttpRemoveRequestHeader); + REG_FUNC(0x11F6C27F, sceHttpGetAllResponseHeaders); + REG_FUNC(0x03A6C89E, sceHttpParseResponseHeader); + REG_FUNC(0x179C56DB, sceHttpParseStatusLine); + REG_FUNC(0x1DA2A673, sceHttpUriEscape); + REG_FUNC(0x1274D318, sceHttpUriUnescape); + REG_FUNC(0x1D45F24E, sceHttpUriParse); + REG_FUNC(0x47664424, sceHttpUriBuild); + REG_FUNC(0x75027D1D, sceHttpUriMerge); + REG_FUNC(0x50737A3F, sceHttpUriSweepPath); + REG_FUNC(0x37C30C90, sceHttpSetRequestContentLength); + REG_FUNC(0x11EC42D0, sceHttpSetAuthEnabled); + REG_FUNC(0x6727874C, sceHttpGetAuthEnabled); + REG_FUNC(0x34891C3F, sceHttpSetAutoRedirect); + REG_FUNC(0x6EAD73EB, sceHttpGetAutoRedirect); + REG_FUNC(0xE0A3A88D, sceHttpSetAuthInfoCallback); + REG_FUNC(0x4E08167D, sceHttpSetRedirectCallback); + REG_FUNC(0x8455B5B3, sceHttpSetResolveTimeOut); + REG_FUNC(0x9AB56EA7, sceHttpSetResolveRetry); + REG_FUNC(0x237CA86E, sceHttpSetConnectTimeOut); + REG_FUNC(0x8AE3F008, sceHttpSetSendTimeOut); + REG_FUNC(0x94BF196E, sceHttpSetRecvTimeOut); //REG_FUNC(0x27A98BDA, sceHttpSetNonblock); //REG_FUNC(0xD65746BC, sceHttpGetNonblock); //REG_FUNC(0x5CEB6554, sceHttpSetEpollId); @@ -61,22 +410,22 @@ psv_log_base sceHttp("SceHttp", []() //REG_FUNC(0xCFB1DA4B, sceHttpUnsetEpoll); //REG_FUNC(0x65FE983F, sceHttpGetEpoll); //REG_FUNC(0x07D9F8BB, sceHttpDestroyEpoll); - //REG_FUNC(0xAEE573A3, sceHttpSetCookieEnabled); - //REG_FUNC(0x1B6EF66E, sceHttpGetCookieEnabled); - //REG_FUNC(0x70220BFA, sceHttpGetCookie); - //REG_FUNC(0xBEDB988D, sceHttpAddCookie); + REG_FUNC(0xAEE573A3, sceHttpSetCookieEnabled); + REG_FUNC(0x1B6EF66E, sceHttpGetCookieEnabled); + REG_FUNC(0x70220BFA, sceHttpGetCookie); + REG_FUNC(0xBEDB988D, sceHttpAddCookie); //REG_FUNC(0x4259FB9E, sceHttpCookieExport); //REG_FUNC(0x9DF48282, sceHttpCookieImport); - //REG_FUNC(0xD4F32A23, sceHttpSetCookieRecvCallback); - //REG_FUNC(0x11C03867, sceHttpSetCookieSendCallback); - //REG_FUNC(0xAE8D7C33, sceHttpsLoadCert); - //REG_FUNC(0x8577833F, sceHttpsUnloadCert); - //REG_FUNC(0x9FBE2869, sceHttpsEnableOption); - //REG_FUNC(0xC6D60403, sceHttpsDisableOption); + REG_FUNC(0xD4F32A23, sceHttpSetCookieRecvCallback); + REG_FUNC(0x11C03867, sceHttpSetCookieSendCallback); + REG_FUNC(0xAE8D7C33, sceHttpsLoadCert); + REG_FUNC(0x8577833F, sceHttpsUnloadCert); + REG_FUNC(0x9FBE2869, sceHttpsEnableOption); + REG_FUNC(0xC6D60403, sceHttpsDisableOption); //REG_FUNC(0x72CB0741, sceHttpsEnableOptionPrivate); //REG_FUNC(0x00659635, sceHttpsDisableOptionPrivate); - //REG_FUNC(0x2B79BDE0, sceHttpsGetSslError); - //REG_FUNC(0xA0926037, sceHttpsSetSslCallback); - //REG_FUNC(0xF71AA58D, sceHttpsGetCaList); - //REG_FUNC(0x56C95D94, sceHttpsFreeCaList); + REG_FUNC(0x2B79BDE0, sceHttpsGetSslError); + REG_FUNC(0xA0926037, sceHttpsSetSslCallback); + REG_FUNC(0xF71AA58D, sceHttpsGetCaList); + REG_FUNC(0x56C95D94, sceHttpsFreeCaList); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp b/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp index 5ec6f79614..06e8e0ec00 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceJpeg.cpp @@ -4,6 +4,108 @@ extern psv_log_base sceJpeg; +struct SceJpegOutputInfo +{ + s32 colorSpace; + u16 imageWidth; + u16 imageHeight; + u32 outputBufferSize; + u32 tempBufferSize; + u32 coefBufferSize; + + struct { u32 x, y; } pitch[4]; +}; + +struct SceJpegSplitDecodeCtrl +{ + vm::psv::ptr pStreamBuffer; + u32 streamBufferSize; + vm::psv::ptr pWriteBuffer; + u32 writeBufferSize; + s32 isEndOfStream; + s32 decodeMode; + + SceJpegOutputInfo outputInfo; + + vm::psv::ptr pOutputBuffer; + vm::psv::ptr pCoefBuffer; + + u32 internalData[3]; +}; + +s32 sceJpegInitMJpeg(s32 maxSplitDecoder) +{ + throw __FUNCTION__; +} + +s32 sceJpegFinishMJpeg() +{ + throw __FUNCTION__; +} + +s32 sceJpegDecodeMJpeg( + vm::psv::ptr pJpeg, + u32 isize, + vm::psv::ptr pRGBA, + u32 osize, + s32 decodeMode, + vm::psv::ptr pTempBuffer, + u32 tempBufferSize, + vm::psv::ptr pCoefBuffer, + u32 coefBufferSize) +{ + throw __FUNCTION__; +} + +s32 sceJpegDecodeMJpegYCbCr( + vm::psv::ptr pJpeg, + u32 isize, + vm::psv::ptr pYCbCr, + u32 osize, + s32 decodeMode, + vm::psv::ptr pCoefBuffer, + u32 coefBufferSize) +{ + throw __FUNCTION__; +} + +s32 sceJpegMJpegCsc( + vm::psv::ptr pRGBA, + vm::psv::ptr pYCbCr, + s32 xysize, + s32 iFrameWidth, + s32 colorOption, + s32 sampling) +{ + throw __FUNCTION__; +} + +s32 sceJpegGetOutputInfo( + vm::psv::ptr pJpeg, + u32 isize, + s32 outputFormat, + s32 decodeMode, + vm::psv::ptr pOutputInfo) +{ + throw __FUNCTION__; +} + +s32 sceJpegCreateSplitDecoder(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceJpegDeleteSplitDecoder(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceJpegSplitDecodeMJpeg(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceJpeg, #name, name) psv_log_base sceJpeg("SceJpeg", []() @@ -12,13 +114,13 @@ psv_log_base sceJpeg("SceJpeg", []() sceJpeg.on_unload = nullptr; sceJpeg.on_stop = nullptr; - //REG_FUNC(0xB030773B, sceJpegInitMJpeg); - //REG_FUNC(0x62842598, sceJpegFinishMJpeg); - //REG_FUNC(0x6215B095, sceJpegDecodeMJpeg); - //REG_FUNC(0x2A769BD8, sceJpegDecodeMJpegYCbCr); - //REG_FUNC(0xC2380E3A, sceJpegMJpegCsc); - //REG_FUNC(0x353BA9B0, sceJpegGetOutputInfo); - //REG_FUNC(0x123B4734, sceJpegCreateSplitDecoder); - //REG_FUNC(0xDE8D5FA1, sceJpegDeleteSplitDecoder); - //REG_FUNC(0x4598EC9C, sceJpegSplitDecodeMJpeg); + REG_FUNC(0xB030773B, sceJpegInitMJpeg); + REG_FUNC(0x62842598, sceJpegFinishMJpeg); + REG_FUNC(0x6215B095, sceJpegDecodeMJpeg); + REG_FUNC(0x2A769BD8, sceJpegDecodeMJpegYCbCr); + REG_FUNC(0xC2380E3A, sceJpegMJpegCsc); + REG_FUNC(0x353BA9B0, sceJpegGetOutputInfo); + REG_FUNC(0x123B4734, sceJpegCreateSplitDecoder); + REG_FUNC(0xDE8D5FA1, sceJpegDeleteSplitDecoder); + REG_FUNC(0x4598EC9C, sceJpegSplitDecodeMJpeg); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp b/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp index 1567f5487d..690afd9e04 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceJpegEnc.cpp @@ -4,6 +4,77 @@ extern psv_log_base sceJpegEnc; +typedef vm::psv::ptr SceJpegEncoderContext; + +s32 sceJpegEncoderGetContextSize() +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderInit( + SceJpegEncoderContext context, + s32 iFrameWidth, + s32 iFrameHeight, + s32 pixelFormat, + vm::psv::ptr pJpeg, + u32 oJpegbufSize) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderEncode( + SceJpegEncoderContext context, + vm::psv::ptr pYCbCr) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderEnd(SceJpegEncoderContext context) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderSetValidRegion( + SceJpegEncoderContext context, + s32 iFrameWidth, + s32 iFrameHeight) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderSetCompressionRatio( + SceJpegEncoderContext context, + s32 compratio) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderSetHeaderMode( + SceJpegEncoderContext context, + s32 headerMode) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderSetOutputAddr( + SceJpegEncoderContext context, + vm::psv::ptr pJpeg, + u32 oJpegbufSize) +{ + throw __FUNCTION__; +} + +s32 sceJpegEncoderCsc( + SceJpegEncoderContext context, + vm::psv::ptr pYCbCr, + vm::psv::ptr pRGBA, + s32 iFrameWidth, + s32 inputPixelFormat) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceJpegEnc, #name, name) psv_log_base sceJpegEnc("SceJpegEnc", []() @@ -12,13 +83,13 @@ psv_log_base sceJpegEnc("SceJpegEnc", []() sceJpegEnc.on_unload = nullptr; sceJpegEnc.on_stop = nullptr; - //REG_FUNC(0x2B55844D, sceJpegEncoderGetContextSize); - //REG_FUNC(0x88DA92B4, sceJpegEncoderInit); - //REG_FUNC(0xC60DE94C, sceJpegEncoderEncode); - //REG_FUNC(0xC87AA849, sceJpegEncoderEnd); - //REG_FUNC(0x9511F3BC, sceJpegEncoderSetValidRegion); - //REG_FUNC(0xB2B828EC, sceJpegEncoderSetCompressionRatio); - //REG_FUNC(0x2F58B12C, sceJpegEncoderSetHeaderMode); - //REG_FUNC(0x25D52D97, sceJpegEncoderSetOutputAddr); - //REG_FUNC(0x824A7D4F, sceJpegEncoderCsc); + REG_FUNC(0x2B55844D, sceJpegEncoderGetContextSize); + REG_FUNC(0x88DA92B4, sceJpegEncoderInit); + REG_FUNC(0xC60DE94C, sceJpegEncoderEncode); + REG_FUNC(0xC87AA849, sceJpegEncoderEnd); + REG_FUNC(0x9511F3BC, sceJpegEncoderSetValidRegion); + REG_FUNC(0xB2B828EC, sceJpegEncoderSetCompressionRatio); + REG_FUNC(0x2F58B12C, sceJpegEncoderSetHeaderMode); + REG_FUNC(0x25D52D97, sceJpegEncoderSetOutputAddr); + REG_FUNC(0x824A7D4F, sceJpegEncoderCsc); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp b/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp index 4511ca2ae7..62eea18429 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLiveArea.cpp @@ -4,6 +4,16 @@ extern psv_log_base sceLiveArea; +s32 sceLiveAreaResourceReplaceAll(vm::psv::ptr dirpath) +{ + throw __FUNCTION__; +} + +s32 sceLiveAreaResourceGetStatus() +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceLiveArea, #name, name) psv_log_base sceLiveArea("SceLiveArea", []() @@ -12,6 +22,6 @@ psv_log_base sceLiveArea("SceLiveArea", []() sceLiveArea.on_unload = nullptr; sceLiveArea.on_stop = nullptr; - //REG_FUNC(0xA4B506F9, sceLiveAreaResourceReplaceAll); - //REG_FUNC(0x54A395FB, sceLiveAreaResourceGetStatus); + REG_FUNC(0xA4B506F9, sceLiveAreaResourceReplaceAll); + REG_FUNC(0x54A395FB, sceLiveAreaResourceGetStatus); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp b/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp index 734f7f62e1..8b61bca224 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLocation.cpp @@ -4,6 +4,174 @@ extern psv_log_base sceLocation; +typedef u8 SceLocationHandle; + +enum SceLocationLocationMethod : s32 +{ + SCE_LOCATION_LMETHOD_NONE = 0, + SCE_LOCATION_LMETHOD_AGPS_AND_3G_AND_WIFI = 1, + SCE_LOCATION_LMETHOD_GPS_AND_WIFI = 2, + SCE_LOCATION_LMETHOD_WIFI = 3, + SCE_LOCATION_LMETHOD_3G = 4, + SCE_LOCATION_LMETHOD_GPS = 5 +}; + +enum SceLocationHeadingMethod : s32 +{ + SCE_LOCATION_HMETHOD_NONE = 0, + SCE_LOCATION_HMETHOD_AUTO = 1, + SCE_LOCATION_HMETHOD_VERTICAL = 2, + SCE_LOCATION_HMETHOD_HORIZONTAL = 3, + SCE_LOCATION_HMETHOD_CAMERA = 4 +}; + +enum SceLocationDialogStatus : s32 +{ + SCE_LOCATION_DIALOG_STATUS_IDLE = 0, + SCE_LOCATION_DIALOG_STATUS_RUNNING = 1, + SCE_LOCATION_DIALOG_STATUS_FINISHED = 2 +}; + +enum SceLocationDialogResult : s32 +{ + SCE_LOCATION_DIALOG_RESULT_NONE = 0, + SCE_LOCATION_DIALOG_RESULT_DISABLE = 1, + SCE_LOCATION_DIALOG_RESULT_ENABLE = 2 +}; + +enum SceLocationPermissionApplicationStatus : s32 +{ + SCE_LOCATION_PERMISSION_APPLICATION_NONE = 0, + SCE_LOCATION_PERMISSION_APPLICATION_INIT = 1, + SCE_LOCATION_PERMISSION_APPLICATION_DENY = 2, + SCE_LOCATION_PERMISSION_APPLICATION_ALLOW = 3 +}; + +enum SceLocationPermissionStatus : s32 +{ + SCE_LOCATION_PERMISSION_DENY = 0, + SCE_LOCATION_PERMISSION_ALLOW = 1 +}; + +struct SceLocationLocationInfo +{ + double latitude; + double longitude; + double altitude; + float accuracy; + float reserve; + float direction; + float speed; + u64 timestamp; +}; + +struct SceLocationHeadingInfo +{ + float trueHeading; + float headingVectorX; + float headingVectorY; + float headingVectorZ; + float reserve; + float reserve2; + u64 timestamp; +}; + +typedef vm::psv::ptr location, vm::psv::ptr userdata)> SceLocationLocationInfoCallback; +typedef vm::psv::ptr heading, vm::psv::ptr userdata)> SceLocationHeadingInfoCallback; + +struct SceLocationPermissionInfo +{ + SceLocationPermissionStatus parentalstatus; + SceLocationPermissionStatus mainstatus; + SceLocationPermissionApplicationStatus applicationstatus; +}; + +s32 sceLocationOpen(vm::psv::ptr handle, SceLocationLocationMethod lmethod, SceLocationHeadingMethod hmethod) +{ + throw __FUNCTION__; +} + +s32 sceLocationClose(SceLocationHandle handle) +{ + throw __FUNCTION__; +} + +s32 sceLocationReopen(SceLocationHandle handle, SceLocationLocationMethod lmethod, SceLocationHeadingMethod hmethod) +{ + throw __FUNCTION__; +} + +s32 sceLocationGetMethod(SceLocationHandle handle, vm::psv::ptr lmethod, vm::psv::ptr hmethod) +{ + throw __FUNCTION__; +} + +s32 sceLocationGetLocation(SceLocationHandle handle, vm::psv::ptr linfo) +{ + throw __FUNCTION__; +} + +s32 sceLocationCancelGetLocation(SceLocationHandle handle) +{ + throw __FUNCTION__; +} + +s32 sceLocationStartLocationCallback(SceLocationHandle handle, u32 distance, SceLocationLocationInfoCallback callback, vm::psv::ptr userdata) +{ + throw __FUNCTION__; +} + +s32 sceLocationStopLocationCallback(SceLocationHandle handle) +{ + throw __FUNCTION__; +} + +s32 sceLocationGetHeading(SceLocationHandle handle, vm::psv::ptr hinfo) +{ + throw __FUNCTION__; +} + +s32 sceLocationStartHeadingCallback(SceLocationHandle handle, u32 difference, SceLocationHeadingInfoCallback callback, vm::psv::ptr userdata) +{ + throw __FUNCTION__; +} + +s32 sceLocationStopHeadingCallback(SceLocationHandle handle) +{ + throw __FUNCTION__; +} + +s32 sceLocationConfirm(SceLocationHandle handle) +{ + throw __FUNCTION__; +} + +s32 sceLocationConfirmGetStatus(SceLocationHandle handle, vm::psv::ptr status) +{ + throw __FUNCTION__; +} + +s32 sceLocationConfirmGetResult(SceLocationHandle handle, vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceLocationConfirmAbort(SceLocationHandle handle) +{ + throw __FUNCTION__; +} + +s32 sceLocationGetPermission(SceLocationHandle handle, vm::psv::ptr info) +{ + throw __FUNCTION__; +} + +s32 sceLocationSetGpsEmulationFile(vm::psv::ptr filename) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceLocation, #name, name) psv_log_base sceLocation("SceLibLocation", []() @@ -12,23 +180,23 @@ psv_log_base sceLocation("SceLibLocation", []() sceLocation.on_unload = nullptr; sceLocation.on_stop = nullptr; - //REG_FUNC(0xDD271661, sceLocationOpen); - //REG_FUNC(0x14FE76E8, sceLocationClose); - //REG_FUNC(0xB1F55065, sceLocationReopen); - //REG_FUNC(0x188CE004, sceLocationGetMethod); - //REG_FUNC(0x15BC27C8, sceLocationGetLocation); - //REG_FUNC(0x71503251, sceLocationCancelGetLocation); - //REG_FUNC(0x12D1F0EA, sceLocationStartLocationCallback); - //REG_FUNC(0xED378700, sceLocationStopLocationCallback); - //REG_FUNC(0x4E9E5ED9, sceLocationGetHeading); - //REG_FUNC(0x07D4DFE0, sceLocationStartHeadingCallback); - //REG_FUNC(0x92E53F94, sceLocationStopHeadingCallback); + REG_FUNC(0xDD271661, sceLocationOpen); + REG_FUNC(0x14FE76E8, sceLocationClose); + REG_FUNC(0xB1F55065, sceLocationReopen); + REG_FUNC(0x188CE004, sceLocationGetMethod); + REG_FUNC(0x15BC27C8, sceLocationGetLocation); + REG_FUNC(0x71503251, sceLocationCancelGetLocation); + REG_FUNC(0x12D1F0EA, sceLocationStartLocationCallback); + REG_FUNC(0xED378700, sceLocationStopLocationCallback); + REG_FUNC(0x4E9E5ED9, sceLocationGetHeading); + REG_FUNC(0x07D4DFE0, sceLocationStartHeadingCallback); + REG_FUNC(0x92E53F94, sceLocationStopHeadingCallback); //REG_FUNC(0xE055BCF5, sceLocationSetHeapAllocator); - //REG_FUNC(0xC895E567, sceLocationConfirm); - //REG_FUNC(0x730FF842, sceLocationConfirmGetStatus); - //REG_FUNC(0xFF016C13, sceLocationConfirmGetResult); - //REG_FUNC(0xE3CBF875, sceLocationConfirmAbort); - //REG_FUNC(0x482622C6, sceLocationGetPermission); - //REG_FUNC(0xDE0A9EA4, sceLocationSetGpsEmulationFile); + REG_FUNC(0xC895E567, sceLocationConfirm); + REG_FUNC(0x730FF842, sceLocationConfirmGetStatus); + REG_FUNC(0xFF016C13, sceLocationConfirmGetResult); + REG_FUNC(0xE3CBF875, sceLocationConfirmAbort); + REG_FUNC(0x482622C6, sceLocationGetPermission); + REG_FUNC(0xDE0A9EA4, sceLocationSetGpsEmulationFile); //REG_FUNC(0x760D08FF, sceLocationConfirmSetMessage); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp b/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp index aed0422ed4..d31e193e81 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceMd5.cpp @@ -4,6 +4,37 @@ extern psv_log_base sceMd5; +struct SceMd5Context +{ + u32 h[4]; + u32 pad; + u16 usRemains; + u16 usComputed; + u64 ullTotalLen; + u8 buf[64]; + u8 result[64]; +}; + +s32 sceMd5Digest(vm::psv::ptr plain, u32 len, vm::psv::ptr digest) +{ + throw __FUNCTION__; +} + +s32 sceMd5BlockInit(vm::psv::ptr pContext) +{ + throw __FUNCTION__; +} + +s32 sceMd5BlockUpdate(vm::psv::ptr pContext, vm::psv::ptr plain, u32 len) +{ + throw __FUNCTION__; +} + +s32 sceMd5BlockResult(vm::psv::ptr pContext, vm::psv::ptr digest) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceMd5, #name, name) psv_log_base sceMd5("SceMd5", []() @@ -12,8 +43,8 @@ psv_log_base sceMd5("SceMd5", []() sceMd5.on_unload = nullptr; sceMd5.on_stop = nullptr; - //REG_FUNC(0xB845BCCB, sceMd5Digest); - //REG_FUNC(0x4D6436F9, sceMd5BlockInit); - //REG_FUNC(0x094A4902, sceMd5BlockUpdate); - //REG_FUNC(0xB94ABF83, sceMd5BlockResult); + REG_FUNC(0xB845BCCB, sceMd5Digest); + REG_FUNC(0x4D6436F9, sceMd5BlockInit); + REG_FUNC(0x094A4902, sceMd5BlockUpdate); + REG_FUNC(0xB94ABF83, sceMd5BlockResult); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp b/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp index bc86726bb2..4128c78a65 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceMotion.cpp @@ -4,6 +4,113 @@ extern psv_log_base sceMotion; +struct SceMotionState +{ + u32 timestamp; + SceFVector3 acceleration; + SceFVector3 angularVelocity; + u8 reserve1[12]; + SceFQuaternion deviceQuat; + SceUMatrix4 rotationMatrix; + SceUMatrix4 nedMatrix; + u8 reserve2[4]; + SceFVector3 basicOrientation; + u64 hostTimestamp; + u8 reserve3[40]; +}; + +struct SceMotionSensorState +{ + SceFVector3 accelerometer; + SceFVector3 gyro; + u8 reserve1[12]; + u32 timestamp; + u32 counter; + u8 reserve2[4]; + u64 hostTimestamp; + u8 reserve3[8]; +}; + +s32 sceMotionGetState(vm::psv::ptr motionState) +{ + throw __FUNCTION__; +} + +s32 sceMotionGetSensorState(vm::psv::ptr sensorState, s32 numRecords) +{ + throw __FUNCTION__; +} + +s32 sceMotionGetBasicOrientation(vm::psv::ptr basicOrientation) +{ + throw __FUNCTION__; +} + +//s32 sceMotionRotateYaw(const float radians) +//{ +// throw __FUNCTION__; +//} + +s32 sceMotionGetTiltCorrection() +{ + throw __FUNCTION__; +} + +s32 sceMotionSetTiltCorrection(s32 setValue) +{ + throw __FUNCTION__; +} + +s32 sceMotionGetDeadband() +{ + throw __FUNCTION__; +} + +s32 sceMotionSetDeadband(s32 setValue) +{ + throw __FUNCTION__; +} + +//s32 sceMotionSetAngleThreshold(const float angle) +//{ +// throw __FUNCTION__; +//} + +//float sceMotionGetAngleThreshold() +//{ +// throw __FUNCTION__; +//} + +s32 sceMotionReset() +{ + throw __FUNCTION__; +} + +s32 sceMotionMagnetometerOn() +{ + throw __FUNCTION__; +} + +s32 sceMotionMagnetometerOff() +{ + throw __FUNCTION__; +} + +s32 sceMotionGetMagnetometerState() +{ + throw __FUNCTION__; +} + +s32 sceMotionStartSampling() +{ + throw __FUNCTION__; +} + +s32 sceMotionStopSampling() +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceMotion, #name, name) psv_log_base sceMotion("SceMotion", []() @@ -12,20 +119,20 @@ psv_log_base sceMotion("SceMotion", []() sceMotion.on_unload = nullptr; sceMotion.on_stop = nullptr; - //REG_FUNC(0xBDB32767, sceMotionGetState); - //REG_FUNC(0x47D679EA, sceMotionGetSensorState); - //REG_FUNC(0xC1652201, sceMotionGetTiltCorrection); - //REG_FUNC(0xAF09FCDB, sceMotionSetTiltCorrection); - //REG_FUNC(0x112E0EAE, sceMotionGetDeadband); - //REG_FUNC(0x917EA390, sceMotionSetDeadband); + REG_FUNC(0xBDB32767, sceMotionGetState); + REG_FUNC(0x47D679EA, sceMotionGetSensorState); + REG_FUNC(0xC1652201, sceMotionGetTiltCorrection); + REG_FUNC(0xAF09FCDB, sceMotionSetTiltCorrection); + REG_FUNC(0x112E0EAE, sceMotionGetDeadband); + REG_FUNC(0x917EA390, sceMotionSetDeadband); //REG_FUNC(0x20F00078, sceMotionRotateYaw); - //REG_FUNC(0x0FD2CDA2, sceMotionReset); - //REG_FUNC(0x28034AC9, sceMotionStartSampling); - //REG_FUNC(0xAF32CB1D, sceMotionStopSampling); + REG_FUNC(0x0FD2CDA2, sceMotionReset); + REG_FUNC(0x28034AC9, sceMotionStartSampling); + REG_FUNC(0xAF32CB1D, sceMotionStopSampling); //REG_FUNC(0xDACB2A41, sceMotionSetAngleThreshold); //REG_FUNC(0x499B6C87, sceMotionGetAngleThreshold); - //REG_FUNC(0x4F28BFE0, sceMotionGetBasicOrientation); - //REG_FUNC(0x122A79F8, sceMotionMagnetometerOn); - //REG_FUNC(0xC1A7395A, sceMotionMagnetometerOff); - //REG_FUNC(0x3D4813AE, sceMotionGetMagnetometerState); + REG_FUNC(0x4F28BFE0, sceMotionGetBasicOrientation); + REG_FUNC(0x122A79F8, sceMotionMagnetometerOn); + REG_FUNC(0xC1A7395A, sceMotionMagnetometerOff); + REG_FUNC(0x3D4813AE, sceMotionGetMagnetometerState); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp b/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp index 3893d344bf..6a125206ec 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceMt19937.cpp @@ -4,6 +4,23 @@ extern psv_log_base sceMt19937; +struct SceMt19937Context +{ + u32 count; + u32 state[624]; +}; + +s32 sceMt19937Init(vm::psv::ptr pCtx, u32 seed) +{ + throw __FUNCTION__; +} + +u32 sceMt19937UInt(vm::psv::ptr pCtx) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceMt19937, #name, name) psv_log_base sceMt19937("SceMt19937", []() @@ -12,6 +29,6 @@ psv_log_base sceMt19937("SceMt19937", []() sceMt19937.on_unload = nullptr; sceMt19937.on_stop = nullptr; - //REG_FUNC(0xEE5BA27C, sceMt19937Init); - //REG_FUNC(0x29E43BB5, sceMt19937UInt); + REG_FUNC(0xEE5BA27C, sceMt19937Init); + REG_FUNC(0x29E43BB5, sceMt19937UInt); }); diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index 0326208f9f..a1948dcbec 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -647,3 +647,19 @@ struct SceDateTime u16 second; u32 microsecond; }; + +struct SceFVector3 +{ + float x, y, z; +}; + +struct SceFQuaternion +{ + float x, y, z, w; +}; + +union SceUMatrix4 +{ + float f[4][4]; + s32 i[4][4]; +}; From cd6f95c90d6e09d9ddbd7740f2234d5e3ce92a34 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 13:48:12 +0300 Subject: [PATCH 38/94] Some functions added --- rpcs3/Emu/ARMv7/Modules/sceHttp.cpp | 4 +- rpcs3/Emu/ARMv7/Modules/sceNet.cpp | 409 +++++++++++++++++--- rpcs3/Emu/ARMv7/Modules/sceNet.h | 187 +++++++++ rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp | 156 +++++++- rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp | 40 +- rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp | 21 +- rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp | 37 +- rpcs3/Emu/ARMv7/Modules/sceSsl.cpp | 80 +++- rpcs3/Emu/ARMv7/Modules/sceSsl.h | 14 + rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp | 104 ++++- rpcs3/Emu/ARMv7/Modules/sceTouch.cpp | 69 +++- rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp | 190 ++++++++- rpcs3/Emu/ARMv7/Modules/sceVoice.cpp | 294 ++++++++++++-- rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp | 142 ++++++- rpcs3/emucore.vcxproj | 2 + rpcs3/emucore.vcxproj.filters | 6 + 16 files changed, 1589 insertions(+), 166 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNet.h create mode 100644 rpcs3/Emu/ARMv7/Modules/sceSsl.h diff --git a/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp b/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp index 814159303e..c98509fac4 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceHttp.cpp @@ -2,6 +2,8 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceSsl.h" + extern psv_log_base sceHttp; enum SceHttpHttpVersion : s32 @@ -61,8 +63,6 @@ typedef vm::psv::ptr url, vm::psv::ptr typedef vm::psv::ptr url, vm::psv::ptr cookieHeader, vm::psv::ptr userArg)> SceHttpCookieSendCallback; -struct SceSslCert; - struct SceHttpsData { vm::psv::ptr ptr; diff --git a/rpcs3/Emu/ARMv7/Modules/sceNet.cpp b/rpcs3/Emu/ARMv7/Modules/sceNet.cpp index f68a283618..347ba76df5 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNet.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNet.cpp @@ -2,7 +2,298 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" -extern psv_log_base sceNet; +#include "sceNet.h" + +s32 sceNetSetDnsInfo(vm::psv::ptr info, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetClearDnsCache(s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetDumpCreate(vm::psv::ptr name, s32 len, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetDumpRead(s32 id, vm::psv::ptr buf, s32 len, vm::psv::ptr pflags) +{ + throw __FUNCTION__; +} + +s32 sceNetDumpDestroy(s32 id) +{ + throw __FUNCTION__; +} + +s32 sceNetDumpAbort(s32 id, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetEpollCreate(vm::psv::ptr name, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetEpollControl(s32 eid, s32 op, s32 id, vm::psv::ptr event) +{ + throw __FUNCTION__; +} + +s32 sceNetEpollWait(s32 eid, vm::psv::ptr events, s32 maxevents, s32 timeout) +{ + throw __FUNCTION__; +} + +s32 sceNetEpollWaitCB(s32 eid, vm::psv::ptr events, s32 maxevents, s32 timeout) +{ + throw __FUNCTION__; +} + +s32 sceNetEpollDestroy(s32 eid) +{ + throw __FUNCTION__; +} + +s32 sceNetEpollAbort(s32 eid, s32 flags) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNetErrnoLoc() +{ + throw __FUNCTION__; +} + +s32 sceNetEtherStrton(vm::psv::ptr str, vm::psv::ptr n) +{ + throw __FUNCTION__; +} + +s32 sceNetEtherNtostr(vm::psv::ptr n, vm::psv::ptr str, u32 len) +{ + throw __FUNCTION__; +} + +s32 sceNetGetMacAddress(vm::psv::ptr addr, s32 flags) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNetInetNtop(s32 af, vm::psv::ptr src, vm::psv::ptr dst, SceNetSocklen_t size) +{ + throw __FUNCTION__; +} + +s32 sceNetInetPton(s32 af, vm::psv::ptr src, vm::psv::ptr dst) +{ + throw __FUNCTION__; +} + +u64 sceNetHtonll(u64 host64) +{ + throw __FUNCTION__; +} + +u32 sceNetHtonl(u32 host32) +{ + throw __FUNCTION__; +} + +u16 sceNetHtons(u16 host16) +{ + throw __FUNCTION__; +} + +u64 sceNetNtohll(u64 net64) +{ + throw __FUNCTION__; +} + +u32 sceNetNtohl(u32 net32) +{ + throw __FUNCTION__; +} + +u16 sceNetNtohs(u16 net16) +{ + throw __FUNCTION__; +} + +s32 sceNetInit(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceNetTerm() +{ + throw __FUNCTION__; +} + +s32 sceNetShowIfconfig() +{ + throw __FUNCTION__; +} + +s32 sceNetShowRoute() +{ + throw __FUNCTION__; +} + +s32 sceNetShowNetstat() +{ + throw __FUNCTION__; +} + +s32 sceNetEmulationSet(vm::psv::ptr param, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetEmulationGet(vm::psv::ptr param, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetResolverCreate(vm::psv::ptr name, vm::psv::ptr param, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetResolverStartNtoa(s32 rid, vm::psv::ptr hostname, vm::psv::ptr addr, s32 timeout, s32 retry, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetResolverStartAton(s32 rid, vm::psv::ptr addr, vm::psv::ptr hostname, s32 len, s32 timeout, s32 retry, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetResolverGetError(s32 rid, vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNetResolverDestroy(s32 rid) +{ + throw __FUNCTION__; +} + +s32 sceNetResolverAbort(s32 rid, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetSocket(vm::psv::ptr name, s32 domain, s32 type, s32 protocol) +{ + throw __FUNCTION__; +} + +s32 sceNetAccept(s32 s, vm::psv::ptr addr, vm::psv::ptr addrlen) +{ + throw __FUNCTION__; +} + +s32 sceNetBind(s32 s, vm::psv::ptr addr, SceNetSocklen_t addrlen) +{ + throw __FUNCTION__; +} + +s32 sceNetConnect(s32 s, vm::psv::ptr name, SceNetSocklen_t namelen) +{ + throw __FUNCTION__; +} + +s32 sceNetGetpeername(s32 s, vm::psv::ptr name, vm::psv::ptr namelen) +{ + throw __FUNCTION__; +} + +s32 sceNetGetsockname(s32 s, vm::psv::ptr name, vm::psv::ptr namelen) +{ + throw __FUNCTION__; +} + +s32 sceNetGetsockopt(s32 s, s32 level, s32 optname, vm::psv::ptr optval, vm::psv::ptr optlen) +{ + throw __FUNCTION__; +} + +s32 sceNetListen(s32 s, s32 backlog) +{ + throw __FUNCTION__; +} + +s32 sceNetRecv(s32 s, vm::psv::ptr buf, u32 len, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetRecvfrom(s32 s, vm::psv::ptr buf, u32 len, s32 flags, vm::psv::ptr from, vm::psv::ptr fromlen) +{ + throw __FUNCTION__; +} + +s32 sceNetRecvmsg(s32 s, vm::psv::ptr msg, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetSend(s32 s, vm::psv::ptr msg, u32 len, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetSendto(s32 s, vm::psv::ptr msg, u32 len, s32 flags, vm::psv::ptr to, SceNetSocklen_t tolen) +{ + throw __FUNCTION__; +} + +s32 sceNetSendmsg(s32 s, vm::psv::ptr msg, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetSetsockopt(s32 s, s32 level, s32 optname, vm::psv::ptr optval, SceNetSocklen_t optlen) +{ + throw __FUNCTION__; +} + +s32 sceNetShutdown(s32 s, s32 how) +{ + throw __FUNCTION__; +} + +s32 sceNetSocketClose(s32 s) +{ + throw __FUNCTION__; +} + +s32 sceNetSocketAbort(s32 s, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetGetSockInfo(s32 s, vm::psv::ptr info, s32 n, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetGetSockIdInfo(vm::psv::ptr fds, s32 sockinfoflags, s32 flags) +{ + throw __FUNCTION__; +} + +s32 sceNetGetStatisticsInfo(vm::psv::ptr info, s32 flags) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNet, #name, name) @@ -12,62 +303,62 @@ psv_log_base sceNet("SceNet", []() sceNet.on_unload = nullptr; sceNet.on_stop = nullptr; - //REG_FUNC(0xD62EF218, sceNetSetDnsInfo); - //REG_FUNC(0xFEC1166D, sceNetClearDnsCache); - //REG_FUNC(0xAFF9FA4D, sceNetDumpCreate); - //REG_FUNC(0x04042925, sceNetDumpRead); - //REG_FUNC(0x82DDCF63, sceNetDumpDestroy); - //REG_FUNC(0x3B24E75F, sceNetDumpAbort); - //REG_FUNC(0xF9D102AE, sceNetEpollCreate); - //REG_FUNC(0x4C8764AC, sceNetEpollControl); - //REG_FUNC(0x45CE337D, sceNetEpollWait); - //REG_FUNC(0x92D3E767, sceNetEpollWaitCB); - //REG_FUNC(0x7915CAF3, sceNetEpollDestroy); - //REG_FUNC(0x93FCC4E8, sceNetEpollAbort); - //REG_FUNC(0xE37F34AA, sceNetErrnoLoc); - //REG_FUNC(0xEEC6D75F, sceNetEtherStrton); - //REG_FUNC(0x84334EB2, sceNetEtherNtostr); - //REG_FUNC(0x06C05518, sceNetGetMacAddress); - //REG_FUNC(0x98839B74, sceNetInetNtop); - //REG_FUNC(0xD5EEB048, sceNetInetPton); - //REG_FUNC(0x12C19209, sceNetHtonll); - //REG_FUNC(0x4C30B03C, sceNetHtonl); - //REG_FUNC(0x9FA3207B, sceNetHtons); - //REG_FUNC(0xFB3336A6, sceNetNtohll); - //REG_FUNC(0xD2EAA645, sceNetNtohl); - //REG_FUNC(0x07845128, sceNetNtohs); - //REG_FUNC(0xEB03E265, sceNetInit); - //REG_FUNC(0xEA3CC286, sceNetTerm); - //REG_FUNC(0x658B903B, sceNetShowIfconfig); - //REG_FUNC(0x6AB3B74B, sceNetShowRoute); - //REG_FUNC(0x338EDC2E, sceNetShowNetstat); - //REG_FUNC(0x561DFD03, sceNetEmulationSet); - //REG_FUNC(0xAE3F4AC6, sceNetEmulationGet); - //REG_FUNC(0x6DA29319, sceNetResolverCreate); - //REG_FUNC(0x1EB11857, sceNetResolverStartNtoa); - //REG_FUNC(0x0424AE26, sceNetResolverStartAton); - //REG_FUNC(0x874EF500, sceNetResolverGetError); - //REG_FUNC(0x3559F098, sceNetResolverDestroy); - //REG_FUNC(0x38EBBD57, sceNetResolverAbort); - //REG_FUNC(0xF084FCE3, sceNetSocket); - //REG_FUNC(0x1ADF9BB1, sceNetAccept); - //REG_FUNC(0x1296A94B, sceNetBind); - //REG_FUNC(0x11E5B6F6, sceNetConnect); - //REG_FUNC(0x2348D353, sceNetGetpeername); - //REG_FUNC(0x1C66A6DB, sceNetGetsockname); - //REG_FUNC(0xBA652062, sceNetGetsockopt); - //REG_FUNC(0x7A8DA094, sceNetListen); - //REG_FUNC(0x023643B7, sceNetRecv); - //REG_FUNC(0xB226138B, sceNetRecvfrom); - //REG_FUNC(0xDE94C6FE, sceNetRecvmsg); - //REG_FUNC(0xE3DD8CD9, sceNetSend); - //REG_FUNC(0x52DB31D5, sceNetSendto); - //REG_FUNC(0x99C579AE, sceNetSendmsg); - //REG_FUNC(0x065505CA, sceNetSetsockopt); - //REG_FUNC(0x69E50BB5, sceNetShutdown); - //REG_FUNC(0x29822B4D, sceNetSocketClose); - //REG_FUNC(0x891C1B9B, sceNetSocketAbort); - //REG_FUNC(0xB1AF6840, sceNetGetSockInfo); - //REG_FUNC(0x138CF1D6, sceNetGetSockIdInfo); - //REG_FUNC(0xA86F8FE5, sceNetGetStatisticsInfo); + REG_FUNC(0xD62EF218, sceNetSetDnsInfo); + REG_FUNC(0xFEC1166D, sceNetClearDnsCache); + REG_FUNC(0xAFF9FA4D, sceNetDumpCreate); + REG_FUNC(0x04042925, sceNetDumpRead); + REG_FUNC(0x82DDCF63, sceNetDumpDestroy); + REG_FUNC(0x3B24E75F, sceNetDumpAbort); + REG_FUNC(0xF9D102AE, sceNetEpollCreate); + REG_FUNC(0x4C8764AC, sceNetEpollControl); + REG_FUNC(0x45CE337D, sceNetEpollWait); + REG_FUNC(0x92D3E767, sceNetEpollWaitCB); + REG_FUNC(0x7915CAF3, sceNetEpollDestroy); + REG_FUNC(0x93FCC4E8, sceNetEpollAbort); + REG_FUNC(0xE37F34AA, sceNetErrnoLoc); + REG_FUNC(0xEEC6D75F, sceNetEtherStrton); + REG_FUNC(0x84334EB2, sceNetEtherNtostr); + REG_FUNC(0x06C05518, sceNetGetMacAddress); + REG_FUNC(0x98839B74, sceNetInetNtop); + REG_FUNC(0xD5EEB048, sceNetInetPton); + REG_FUNC(0x12C19209, sceNetHtonll); + REG_FUNC(0x4C30B03C, sceNetHtonl); + REG_FUNC(0x9FA3207B, sceNetHtons); + REG_FUNC(0xFB3336A6, sceNetNtohll); + REG_FUNC(0xD2EAA645, sceNetNtohl); + REG_FUNC(0x07845128, sceNetNtohs); + REG_FUNC(0xEB03E265, sceNetInit); + REG_FUNC(0xEA3CC286, sceNetTerm); + REG_FUNC(0x658B903B, sceNetShowIfconfig); + REG_FUNC(0x6AB3B74B, sceNetShowRoute); + REG_FUNC(0x338EDC2E, sceNetShowNetstat); + REG_FUNC(0x561DFD03, sceNetEmulationSet); + REG_FUNC(0xAE3F4AC6, sceNetEmulationGet); + REG_FUNC(0x6DA29319, sceNetResolverCreate); + REG_FUNC(0x1EB11857, sceNetResolverStartNtoa); + REG_FUNC(0x0424AE26, sceNetResolverStartAton); + REG_FUNC(0x874EF500, sceNetResolverGetError); + REG_FUNC(0x3559F098, sceNetResolverDestroy); + REG_FUNC(0x38EBBD57, sceNetResolverAbort); + REG_FUNC(0xF084FCE3, sceNetSocket); + REG_FUNC(0x1ADF9BB1, sceNetAccept); + REG_FUNC(0x1296A94B, sceNetBind); + REG_FUNC(0x11E5B6F6, sceNetConnect); + REG_FUNC(0x2348D353, sceNetGetpeername); + REG_FUNC(0x1C66A6DB, sceNetGetsockname); + REG_FUNC(0xBA652062, sceNetGetsockopt); + REG_FUNC(0x7A8DA094, sceNetListen); + REG_FUNC(0x023643B7, sceNetRecv); + REG_FUNC(0xB226138B, sceNetRecvfrom); + REG_FUNC(0xDE94C6FE, sceNetRecvmsg); + REG_FUNC(0xE3DD8CD9, sceNetSend); + REG_FUNC(0x52DB31D5, sceNetSendto); + REG_FUNC(0x99C579AE, sceNetSendmsg); + REG_FUNC(0x065505CA, sceNetSetsockopt); + REG_FUNC(0x69E50BB5, sceNetShutdown); + REG_FUNC(0x29822B4D, sceNetSocketClose); + REG_FUNC(0x891C1B9B, sceNetSocketAbort); + REG_FUNC(0xB1AF6840, sceNetGetSockInfo); + REG_FUNC(0x138CF1D6, sceNetGetSockIdInfo); + REG_FUNC(0xA86F8FE5, sceNetGetStatisticsInfo); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNet.h b/rpcs3/Emu/ARMv7/Modules/sceNet.h new file mode 100644 index 0000000000..1d30bdfdd0 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNet.h @@ -0,0 +1,187 @@ +#pragma once + +typedef u32 SceNetInAddr_t; +typedef u16 SceNetInPort_t; +typedef u8 SceNetSaFamily_t; +typedef u32 SceNetSocklen_t; + +struct SceNetInAddr +{ + SceNetInAddr_t s_addr; +}; + +struct SceNetSockaddrIn +{ + u8 sin_len; + SceNetSaFamily_t sin_family; + SceNetInPort_t sin_port; + SceNetInAddr sin_addr; + SceNetInPort_t sin_vport; + char sin_zero[6]; +}; + +struct SceNetDnsInfo +{ + SceNetInAddr dns_addr[2]; +}; + +struct SceNetSockaddr +{ + u8 sa_len; + SceNetSaFamily_t sa_family; + char sa_data[14]; +}; + +struct SceNetEpollDataExt +{ + s32 id; + u32 u32; +}; + +union SceNetEpollData +{ + vm::psv::ptr ptr; + s32 fd; + u32 u32; + u64 u64; + SceNetEpollDataExt ext; +}; + +struct SceNetEpollSystemData +{ + u32 system[4]; +}; + +struct SceNetEpollEvent +{ + u32 events; + u32 reserved; + SceNetEpollSystemData system; + SceNetEpollData data; +}; + +struct SceNetEtherAddr +{ + u8 data[6]; +}; + +typedef u32 SceNetIdMask; + +struct SceNetFdSet +{ + SceNetIdMask bits[32]; +}; + +struct SceNetIpMreq +{ + SceNetInAddr imr_multiaddr; + SceNetInAddr imr_interface; +}; + +struct SceNetInitParam +{ + vm::psv::ptr memory; + s32 size; + s32 flags; +}; + +struct SceNetEmulationData +{ + u16 drop_rate; + u16 drop_duration; + u16 pass_duration; + u16 delay_time; + u16 delay_jitter; + u16 order_rate; + u16 order_delay_time; + u16 duplication_rate; + u32 bps_limit; + u16 lower_size_limit; + u16 upper_size_limit; + u32 system_policy_pattern; + u32 game_policy_pattern; + u16 policy_flags[64]; + u8 reserved[64]; +}; + +struct SceNetEmulationParam +{ + u16 version; + u16 option_number; + u16 current_version; + u16 result; + u32 flags; + u32 reserved1; + SceNetEmulationData send; + SceNetEmulationData recv; + u32 seed; + u8 reserved[44]; +}; + +typedef vm::psv::ptr(u32 size, s32 rid, vm::psv::ptr name, vm::psv::ptr user)> SceNetResolverFunctionAllocate; + +typedef vm::psv::ptr ptr, s32 rid, vm::psv::ptr name, vm::psv::ptr user)> SceNetResolverFunctionFree; + +struct SceNetResolverParam +{ + SceNetResolverFunctionAllocate allocate; + SceNetResolverFunctionFree free; + vm::psv::ptr user; +}; + +struct SceNetLinger +{ + s32 l_onoff; + s32 l_linger; +}; + +struct SceNetIovec +{ + vm::psv::ptr iov_base; + u32 iov_len; +}; + +struct SceNetMsghdr +{ + vm::psv::ptr msg_name; + SceNetSocklen_t msg_namelen; + vm::psv::ptr msg_iov; + s32 msg_iovlen; + vm::psv::ptr msg_control; + SceNetSocklen_t msg_controllen; + s32 msg_flags; +}; + +struct SceNetSockInfo +{ + char name[32]; + s32 pid; + s32 s; + s8 socket_type; + s8 policy; + s16 reserved16; + s32 recv_queue_length; + s32 send_queue_length; + SceNetInAddr local_adr; + SceNetInAddr remote_adr; + SceNetInPort_t local_port; + SceNetInPort_t remote_port; + SceNetInPort_t local_vport; + SceNetInPort_t remote_vport; + s32 state; + s32 flags; + s32 reserved[8]; +}; + +struct SceNetStatisticsInfo +{ + s32 kernel_mem_free_size; + s32 kernel_mem_free_min; + s32 packet_count; + s32 packet_qos_count; + s32 libnet_mem_free_size; + s32 libnet_mem_free_min; +}; + + +extern psv_log_base sceNet; diff --git a/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp b/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp index cde7d28916..7f15d6bf1f 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNetCtl.cpp @@ -2,8 +2,132 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceNet.h" + extern psv_log_base sceNetCtl; +union SceNetCtlInfo +{ + char cnf_name[65]; + u32 device; + SceNetEtherAddr ether_addr; + u32 mtu; + u32 link; + SceNetEtherAddr bssid; + char ssid[33]; + u32 wifi_security; + u32 rssi_dbm; + u32 rssi_percentage; + u32 channel; + u32 ip_config; + char dhcp_hostname[256]; + char pppoe_auth_name[128]; + char ip_address[16]; + char netmask[16]; + char default_route[16]; + char primary_dns[16]; + char secondary_dns[16]; + u32 http_proxy_config; + char http_proxy_server[256]; + u32 http_proxy_port; +}; + +struct SceNetCtlNatInfo +{ + u32 size; + s32 stun_status; + s32 nat_type; + SceNetInAddr mapped_addr; +}; + +struct SceNetCtlAdhocPeerInfo +{ + vm::psv::ptr next; + SceNetInAddr inet_addr; +}; + +typedef vm::psv::ptr arg)> SceNetCtlCallback; + +s32 sceNetCtlInit() +{ + throw __FUNCTION__; +} + +void sceNetCtlTerm() +{ + throw __FUNCTION__; +} + +s32 sceNetCtlCheckCallback() +{ + throw __FUNCTION__; +} + +s32 sceNetCtlInetGetResult(s32 eventType, vm::psv::ptr errorCode) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocGetResult(s32 eventType, vm::psv::ptr errorCode) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlInetGetInfo(s32 code, vm::psv::ptr info) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlInetGetState(vm::psv::ptr state) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlGetNatInfo(vm::psv::ptr natinfo) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlInetRegisterCallback(SceNetCtlCallback func, vm::psv::ptr arg, vm::psv::ptr cid) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlInetUnregisterCallback(s32 cid) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocRegisterCallback(SceNetCtlCallback func, vm::psv::ptr arg, vm::psv::ptr cid) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocUnregisterCallback(s32 cid) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocGetState(vm::psv::ptr state) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocDisconnect() +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocGetPeerList(vm::psv::ptr buflen, vm::psv::ptr buf) +{ + throw __FUNCTION__; +} + +s32 sceNetCtlAdhocGetInAddr(vm::psv::ptr inaddr) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNetCtl, #name, name) psv_log_base sceNetCtl("SceNetCtl", []() @@ -12,20 +136,20 @@ psv_log_base sceNetCtl("SceNetCtl", []() sceNetCtl.on_unload = nullptr; sceNetCtl.on_stop = nullptr; - //REG_FUNC(0x495CA1DB, sceNetCtlInit); - //REG_FUNC(0xCD188648, sceNetCtlTerm); - //REG_FUNC(0xDFFC3ED4, sceNetCtlCheckCallback); - //REG_FUNC(0x6B20EC02, sceNetCtlInetGetResult); - //REG_FUNC(0x7AE0ED19, sceNetCtlAdhocGetResult); - //REG_FUNC(0xB26D07F3, sceNetCtlInetGetInfo); - //REG_FUNC(0x6D26AC68, sceNetCtlInetGetState); - //REG_FUNC(0xEAEE6185, sceNetCtlInetRegisterCallback); - //REG_FUNC(0xD0C3BF3F, sceNetCtlInetUnregisterCallback); - //REG_FUNC(0x4DDD6149, sceNetCtlGetNatInfo); - //REG_FUNC(0x0961A561, sceNetCtlAdhocGetState); - //REG_FUNC(0xFFA9D594, sceNetCtlAdhocRegisterCallback); - //REG_FUNC(0xA4471E10, sceNetCtlAdhocUnregisterCallback); - //REG_FUNC(0xED43B79A, sceNetCtlAdhocDisconnect); - //REG_FUNC(0x77586C59, sceNetCtlAdhocGetPeerList); - //REG_FUNC(0x7118C99D, sceNetCtlAdhocGetInAddr); + REG_FUNC(0x495CA1DB, sceNetCtlInit); + REG_FUNC(0xCD188648, sceNetCtlTerm); + REG_FUNC(0xDFFC3ED4, sceNetCtlCheckCallback); + REG_FUNC(0x6B20EC02, sceNetCtlInetGetResult); + REG_FUNC(0x7AE0ED19, sceNetCtlAdhocGetResult); + REG_FUNC(0xB26D07F3, sceNetCtlInetGetInfo); + REG_FUNC(0x6D26AC68, sceNetCtlInetGetState); + REG_FUNC(0xEAEE6185, sceNetCtlInetRegisterCallback); + REG_FUNC(0xD0C3BF3F, sceNetCtlInetUnregisterCallback); + REG_FUNC(0x4DDD6149, sceNetCtlGetNatInfo); + REG_FUNC(0x0961A561, sceNetCtlAdhocGetState); + REG_FUNC(0xFFA9D594, sceNetCtlAdhocRegisterCallback); + REG_FUNC(0xA4471E10, sceNetCtlAdhocUnregisterCallback); + REG_FUNC(0xED43B79A, sceNetCtlAdhocDisconnect); + REG_FUNC(0x77586C59, sceNetCtlAdhocGetPeerList); + REG_FUNC(0x7118C99D, sceNetCtlAdhocGetInAddr); }); diff --git a/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp b/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp index 2fab7c29d4..2046dff9ca 100644 --- a/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp +++ b/rpcs3/Emu/ARMv7/Modules/scePhotoExport.cpp @@ -4,6 +4,42 @@ extern psv_log_base scePhotoExport; +struct ScePhotoExportParam +{ + u32 version; + vm::psv::ptr photoTitle; + vm::psv::ptr gameTitle; + vm::psv::ptr gameComment; + char reserved[32]; +}; + +typedef vm::psv::ptr)> ScePhotoExportCancelFunc; + +s32 scePhotoExportFromData( + vm::psv::ptr photodata, + s32 photodataSize, + vm::psv::ptr param, + vm::psv::ptr workMemory, + ScePhotoExportCancelFunc cancelFunc, + vm::psv::ptr userdata, + vm::psv::ptr exportedPath, + s32 exportedPathLength) +{ + throw __FUNCTION__; +} + +s32 scePhotoExportFromFile( + vm::psv::ptr photodataPath, + vm::psv::ptr param, + vm::psv::ptr workMemory, + ScePhotoExportCancelFunc cancelFunc, + vm::psv::ptr userdata, + vm::psv::ptr exportedPath, + s32 exportedPathLength) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &scePhotoExport, #name, name) psv_log_base scePhotoExport("ScePhotoExport", []() @@ -12,6 +48,6 @@ psv_log_base scePhotoExport("ScePhotoExport", []() scePhotoExport.on_unload = nullptr; scePhotoExport.on_stop = nullptr; - //REG_FUNC(0x70512321, scePhotoExportFromData); - //REG_FUNC(0x84FD9FC5, scePhotoExportFromFile); + REG_FUNC(0x70512321, scePhotoExportFromData); + REG_FUNC(0x84FD9FC5, scePhotoExportFromFile); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp b/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp index 4eaeb11070..c14fba50b6 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceRazorCapture.cpp @@ -4,6 +4,21 @@ extern psv_log_base sceRazorCapture; +void sceRazorCaptureSetTrigger(u32 frameIndex, vm::psv::ptr captureFilename) +{ + throw __FUNCTION__; +} + +void sceRazorCaptureSetTriggerNextFrame(vm::psv::ptr captureFilename) +{ + throw __FUNCTION__; +} + +bool sceRazorCaptureIsInProgress() +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceRazorCapture, #name, name) psv_log_base sceRazorCapture("SceRazorCapture", []() @@ -12,7 +27,7 @@ psv_log_base sceRazorCapture("SceRazorCapture", []() sceRazorCapture.on_unload = nullptr; sceRazorCapture.on_stop = nullptr; - //REG_FUNC(0x911E0AA0, sceRazorCaptureIsInProgress); - //REG_FUNC(0xE916B538, sceRazorCaptureSetTrigger); - //REG_FUNC(0x3D4B7E68, sceRazorCaptureSetTriggerNextFrame); + REG_FUNC(0x911E0AA0, sceRazorCaptureIsInProgress); + REG_FUNC(0xE916B538, sceRazorCaptureSetTrigger); + REG_FUNC(0x3D4B7E68, sceRazorCaptureSetTriggerNextFrame); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp b/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp index 47ab0d614c..07b3f0a467 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceScreenShot.cpp @@ -4,6 +4,35 @@ extern psv_log_base sceScreenShot; +struct SceScreenShotParam +{ + vm::psv::ptr photoTitle; + vm::psv::ptr gameTitle; + vm::psv::ptr gameComment; + vm::psv::ptr reserved; +}; + +s32 sceScreenShotSetParam(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceScreenShotSetOverlayImage(vm::psv::ptr filePath, s32 offsetX, s32 offsetY) +{ + throw __FUNCTION__; +} + +s32 sceScreenShotDisable() +{ + throw __FUNCTION__; +} + +s32 sceScreenShotEnable() +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceScreenShot, #name, name) psv_log_base sceScreenShot("SceScreenShot", []() @@ -12,8 +41,8 @@ psv_log_base sceScreenShot("SceScreenShot", []() sceScreenShot.on_unload = nullptr; sceScreenShot.on_stop = nullptr; - //REG_FUNC(0x05DB59C7, sceScreenShotSetParam); - //REG_FUNC(0x7061665B, sceScreenShotSetOverlayImage); - //REG_FUNC(0x50AE9FF9, sceScreenShotDisable); - //REG_FUNC(0x76E674D1, sceScreenShotEnable); + REG_FUNC(0x05DB59C7, sceScreenShotSetParam); + REG_FUNC(0x7061665B, sceScreenShotSetOverlayImage); + REG_FUNC(0x50AE9FF9, sceScreenShotDisable); + REG_FUNC(0x76E674D1, sceScreenShotEnable); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp b/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp index 51032ab5fd..02a377996a 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSsl.cpp @@ -2,7 +2,63 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" -extern psv_log_base sceSsl; +#include "sceSsl.h" + +s32 sceSslInit(u32 poolSize) +{ + throw __FUNCTION__; +} + +s32 sceSslTerm() +{ + throw __FUNCTION__; +} + +s32 sceSslGetMemoryPoolStats(vm::psv::ptr currentStat) +{ + throw __FUNCTION__; +} + +s32 sceSslGetSerialNumber(vm::psv::ptr sslCert, vm::psv::ptr> sboData, vm::psv::ptr sboLen) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceSslGetSubjectName(vm::psv::ptr sslCert) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceSslGetIssuerName(vm::psv::ptr sslCert) +{ + throw __FUNCTION__; +} + +s32 sceSslGetNotBefore(vm::psv::ptr sslCert, vm::psv::ptr begin) +{ + throw __FUNCTION__; +} + +s32 sceSslGetNotAfter(vm::psv::ptr sslCert, vm::psv::ptr limit) +{ + throw __FUNCTION__; +} + +s32 sceSslGetNameEntryCount(vm::psv::ptr certName) +{ + throw __FUNCTION__; +} + +s32 sceSslGetNameEntryInfo(vm::psv::ptr certName, s32 entryNum, vm::psv::ptr oidname, u32 maxOidnameLen, vm::psv::ptr value, u32 maxValueLen, vm::psv::ptr valueLen) +{ + throw __FUNCTION__; +} + +s32 sceSslFreeSslCertName(vm::psv::ptr certName) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceSsl, #name, name) @@ -12,15 +68,15 @@ psv_log_base sceSsl("SceSsl", []() sceSsl.on_unload = nullptr; sceSsl.on_stop = nullptr; - //REG_FUNC(0x3C733316, sceSslInit); - //REG_FUNC(0x03CE6E3A, sceSslTerm); - //REG_FUNC(0xBD203262, sceSslGetMemoryPoolStats); - //REG_FUNC(0x901C5C15, sceSslGetSerialNumber); - //REG_FUNC(0x9B2F1BC1, sceSslGetSubjectName); - //REG_FUNC(0x412711E5, sceSslGetIssuerName); - //REG_FUNC(0x70DEA174, sceSslGetNotBefore); - //REG_FUNC(0xF5ED7B68, sceSslGetNotAfter); - //REG_FUNC(0x95E14CA6, sceSslGetNameEntryCount); - //REG_FUNC(0x2A857867, sceSslGetNameEntryInfo); - //REG_FUNC(0xC73687E4, sceSslFreeSslCertName); + REG_FUNC(0x3C733316, sceSslInit); + REG_FUNC(0x03CE6E3A, sceSslTerm); + REG_FUNC(0xBD203262, sceSslGetMemoryPoolStats); + REG_FUNC(0x901C5C15, sceSslGetSerialNumber); + REG_FUNC(0x9B2F1BC1, sceSslGetSubjectName); + REG_FUNC(0x412711E5, sceSslGetIssuerName); + REG_FUNC(0x70DEA174, sceSslGetNotBefore); + REG_FUNC(0xF5ED7B68, sceSslGetNotAfter); + REG_FUNC(0x95E14CA6, sceSslGetNameEntryCount); + REG_FUNC(0x2A857867, sceSslGetNameEntryInfo); + REG_FUNC(0xC73687E4, sceSslFreeSslCertName); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSsl.h b/rpcs3/Emu/ARMv7/Modules/sceSsl.h new file mode 100644 index 0000000000..3d60ac45e5 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceSsl.h @@ -0,0 +1,14 @@ +#pragma once + +typedef void SceSslCert; +typedef void SceSslCertName; + +struct SceSslMemoryPoolStats +{ + u32 poolSize; + u32 maxInuseSize; + u32 currentInuseSize; + s32 reserved; +}; + +extern psv_log_base sceSsl; diff --git a/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp b/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp index 09c50ce4e9..3df26668a4 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSulpha.cpp @@ -4,6 +4,84 @@ extern psv_log_base sceSulpha; +typedef vm::psv::ptr arg)> SceSulphaCallback; + +struct SceSulphaConfig +{ + SceSulphaCallback notifyCallback; + u32 port; + u32 bookmarkCount; +}; + +struct SceSulphaAgentsRegister; +typedef void SceSulphaHandle; + +s32 sceSulphaNetworkInit() +{ + throw __FUNCTION__; +} + +s32 sceSulphaNetworkShutdown() +{ + throw __FUNCTION__; +} + +s32 sceSulphaGetDefaultConfig(vm::psv::ptr config) +{ + throw __FUNCTION__; +} + +s32 sceSulphaGetNeededMemory(vm::psv::ptr config, vm::psv::ptr sizeInBytes) +{ + throw __FUNCTION__; +} + +s32 sceSulphaInit(vm::psv::ptr config, vm::psv::ptr buffer, u32 sizeInBytes) +{ + throw __FUNCTION__; +} + +s32 sceSulphaShutdown() +{ + throw __FUNCTION__; +} + +s32 sceSulphaUpdate() +{ + throw __FUNCTION__; +} + +s32 sceSulphaFileConnect(vm::psv::ptr filename) +{ + throw __FUNCTION__; +} + +s32 sceSulphaFileDisconnect() +{ + throw __FUNCTION__; +} + +s32 sceSulphaSetBookmark(vm::psv::ptr name, s32 id) +{ + throw __FUNCTION__; +} + +s32 sceSulphaAgentsGetNeededMemory(vm::psv::ptr config, vm::psv::ptr sizeInBytes) +{ + throw __FUNCTION__; +} + +s32 sceSulphaAgentsRegister(vm::psv::ptr config, vm::psv::ptr buffer, u32 sizeInBytes, vm::psv::ptr handles) +{ + throw __FUNCTION__; +} + +s32 sceSulphaAgentsUnregister(vm::psv::ptr handles, u32 agentCount) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceSulpha, #name, name) psv_log_base sceSulpha("SceSulpha", []() @@ -12,19 +90,19 @@ psv_log_base sceSulpha("SceSulpha", []() sceSulpha.on_unload = nullptr; sceSulpha.on_stop = nullptr; - //REG_FUNC(0xB4668AEA, sceSulphaNetworkInit); - //REG_FUNC(0x0FC71B72, sceSulphaNetworkShutdown); - //REG_FUNC(0xA6A05C50, sceSulphaGetDefaultConfig); - //REG_FUNC(0xD52E5A5A, sceSulphaGetNeededMemory); - //REG_FUNC(0x324F158F, sceSulphaInit); - //REG_FUNC(0x10770BA7, sceSulphaShutdown); - //REG_FUNC(0x920EC7BF, sceSulphaUpdate); - //REG_FUNC(0x7968A138, sceSulphaFileConnect); - //REG_FUNC(0xB16E7B88, sceSulphaFileDisconnect); - //REG_FUNC(0x5E15E164, sceSulphaSetBookmark); - //REG_FUNC(0xC5752B6B, sceSulphaAgentsGetNeededMemory); - //REG_FUNC(0x7ADB454D, sceSulphaAgentsRegister); - //REG_FUNC(0x2A8B74D7, sceSulphaAgentsUnregister); + REG_FUNC(0xB4668AEA, sceSulphaNetworkInit); + REG_FUNC(0x0FC71B72, sceSulphaNetworkShutdown); + REG_FUNC(0xA6A05C50, sceSulphaGetDefaultConfig); + REG_FUNC(0xD52E5A5A, sceSulphaGetNeededMemory); + REG_FUNC(0x324F158F, sceSulphaInit); + REG_FUNC(0x10770BA7, sceSulphaShutdown); + REG_FUNC(0x920EC7BF, sceSulphaUpdate); + REG_FUNC(0x7968A138, sceSulphaFileConnect); + REG_FUNC(0xB16E7B88, sceSulphaFileDisconnect); + REG_FUNC(0x5E15E164, sceSulphaSetBookmark); + REG_FUNC(0xC5752B6B, sceSulphaAgentsGetNeededMemory); + REG_FUNC(0x7ADB454D, sceSulphaAgentsRegister); + REG_FUNC(0x2A8B74D7, sceSulphaAgentsUnregister); //REG_FUNC(0xDE7E2911, sceSulphaGetAgent); //REG_FUNC(0xA41B7402, sceSulphaNodeNew); //REG_FUNC(0xD44C9F86, sceSulphaNodeDelete); diff --git a/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp b/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp index 6636644e0d..ee13162e61 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp @@ -4,6 +4,65 @@ extern psv_log_base sceTouch; +struct SceTouchPanelInfo +{ + s16 minAaX; + s16 minAaY; + s16 maxAaX; + s16 maxAaY; + s16 minDispX; + s16 minDispY; + s16 maxDispX; + s16 maxDispY; + u8 minForce; + u8 maxForce; + u8 rsv[30]; +}; + +struct SceTouchReport +{ + u8 id; + u8 force; + s16 x; + s16 y; + s8 rsv[8]; + u16 info; +}; + +struct SceTouchData +{ + u64 timeStamp; + u32 status; + u32 reportNum; + SceTouchReport report[8]; +}; + +s32 sceTouchGetPanelInfo(u32 port, vm::psv::ptr pPanelInfo) +{ + throw __FUNCTION__; +} + +s32 sceTouchRead(u32 port, vm::psv::ptr pData, u32 nBufs) +{ + throw __FUNCTION__; +} + +s32 sceTouchPeek(u32 port, vm::psv::ptr pData, u32 nBufs) +{ + throw __FUNCTION__; +} + +s32 sceTouchSetSamplingState(u32 port, u32 state) +{ + throw __FUNCTION__; +} + +s32 sceTouchGetSamplingState(u32 port, vm::psv::ptr pState) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceTouch, #name, name) psv_log_base sceTouch("SceTouch", []() @@ -12,9 +71,9 @@ psv_log_base sceTouch("SceTouch", []() sceTouch.on_unload = nullptr; sceTouch.on_stop = nullptr; - //REG_FUNC(0x169A1D58, sceTouchRead); - //REG_FUNC(0xFF082DF0, sceTouchPeek); - //REG_FUNC(0x1B9C5D14, sceTouchSetSamplingState); - //REG_FUNC(0x26531526, sceTouchGetSamplingState); - //REG_FUNC(0x10A2CA25, sceTouchGetPanelInfo); + REG_FUNC(0x169A1D58, sceTouchRead); + REG_FUNC(0xFF082DF0, sceTouchPeek); + REG_FUNC(0x1B9C5D14, sceTouchSetSamplingState); + REG_FUNC(0x26531526, sceTouchGetSamplingState); + REG_FUNC(0x10A2CA25, sceTouchGetPanelInfo); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp b/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp index 472c7bbfb3..bec390ebe1 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceVideodec.cpp @@ -4,6 +4,178 @@ extern psv_log_base sceVideodec; +struct SceVideodecQueryInitInfoHwAvcdec +{ + u32 size; + u32 horizontal; + u32 vertical; + u32 numOfRefFrames; + u32 numOfStreams; +}; + +union SceVideodecQueryInitInfo +{ + u8 reserved[32]; + SceVideodecQueryInitInfoHwAvcdec hwAvc; +}; + +struct SceVideodecTimeStamp +{ + u32 upper; + u32 lower; +}; + +struct SceAvcdecQueryDecoderInfo +{ + u32 horizontal; + u32 vertical; + u32 numOfRefFrames; + +}; + +struct SceAvcdecDecoderInfo +{ + u32 frameMemSize; + +}; + +struct SceAvcdecBuf +{ + vm::psv::ptr pBuf; + u32 size; +}; + +struct SceAvcdecCtrl +{ + u32 handle; + SceAvcdecBuf frameBuf; +}; + +struct SceAvcdecAu +{ + SceVideodecTimeStamp pts; + SceVideodecTimeStamp dts; + SceAvcdecBuf es; +}; + +struct SceAvcdecInfo +{ + u32 numUnitsInTick; + u32 timeScale; + u8 fixedFrameRateFlag; + + u8 aspectRatioIdc; + u16 sarWidth; + u16 sarHeight; + + u8 colourPrimaries; + u8 transferCharacteristics; + u8 matrixCoefficients; + + u8 videoFullRangeFlag; + + u8 picStruct[2]; + u8 ctType; + + u8 padding[3]; +}; + +struct SceAvcdecFrameOptionRGBA +{ + u8 alpha; + u8 cscCoefficient; + u8 reserved[14]; +}; + +union SceAvcdecFrameOption +{ + u8 reserved[16]; + SceAvcdecFrameOptionRGBA rgba; +}; + + +struct SceAvcdecFrame +{ + u32 pixelType; + u32 framePitch; + u32 frameWidth; + u32 frameHeight; + + u32 horizontalSize; + u32 verticalSize; + + u32 frameCropLeftOffset; + u32 frameCropRightOffset; + u32 frameCropTopOffset; + u32 frameCropBottomOffset; + + SceAvcdecFrameOption opt; + + vm::psv::ptr pPicture[2]; +}; + + +struct SceAvcdecPicture +{ + u32 size; + SceAvcdecFrame frame; + SceAvcdecInfo info; +}; + +struct SceAvcdecArrayPicture +{ + u32 numOfOutput; + u32 numOfElm; + vm::psv::ptr> pPicture; +}; + + +s32 sceVideodecInitLibrary(u32 codecType, vm::psv::ptr pInitInfo) +{ + throw __FUNCTION__; +} + +s32 sceVideodecTermLibrary(u32 codecType) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecQueryDecoderMemSize(u32 codecType, vm::psv::ptr pDecoderInfo, vm::psv::ptr pMemInfo) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecCreateDecoder(u32 codecType, vm::psv::ptr pCtrl, vm::psv::ptr pDecoderInfo) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecDeleteDecoder(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecDecodeAvailableSize(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecDecode(vm::psv::ptr pCtrl, vm::psv::ptr pAu, vm::psv::ptr pArrayPicture) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecDecodeStop(vm::psv::ptr pCtrl, vm::psv::ptr pArrayPicture) +{ + throw __FUNCTION__; +} + +s32 sceAvcdecDecodeFlush(vm::psv::ptr pCtrl) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceVideodec, #name, name) psv_log_base sceVideodec("SceVideodec", []() @@ -12,15 +184,15 @@ psv_log_base sceVideodec("SceVideodec", []() sceVideodec.on_unload = nullptr; sceVideodec.on_stop = nullptr; - //REG_FUNC(0xF1AF65A3, sceVideodecInitLibrary); - //REG_FUNC(0x3A5F4924, sceVideodecTermLibrary); - //REG_FUNC(0x97E95EDB, sceAvcdecQueryDecoderMemSize); - //REG_FUNC(0xE82BB69B, sceAvcdecCreateDecoder); - //REG_FUNC(0x8A0E359E, sceAvcdecDeleteDecoder); - //REG_FUNC(0x441673E3, sceAvcdecDecodeAvailableSize); - //REG_FUNC(0xD6190A06, sceAvcdecDecode); - //REG_FUNC(0x9648D853, sceAvcdecDecodeStop); - //REG_FUNC(0x25F31020, sceAvcdecDecodeFlush); + REG_FUNC(0xF1AF65A3, sceVideodecInitLibrary); + REG_FUNC(0x3A5F4924, sceVideodecTermLibrary); + REG_FUNC(0x97E95EDB, sceAvcdecQueryDecoderMemSize); + REG_FUNC(0xE82BB69B, sceAvcdecCreateDecoder); + REG_FUNC(0x8A0E359E, sceAvcdecDeleteDecoder); + REG_FUNC(0x441673E3, sceAvcdecDecodeAvailableSize); + REG_FUNC(0xD6190A06, sceAvcdecDecode); + REG_FUNC(0x9648D853, sceAvcdecDecodeStop); + REG_FUNC(0x25F31020, sceAvcdecDecodeFlush); //REG_FUNC(0xB2A428DB, sceAvcdecCsc); //REG_FUNC(0x6C68A38F, sceAvcdecDecodeNalAu); //REG_FUNC(0xC67C1A80, sceM4vdecQueryDecoderMemSize); diff --git a/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp b/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp index 072f3d3303..cb0cfc8f53 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp @@ -4,6 +4,252 @@ extern psv_log_base sceVoice; +enum SceVoicePortType : s32 +{ + SCEVOICE_PORTTYPE_NULL = -1, + SCEVOICE_PORTTYPE_IN_DEVICE = 0, + SCEVOICE_PORTTYPE_IN_PCMAUDIO = 1, + SCEVOICE_PORTTYPE_IN_VOICE = 2, + SCEVOICE_PORTTYPE_OUT_PCMAUDIO = 3, + SCEVOICE_PORTTYPE_OUT_VOICE = 4, + SCEVOICE_PORTTYPE_OUT_DEVICE = 5 +}; + +enum SceVoicePortState : s32 +{ + SCEVOICE_PORTSTATE_NULL = -1, + SCEVOICE_PORTSTATE_IDLE = 0, + SCEVOICE_PORTSTATE_READY = 1, + SCEVOICE_PORTSTATE_BUFFERING = 2, + SCEVOICE_PORTSTATE_RUNNING = 3 +}; + +enum SceVoiceBitRate : s32 +{ + SCEVOICE_BITRATE_NULL = -1, + SCEVOICE_BITRATE_3850 = 3850, + SCEVOICE_BITRATE_4650 = 4650, + SCEVOICE_BITRATE_5700 = 5700, + SCEVOICE_BITRATE_7300 = 7300 +}; + +enum SceVoiceSamplingRate : s32 +{ + SCEVOICE_SAMPLINGRATE_NULL = -1, + SCEVOICE_SAMPLINGRATE_16000 = 16000 +}; + +enum SceVoicePcmDataType : s32 +{ + SCEVOICE_PCM_NULL = -1, + SCEVOICE_PCM_SHORT_LITTLE_ENDIAN = 0 +}; + +enum SceVoiceVersion : s32 +{ + SCEVOICE_VERSION_100 = 100 +}; + +enum SceVoiceAppType : s32 +{ + SCEVOICE_APPTYPE_GAME = 1 << 29 +}; + +struct SceVoicePCMFormat +{ + SceVoicePcmDataType dataType; + SceVoiceSamplingRate sampleRate; +}; + +struct SceVoiceResourceInfo +{ + u16 maxInVoicePort; + u16 maxOutVoicePort; + u16 maxInDevicePort; + u16 maxOutDevicePort; + u16 maxTotalPort; +}; + +struct SceVoiceBasePortInfo +{ + SceVoicePortType portType; + SceVoicePortState state; + vm::psv::ptr pEdge; + u32 numByte; + u32 frameSize; + u16 numEdge; + u16 reserved; +}; + +struct SceVoicePortParam +{ + SceVoicePortType portType; + u16 threshold; + u16 bMute; + float volume; + + union + { + struct + { + SceVoiceBitRate bitrate; + } voice; + + struct + { + u32 bufSize; + SceVoicePCMFormat format; + } pcmaudio; + + + struct + { + u32 playerId; + } device; + }; +}; + +typedef vm::psv::ptr event)> SceVoiceEventCallback; + +struct SceVoiceInitParam +{ + s32 appType; + SceVoiceEventCallback onEvent; + u8 reserved[24]; +}; + +struct SceVoiceStartParam +{ + s32 container; + u8 reserved[28]; +}; + +s32 sceVoiceInit(vm::psv::ptr pArg, SceVoiceVersion version) +{ + throw __FUNCTION__; +} + +s32 sceVoiceEnd() +{ + throw __FUNCTION__; +} + +s32 sceVoiceStart(vm::psv::ptr pArg) +{ + throw __FUNCTION__; +} + +s32 sceVoiceStop() +{ + throw __FUNCTION__; +} + +s32 sceVoiceResetPort(u32 portId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceCreatePort(vm::psv::ptr portId, vm::psv::ptr pArg) +{ + throw __FUNCTION__; +} + +s32 sceVoiceUpdatePort(u32 portId, vm::psv::ptr pArg) +{ + throw __FUNCTION__; +} + +s32 sceVoiceConnectIPortToOPort(u32 ips, u32 ops) +{ + throw __FUNCTION__; +} + +s32 sceVoiceDisconnectIPortFromOPort(u32 ips, u32 ops) +{ + throw __FUNCTION__; +} + +s32 sceVoiceDeletePort(u32 portId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceWriteToIPort(u32 ips, vm::psv::ptr data, vm::psv::ptr size, int16_t frameGaps) +{ + throw __FUNCTION__; +} + +s32 sceVoiceReadFromOPort(u32 ops, vm::psv::ptr data, vm::psv::ptr size) +{ + throw __FUNCTION__; +} + +s32 sceVoiceSetMuteFlagAll(u16 bMuted) +{ + throw __FUNCTION__; +} + +s32 sceVoiceSetMuteFlag(u32 portId, u16 bMuted) +{ + throw __FUNCTION__; +} + +s32 sceVoiceGetMuteFlag(u32 portId, vm::psv::ptr bMuted) +{ + throw __FUNCTION__; +} + +//s32 sceVoiceSetVolume(u32 portId, float volume) +//{ +// throw __FUNCTION__; +//} + +s32 sceVoiceGetVolume(u32 portId, vm::psv::ptr volume) +{ + throw __FUNCTION__; +} + +s32 sceVoiceSetBitRate(u32 portId, SceVoiceBitRate bitrate) +{ + throw __FUNCTION__; +} + +s32 sceVoiceGetBitRate(u32 portId, vm::psv::ptr bitrate) +{ + throw __FUNCTION__; +} + +s32 sceVoiceGetPortInfo(u32 portId, vm::psv::ptr pInfo) +{ + throw __FUNCTION__; +} + +s32 sceVoicePausePort(u32 portId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceResumePort(u32 portId) +{ + throw __FUNCTION__; +} + +s32 sceVoicePausePortAll() +{ + throw __FUNCTION__; +} + +s32 sceVoiceResumePortAll() +{ + throw __FUNCTION__; +} + +s32 sceVoiceGetResourceInfo(vm::psv::ptr pInfo) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceVoice, #name, name) psv_log_base sceVoice("SceVoice", []() @@ -12,29 +258,29 @@ psv_log_base sceVoice("SceVoice", []() sceVoice.on_unload = nullptr; sceVoice.on_stop = nullptr; - //REG_FUNC(0xD02C00B4, sceVoiceGetBitRate); - //REG_FUNC(0xC913F7E9, sceVoiceGetMuteFlag); - //REG_FUNC(0x875CC80D, sceVoiceGetVolume); - //REG_FUNC(0x02F58D6F, sceVoiceSetBitRate); - //REG_FUNC(0x0B9E4AE2, sceVoiceSetMuteFlag); - //REG_FUNC(0xDB90EAC4, sceVoiceSetMuteFlagAll); + REG_FUNC(0xD02C00B4, sceVoiceGetBitRate); + REG_FUNC(0xC913F7E9, sceVoiceGetMuteFlag); + REG_FUNC(0x875CC80D, sceVoiceGetVolume); + REG_FUNC(0x02F58D6F, sceVoiceSetBitRate); + REG_FUNC(0x0B9E4AE2, sceVoiceSetMuteFlag); + REG_FUNC(0xDB90EAC4, sceVoiceSetMuteFlagAll); //REG_FUNC(0xD93769E6, sceVoiceSetVolume); - //REG_FUNC(0x6E46950E, sceVoiceGetResourceInfo); - //REG_FUNC(0xAC98853E, sceVoiceEnd); - //REG_FUNC(0x805CC20F, sceVoiceInit); - //REG_FUNC(0xB2ED725B, sceVoiceStart); - //REG_FUNC(0xC3868DF6, sceVoiceStop); - //REG_FUNC(0x698BDAAE, sceVoiceConnectIPortToOPort); - //REG_FUNC(0xFA4E57B1, sceVoiceCreatePort); - //REG_FUNC(0xAE46564D, sceVoiceDeletePort); - //REG_FUNC(0x5F0260F4, sceVoiceDisconnectIPortFromOPort); - //REG_FUNC(0x5933CCFB, sceVoiceGetPortInfo); - //REG_FUNC(0x23C6B16B, sceVoicePausePort); - //REG_FUNC(0x39AA3884, sceVoicePausePortAll); - //REG_FUNC(0x09E4D18C, sceVoiceReadFromOPort); - //REG_FUNC(0x5E1CE910, sceVoiceResetPort); - //REG_FUNC(0x2DE35411, sceVoiceResumePort); - //REG_FUNC(0x1F93FC0C, sceVoiceResumePortAll); - //REG_FUNC(0xCE855C50, sceVoiceUpdatePort); - //REG_FUNC(0x0A22EC0E, sceVoiceWriteToIPort); + REG_FUNC(0x6E46950E, sceVoiceGetResourceInfo); + REG_FUNC(0xAC98853E, sceVoiceEnd); + REG_FUNC(0x805CC20F, sceVoiceInit); + REG_FUNC(0xB2ED725B, sceVoiceStart); + REG_FUNC(0xC3868DF6, sceVoiceStop); + REG_FUNC(0x698BDAAE, sceVoiceConnectIPortToOPort); + REG_FUNC(0xFA4E57B1, sceVoiceCreatePort); + REG_FUNC(0xAE46564D, sceVoiceDeletePort); + REG_FUNC(0x5F0260F4, sceVoiceDisconnectIPortFromOPort); + REG_FUNC(0x5933CCFB, sceVoiceGetPortInfo); + REG_FUNC(0x23C6B16B, sceVoicePausePort); + REG_FUNC(0x39AA3884, sceVoicePausePortAll); + REG_FUNC(0x09E4D18C, sceVoiceReadFromOPort); + REG_FUNC(0x5E1CE910, sceVoiceResetPort); + REG_FUNC(0x2DE35411, sceVoiceResumePort); + REG_FUNC(0x1F93FC0C, sceVoiceResumePortAll); + REG_FUNC(0xCE855C50, sceVoiceUpdatePort); + REG_FUNC(0x0A22EC0E, sceVoiceWriteToIPort); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp b/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp index bc5fb062a3..050570aaa9 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceVoiceQoS.cpp @@ -4,6 +4,114 @@ extern psv_log_base sceVoiceQoS; +typedef s32 SceVoiceQoSLocalId; +typedef s32 SceVoiceQoSRemoteId; +typedef s32 SceVoiceQoSConnectionId; + +enum SceVoiceQoSAttributeId : s32 +{ + SCE_VOICE_QOS_ATTR_MIC_VOLUME, + SCE_VOICE_QOS_ATTR_MIC_MUTE, + SCE_VOICE_QOS_ATTR_SPEAKER_VOLUME, + SCE_VOICE_QOS_ATTR_SPEAKER_MUTE, + SCE_VOICE_QOS_ATTR_DESIRED_OUT_BIT_RATE +}; + +enum SceVoiceQoSStatusId : s32 +{ + SCE_VOICE_QOS_IN_BITRATE, + SCE_VOICE_QOS_OUT_BITRATE, + SCE_VOICE_QOS_OUT_READ_BITRATE, + SCE_VOICE_QOS_IN_FRAME_RECEIVED_RATIO, + SCE_VOICE_QOS_HEARTBEAT_FLAG +}; + +s32 sceVoiceQoSInit() +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSEnd() +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSCreateLocalEndpoint(vm::psv::ptr pLocalId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSDeleteLocalEndpoint(SceVoiceQoSLocalId localId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSCreateRemoteEndpoint(vm::psv::ptr pRemoteId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSDeleteRemoteEndpoint(SceVoiceQoSRemoteId remoteId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSConnect(vm::psv::ptr pConnectionId, SceVoiceQoSLocalId localId, SceVoiceQoSRemoteId remoteId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSDisconnect(SceVoiceQoSConnectionId connectionId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSGetLocalEndpoint(SceVoiceQoSConnectionId connectionId, vm::psv::ptr pLocalId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSGetRemoteEndpoint(SceVoiceQoSConnectionId connectionId, vm::psv::ptr pRemoteId) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSSetLocalEndpointAttribute(SceVoiceQoSLocalId localId, SceVoiceQoSAttributeId attributeId, vm::psv::ptr pAttributeValue, s32 attributeSize) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSGetLocalEndpointAttribute(SceVoiceQoSLocalId localId, SceVoiceQoSAttributeId attributeId, vm::psv::ptr pAttributeValue, s32 attributeSize) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSSetConnectionAttribute(SceVoiceQoSConnectionId connectionId, SceVoiceQoSAttributeId attributeId, vm::psv::ptr pAttributeValue, s32 attributeSize) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSGetConnectionAttribute(SceVoiceQoSConnectionId connectionId, SceVoiceQoSAttributeId attributeId, vm::psv::ptr pAttributeValue, s32 attributeSize) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSGetStatus(SceVoiceQoSConnectionId connectionId, SceVoiceQoSStatusId statusId, vm::psv::ptr pStatusValue, s32 statusSize) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSWritePacket(SceVoiceQoSConnectionId connectionId, vm::psv::ptr pData, vm::psv::ptr pSize) +{ + throw __FUNCTION__; +} + +s32 sceVoiceQoSReadPacket(SceVoiceQoSConnectionId connectionId, vm::psv::ptr pData, vm::psv::ptr pSize) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceVoiceQoS, #name, name) psv_log_base sceVoiceQoS("SceVoiceQos", []() @@ -12,21 +120,21 @@ psv_log_base sceVoiceQoS("SceVoiceQos", []() sceVoiceQoS.on_unload = nullptr; sceVoiceQoS.on_stop = nullptr; - //REG_FUNC(0x4B5FFF1C, sceVoiceQoSInit); - //REG_FUNC(0xFB0B747B, sceVoiceQoSEnd); - //REG_FUNC(0xAAB54BE4, sceVoiceQoSCreateLocalEndpoint); - //REG_FUNC(0x68FABF6F, sceVoiceQoSDeleteLocalEndpoint); - //REG_FUNC(0xBAB98727, sceVoiceQoSCreateRemoteEndpoint); - //REG_FUNC(0xC2F2C771, sceVoiceQoSDeleteRemoteEndpoint); - //REG_FUNC(0xE0C5CEEE, sceVoiceQoSConnect); - //REG_FUNC(0x3C7A08B0, sceVoiceQoSDisconnect); - //REG_FUNC(0xE5B4527D, sceVoiceQoSGetLocalEndpoint); - //REG_FUNC(0x876A9B9C, sceVoiceQoSGetRemoteEndpoint); - //REG_FUNC(0x540CEBA5, sceVoiceQoSSetLocalEndpointAttribute); - //REG_FUNC(0xC981AB3B, sceVoiceQoSGetLocalEndpointAttribute); - //REG_FUNC(0xE757806F, sceVoiceQoSSetConnectionAttribute); - //REG_FUNC(0xE81B8D44, sceVoiceQoSGetConnectionAttribute); - //REG_FUNC(0xC9DC1425, sceVoiceQoSGetStatus); - //REG_FUNC(0x2FE1F28F, sceVoiceQoSWritePacket); - //REG_FUNC(0x2D613549, sceVoiceQoSReadPacket); + REG_FUNC(0x4B5FFF1C, sceVoiceQoSInit); + REG_FUNC(0xFB0B747B, sceVoiceQoSEnd); + REG_FUNC(0xAAB54BE4, sceVoiceQoSCreateLocalEndpoint); + REG_FUNC(0x68FABF6F, sceVoiceQoSDeleteLocalEndpoint); + REG_FUNC(0xBAB98727, sceVoiceQoSCreateRemoteEndpoint); + REG_FUNC(0xC2F2C771, sceVoiceQoSDeleteRemoteEndpoint); + REG_FUNC(0xE0C5CEEE, sceVoiceQoSConnect); + REG_FUNC(0x3C7A08B0, sceVoiceQoSDisconnect); + REG_FUNC(0xE5B4527D, sceVoiceQoSGetLocalEndpoint); + REG_FUNC(0x876A9B9C, sceVoiceQoSGetRemoteEndpoint); + REG_FUNC(0x540CEBA5, sceVoiceQoSSetLocalEndpointAttribute); + REG_FUNC(0xC981AB3B, sceVoiceQoSGetLocalEndpointAttribute); + REG_FUNC(0xE757806F, sceVoiceQoSSetConnectionAttribute); + REG_FUNC(0xE81B8D44, sceVoiceQoSGetConnectionAttribute); + REG_FUNC(0xC9DC1425, sceVoiceQoSGetStatus); + REG_FUNC(0x2FE1F28F, sceVoiceQoSWritePacket); + REG_FUNC(0x2D613549, sceVoiceQoSReadPacket); }); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index fb672d63a6..69cbaaf944 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -339,6 +339,8 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 6e45634fea..7935e1ddc6 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1492,5 +1492,11 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + + + Emu\CPU\ARMv7\Modules + \ No newline at end of file From 6cab4d7100abdd7c7bd41dcb18355cf2c8fb49d1 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 15:19:01 +0300 Subject: [PATCH 39/94] Some functions added --- rpcs3/Emu/ARMv7/Modules/sceGxm.cpp | 12 +- rpcs3/Emu/ARMv7/Modules/sceNet.h | 6 +- rpcs3/Emu/ARMv7/Modules/sceNgs.cpp | 549 ++++++++++++++++--- rpcs3/Emu/ARMv7/Modules/sceRtc.cpp | 260 +++++++-- rpcs3/Emu/ARMv7/Modules/sceSas.cpp | 204 ++++++- rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp | 276 +++++++++- rpcs3/Emu/ARMv7/Modules/sceTouch.cpp | 35 +- rpcs3/Emu/ARMv7/Modules/sceTouch.h | 36 ++ rpcs3/Emu/ARMv7/Modules/sceVoice.cpp | 2 +- rpcs3/Emu/Memory/vm_ptr.h | 2 + rpcs3/Emu/SysCalls/Modules/sceNp.h | 2 +- rpcs3/Emu/SysCalls/Modules/sceNpClans.h | 2 +- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 14 files changed, 1199 insertions(+), 191 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceTouch.h diff --git a/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp b/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp index 3614803537..f65f49b349 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceGxm.cpp @@ -257,23 +257,23 @@ void sceGxmSetBackPolygonMode(vm::psv::ptr context, SceGxmPolygon throw __FUNCTION__; } -void sceGxmSetFrontStencilFunc(vm::psv::ptr context, SceGxmStencilFunc func, SceGxmStencilOp stencilFail, SceGxmStencilOp depthFail, SceGxmStencilOp depthPass, uint8_t compareMask, uint8_t writeMask) +void sceGxmSetFrontStencilFunc(vm::psv::ptr context, SceGxmStencilFunc func, SceGxmStencilOp stencilFail, SceGxmStencilOp depthFail, SceGxmStencilOp depthPass, u8 compareMask, u8 writeMask) { throw __FUNCTION__; } -void sceGxmSetBackStencilFunc(vm::psv::ptr context, SceGxmStencilFunc func, SceGxmStencilOp stencilFail, SceGxmStencilOp depthFail, SceGxmStencilOp depthPass, uint8_t compareMask, uint8_t writeMask) +void sceGxmSetBackStencilFunc(vm::psv::ptr context, SceGxmStencilFunc func, SceGxmStencilOp stencilFail, SceGxmStencilOp depthFail, SceGxmStencilOp depthPass, u8 compareMask, u8 writeMask) { throw __FUNCTION__; } -void sceGxmSetFrontDepthBias(vm::psv::ptr context, int32_t factor, int32_t units) +void sceGxmSetFrontDepthBias(vm::psv::ptr context, s32 factor, s32 units) { throw __FUNCTION__; } -void sceGxmSetBackDepthBias(vm::psv::ptr context, int32_t factor, int32_t units) +void sceGxmSetBackDepthBias(vm::psv::ptr context, s32 factor, s32 units) { throw __FUNCTION__; } @@ -463,12 +463,12 @@ s32 sceGxmDepthStencilSurfaceInitDisabled(vm::psv::ptr surface) +u8 sceGxmDepthStencilSurfaceGetBackgroundStencil(vm::psv::ptr surface) { throw __FUNCTION__; } -void sceGxmDepthStencilSurfaceSetBackgroundStencil(vm::psv::ptr surface, uint8_t backgroundStencil) +void sceGxmDepthStencilSurfaceSetBackgroundStencil(vm::psv::ptr surface, u8 backgroundStencil) { throw __FUNCTION__; } diff --git a/rpcs3/Emu/ARMv7/Modules/sceNet.h b/rpcs3/Emu/ARMv7/Modules/sceNet.h index 1d30bdfdd0..6dc25e1ea9 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNet.h +++ b/rpcs3/Emu/ARMv7/Modules/sceNet.h @@ -35,15 +35,15 @@ struct SceNetSockaddr struct SceNetEpollDataExt { s32 id; - u32 u32; + u32 data; }; union SceNetEpollData { vm::psv::ptr ptr; s32 fd; - u32 u32; - u64 u64; + u32 _u32; + u64 _u64; SceNetEpollDataExt ext; }; diff --git a/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp b/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp index 5798792b12..f09993ba24 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNgs.cpp @@ -4,6 +4,431 @@ extern psv_log_base sceNgs; +struct SceNgsVoiceDefinition; + +typedef u32 SceNgsModuleID; +typedef u32 SceNgsParamsID; +typedef vm::psv::ptr SceNgsHVoice; +typedef vm::psv::ptr SceNgsHPatch; +typedef vm::psv::ptr SceNgsHSynSystem; +typedef vm::psv::ptr SceNgsHRack; + +struct SceNgsModuleParamHeader +{ + s32 moduleId; + s32 chan; +}; + +struct SceNgsParamsDescriptor +{ + SceNgsParamsID id; + u32 size; +}; + +struct SceNgsBufferInfo +{ + vm::psv::ptr data; + u32 size; +}; + +struct SceNgsVoicePreset +{ + s32 nNameOffset; + u32 uNameLength; + s32 nPresetDataOffset; + u32 uSizePresetData; + s32 nBypassFlagsOffset; + u32 uNumBypassFlags; +}; + +struct SceNgsSystemInitParams +{ + s32 nMaxRacks; + s32 nMaxVoices; + s32 nGranularity; + s32 nSampleRate; + s32 nMaxModules; +}; + +struct SceNgsRackDescription +{ + vm::psv::ptr pVoiceDefn; + s32 nVoices; + s32 nChannelsPerVoice; + s32 nMaxPatchesPerInput; + s32 nPatchesPerOutput; + vm::psv::ptr pUserReleaseData; +}; + +struct SceNgsPatchSetupInfo +{ + SceNgsHVoice hVoiceSource; + s32 nSourceOutputIndex; + s32 nSourceOutputSubIndex; + SceNgsHVoice hVoiceDestination; + s32 nTargetInputIndex; +}; + +struct SceNgsVolumeMatrix +{ + float m[2][2]; +}; + +struct SceNgsPatchRouteInfo +{ + s32 nOutputChannels; + s32 nInputChannels; + SceNgsVolumeMatrix vols; +}; + +struct SceNgsVoiceInfo +{ + u32 uVoiceState; + u32 uNumModules; + u32 uNumInputs; + u32 uNumOutputs; + u32 uNumPatchesPerOutput; +}; + +struct SceNgsCallbackInfo +{ + SceNgsHVoice hVoiceHandle; + SceNgsHRack hRackHandle; + SceNgsModuleID uModuleID; + s32 nCallbackData; + s32 nCallbackData2; + vm::psv::ptr pCallbackPtr; + vm::psv::ptr pUserData; +}; + +typedef vm::psv::ptr pCallbackInfo)> SceNgsCallbackFunc; + +typedef SceNgsCallbackFunc SceNgsRackReleaseCallbackFunc; +typedef SceNgsCallbackFunc SceNgsModuleCallbackFunc; +typedef SceNgsCallbackFunc SceNgsParamsErrorCallbackFunc; + +struct SceSulphaNgsConfig +{ + u32 maxNamedObjects; + u32 maxTraceBufferBytes; +}; + +s32 sceNgsSystemGetRequiredMemorySize(vm::psv::ptr pSynthParams, vm::psv::ptr pnSize) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemInit(vm::psv::ptr pSynthSysMemory, const u32 uMemSize, vm::psv::ptr pSynthParams, vm::psv::ptr pSystemHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemUpdate(SceNgsHSynSystem hSystemHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemRelease(SceNgsHSynSystem hSystemHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemLock(SceNgsHSynSystem hSystemHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemUnlock(SceNgsHSynSystem hSystemHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemSetParamErrorCallback(SceNgsHSynSystem hSystemHandle, const SceNgsParamsErrorCallbackFunc callbackFuncPtr) +{ + throw __FUNCTION__; +} + +s32 sceNgsSystemSetFlags(SceNgsHSynSystem hSystemHandle, const u32 uSystemFlags) +{ + throw __FUNCTION__; +} + +s32 sceNgsRackGetRequiredMemorySize(SceNgsHSynSystem hSystemHandle, vm::psv::ptr pRackDesc, vm::psv::ptr pnSize) +{ + throw __FUNCTION__; +} + +s32 sceNgsRackInit(SceNgsHSynSystem hSystemHandle, vm::psv::ptr pRackBuffer, vm::psv::ptr pRackDesc, vm::psv::ptr pRackHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsRackGetVoiceHandle(SceNgsHRack hRackHandle, const u32 uIndex, vm::psv::ptr pVoiceHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsRackRelease(SceNgsHRack hRackHandle, const SceNgsRackReleaseCallbackFunc callbackFuncPtr) +{ + throw __FUNCTION__; +} + +s32 sceNgsRackSetParamErrorCallback(SceNgsHRack hRackHandle, const SceNgsParamsErrorCallbackFunc callbackFuncPtr) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceInit(SceNgsHVoice hVoiceHandle, vm::psv::ptr pPreset, const u32 uInitFlags) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoicePlay(SceNgsHVoice hVoiceHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceKeyOff(SceNgsHVoice hVoiceHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceKill(SceNgsHVoice hVoiceHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoicePause(SceNgsHVoice hVoiceHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceResume(SceNgsHVoice hVoiceHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceSetPreset(SceNgsHVoice hVoiceHandle, vm::psv::ptr pVoicePreset) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceLockParams(SceNgsHVoice hVoiceHandle, const u32 uModule, const SceNgsParamsID uParamsInterfaceId, vm::psv::ptr pParamsBuffer) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceUnlockParams(SceNgsHVoice hVoiceHandle, const u32 uModule) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceSetParamsBlock(SceNgsHVoice hVoiceHandle, vm::psv::ptr pParamData, const u32 uSize, vm::psv::ptr pnErrorCount) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceBypassModule(SceNgsHVoice hVoiceHandle, const u32 uModule, const u32 uBypassFlag) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceSetModuleCallback(SceNgsHVoice hVoiceHandle, const u32 uModule, const SceNgsModuleCallbackFunc callbackFuncPtr, vm::psv::ptr pUserData) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceSetFinishedCallback(SceNgsHVoice hVoiceHandle, const SceNgsCallbackFunc callbackFuncPtr, vm::psv::ptr pUserData) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceGetStateData(SceNgsHVoice hVoiceHandle, const u32 uModule, vm::psv::ptr pMem, const u32 uMemSize) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceGetInfo(SceNgsHVoice hVoiceHandle, vm::psv::ptr pInfo) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceGetModuleType(SceNgsHVoice hVoiceHandle, const u32 uModule, vm::psv::ptr pModuleType) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceGetModuleBypass(SceNgsHVoice hVoiceHandle, const u32 uModule, vm::psv::ptr puBypassFlag) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceGetParamsOutOfRange(SceNgsHVoice hVoiceHandle, const u32 uModule, vm::psv::ptr pszMessageBuffer) +{ + throw __FUNCTION__; +} + +s32 sceNgsPatchCreateRouting(vm::psv::ptr pPatchInfo, vm::psv::ptr pPatchHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsPatchGetInfo(SceNgsHPatch hPatchHandle, vm::psv::ptr pRouteInfo, vm::psv::ptr pSetup) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoiceGetOutputPatch(SceNgsHVoice hVoiceHandle, const s32 nOutputIndex, const s32 nSubIndex, vm::psv::ptr pPatchHandle) +{ + throw __FUNCTION__; +} + +s32 sceNgsPatchRemoveRouting(SceNgsHPatch hPatchHandle) +{ + throw __FUNCTION__; +} + +//s32 sceNgsVoicePatchSetVolume(SceNgsHPatch hPatchHandle, const s32 nOutputChannel, const s32 nInputChannel, const float fVol) +//{ +// throw __FUNCTION__; +//} + +s32 sceNgsVoicePatchSetVolumes(SceNgsHPatch hPatchHandle, const s32 nOutputChannel, vm::psv::ptr pVolumes, const s32 nVols) +{ + throw __FUNCTION__; +} + +s32 sceNgsVoicePatchSetVolumesMatrix(SceNgsHPatch hPatchHandle, vm::psv::ptr pMatrix) +{ + throw __FUNCTION__; +} + +s32 sceNgsModuleGetNumPresets(SceNgsHSynSystem hSystemHandle, const SceNgsModuleID uModuleID, vm::psv::ptr puNumPresets) +{ + throw __FUNCTION__; +} + +s32 sceNgsModuleGetPreset(SceNgsHSynSystem hSystemHandle, const SceNgsModuleID uModuleID, const u32 uPresetIndex, vm::psv::ptr pParamsBuffer) +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetCompressorBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetCompressorSideChainBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetDelayBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetDistortionBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetEnvelopeBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetEqBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetMasterBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetMixerBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetPauserBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetReverbBuss() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetSasEmuVoice() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetSimpleVoice() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetTemplate1() +{ + throw __FUNCTION__; +} + +vm::psv::ptr sceNgsVoiceDefGetAtrac9Voice() +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsGetDefaultConfig(vm::psv::ptr config) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsGetNeededMemory(vm::psv::ptr config, vm::psv::ptr sizeInBytes) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsInit(vm::psv::ptr config, vm::psv::ptr buffer, u32 sizeInBytes) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsShutdown() +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsSetSynthName(SceNgsHSynSystem synthHandle, vm::psv::ptr name) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsSetRackName(SceNgsHRack rackHandle, vm::psv::ptr name) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsSetVoiceName(SceNgsHVoice voiceHandle, vm::psv::ptr name) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsSetSampleName(vm::psv::ptr location, u32 length, vm::psv::ptr name) +{ + throw __FUNCTION__; +} + +s32 sceSulphaNgsTrace(vm::psv::ptr message) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNgs, #name, name) psv_log_base sceNgs("SceNgs", []() @@ -12,67 +437,67 @@ psv_log_base sceNgs("SceNgs", []() sceNgs.on_unload = nullptr; sceNgs.on_stop = nullptr; - //REG_FUNC(0x6CE8B36F, sceNgsSystemGetRequiredMemorySize); - //REG_FUNC(0xED14CF4A, sceNgsSystemInit); - //REG_FUNC(0x684F080C, sceNgsSystemUpdate); - //REG_FUNC(0x4A25BEBC, sceNgsSystemRelease); - //REG_FUNC(0xB9D971F2, sceNgsSystemLock); - //REG_FUNC(0x0A93EA96, sceNgsSystemUnlock); - //REG_FUNC(0x5ADD22DC, sceNgsSystemSetParamErrorCallback); - //REG_FUNC(0x64D80013, sceNgsSystemSetFlags); - //REG_FUNC(0x477318C0, sceNgsRackGetRequiredMemorySize); - //REG_FUNC(0x0A92E4EC, sceNgsRackInit); - //REG_FUNC(0xFE1A98E9, sceNgsRackGetVoiceHandle); - //REG_FUNC(0xDD5CA10B, sceNgsRackRelease); - //REG_FUNC(0x534B6E3F, sceNgsRackSetParamErrorCallback); - //REG_FUNC(0x1DDBEBEB, sceNgsVoiceInit); - //REG_FUNC(0xFA0A0F34, sceNgsVoicePlay); - //REG_FUNC(0xBB13373D, sceNgsVoiceKeyOff); - //REG_FUNC(0x0E291AAD, sceNgsVoiceKill); - //REG_FUNC(0xD7786E99, sceNgsVoicePause); - //REG_FUNC(0x54CFB981, sceNgsVoiceResume); - //REG_FUNC(0x8A88E665, sceNgsVoiceSetPreset); - //REG_FUNC(0xAB6BEF8F, sceNgsVoiceLockParams); - //REG_FUNC(0x3D46D8A7, sceNgsVoiceUnlockParams); - //REG_FUNC(0xFB8174B1, sceNgsVoiceSetParamsBlock); - //REG_FUNC(0x9AB87E71, sceNgsVoiceBypassModule); - //REG_FUNC(0x24E909A8, sceNgsVoiceSetModuleCallback); - //REG_FUNC(0x17A6F564, sceNgsVoiceSetFinishedCallback); - //REG_FUNC(0xC9B8C0B4, sceNgsVoiceGetStateData); - //REG_FUNC(0x5551410D, sceNgsVoiceGetInfo); - //REG_FUNC(0xB307185E, sceNgsVoiceGetModuleType); - //REG_FUNC(0x431BF3AB, sceNgsVoiceGetModuleBypass); - //REG_FUNC(0xD668B49C, sceNgsPatchCreateRouting); - //REG_FUNC(0x98703DBC, sceNgsPatchGetInfo); - //REG_FUNC(0x01A52E3A, sceNgsVoiceGetOutputPatch); - //REG_FUNC(0xD0C9AE5A, sceNgsPatchRemoveRouting); + REG_FUNC(0x6CE8B36F, sceNgsSystemGetRequiredMemorySize); + REG_FUNC(0xED14CF4A, sceNgsSystemInit); + REG_FUNC(0x684F080C, sceNgsSystemUpdate); + REG_FUNC(0x4A25BEBC, sceNgsSystemRelease); + REG_FUNC(0xB9D971F2, sceNgsSystemLock); + REG_FUNC(0x0A93EA96, sceNgsSystemUnlock); + REG_FUNC(0x5ADD22DC, sceNgsSystemSetParamErrorCallback); + REG_FUNC(0x64D80013, sceNgsSystemSetFlags); + REG_FUNC(0x477318C0, sceNgsRackGetRequiredMemorySize); + REG_FUNC(0x0A92E4EC, sceNgsRackInit); + REG_FUNC(0xFE1A98E9, sceNgsRackGetVoiceHandle); + REG_FUNC(0xDD5CA10B, sceNgsRackRelease); + REG_FUNC(0x534B6E3F, sceNgsRackSetParamErrorCallback); + REG_FUNC(0x1DDBEBEB, sceNgsVoiceInit); + REG_FUNC(0xFA0A0F34, sceNgsVoicePlay); + REG_FUNC(0xBB13373D, sceNgsVoiceKeyOff); + REG_FUNC(0x0E291AAD, sceNgsVoiceKill); + REG_FUNC(0xD7786E99, sceNgsVoicePause); + REG_FUNC(0x54CFB981, sceNgsVoiceResume); + REG_FUNC(0x8A88E665, sceNgsVoiceSetPreset); + REG_FUNC(0xAB6BEF8F, sceNgsVoiceLockParams); + REG_FUNC(0x3D46D8A7, sceNgsVoiceUnlockParams); + REG_FUNC(0xFB8174B1, sceNgsVoiceSetParamsBlock); + REG_FUNC(0x9AB87E71, sceNgsVoiceBypassModule); + REG_FUNC(0x24E909A8, sceNgsVoiceSetModuleCallback); + REG_FUNC(0x17A6F564, sceNgsVoiceSetFinishedCallback); + REG_FUNC(0xC9B8C0B4, sceNgsVoiceGetStateData); + REG_FUNC(0x5551410D, sceNgsVoiceGetInfo); + REG_FUNC(0xB307185E, sceNgsVoiceGetModuleType); + REG_FUNC(0x431BF3AB, sceNgsVoiceGetModuleBypass); + REG_FUNC(0xD668B49C, sceNgsPatchCreateRouting); + REG_FUNC(0x98703DBC, sceNgsPatchGetInfo); + REG_FUNC(0x01A52E3A, sceNgsVoiceGetOutputPatch); + REG_FUNC(0xD0C9AE5A, sceNgsPatchRemoveRouting); //REG_FUNC(0xA3C807BC, sceNgsVoicePatchSetVolume); - //REG_FUNC(0xBD6F57F0, sceNgsVoicePatchSetVolumes); - //REG_FUNC(0xA0F5402D, sceNgsVoicePatchSetVolumesMatrix); - //REG_FUNC(0xF6B68C31, sceNgsVoiceDefGetEnvelopeBuss); - //REG_FUNC(0x9DCF50F5, sceNgsVoiceDefGetReverbBuss); - //REG_FUNC(0x214485D6, sceNgsVoiceDefGetPauserBuss); - //REG_FUNC(0xE0AC8776, sceNgsVoiceDefGetMixerBuss); - //REG_FUNC(0x79A121D1, sceNgsVoiceDefGetMasterBuss); - //REG_FUNC(0x0E0ACB68, sceNgsVoiceDefGetCompressorBuss); - //REG_FUNC(0x1AF83512, sceNgsVoiceDefGetCompressorSideChainBuss); - //REG_FUNC(0xAAD90DEB, sceNgsVoiceDefGetDistortionBuss); - //REG_FUNC(0xF964120E, sceNgsVoiceDefGetEqBuss); - //REG_FUNC(0xE9B572B7, sceNgsVoiceDefGetTemplate1); - //REG_FUNC(0x0D5399CF, sceNgsVoiceDefGetSimpleVoice); - //REG_FUNC(0x1F51C2BA, sceNgsVoiceDefGetSasEmuVoice); - //REG_FUNC(0x4CBE08F3, sceNgsVoiceGetParamsOutOfRange); - //REG_FUNC(0x14EF65A0, sceNgsVoiceDefGetAtrac9Voice); - //REG_FUNC(0x4D705E3E, sceNgsVoiceDefGetDelayBuss); - //REG_FUNC(0x5FD8AEDB, sceSulphaNgsGetDefaultConfig); - //REG_FUNC(0x793E3E8C, sceSulphaNgsGetNeededMemory); - //REG_FUNC(0xAFCD824F, sceSulphaNgsInit); - //REG_FUNC(0xD124BFB1, sceSulphaNgsShutdown); - //REG_FUNC(0x2F3F7515, sceSulphaNgsSetSynthName); - //REG_FUNC(0x251AF6A9, sceSulphaNgsSetRackName); - //REG_FUNC(0x508975BD, sceSulphaNgsSetVoiceName); - //REG_FUNC(0x54EC5B8D, sceSulphaNgsSetSampleName); - //REG_FUNC(0xDC7C0F05, sceSulphaNgsTrace); - //REG_FUNC(0x5C71FE09, sceNgsModuleGetNumPresets); - //REG_FUNC(0xC58298A7, sceNgsModuleGetPreset); + REG_FUNC(0xBD6F57F0, sceNgsVoicePatchSetVolumes); + REG_FUNC(0xA0F5402D, sceNgsVoicePatchSetVolumesMatrix); + REG_FUNC(0xF6B68C31, sceNgsVoiceDefGetEnvelopeBuss); + REG_FUNC(0x9DCF50F5, sceNgsVoiceDefGetReverbBuss); + REG_FUNC(0x214485D6, sceNgsVoiceDefGetPauserBuss); + REG_FUNC(0xE0AC8776, sceNgsVoiceDefGetMixerBuss); + REG_FUNC(0x79A121D1, sceNgsVoiceDefGetMasterBuss); + REG_FUNC(0x0E0ACB68, sceNgsVoiceDefGetCompressorBuss); + REG_FUNC(0x1AF83512, sceNgsVoiceDefGetCompressorSideChainBuss); + REG_FUNC(0xAAD90DEB, sceNgsVoiceDefGetDistortionBuss); + REG_FUNC(0xF964120E, sceNgsVoiceDefGetEqBuss); + REG_FUNC(0xE9B572B7, sceNgsVoiceDefGetTemplate1); + REG_FUNC(0x0D5399CF, sceNgsVoiceDefGetSimpleVoice); + REG_FUNC(0x1F51C2BA, sceNgsVoiceDefGetSasEmuVoice); + REG_FUNC(0x4CBE08F3, sceNgsVoiceGetParamsOutOfRange); + REG_FUNC(0x14EF65A0, sceNgsVoiceDefGetAtrac9Voice); + REG_FUNC(0x4D705E3E, sceNgsVoiceDefGetDelayBuss); + REG_FUNC(0x5FD8AEDB, sceSulphaNgsGetDefaultConfig); + REG_FUNC(0x793E3E8C, sceSulphaNgsGetNeededMemory); + REG_FUNC(0xAFCD824F, sceSulphaNgsInit); + REG_FUNC(0xD124BFB1, sceSulphaNgsShutdown); + REG_FUNC(0x2F3F7515, sceSulphaNgsSetSynthName); + REG_FUNC(0x251AF6A9, sceSulphaNgsSetRackName); + REG_FUNC(0x508975BD, sceSulphaNgsSetVoiceName); + REG_FUNC(0x54EC5B8D, sceSulphaNgsSetSampleName); + REG_FUNC(0xDC7C0F05, sceSulphaNgsTrace); + REG_FUNC(0x5C71FE09, sceNgsModuleGetNumPresets); + REG_FUNC(0xC58298A7, sceNgsModuleGetPreset); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp index 72d81d8e15..96d44a3686 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp @@ -4,6 +4,192 @@ extern psv_log_base sceRtc; +u32 sceRtcGetTickResolution() +{ + throw __FUNCTION__; +} + +s32 sceRtcGetCurrentTick(vm::psv::ptr pTick) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetCurrentClock(vm::psv::ptr pTime, s32 iTimeZone) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetCurrentClockLocalTime(vm::psv::ptr pTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetCurrentNetworkTick(vm::psv::ptr pTick) +{ + throw __FUNCTION__; +} + +s32 sceRtcConvertUtcToLocalTime(vm::psv::ptr pUtc, vm::psv::ptr pLocalTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcConvertLocalTimeToUtc(vm::psv::ptr pLocalTime, vm::psv::ptr pUtc) +{ + throw __FUNCTION__; +} + +s32 sceRtcIsLeapYear(s32 year) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetDaysInMonth(s32 year, s32 month) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetDayOfWeek(s32 year, s32 month, s32 day) +{ + throw __FUNCTION__; +} + +s32 sceRtcCheckValid(vm::psv::ptr pTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcSetTime_t(vm::psv::ptr pTime, time_t iTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcSetTime64_t(vm::psv::ptr pTime, u64 ullTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetTime_t(vm::psv::ptr pTime, vm::psv::ptr piTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetTime64_t(vm::psv::ptr pTime, vm::psv::ptr pullTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcSetDosTime(vm::psv::ptr pTime, u32 uiDosTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetDosTime(vm::psv::ptr pTime, vm::psv::ptr puiDosTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcSetWin32FileTime(vm::psv::ptr pTime, u64 ulWin32Time) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetWin32FileTime(vm::psv::ptr pTime, vm::psv::ptr ulWin32Time) +{ + throw __FUNCTION__; +} + +s32 sceRtcSetTick(vm::psv::ptr pTime, vm::psv::ptr pTick) +{ + throw __FUNCTION__; +} + +s32 sceRtcGetTick(vm::psv::ptr pTime, vm::psv::ptr pTick) +{ + throw __FUNCTION__; +} + +s32 sceRtcCompareTick(vm::psv::ptr pTick1, vm::psv::ptr pTick2) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddTicks(vm::psv::ptr pTick0, vm::psv::ptr pTick1, u64 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddMicroseconds(vm::psv::ptr pTick0, vm::psv::ptr pTick1, u64 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddSeconds(vm::psv::ptr pTick0, vm::psv::ptr pTick1, u64 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddMinutes(vm::psv::ptr pTick0, vm::psv::ptr pTick1, u64 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddHours(vm::psv::ptr pTick0, vm::psv::ptr pTick1, s32 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddDays(vm::psv::ptr pTick0, vm::psv::ptr pTick1, s32 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddWeeks(vm::psv::ptr pTick0, vm::psv::ptr pTick1, s32 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddMonths(vm::psv::ptr pTick0, vm::psv::ptr pTick1, s32 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcTickAddYears(vm::psv::ptr pTick0, vm::psv::ptr pTick1, s32 lAdd) +{ + throw __FUNCTION__; +} + +s32 sceRtcFormatRFC2822(vm::psv::ptr pszDateTime, vm::psv::ptr pUtc, s32 iTimeZoneMinutes) +{ + throw __FUNCTION__; +} + +s32 sceRtcFormatRFC2822LocalTime(vm::psv::ptr pszDateTime, vm::psv::ptr pUtc) +{ + throw __FUNCTION__; +} + +s32 sceRtcFormatRFC3339(vm::psv::ptr pszDateTime, vm::psv::ptr pUtc, s32 iTimeZoneMinutes) +{ + throw __FUNCTION__; +} + +s32 sceRtcFormatRFC3339LocalTime(vm::psv::ptr pszDateTime, vm::psv::ptr pUtc) +{ + throw __FUNCTION__; +} + +s32 sceRtcParseDateTime(vm::psv::ptr pUtc, vm::psv::ptr pszDateTime) +{ + throw __FUNCTION__; +} + +s32 sceRtcParseRFC3339(vm::psv::ptr pUtc, vm::psv::ptr pszDateTime) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceRtc, #name, name) psv_log_base sceRtc("SceRtc", []() @@ -12,41 +198,41 @@ psv_log_base sceRtc("SceRtc", []() sceRtc.on_unload = nullptr; sceRtc.on_stop = nullptr; - //REG_FUNC(0x23F79274, sceRtcGetCurrentTick); - //REG_FUNC(0xCDDD25FE, sceRtcGetCurrentNetworkTick); - //REG_FUNC(0x70FDE8F1, sceRtcGetCurrentClock); - //REG_FUNC(0x0572EDDC, sceRtcGetCurrentClockLocalTime); - //REG_FUNC(0x1282C436, sceRtcConvertUtcToLocalTime); - //REG_FUNC(0x0A05E201, sceRtcConvertLocalTimeToUtc); - //REG_FUNC(0x42CA8EB5, sceRtcFormatRFC2822LocalTime); - //REG_FUNC(0x147F2138, sceRtcFormatRFC2822); - //REG_FUNC(0x742250A9, sceRtcFormatRFC3339LocalTime); - //REG_FUNC(0xCCEA2B54, sceRtcFormatRFC3339); - //REG_FUNC(0xF17FD8B5, sceRtcIsLeapYear); - //REG_FUNC(0x49EB4556, sceRtcGetDaysInMonth); - //REG_FUNC(0x2F3531EB, sceRtcGetDayOfWeek); - //REG_FUNC(0xD7622935, sceRtcCheckValid); - //REG_FUNC(0x3A332F81, sceRtcSetTime_t); - //REG_FUNC(0xA6C36B6A, sceRtcSetTime64_t); - //REG_FUNC(0x8DE6FEB7, sceRtcGetTime_t); - //REG_FUNC(0xC995DE02, sceRtcGetTime64_t); - //REG_FUNC(0xF8B22B07, sceRtcSetDosTime); - //REG_FUNC(0x92ABEBAF, sceRtcGetDosTime); - //REG_FUNC(0xA79A8846, sceRtcSetWin32FileTime); - //REG_FUNC(0x8A95E119, sceRtcGetWin32FileTime); - //REG_FUNC(0x811313B3, sceRtcGetTickResolution); - //REG_FUNC(0xCD89F464, sceRtcSetTick); - //REG_FUNC(0xF2B238E2, sceRtcGetTick); - //REG_FUNC(0xC7385158, sceRtcCompareTick); - //REG_FUNC(0x4559E2DB, sceRtcTickAddTicks); - //REG_FUNC(0xAE26D920, sceRtcTickAddMicroseconds); - //REG_FUNC(0x979AFD79, sceRtcTickAddSeconds); - //REG_FUNC(0x4C358871, sceRtcTickAddMinutes); - //REG_FUNC(0x6F193F55, sceRtcTickAddHours); - //REG_FUNC(0x58DE3C70, sceRtcTickAddDays); - //REG_FUNC(0xE713C640, sceRtcTickAddWeeks); - //REG_FUNC(0x6321B4AA, sceRtcTickAddMonths); - //REG_FUNC(0xDF6C3E1B, sceRtcTickAddYears); - //REG_FUNC(0x2347CE12, sceRtcParseDateTime); - //REG_FUNC(0x2D18AEEC, sceRtcParseRFC3339); + REG_FUNC(0x23F79274, sceRtcGetCurrentTick); + REG_FUNC(0xCDDD25FE, sceRtcGetCurrentNetworkTick); + REG_FUNC(0x70FDE8F1, sceRtcGetCurrentClock); + REG_FUNC(0x0572EDDC, sceRtcGetCurrentClockLocalTime); + REG_FUNC(0x1282C436, sceRtcConvertUtcToLocalTime); + REG_FUNC(0x0A05E201, sceRtcConvertLocalTimeToUtc); + REG_FUNC(0x42CA8EB5, sceRtcFormatRFC2822LocalTime); + REG_FUNC(0x147F2138, sceRtcFormatRFC2822); + REG_FUNC(0x742250A9, sceRtcFormatRFC3339LocalTime); + REG_FUNC(0xCCEA2B54, sceRtcFormatRFC3339); + REG_FUNC(0xF17FD8B5, sceRtcIsLeapYear); + REG_FUNC(0x49EB4556, sceRtcGetDaysInMonth); + REG_FUNC(0x2F3531EB, sceRtcGetDayOfWeek); + REG_FUNC(0xD7622935, sceRtcCheckValid); + REG_FUNC(0x3A332F81, sceRtcSetTime_t); + REG_FUNC(0xA6C36B6A, sceRtcSetTime64_t); + REG_FUNC(0x8DE6FEB7, sceRtcGetTime_t); + REG_FUNC(0xC995DE02, sceRtcGetTime64_t); + REG_FUNC(0xF8B22B07, sceRtcSetDosTime); + REG_FUNC(0x92ABEBAF, sceRtcGetDosTime); + REG_FUNC(0xA79A8846, sceRtcSetWin32FileTime); + REG_FUNC(0x8A95E119, sceRtcGetWin32FileTime); + REG_FUNC(0x811313B3, sceRtcGetTickResolution); + REG_FUNC(0xCD89F464, sceRtcSetTick); + REG_FUNC(0xF2B238E2, sceRtcGetTick); + REG_FUNC(0xC7385158, sceRtcCompareTick); + REG_FUNC(0x4559E2DB, sceRtcTickAddTicks); + REG_FUNC(0xAE26D920, sceRtcTickAddMicroseconds); + REG_FUNC(0x979AFD79, sceRtcTickAddSeconds); + REG_FUNC(0x4C358871, sceRtcTickAddMinutes); + REG_FUNC(0x6F193F55, sceRtcTickAddHours); + REG_FUNC(0x58DE3C70, sceRtcTickAddDays); + REG_FUNC(0xE713C640, sceRtcTickAddWeeks); + REG_FUNC(0x6321B4AA, sceRtcTickAddMonths); + REG_FUNC(0xDF6C3E1B, sceRtcTickAddYears); + REG_FUNC(0x2347CE12, sceRtcParseDateTime); + REG_FUNC(0x2D18AEEC, sceRtcParseRFC3339); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSas.cpp b/rpcs3/Emu/ARMv7/Modules/sceSas.cpp index 0db6b65e16..3d11ff98f1 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSas.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSas.cpp @@ -4,6 +4,152 @@ extern psv_log_base sceSas; +s32 sceSasGetNeededMemorySize(vm::psv::ptr config, vm::psv::ptr outSize) +{ + throw __FUNCTION__; +} + +s32 sceSasInit(vm::psv::ptr config, vm::psv::ptr buffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +s32 sceSasInitWithGrain(vm::psv::ptr config, u32 grain, vm::psv::ptr buffer, u32 bufferSize) +{ + throw __FUNCTION__; +} + +s32 sceSasExit(vm::psv::ptr> outBuffer, vm::psv::ptr outBufferSize) +{ + throw __FUNCTION__; +} + +s32 sceSasSetGrain(u32 grain) +{ + throw __FUNCTION__; +} + +s32 sceSasGetGrain() +{ + throw __FUNCTION__; +} + +s32 sceSasSetOutputmode(u32 outputmode) +{ + throw __FUNCTION__; +} + +s32 sceSasGetOutputmode() +{ + throw __FUNCTION__; +} + +s32 sceSasCore(vm::psv::ptr out) +{ + throw __FUNCTION__; +} + +s32 sceSasCoreWithMix(vm::psv::ptr inOut, s32 lvol, s32 rvol) +{ + throw __FUNCTION__; +} + +s32 sceSasSetVoice(s32 iVoiceNum, vm::psv::ptr vagBuf, u32 size, u32 loopflag) +{ + throw __FUNCTION__; +} + +s32 sceSasSetVoicePCM(s32 iVoiceNum, vm::psv::ptr pcmBuf, u32 size, s32 loopsize) +{ + throw __FUNCTION__; +} + +s32 sceSasSetNoise(s32 iVoiceNum, u32 uClk) +{ + throw __FUNCTION__; +} + +s32 sceSasSetVolume(s32 iVoiceNum, s32 l, s32 r, s32 wl, s32 wr) +{ + throw __FUNCTION__; +} + +s32 sceSasSetPitch(s32 iVoiceNum, s32 pitch) +{ + throw __FUNCTION__; +} + +s32 sceSasSetADSR(s32 iVoiceNum, u32 flag, u32 ar, u32 dr, u32 sr, u32 rr) +{ + throw __FUNCTION__; +} + +s32 sceSasSetADSRmode(s32 iVoiceNum, u32 flag, u32 am, u32 dm, u32 sm, u32 rm) +{ + throw __FUNCTION__; +} + +s32 sceSasSetSL(s32 iVoiceNum, u32 sl) +{ + throw __FUNCTION__; +} + +s32 sceSasSetSimpleADSR(s32 iVoiceNum, u16 adsr1, u16 adsr2) +{ + throw __FUNCTION__; +} + +s32 sceSasSetKeyOn(s32 iVoiceNum) +{ + throw __FUNCTION__; +} + +s32 sceSasSetKeyOff(s32 iVoiceNum) +{ + throw __FUNCTION__; +} + +s32 sceSasSetPause(s32 iVoiceNum, u32 pauseFlag) +{ + throw __FUNCTION__; +} + +s32 sceSasGetPauseState(s32 iVoiceNum) +{ + throw __FUNCTION__; +} + +s32 sceSasGetEndState(s32 iVoiceNum) +{ + throw __FUNCTION__; +} + +s32 sceSasGetEnvelope(s32 iVoiceNum) +{ + throw __FUNCTION__; +} + +s32 sceSasSetEffect(s32 drySwitch, s32 wetSwitch) +{ + throw __FUNCTION__; +} + +s32 sceSasSetEffectType(s32 type) +{ + throw __FUNCTION__; +} + +s32 sceSasSetEffectVolume(s32 valL, s32 valR) +{ + throw __FUNCTION__; +} + +s32 sceSasSetEffectParam(u32 delayTime, u32 feedback) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceSas, #name, name) psv_log_base sceSas("SceSas", []() @@ -28,36 +174,36 @@ psv_log_base sceSas("SceSas", []() //REG_FUNC(0xC72F1EEF, sceAsRender); //REG_FUNC(0xCE23F057, sceAsLockUpdate); //REG_FUNC(0x8BEF3C92, sceAsUnlockUpdate); - //REG_FUNC(0x180C6824, sceSasGetNeededMemorySize); - //REG_FUNC(0x449B5974, sceSasInit); - //REG_FUNC(0x820D5F82, sceSasInitWithGrain); - //REG_FUNC(0xBB7D6790, sceSasExit); - //REG_FUNC(0x2B4A207C, sceSasSetGrain); - //REG_FUNC(0x2BEA45BC, sceSasGetGrain); - //REG_FUNC(0x44DDB3C4, sceSasSetOutputmode); - //REG_FUNC(0x2C36E150, sceSasGetOutputmode); - //REG_FUNC(0x7A4672B2, sceSasCore); - //REG_FUNC(0xBD496983, sceSasCoreWithMix); - //REG_FUNC(0x2B75F9BC, sceSasSetVoice); - //REG_FUNC(0xB1756EFC, sceSasSetVoicePCM); - //REG_FUNC(0xF1C63CB9, sceSasSetNoise); - //REG_FUNC(0x0BE8204D, sceSasSetVolume); + REG_FUNC(0x180C6824, sceSasGetNeededMemorySize); + REG_FUNC(0x449B5974, sceSasInit); + REG_FUNC(0x820D5F82, sceSasInitWithGrain); + REG_FUNC(0xBB7D6790, sceSasExit); + REG_FUNC(0x2B4A207C, sceSasSetGrain); + REG_FUNC(0x2BEA45BC, sceSasGetGrain); + REG_FUNC(0x44DDB3C4, sceSasSetOutputmode); + REG_FUNC(0x2C36E150, sceSasGetOutputmode); + REG_FUNC(0x7A4672B2, sceSasCore); + REG_FUNC(0xBD496983, sceSasCoreWithMix); + REG_FUNC(0x2B75F9BC, sceSasSetVoice); + REG_FUNC(0xB1756EFC, sceSasSetVoicePCM); + REG_FUNC(0xF1C63CB9, sceSasSetNoise); + REG_FUNC(0x0BE8204D, sceSasSetVolume); //REG_FUNC(0x011788BE, sceSasSetDistortion); - //REG_FUNC(0x2C48A08C, sceSasSetPitch); - //REG_FUNC(0x18A5EFA2, sceSasSetADSR); - //REG_FUNC(0x5207F9D2, sceSasSetADSRmode); - //REG_FUNC(0xDE6227B8, sceSasSetSL); - //REG_FUNC(0xECCE0DB8, sceSasSetSimpleADSR); - //REG_FUNC(0xC838DB6F, sceSasSetKeyOn); - //REG_FUNC(0x5E42ADAB, sceSasSetKeyOff); - //REG_FUNC(0x59C7A9DF, sceSasSetPause); - //REG_FUNC(0x007E63E6, sceSasGetEndState); - //REG_FUNC(0xFD1A0CBF, sceSasGetPauseState); - //REG_FUNC(0x296A9910, sceSasGetEnvelope); - //REG_FUNC(0xB0444E69, sceSasSetEffect); - //REG_FUNC(0xCDF2DDD5, sceSasSetEffectType); - //REG_FUNC(0x55EDDBFA, sceSasSetEffectVolume); - //REG_FUNC(0xBAD546A0, sceSasSetEffectParam); + REG_FUNC(0x2C48A08C, sceSasSetPitch); + REG_FUNC(0x18A5EFA2, sceSasSetADSR); + REG_FUNC(0x5207F9D2, sceSasSetADSRmode); + REG_FUNC(0xDE6227B8, sceSasSetSL); + REG_FUNC(0xECCE0DB8, sceSasSetSimpleADSR); + REG_FUNC(0xC838DB6F, sceSasSetKeyOn); + REG_FUNC(0x5E42ADAB, sceSasSetKeyOff); + REG_FUNC(0x59C7A9DF, sceSasSetPause); + REG_FUNC(0x007E63E6, sceSasGetEndState); + REG_FUNC(0xFD1A0CBF, sceSasGetPauseState); + REG_FUNC(0x296A9910, sceSasGetEnvelope); + REG_FUNC(0xB0444E69, sceSasSetEffect); + REG_FUNC(0xCDF2DDD5, sceSasSetEffectType); + REG_FUNC(0x55EDDBFA, sceSasSetEffectVolume); + REG_FUNC(0xBAD546A0, sceSasSetEffectParam); //REG_FUNC(0xB6642276, sceSasGetDryPeak); //REG_FUNC(0x4314F0E9, sceSasGetWetPeak); //REG_FUNC(0x1568017A, sceSasGetPreMasterPeak); diff --git a/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp b/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp index b70a5a27c4..0e894f79fb 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSystemGesture.cpp @@ -2,8 +2,250 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceTouch.h" + extern psv_log_base sceSystemGesture; +enum SceSystemGestureTouchState : s32 +{ + SCE_SYSTEM_GESTURE_TOUCH_STATE_INACTIVE = 0, + SCE_SYSTEM_GESTURE_TOUCH_STATE_BEGIN = 1, + SCE_SYSTEM_GESTURE_TOUCH_STATE_ACTIVE = 2, + SCE_SYSTEM_GESTURE_TOUCH_STATE_END = 3 +}; + +enum SceSystemGestureType : s32 +{ + SCE_SYSTEM_GESTURE_TYPE_TAP = 1, + SCE_SYSTEM_GESTURE_TYPE_DRAG = 2, + SCE_SYSTEM_GESTURE_TYPE_TAP_AND_HOLD = 4, + SCE_SYSTEM_GESTURE_TYPE_PINCH_OUT_IN = 8 +}; + +struct SceSystemGestureVector2 +{ + s16 x; + s16 y; +}; + +struct SceSystemGestureRectangle +{ + s16 x; + s16 y; + s16 width; + s16 height; +}; + +struct SceSystemGesturePrimitiveTouchEvent +{ + SceSystemGestureTouchState eventState; + u16 primitiveID; + SceSystemGestureVector2 pressedPosition; + s16 pressedForce; + SceSystemGestureVector2 currentPosition; + s16 currentForce; + SceSystemGestureVector2 deltaVector; + s16 deltaForce; + u64 deltaTime; + u64 elapsedTime; + u8 reserved[56]; +}; + +struct SceSystemGesturePrimitiveTouchRecognizerParameter +{ + u8 reserved[64]; +}; + +struct SceSystemGestureTouchRecognizer +{ + u64 reserved[307]; +}; + +struct SceSystemGestureTouchRecognizerInformation +{ + SceSystemGestureType gestureType; + u32 touchPanelPortID; + SceSystemGestureRectangle rectangle; + u64 updatedTime; + u8 reserved[256]; +}; + +struct SceSystemGestureTapRecognizerParameter +{ + u8 maxTapCount; + u8 reserved[63]; +}; + +struct SceSystemGestureDragRecognizerParameter +{ + u8 reserved[64]; +}; + +struct SceSystemGestureTapAndHoldRecognizerParameter +{ + u64 timeToInvokeEvent; + u8 reserved[56]; +}; + +struct SceSystemGesturePinchOutInRecognizerParameter +{ + u8 reserved[64]; +}; + +union SceSystemGestureTouchRecognizerParameter +{ + u8 parameterBuf[64]; + SceSystemGestureTapRecognizerParameter tap; + SceSystemGestureDragRecognizerParameter drag; + SceSystemGestureTapAndHoldRecognizerParameter tapAndHold; + SceSystemGesturePinchOutInRecognizerParameter pinchOutIn; +}; + +struct SceSystemGestureTapEventProperty +{ + u16 primitiveID; + SceSystemGestureVector2 position; + u8 tappedCount; + u8 reserved[57]; +}; + +struct SceSystemGestureDragEventProperty +{ + u16 primitiveID; + SceSystemGestureVector2 deltaVector; + SceSystemGestureVector2 currentPosition; + SceSystemGestureVector2 pressedPosition; + u8 reserved[50]; +}; + +struct SceSystemGestureTapAndHoldEventProperty +{ + u16 primitiveID; + SceSystemGestureVector2 pressedPosition; + u8 reserved[58]; +}; + +struct SceSystemGesturePinchOutInEventProperty +{ + float scale; + + struct + { + u16 primitiveID; + SceSystemGestureVector2 currentPosition; + SceSystemGestureVector2 deltaVector; + SceSystemGestureVector2 pairedPosition; + } primitive[2]; + + u8 reserved[32]; +}; + +struct SceSystemGestureTouchEvent +{ + u32 eventID; + SceSystemGestureTouchState eventState; + SceSystemGestureType gestureType; + u8 padding[4]; + u64 updatedTime; + + union + { + u8 propertyBuf[64]; + SceSystemGestureTapEventProperty tap; + SceSystemGestureDragEventProperty drag; + SceSystemGestureTapAndHoldEventProperty tapAndHold; + SceSystemGesturePinchOutInEventProperty pinchOutIn; + } property; + + u8 reserved[56]; +}; + +s32 sceSystemGestureInitializePrimitiveTouchRecognizer(vm::psv::ptr parameter) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureFinalizePrimitiveTouchRecognizer() +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureResetPrimitiveTouchRecognizer() +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureUpdatePrimitiveTouchRecognizer(vm::psv::ptr pFrontData, vm::psv::ptr pBackData) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetPrimitiveTouchEvents(vm::psv::ptr primitiveEventBuffer, const u32 capacityOfBuffer, vm::psv::ptr numberOfEvent) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetPrimitiveTouchEventsCount() +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetPrimitiveTouchEventByIndex(const u32 index, vm::psv::ptr primitiveTouchEvent) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetPrimitiveTouchEventByPrimitiveID(const u16 primitiveID, vm::psv::ptr primitiveTouchEvent) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureCreateTouchRecognizer(vm::psv::ptr touchRecognizer, const SceSystemGestureType gestureType, const u8 touchPanelPortID, vm::psv::ptr rectangle, vm::psv::ptr touchRecognizerParameter) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetTouchRecognizerInformation(vm::psv::ptr touchRecognizer, vm::psv::ptr information) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureResetTouchRecognizer(vm::psv::ptr touchRecognizer) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureUpdateTouchRecognizer(vm::psv::ptr touchRecognizer) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureUpdateTouchRecognizerRectangle(vm::psv::ptr touchRecognizer, vm::psv::ptr rectangle) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetTouchEvents(vm::psv::ptr touchRecognizer, vm::psv::ptr eventBuffer, const u32 capacityOfBuffer, vm::psv::ptr numberOfEvent) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetTouchEventsCount(vm::psv::ptr touchRecognizer) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetTouchEventByIndex(vm::psv::ptr touchRecognizer, const u32 index, vm::psv::ptr touchEvent) +{ + throw __FUNCTION__; +} + +s32 sceSystemGestureGetTouchEventByEventID(vm::psv::ptr touchRecognizer, const u32 eventID, vm::psv::ptr touchEvent) +{ + throw __FUNCTION__; +} + + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceSystemGesture, #name, name) psv_log_base sceSystemGesture("SceSystemGesture", []() @@ -12,21 +254,21 @@ psv_log_base sceSystemGesture("SceSystemGesture", []() sceSystemGesture.on_unload = nullptr; sceSystemGesture.on_stop = nullptr; - //REG_FUNC(0x6078A08B, sceSystemGestureInitializePrimitiveTouchRecognizer); - //REG_FUNC(0xFD5A6504, sceSystemGestureResetPrimitiveTouchRecognizer); - //REG_FUNC(0xB3875104, sceSystemGestureFinalizePrimitiveTouchRecognizer); - //REG_FUNC(0xDF4C665A, sceSystemGestureUpdatePrimitiveTouchRecognizer); - //REG_FUNC(0xC750D3DA, sceSystemGestureGetPrimitiveTouchEvents); - //REG_FUNC(0xBAB8ECCB, sceSystemGestureGetPrimitiveTouchEventsCount); - //REG_FUNC(0xE0577765, sceSystemGestureGetPrimitiveTouchEventByIndex); - //REG_FUNC(0x480564C9, sceSystemGestureGetPrimitiveTouchEventByPrimitiveID); - //REG_FUNC(0xC3367370, sceSystemGestureCreateTouchRecognizer); - //REG_FUNC(0xF0DB1AE5, sceSystemGestureGetTouchRecognizerInformation); - //REG_FUNC(0x0D941B90, sceSystemGestureResetTouchRecognizer); - //REG_FUNC(0x851FB144, sceSystemGestureUpdateTouchRecognizer); - //REG_FUNC(0xA9DB29F6, sceSystemGestureUpdateTouchRecognizerRectangle); - //REG_FUNC(0x789D867C, sceSystemGestureGetTouchEvents); - //REG_FUNC(0x13AD2218, sceSystemGestureGetTouchEventsCount); - //REG_FUNC(0x74724147, sceSystemGestureGetTouchEventByIndex); - //REG_FUNC(0x5570B83E, sceSystemGestureGetTouchEventByEventID); + REG_FUNC(0x6078A08B, sceSystemGestureInitializePrimitiveTouchRecognizer); + REG_FUNC(0xFD5A6504, sceSystemGestureResetPrimitiveTouchRecognizer); + REG_FUNC(0xB3875104, sceSystemGestureFinalizePrimitiveTouchRecognizer); + REG_FUNC(0xDF4C665A, sceSystemGestureUpdatePrimitiveTouchRecognizer); + REG_FUNC(0xC750D3DA, sceSystemGestureGetPrimitiveTouchEvents); + REG_FUNC(0xBAB8ECCB, sceSystemGestureGetPrimitiveTouchEventsCount); + REG_FUNC(0xE0577765, sceSystemGestureGetPrimitiveTouchEventByIndex); + REG_FUNC(0x480564C9, sceSystemGestureGetPrimitiveTouchEventByPrimitiveID); + REG_FUNC(0xC3367370, sceSystemGestureCreateTouchRecognizer); + REG_FUNC(0xF0DB1AE5, sceSystemGestureGetTouchRecognizerInformation); + REG_FUNC(0x0D941B90, sceSystemGestureResetTouchRecognizer); + REG_FUNC(0x851FB144, sceSystemGestureUpdateTouchRecognizer); + REG_FUNC(0xA9DB29F6, sceSystemGestureUpdateTouchRecognizerRectangle); + REG_FUNC(0x789D867C, sceSystemGestureGetTouchEvents); + REG_FUNC(0x13AD2218, sceSystemGestureGetTouchEventsCount); + REG_FUNC(0x74724147, sceSystemGestureGetTouchEventByIndex); + REG_FUNC(0x5570B83E, sceSystemGestureGetTouchEventByEventID); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp b/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp index ee13162e61..b6ce6ccc77 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceTouch.cpp @@ -2,40 +2,7 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" -extern psv_log_base sceTouch; - -struct SceTouchPanelInfo -{ - s16 minAaX; - s16 minAaY; - s16 maxAaX; - s16 maxAaY; - s16 minDispX; - s16 minDispY; - s16 maxDispX; - s16 maxDispY; - u8 minForce; - u8 maxForce; - u8 rsv[30]; -}; - -struct SceTouchReport -{ - u8 id; - u8 force; - s16 x; - s16 y; - s8 rsv[8]; - u16 info; -}; - -struct SceTouchData -{ - u64 timeStamp; - u32 status; - u32 reportNum; - SceTouchReport report[8]; -}; +#include "sceTouch.h" s32 sceTouchGetPanelInfo(u32 port, vm::psv::ptr pPanelInfo) { diff --git a/rpcs3/Emu/ARMv7/Modules/sceTouch.h b/rpcs3/Emu/ARMv7/Modules/sceTouch.h new file mode 100644 index 0000000000..a71f6003c2 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceTouch.h @@ -0,0 +1,36 @@ +#pragma once + +struct SceTouchPanelInfo +{ + s16 minAaX; + s16 minAaY; + s16 maxAaX; + s16 maxAaY; + s16 minDispX; + s16 minDispY; + s16 maxDispX; + s16 maxDispY; + u8 minForce; + u8 maxForce; + u8 rsv[30]; +}; + +struct SceTouchReport +{ + u8 id; + u8 force; + s16 x; + s16 y; + s8 rsv[8]; + u16 info; +}; + +struct SceTouchData +{ + u64 timeStamp; + u32 status; + u32 reportNum; + SceTouchReport report[8]; +}; + +extern psv_log_base sceTouch; diff --git a/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp b/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp index cb0cfc8f53..cddc5f43d2 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceVoice.cpp @@ -174,7 +174,7 @@ s32 sceVoiceDeletePort(u32 portId) throw __FUNCTION__; } -s32 sceVoiceWriteToIPort(u32 ips, vm::psv::ptr data, vm::psv::ptr size, int16_t frameGaps) +s32 sceVoiceWriteToIPort(u32 ips, vm::psv::ptr data, vm::psv::ptr size, s16 frameGaps) { throw __FUNCTION__; } diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index ead6e577a0..0c588cd7ee 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -108,6 +108,8 @@ namespace vm AT m_addr; public: + static_assert(!std::is_pointer::value, "vm::_ptr_base<> error: invalid type (pointer)"); + static_assert(!std::is_reference::value, "vm::_ptr_base<> error: invalid type (reference)"); typedef typename std::remove_cv::type type; __forceinline static const u32 data_size() diff --git a/rpcs3/Emu/SysCalls/Modules/sceNp.h b/rpcs3/Emu/SysCalls/Modules/sceNp.h index ddce57f3dd..35be94177a 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNp.h +++ b/rpcs3/Emu/SysCalls/Modules/sceNp.h @@ -1957,7 +1957,7 @@ struct SceNpScoreClanRankData CellRtcTick recordDate; SceNpId npId; SceNpOnlineName onlineName; - uint8_t reserved[32]; + u8 reserved[32]; }; // Clan ranking information to be obtained for a specified clan ID diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpClans.h b/rpcs3/Emu/SysCalls/Modules/sceNpClans.h index faf47e3062..d870d5bd07 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpClans.h +++ b/rpcs3/Emu/SysCalls/Modules/sceNpClans.h @@ -109,7 +109,7 @@ enum // Request handle for clan API struct SceNpClansRequest; -typedef SceNpClansRequest* SceNpClansRequestHandle; +typedef vm::ptr SceNpClansRequestHandle; // Paging request structure struct SceNpClansPagingRequest diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 69cbaaf944..1e6d47a50e 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -341,6 +341,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 7935e1ddc6..ac1531ee30 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1498,5 +1498,8 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + \ No newline at end of file From bdd458d2ae1bbd029eca9a116eb3de5618f2ad99 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 20:19:11 +0300 Subject: [PATCH 40/94] Some functions added --- rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp | 242 +++- rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp | 79 +- rpcs3/Emu/ARMv7/Modules/sceNpCommon.h | 154 +++ rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp | 79 +- rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp | 1360 ++++++++++++++++++++- rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp | 387 +++++- rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp | 172 ++- rpcs3/Emu/ARMv7/Modules/sceUlt.cpp | 643 +++++++++- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 10 files changed, 2946 insertions(+), 174 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/sceNpCommon.h diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp index 1afa85a9cc..e798df5f48 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNpBasic.cpp @@ -1,9 +1,213 @@ -#include "stdafx.h" +#include "stdafx.h" #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceNpCommon.h" + extern psv_log_base sceNpBasic; +enum SceNpBasicFriendListEventType : s32 +{ + SCE_NP_BASIC_FRIEND_LIST_EVENT_TYPE_SYNC = 1, + SCE_NP_BASIC_FRIEND_LIST_EVENT_TYPE_SYNC_DONE = 2, + SCE_NP_BASIC_FRIEND_LIST_EVENT_TYPE_ADDED = 3, + SCE_NP_BASIC_FRIEND_LIST_EVENT_TYPE_DELETED = 4 +}; + +typedef vm::psv::ptr friendId, vm::psv::ptr userdata)> SceNpBasicFriendListEventHandler; + +enum SceNpBasicFriendOnlineStatusEventType : s32 +{ + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_EVENT_TYPE_SYNC = 1, + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_EVENT_TYPE_SYNC_DONE = 2, + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_EVENT_TYPE_UPDATED = 3 +}; + +enum SceNpBasicFriendOnlineStatus : s32 +{ + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_UNKNOWN = 0, + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_OFFLINE = 1, + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_STANDBY = 2, + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_ONLINE_OUT_OF_CONTEXT = 3, + SCE_NP_BASIC_FRIEND_ONLINE_STATUS_ONLINE_IN_CONTEXT = 4 +}; + +typedef vm::psv::ptr friendId, SceNpBasicFriendOnlineStatus status, vm::psv::ptr userdata)> SceNpBasicFriendOnlineStatusEventHandler; + +enum SceNpBasicBlockListEventType : s32 +{ + SCE_NP_BASIC_BLOCK_LIST_EVENT_TYPE_SYNC = 1, + SCE_NP_BASIC_BLOCK_LIST_EVENT_TYPE_SYNC_DONE = 2, + SCE_NP_BASIC_BLOCK_LIST_EVENT_TYPE_ADDED = 3, + SCE_NP_BASIC_BLOCK_LIST_EVENT_TYPE_DELETED = 4 +}; + +typedef vm::psv::ptr playerId, vm::psv::ptr userdata)> SceNpBasicBlockListEventHandler; + +enum SceNpBasicFriendGamePresenceEventType : s32 +{ + SCE_NP_BASIC_FRIEND_GAME_PRESENCE_EVENT_TYPE_SYNC = 1, + SCE_NP_BASIC_FRIEND_GAME_PRESENCE_EVENT_TYPE_SYNC_DONE = 2, + SCE_NP_BASIC_FRIEND_GAME_PRESENCE_EVENT_TYPE_UPDATED = 3 +}; + +enum SceNpBasicInGamePresenceType +{ + SCE_NP_BASIC_IN_GAME_PRESENCE_TYPE_UNKNOWN = -1, + SCE_NP_BASIC_IN_GAME_PRESENCE_TYPE_NONE = 0, + SCE_NP_BASIC_IN_GAME_PRESENCE_TYPE_DEFAULT = 1, + SCE_NP_BASIC_IN_GAME_PRESENCE_TYPE_JOINABLE = 2, + SCE_NP_BASIC_IN_GAME_PRESENCE_TYPE_MAX = 3 +}; + +struct SceNpBasicInGamePresence +{ + u32 sdkVersion; + SceNpBasicInGamePresenceType type; + char status[192]; + u8 data[128]; + u32 dataSize; +}; + +struct SceNpBasicGamePresence +{ + u32 size; + char title[128]; + SceNpBasicInGamePresence inGamePresence; +}; + +typedef vm::psv::ptr friendId, vm::psv::ptr presence, vm::psv::ptr userdata)> SceNpBasicFriendGamePresenceEventHandler; + +struct SceNpBasicInGameDataMessage +{ + u8 data[128]; + u32 dataSize; +}; + +typedef vm::psv::ptr from, vm::psv::ptr message, vm::psv::ptr userdata)> SceNpBasicInGameDataMessageEventHandler; + +struct SceNpBasicEventHandlers +{ + u32 sdkVersion; + SceNpBasicFriendListEventHandler friendListEventHandler; + SceNpBasicFriendOnlineStatusEventHandler friendOnlineStatusEventHandler; + SceNpBasicBlockListEventHandler blockListEventHandler; + SceNpBasicFriendGamePresenceEventHandler friendGamePresenceEventHandler; + SceNpBasicInGameDataMessageEventHandler inGameDataMessageEventHandler; +}; + +struct SceNpBasicPlaySessionLogDescription +{ + char text[512]; +}; + +struct SceNpBasicPlaySessionLog +{ + u64 date; + SceNpId withWhom; + SceNpCommunicationId commId; + char title[128]; + SceNpBasicPlaySessionLogDescription description; +}; + +enum SceNpBasicPlaySessionLogType : s32 +{ + SCE_NP_BASIC_PLAY_SESSION_LOG_TYPE_INVALID = -1, + SCE_NP_BASIC_PLAY_SESSION_LOG_TYPE_ALL = 0, + SCE_NP_BASIC_PLAY_SESSION_LOG_TYPE_BY_NP_COMM_ID = 1, + SCE_NP_BASIC_PLAY_SESSION_LOG_TYPE_MAX = 2 +}; + +s32 sceNpBasicInit(vm::psv::ptr opt) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicTerm(ARMv7Context&) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicRegisterHandler(vm::psv::ptr handlers, vm::psv::ptr context, vm::psv::ptr userdata) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicUnregisterHandler(ARMv7Context&) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicCheckCallback() +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetFriendOnlineStatus(vm::psv::ptr friendId, vm::psv::ptr status) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetGamePresenceOfFriend(vm::psv::ptr friendId, vm::psv::ptr presence) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetFriendListEntryCount(vm::psv::ptr count) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetFriendListEntries(u32 startIndex, vm::psv::ptr entries, u32 numEntries, vm::psv::ptr retrieved) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetBlockListEntryCount(vm::psv::ptr count) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetBlockListEntries(u32 startIndex, vm::psv::ptr entries, u32 numEntries, vm::psv::ptr retrieved) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicCheckIfPlayerIsBlocked(vm::psv::ptr player, vm::psv::ptr playerIsBlocked) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicSetInGamePresence(vm::psv::ptr presence) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicUnsetInGamePresence() +{ + throw __FUNCTION__; +} + +s32 sceNpBasicSendInGameDataMessage(vm::psv::ptr to, vm::psv::ptr message) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicRecordPlaySessionLog(vm::psv::ptr withWhom, vm::psv::ptr description) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetPlaySessionLogSize(SceNpBasicPlaySessionLogType type, vm::psv::ptr size) +{ + throw __FUNCTION__; +} + +s32 sceNpBasicGetPlaySessionLog(SceNpBasicPlaySessionLogType type, u32 index, vm::psv::ptr log) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpBasic, #name, name) psv_log_base sceNpBasic("SceNpBasic", []() @@ -12,22 +216,22 @@ psv_log_base sceNpBasic("SceNpBasic", []() sceNpBasic.on_unload = nullptr; sceNpBasic.on_stop = nullptr; - //REG_FUNC(0xEFB91A99, sceNpBasicInit); - //REG_FUNC(0x389BCB3B, sceNpBasicTerm); - //REG_FUNC(0x26E6E048, sceNpBasicRegisterHandler); - //REG_FUNC(0x050AE072, sceNpBasicUnregisterHandler); - //REG_FUNC(0x20146AEC, sceNpBasicCheckCallback); - //REG_FUNC(0x5183A4B5, sceNpBasicGetFriendOnlineStatus); - //REG_FUNC(0xEF8A91BC, sceNpBasicGetGamePresenceOfFriend); - //REG_FUNC(0xDF41F308, sceNpBasicGetFriendListEntryCount); - //REG_FUNC(0xFF07E787, sceNpBasicGetFriendListEntries); - //REG_FUNC(0x407E1E6F, sceNpBasicGetBlockListEntryCount); - //REG_FUNC(0x1211AE8E, sceNpBasicGetBlockListEntries); - //REG_FUNC(0xF51545D8, sceNpBasicCheckIfPlayerIsBlocked); - //REG_FUNC(0x51D75562, sceNpBasicSetInGamePresence); - //REG_FUNC(0xD20C2370, sceNpBasicUnsetInGamePresence); - //REG_FUNC(0x7A5020A5, sceNpBasicSendInGameDataMessage); - //REG_FUNC(0x3B0A7F47, sceNpBasicRecordPlaySessionLog); - //REG_FUNC(0xFB0F7FDF, sceNpBasicGetPlaySessionLogSize); - //REG_FUNC(0x364531A8, sceNpBasicGetPlaySessionLog); + REG_FUNC(0xEFB91A99, sceNpBasicInit); + REG_FUNC(0x389BCB3B, sceNpBasicTerm); + REG_FUNC(0x26E6E048, sceNpBasicRegisterHandler); + REG_FUNC(0x050AE072, sceNpBasicUnregisterHandler); + REG_FUNC(0x20146AEC, sceNpBasicCheckCallback); + REG_FUNC(0x5183A4B5, sceNpBasicGetFriendOnlineStatus); + REG_FUNC(0xEF8A91BC, sceNpBasicGetGamePresenceOfFriend); + REG_FUNC(0xDF41F308, sceNpBasicGetFriendListEntryCount); + REG_FUNC(0xFF07E787, sceNpBasicGetFriendListEntries); + REG_FUNC(0x407E1E6F, sceNpBasicGetBlockListEntryCount); + REG_FUNC(0x1211AE8E, sceNpBasicGetBlockListEntries); + REG_FUNC(0xF51545D8, sceNpBasicCheckIfPlayerIsBlocked); + REG_FUNC(0x51D75562, sceNpBasicSetInGamePresence); + REG_FUNC(0xD20C2370, sceNpBasicUnsetInGamePresence); + REG_FUNC(0x7A5020A5, sceNpBasicSendInGameDataMessage); + REG_FUNC(0x3B0A7F47, sceNpBasicRecordPlaySessionLog); + REG_FUNC(0xFB0F7FDF, sceNpBasicGetPlaySessionLogSize); + REG_FUNC(0x364531A8, sceNpBasicGetPlaySessionLog); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp index 4422bee950..095de28b17 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.cpp @@ -2,7 +2,62 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" -extern psv_log_base sceNpCommon; +#include "sceNpCommon.h" + +s32 sceNpAuthInit() +{ + throw __FUNCTION__; +} + +s32 sceNpAuthTerm() +{ + throw __FUNCTION__; +} + +s32 sceNpAuthCreateStartRequest(vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceNpAuthDestroyRequest(SceNpAuthRequestId id) +{ + throw __FUNCTION__; +} + +s32 sceNpAuthAbortRequest(SceNpAuthRequestId id) +{ + throw __FUNCTION__; +} + +s32 sceNpAuthGetTicket(SceNpAuthRequestId id, vm::psv::ptr buf, u32 len) +{ + throw __FUNCTION__; +} + +s32 sceNpAuthGetTicketParam(vm::psv::ptr ticket, u32 ticketSize, s32 paramId, vm::psv::ptr param) +{ + throw __FUNCTION__; +} + +s32 sceNpAuthGetEntitlementIdList(vm::psv::ptr ticket, u32 ticketSize, vm::psv::ptr entIdList, u32 entIdListNum) +{ + throw __FUNCTION__; +} + +s32 sceNpAuthGetEntitlementById(vm::psv::ptr ticket, u32 ticketSize, vm::psv::ptr entId, vm::psv::ptr ent) +{ + throw __FUNCTION__; +} + +s32 sceNpCmpNpId(vm::psv::ptr npid1, vm::psv::ptr npid2) +{ + throw __FUNCTION__; +} + +s32 sceNpCmpNpIdInOrder(vm::psv::ptr npid1, vm::psv::ptr npid2, vm::psv::ptr order) +{ + throw __FUNCTION__; +} #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpCommon, #name, name) @@ -12,15 +67,15 @@ psv_log_base sceNpCommon("SceNpCommon", []() sceNpCommon.on_unload = nullptr; sceNpCommon.on_stop = nullptr; - //REG_FUNC(0x441D8B4E, sceNpAuthInit); - //REG_FUNC(0x6093B689, sceNpAuthTerm); - //REG_FUNC(0xED42079F, sceNpAuthCreateStartRequest); - //REG_FUNC(0x14FC18AF, sceNpAuthDestroyRequest); - //REG_FUNC(0xE2582575, sceNpAuthAbortRequest); - //REG_FUNC(0x59608D1C, sceNpAuthGetTicket); - //REG_FUNC(0xC1E23E01, sceNpAuthGetTicketParam); - //REG_FUNC(0x3377CD37, sceNpAuthGetEntitlementIdList); - //REG_FUNC(0xF93842F0, sceNpAuthGetEntitlementById); - //REG_FUNC(0xFB8D82E5, sceNpCmpNpId); - //REG_FUNC(0x6BC8150A, sceNpCmpNpIdInOrder); + REG_FUNC(0x441D8B4E, sceNpAuthInit); + REG_FUNC(0x6093B689, sceNpAuthTerm); + REG_FUNC(0xED42079F, sceNpAuthCreateStartRequest); + REG_FUNC(0x14FC18AF, sceNpAuthDestroyRequest); + REG_FUNC(0xE2582575, sceNpAuthAbortRequest); + REG_FUNC(0x59608D1C, sceNpAuthGetTicket); + REG_FUNC(0xC1E23E01, sceNpAuthGetTicketParam); + REG_FUNC(0x3377CD37, sceNpAuthGetEntitlementIdList); + REG_FUNC(0xF93842F0, sceNpAuthGetEntitlementById); + REG_FUNC(0xFB8D82E5, sceNpCmpNpId); + REG_FUNC(0x6BC8150A, sceNpCmpNpIdInOrder); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h new file mode 100644 index 0000000000..2a40b7aee3 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h @@ -0,0 +1,154 @@ +#pragma once + +enum SceNpServiceState : s32 +{ + SCE_NP_SERVICE_STATE_UNKNOWN = 0, + SCE_NP_SERVICE_STATE_SIGNED_OUT, + SCE_NP_SERVICE_STATE_SIGNED_IN, + SCE_NP_SERVICE_STATE_ONLINE +}; + +struct SceNpCommunicationId +{ + char data[9]; + char term; + u8 num; + char dummy; +}; + +struct SceNpCommunicationPassphrase +{ + u8 data[128]; +}; + +struct SceNpCommunicationSignature +{ + u8 data[160]; +}; + +struct SceNpCommunicationConfig +{ + vm::psv::ptr commId; + vm::psv::ptr commPassphrase; + vm::psv::ptr commSignature; +}; + +struct SceNpCountryCode +{ + char data[2]; + char term; + char padding[1]; +}; + +struct SceNpOnlineId +{ + char data[16]; + char term; + char dummy[3]; +}; + +struct SceNpId +{ + SceNpOnlineId handle; + u8 opt[8]; + u8 reserved[8]; +}; + +struct SceNpAvatarUrl +{ + char data[127]; + char term; +}; + +struct SceNpUserInformation +{ + SceNpId userId; + SceNpAvatarUrl icon; + u8 reserved[52]; +}; + +struct SceNpMyLanguages +{ + s32 language1; + s32 language2; + s32 language3; + u8 padding[4]; +}; + +struct SceNpAvatarImage +{ + u8 data[200 * 1024]; + u32 size; + u8 reserved[12]; +}; + +enum SceNpAvatarSizeType : s32 +{ + SCE_NP_AVATAR_SIZE_LARGE, + SCE_NP_AVATAR_SIZE_MIDDLE, + SCE_NP_AVATAR_SIZE_SMALL +}; + +struct SceNpAboutMe +{ + char data[64]; +}; + +typedef s32 SceNpAuthRequestId; +typedef u64 SceNpTime; + +struct SceNpDate +{ + u16 year; + u8 month; + u8 day; +}; + +union SceNpTicketParam +{ + s32 i32; + s64 i64; + u32 u32; + u64 u64; + SceNpDate date; + u8 data[256]; +}; + +struct SceNpTicketVersion +{ + u16 major; + u16 minor; +}; + +typedef vm::psv::ptr arg)> SceNpAuthCallback; + +struct SceNpAuthRequestParameter +{ + u32 size; + SceNpTicketVersion version; + vm::psv::ptr serviceId; + vm::psv::ptr cookie; + u32 cookieSize; + vm::psv::ptr entitlementId; + u32 consumedCount; + SceNpAuthCallback ticketCb; + vm::psv::ptr cbArg; +}; + +struct SceNpEntitlementId +{ + u8 data[32]; +}; + +struct SceNpEntitlement +{ + SceNpEntitlementId id; + SceNpTime createdDate; + SceNpTime expireDate; + u32 type; + s32 remainingCount; + u32 consumedCount; + char padding[4]; +}; + +extern psv_log_base sceNpCommon; diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp index 4771107b92..5fce1c946e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNpManager.cpp @@ -2,8 +2,67 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceNpCommon.h" + extern psv_log_base sceNpManager; +struct SceNpOptParam +{ + u32 optParamSize; +}; + +typedef vm::psv::ptr userdata)> SceNpServiceStateCallback; + +s32 sceNpInit(vm::psv::ptr commConf, vm::psv::ptr opt) +{ + throw __FUNCTION__; +} + +s32 sceNpTerm(ARMv7Context&) +{ + throw __FUNCTION__; +} + +s32 sceNpCheckCallback() +{ + throw __FUNCTION__; +} + +s32 sceNpGetServiceState(vm::psv::ptr state) +{ + throw __FUNCTION__; +} + +s32 sceNpRegisterServiceStateCallback(SceNpServiceStateCallback callback, vm::psv::ptr userdata) +{ + throw __FUNCTION__; +} + +s32 sceNpUnregisterServiceStateCallback() +{ + throw __FUNCTION__; +} + +s32 sceNpManagerGetNpId(vm::psv::ptr npId) +{ + throw __FUNCTION__; +} + +s32 sceNpManagerGetAccountRegion(vm::psv::ptr countryCode, vm::psv::ptr languageCode) +{ + throw __FUNCTION__; +} + +s32 sceNpManagerGetContentRatingFlag(vm::psv::ptr isRestricted, vm::psv::ptr age) +{ + throw __FUNCTION__; +} + +s32 sceNpManagerGetChatRestrictionFlag(vm::psv::ptr isRestricted) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpManager, #name, name) psv_log_base sceNpManager("SceNpManager", []() @@ -12,14 +71,14 @@ psv_log_base sceNpManager("SceNpManager", []() sceNpManager.on_unload = nullptr; sceNpManager.on_stop = nullptr; - //REG_FUNC(0x04D9F484, sceNpInit); - //REG_FUNC(0x19E40AE1, sceNpTerm); - //REG_FUNC(0x3C94B4B4, sceNpManagerGetNpId); - //REG_FUNC(0x54060DF6, sceNpGetServiceState); - //REG_FUNC(0x44239C35, sceNpRegisterServiceStateCallback); - //REG_FUNC(0xD9E6E56C, sceNpUnregisterServiceStateCallback); - //REG_FUNC(0x3B0AE9A9, sceNpCheckCallback); - //REG_FUNC(0xFE835967, sceNpManagerGetAccountRegion); - //REG_FUNC(0xAF0073B2, sceNpManagerGetContentRatingFlag); - //REG_FUNC(0x60C575B1, sceNpManagerGetChatRestrictionFlag); + REG_FUNC(0x04D9F484, sceNpInit); + REG_FUNC(0x19E40AE1, sceNpTerm); + REG_FUNC(0x3C94B4B4, sceNpManagerGetNpId); + REG_FUNC(0x54060DF6, sceNpGetServiceState); + REG_FUNC(0x44239C35, sceNpRegisterServiceStateCallback); + REG_FUNC(0xD9E6E56C, sceNpUnregisterServiceStateCallback); + REG_FUNC(0x3B0AE9A9, sceNpCheckCallback); + REG_FUNC(0xFE835967, sceNpManagerGetAccountRegion); + REG_FUNC(0xAF0073B2, sceNpManagerGetContentRatingFlag); + REG_FUNC(0x60C575B1, sceNpManagerGetChatRestrictionFlag); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp index ffc7d962a7..cdb9f5aa8e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNpMatching.cpp @@ -2,8 +2,1306 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceNet.h" +#include "sceNpCommon.h" + extern psv_log_base sceNpMatching; +struct SceNpMatching2MemoryInfo +{ + u32 totalMemSize; + u32 curMemUsage; + u32 maxMemUsage; + u8 reserved[12]; +}; + +typedef u16 SceNpMatching2ServerId; +typedef u32 SceNpMatching2WorldId; +typedef u16 SceNpMatching2WorldNumber; +typedef u64 SceNpMatching2LobbyId; +typedef u16 SceNpMatching2LobbyNumber; +typedef u64 SceNpMatching2RoomId; +typedef u16 SceNpMatching2RoomNumber; +typedef u16 SceNpMatching2ContextId; +typedef u32 SceNpMatching2RequestId; +typedef u32 SceNpMatching2SignalingRequestId; +typedef u8 SceNpMatching2NatType; +typedef u8 SceNpMatching2Operator; +typedef u8 SceNpMatching2CastType; + +struct SceNpMatching2SessionPassword +{ + u8 data[8]; +}; + +typedef u8 SceNpMatching2SessionType; +typedef u8 SceNpMatching2EventCause; + +struct SceNpMatching2PresenceOptionData +{ + u8 data[16]; + u32 len; +}; + +typedef u16 SceNpMatching2AttributeId; +typedef u32 SceNpMatching2FlagAttr; + +struct SceNpMatching2IntAttr +{ + SceNpMatching2AttributeId id; + u8 padding[2]; + u32 num; +}; + + +struct SceNpMatching2BinAttr +{ + SceNpMatching2AttributeId id; + u8 padding[2]; + vm::psv::ptr ptr; + u32 size; +}; + + +struct SceNpMatching2RangeFilter +{ + u32 startIndex; + u32 max; +}; + + +struct SceNpMatching2IntSearchFilter +{ + SceNpMatching2Operator searchOperator; + u8 padding[3]; + SceNpMatching2IntAttr attr; +}; + + +struct SceNpMatching2BinSearchFilter +{ + SceNpMatching2Operator searchOperator; + u8 padding[3]; + SceNpMatching2BinAttr attr; +}; + + +struct SceNpMatching2Range +{ + u32 startIndex; + u32 total; + u32 resultCount; +}; + + +struct SceNpMatching2JoinedSessionInfo +{ + SceNpMatching2SessionType sessionType; + u8 padding1[1]; + SceNpMatching2ServerId serverId; + SceNpMatching2WorldId worldId; + SceNpMatching2LobbyId lobbyId; + SceNpMatching2RoomId roomId; + u64 joinDate; +}; + + +struct SceNpMatching2UserInfo +{ + vm::psv::ptr next; + SceNpId npId; + vm::psv::ptr userBinAttr; + u32 userBinAttrNum; + vm::psv::ptr joinedSessionInfo; + u32 joinedSessionInfoNum; +}; + +typedef u8 SceNpMatching2ServerStatus; + +struct SceNpMatching2Server +{ + SceNpMatching2ServerId serverId; + SceNpMatching2ServerStatus status; + u8 padding[1]; +}; + + +struct SceNpMatching2World +{ + vm::psv::ptr next; + SceNpMatching2WorldId worldId; + u32 numOfLobby; + u32 maxNumOfTotalLobbyMember; + u32 curNumOfTotalLobbyMember; + u32 curNumOfRoom; + u32 curNumOfTotalRoomMember; + bool withEntitlementId; + SceNpEntitlementId entitlementId; + u8 padding[3]; +}; + +typedef u16 SceNpMatching2LobbyMemberId; + +struct SceNpMatching2LobbyMemberBinAttrInternal +{ + u64 updateDate; + SceNpMatching2BinAttr data; + u8 padding[4]; +}; + + +struct SceNpMatching2LobbyMemberDataInternal +{ + vm::psv::ptr next; + SceNpId npId; + + u64 joinDate; + SceNpMatching2LobbyMemberId memberId; + u8 padding[2]; + + SceNpMatching2FlagAttr flagAttr; + + vm::psv::ptr joinedSessionInfo; + u32 joinedSessionInfoNum; + vm::psv::ptr lobbyMemberBinAttrInternal; + u32 lobbyMemberBinAttrInternalNum; +}; + + +struct SceNpMatching2LobbyMemberIdList +{ + vm::psv::ptr memberId; + u32 memberIdNum; + SceNpMatching2LobbyMemberId me; + u8 padding[6]; +}; + + +struct SceNpMatching2LobbyBinAttrInternal +{ + u64 updateDate; + SceNpMatching2LobbyMemberId updateMemberId; + u8 padding[2]; + SceNpMatching2BinAttr data; +}; + + +struct SceNpMatching2LobbyDataExternal +{ + vm::psv::ptr next; + SceNpMatching2ServerId serverId; + u8 padding1[2]; + SceNpMatching2WorldId worldId; + u8 padding2[4]; + SceNpMatching2LobbyId lobbyId; + u32 maxSlot; + u32 curMemberNum; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr lobbySearchableIntAttrExternal; + u32 lobbySearchableIntAttrExternalNum; + vm::psv::ptr lobbySearchableBinAttrExternal; + u32 lobbySearchableBinAttrExternalNum; + vm::psv::ptr lobbyBinAttrExternal; + u32 lobbyBinAttrExternalNum; + u8 padding3[4]; +}; + + +struct SceNpMatching2LobbyDataInternal +{ + SceNpMatching2ServerId serverId; + u8 padding1[2]; + SceNpMatching2WorldId worldId; + SceNpMatching2LobbyId lobbyId; + + u32 maxSlot; + SceNpMatching2LobbyMemberIdList memberIdList; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr lobbyBinAttrInternal; + u32 lobbyBinAttrInternalNum; +}; + + +union SceNpMatching2LobbyMessageDestination +{ + SceNpMatching2LobbyMemberId unicastTarget; + struct + { + vm::psv::ptr memberId; + u32 memberIdNum; + + } multicastTarget; +}; + +typedef u8 SceNpMatching2RoomGroupId; +typedef u16 SceNpMatching2RoomMemberId; +typedef u8 SceNpMatching2TeamId; +typedef u8 SceNpMatching2Role; +typedef u8 SceNpMatching2BlockKickFlag; + +struct SceNpMatching2GroupLabel +{ + u8 data[8]; +}; + +typedef u64 SceNpMatching2RoomPasswordSlotMask; +typedef u64 SceNpMatching2RoomJoinedSlotMask; + +struct SceNpMatching2RoomGroupConfig +{ + u32 slotNum; + bool withLabel; + SceNpMatching2GroupLabel label; + bool withPassword; + u8 padding[2]; +}; + + +struct SceNpMatching2RoomGroupPasswordConfig +{ + SceNpMatching2RoomGroupId groupId; + bool withPassword; + u8 padding[1]; +}; + + +struct SceNpMatching2RoomMemberBinAttrInternal +{ + u64 updateDate; + SceNpMatching2BinAttr data; + u8 padding[4]; +}; + + +struct SceNpMatching2RoomGroup +{ + SceNpMatching2RoomGroupId groupId; + bool withPassword; + bool withLabel; + u8 padding[1]; + SceNpMatching2GroupLabel label; + u32 slotNum; + u32 curGroupMemberNum; +}; + + +struct SceNpMatching2RoomMemberDataExternal +{ + struct vm::psv::ptr next; + SceNpId npId; + u64 joinDate; + SceNpMatching2Role role; + u8 padding[7]; +}; + + +struct SceNpMatching2RoomMemberDataInternal +{ + struct vm::psv::ptr next; + SceNpId npId; + + u64 joinDate; + SceNpMatching2RoomMemberId memberId; + SceNpMatching2TeamId teamId; + u8 padding1[1]; + + vm::psv::ptr roomGroup; + + SceNpMatching2NatType natType; + u8 padding2[3]; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr roomMemberBinAttrInternal; + u32 roomMemberBinAttrInternalNum; +}; + + +struct SceNpMatching2RoomMemberDataInternalList +{ + vm::psv::ptr members; + u32 membersNum; + vm::psv::ptr me; + vm::psv::ptr owner; +}; + + +struct SceNpMatching2RoomBinAttrInternal +{ + u64 updateDate; + SceNpMatching2RoomMemberId updateMemberId; + u8 padding[2]; + SceNpMatching2BinAttr data; +}; + + +struct SceNpMatching2RoomDataExternal +{ + vm::psv::ptr next; + + u16 maxSlot; + u16 curMemberNum; + + SceNpMatching2ServerId serverId; + u8 padding[2]; + SceNpMatching2WorldId worldId; + SceNpMatching2LobbyId lobbyId; + SceNpMatching2RoomId roomId; + + SceNpMatching2RoomPasswordSlotMask passwordSlotMask; + SceNpMatching2RoomJoinedSlotMask joinedSlotMask; + u16 publicSlotNum; + u16 privateSlotNum; + u16 openPublicSlotNum; + u16 openPrivateSlotNum; + + vm::psv::ptr owner; + SceNpMatching2FlagAttr flagAttr; + + vm::psv::ptr roomGroup; + u32 roomGroupNum; + vm::psv::ptr roomSearchableIntAttrExternal; + u32 roomSearchableIntAttrExternalNum; + vm::psv::ptr roomSearchableBinAttrExternal; + u32 roomSearchableBinAttrExternalNum; + vm::psv::ptr roomBinAttrExternal; + u32 roomBinAttrExternalNum; +}; + + +struct SceNpMatching2RoomDataInternal +{ + u16 maxSlot; + + SceNpMatching2ServerId serverId; + SceNpMatching2WorldId worldId; + SceNpMatching2LobbyId lobbyId; + SceNpMatching2RoomId roomId; + + SceNpMatching2RoomPasswordSlotMask passwordSlotMask; + SceNpMatching2RoomJoinedSlotMask joinedSlotMask; + u16 publicSlotNum; + u16 privateSlotNum; + u16 openPublicSlotNum; + u16 openPrivateSlotNum; + + SceNpMatching2RoomMemberDataInternalList memberList; + + vm::psv::ptr roomGroup; + u32 roomGroupNum; + + SceNpMatching2FlagAttr flagAttr; + u8 padding[4]; + vm::psv::ptr roomBinAttrInternal; + u32 roomBinAttrInternalNum; +}; + + +union SceNpMatching2RoomMessageDestination +{ + SceNpMatching2RoomMemberId unicastTarget; + struct + { + vm::psv::ptr memberId; + u32 memberIdNum; + + } multicastTarget; + SceNpMatching2TeamId multicastTargetTeamId; +}; + + +struct SceNpMatching2InvitationData +{ + vm::psv::ptr targetSession; + u32 targetSessionNum; + vm::psv::ptr optData; + u32 optDataLen; +}; + +typedef u16 SceNpMatching2Event; + +typedef vm::psv::ptr data, + vm::psv::ptr arg + )> SceNpMatching2RequestCallback; + +typedef vm::psv::ptr data, + vm::psv::ptr arg + )> SceNpMatching2LobbyEventCallback; + +typedef vm::psv::ptr data, + vm::psv::ptr arg + )> SceNpMatching2RoomEventCallback; + +typedef vm::psv::ptr data, + vm::psv::ptr arg + )> SceNpMatching2LobbyMessageCallback; + +typedef vm::psv::ptr data, + vm::psv::ptr arg + )> SceNpMatching2RoomMessageCallback; + +typedef vm::psv::ptr arg + )> SceNpMatching2SignalingCallback; + +typedef vm::psv::ptr arg + )> SceNpMatching2ContextCallback; + + +struct SceNpMatching2RequestOptParam +{ + SceNpMatching2RequestCallback cbFunc; + vm::psv::ptr cbFuncArg; + u32 timeout; + u16 appReqId; + u8 padding[2]; +}; + + +struct SceNpMatching2GetWorldInfoListRequest +{ + SceNpMatching2ServerId serverId; +}; + + + +struct SceNpMatching2GetWorldInfoListResponse +{ + vm::psv::ptr world; + u32 worldNum; +}; + +struct SceNpMatching2SetUserInfoRequest +{ + SceNpMatching2ServerId serverId; + u8 padding[2]; + vm::psv::ptr userBinAttr; + u32 userBinAttrNum; +}; + + +struct SceNpMatching2GetUserInfoListRequest +{ + SceNpMatching2ServerId serverId; + u8 padding[2]; + vm::psv::ptr npId; + u32 npIdNum; + vm::psv::ptr attrId; + u32 attrIdNum; + s32 option; +}; + + + +struct SceNpMatching2GetUserInfoListResponse +{ + vm::psv::ptr userInfo; + u32 userInfoNum; +}; + + +struct SceNpMatching2GetRoomMemberDataExternalListRequest +{ + SceNpMatching2RoomId roomId; +}; + + + +struct SceNpMatching2GetRoomMemberDataExternalListResponse +{ + vm::psv::ptr roomMemberDataExternal; + u32 roomMemberDataExternalNum; +}; + + +struct SceNpMatching2SetRoomDataExternalRequest +{ + SceNpMatching2RoomId roomId; + vm::psv::ptr roomSearchableIntAttrExternal; + u32 roomSearchableIntAttrExternalNum; + vm::psv::ptr roomSearchableBinAttrExternal; + u32 roomSearchableBinAttrExternalNum; + vm::psv::ptr roomBinAttrExternal; + u32 roomBinAttrExternalNum; +}; + + +struct SceNpMatching2GetRoomDataExternalListRequest +{ + vm::psv::ptr roomId; + u32 roomIdNum; + vm::psv::ptr attrId; + u32 attrIdNum; +}; + + + +struct SceNpMatching2GetRoomDataExternalListResponse +{ + vm::psv::ptr roomDataExternal; + u32 roomDataExternalNum; +}; + +typedef u8 SceNpMatching2SignalingType; +typedef u8 SceNpMatching2SignalingFlag; + +struct SceNpMatching2SignalingOptParam +{ + SceNpMatching2SignalingType type; + SceNpMatching2SignalingFlag flag; + SceNpMatching2RoomMemberId hubMemberId; + u8 reserved2[4]; +}; + + + +struct SceNpMatching2CreateJoinRoomRequest +{ + SceNpMatching2WorldId worldId; + u8 padding1[4]; + SceNpMatching2LobbyId lobbyId; + + u32 maxSlot; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr roomBinAttrInternal; + u32 roomBinAttrInternalNum; + vm::psv::ptr roomSearchableIntAttrExternal; + u32 roomSearchableIntAttrExternalNum; + vm::psv::ptr roomSearchableBinAttrExternal; + u32 roomSearchableBinAttrExternalNum; + vm::psv::ptr roomBinAttrExternal; + u32 roomBinAttrExternalNum; + vm::psv::ptr roomPassword; + vm::psv::ptr groupConfig; + u32 groupConfigNum; + vm::psv::ptr passwordSlotMask; + vm::psv::ptr allowedUser; + u32 allowedUserNum; + vm::psv::ptr blockedUser; + u32 blockedUserNum; + + vm::psv::ptr joinRoomGroupLabel; + vm::psv::ptr roomMemberBinAttrInternal; + u32 roomMemberBinAttrInternalNum; + SceNpMatching2TeamId teamId; + u8 padding2[3]; + + vm::psv::ptr sigOptParam; + u8 padding3[4]; +}; + + + +struct SceNpMatching2CreateJoinRoomResponse +{ + vm::psv::ptr roomDataInternal; +}; + + +struct SceNpMatching2JoinRoomRequest +{ + SceNpMatching2RoomId roomId; + vm::psv::ptr roomPassword; + vm::psv::ptr joinRoomGroupLabel; + vm::psv::ptr roomMemberBinAttrInternal; + u32 roomMemberBinAttrInternalNum; + SceNpMatching2PresenceOptionData optData; + SceNpMatching2TeamId teamId; + u8 padding[3]; + vm::psv::ptr blockedUser; + u32 blockedUserNum; +}; + + + +struct SceNpMatching2JoinRoomResponse +{ + vm::psv::ptr roomDataInternal; +}; + + +struct SceNpMatching2LeaveRoomRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2PresenceOptionData optData; + u8 padding[4]; +}; + + +struct SceNpMatching2GrantRoomOwnerRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2RoomMemberId newOwner; + u8 padding[2]; + SceNpMatching2PresenceOptionData optData; +}; + + +struct SceNpMatching2KickoutRoomMemberRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2RoomMemberId target; + SceNpMatching2BlockKickFlag blockKickFlag; + u8 padding[1]; + SceNpMatching2PresenceOptionData optData; +}; + + +struct SceNpMatching2SearchRoomRequest +{ + s32 option; + SceNpMatching2WorldId worldId; + SceNpMatching2LobbyId lobbyId; + SceNpMatching2RangeFilter rangeFilter; + SceNpMatching2FlagAttr flagFilter; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr intFilter; + u32 intFilterNum; + vm::psv::ptr binFilter; + u32 binFilterNum; + vm::psv::ptr attrId; + u32 attrIdNum; +}; + + + +struct SceNpMatching2SearchRoomResponse +{ + SceNpMatching2Range range; + vm::psv::ptr roomDataExternal; +}; + + +struct SceNpMatching2SendRoomMessageRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2CastType castType; + u8 padding[3]; + SceNpMatching2RoomMessageDestination dst; + vm::psv::ptr msg; + u32 msgLen; + s32 option; +}; + + +struct SceNpMatching2SendRoomChatMessageRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2CastType castType; + u8 padding[3]; + SceNpMatching2RoomMessageDestination dst; + vm::psv::ptr msg; + u32 msgLen; + s32 option; +}; + + + +struct SceNpMatching2SendRoomChatMessageResponse +{ + bool filtered; +}; + + +struct SceNpMatching2SetRoomDataInternalRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2FlagAttr flagFilter; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr roomBinAttrInternal; + u32 roomBinAttrInternalNum; + vm::psv::ptr passwordConfig; + u32 passwordConfigNum; + vm::psv::ptr passwordSlotMask; + vm::psv::ptr ownerPrivilegeRank; + u32 ownerPrivilegeRankNum; + u8 padding[4]; +}; + + +struct SceNpMatching2GetRoomDataInternalRequest +{ + SceNpMatching2RoomId roomId; + vm::psv::ptr attrId; + u32 attrIdNum; +}; + + + +struct SceNpMatching2GetRoomDataInternalResponse +{ + vm::psv::ptr roomDataInternal; +}; + + +struct SceNpMatching2SetRoomMemberDataInternalRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2RoomMemberId memberId; + SceNpMatching2TeamId teamId; + u8 padding[5]; + SceNpMatching2FlagAttr flagFilter; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr roomMemberBinAttrInternal; + u32 roomMemberBinAttrInternalNum; +}; + + +struct SceNpMatching2GetRoomMemberDataInternalRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2RoomMemberId memberId; + u8 padding[6]; + vm::psv::ptr attrId; + u32 attrIdNum; +}; + + + +struct SceNpMatching2GetRoomMemberDataInternalResponse +{ + vm::psv::ptr roomMemberDataInternal; +}; + + +struct SceNpMatching2SetSignalingOptParamRequest +{ + SceNpMatching2RoomId roomId; + SceNpMatching2SignalingOptParam sigOptParam; +}; + + +struct SceNpMatching2GetLobbyInfoListRequest +{ + SceNpMatching2WorldId worldId; + SceNpMatching2RangeFilter rangeFilter; + vm::psv::ptr attrId; + u32 attrIdNum; +}; + + + +struct SceNpMatching2GetLobbyInfoListResponse +{ + SceNpMatching2Range range; + vm::psv::ptr lobbyDataExternal; +}; + + +struct SceNpMatching2JoinLobbyRequest +{ + SceNpMatching2LobbyId lobbyId; + vm::psv::ptr joinedSessionInfo; + u32 joinedSessionInfoNum; + vm::psv::ptr lobbyMemberBinAttrInternal; + u32 lobbyMemberBinAttrInternalNum; + SceNpMatching2PresenceOptionData optData; + u8 padding[4]; +}; + + + +struct SceNpMatching2JoinLobbyResponse +{ + vm::psv::ptr lobbyDataInternal; +}; + + +struct SceNpMatching2LeaveLobbyRequest +{ + SceNpMatching2LobbyId lobbyId; + SceNpMatching2PresenceOptionData optData; + u8 padding[4]; +}; + + +struct SceNpMatching2SetLobbyMemberDataInternalRequest +{ + SceNpMatching2LobbyId lobbyId; + SceNpMatching2LobbyMemberId memberId; + u8 padding1[2]; + SceNpMatching2FlagAttr flagFilter; + SceNpMatching2FlagAttr flagAttr; + vm::psv::ptr joinedSessionInfo; + u32 joinedSessionInfoNum; + vm::psv::ptr lobbyMemberBinAttrInternal; + u32 lobbyMemberBinAttrInternalNum; + u8 padding2[4]; +}; + + +struct SceNpMatching2GetLobbyMemberDataInternalRequest +{ + SceNpMatching2LobbyId lobbyId; + SceNpMatching2LobbyMemberId memberId; + u8 padding[6]; + vm::psv::ptr attrId; + u32 attrIdNum; +}; + + + +struct SceNpMatching2GetLobbyMemberDataInternalResponse +{ + vm::psv::ptr lobbyMemberDataInternal; +}; + + + +struct SceNpMatching2GetLobbyMemberDataInternalListRequest +{ + SceNpMatching2LobbyId lobbyId; + vm::psv::ptr memberId; + u32 memberIdNum; + vm::psv::ptr attrId; + u32 attrIdNum; + bool extendedData; + u8 padding[7]; +}; + + + +struct SceNpMatching2GetLobbyMemberDataInternalListResponse +{ + vm::psv::ptr lobbyMemberDataInternal; + u32 lobbyMemberDataInternalNum; +}; + + +struct SceNpMatching2SendLobbyChatMessageRequest +{ + SceNpMatching2LobbyId lobbyId; + SceNpMatching2CastType castType; + u8 padding[3]; + SceNpMatching2LobbyMessageDestination dst; + vm::psv::ptr msg; + u32 msgLen; + s32 option; +}; + + + +struct SceNpMatching2SendLobbyChatMessageResponse +{ + bool filtered; +}; + + +struct SceNpMatching2SendLobbyInvitationRequest +{ + SceNpMatching2LobbyId lobbyId; + SceNpMatching2CastType castType; + u8 padding[3]; + SceNpMatching2LobbyMessageDestination dst; + SceNpMatching2InvitationData invitationData; + s32 option; +}; + + +struct SceNpMatching2RoomMemberUpdateInfo +{ + vm::psv::ptr roomMemberDataInternal; + SceNpMatching2EventCause eventCause; + u8 padding[3]; + SceNpMatching2PresenceOptionData optData; +}; + + +struct SceNpMatching2RoomOwnerUpdateInfo +{ + SceNpMatching2RoomMemberId prevOwner; + SceNpMatching2RoomMemberId newOwner; + SceNpMatching2EventCause eventCause; + u8 padding[3]; + vm::psv::ptr roomPassword; + SceNpMatching2PresenceOptionData optData; +}; + + +struct SceNpMatching2RoomUpdateInfo +{ + SceNpMatching2EventCause eventCause; + u8 padding[3]; + s32 errorCode; + SceNpMatching2PresenceOptionData optData; +}; + + +struct SceNpMatching2RoomDataInternalUpdateInfo +{ + vm::psv::ptr newRoomDataInternal; + vm::psv::ptr newFlagAttr; + vm::psv::ptr prevFlagAttr; + vm::psv::ptr newRoomPasswordSlotMask; + vm::psv::ptr prevRoomPasswordSlotMask; + vm::psv::ptr *newRoomGroup; + u32 newRoomGroupNum; + vm::psv::ptr *newRoomBinAttrInternal; + u32 newRoomBinAttrInternalNum; +}; + + +struct SceNpMatching2RoomMemberDataInternalUpdateInfo +{ + vm::psv::ptr newRoomMemberDataInternal; + vm::psv::ptr newFlagAttr; + vm::psv::ptr prevFlagAttr; + vm::psv::ptr newTeamId; + vm::psv::ptr *newRoomMemberBinAttrInternal; + u32 newRoomMemberBinAttrInternalNum; +}; + + +struct SceNpMatching2SignalingOptParamUpdateInfo +{ + SceNpMatching2SignalingOptParam newSignalingOptParam; +}; + + +struct SceNpMatching2RoomMessageInfo +{ + bool filtered; + SceNpMatching2CastType castType; + u8 padding[2]; + vm::psv::ptr dst; + vm::psv::ptr srcMember; + vm::psv::ptr msg; + u32 msgLen; +}; + + +struct SceNpMatching2LobbyMemberUpdateInfo +{ + vm::psv::ptr lobbyMemberDataInternal; + SceNpMatching2EventCause eventCause; + u8 padding[3]; + SceNpMatching2PresenceOptionData optData; +}; + + +struct SceNpMatching2LobbyUpdateInfo +{ + SceNpMatching2EventCause eventCause; + u8 padding[3]; + s32 errorCode; +}; + + +struct SceNpMatching2LobbyMemberDataInternalUpdateInfo +{ + SceNpMatching2LobbyMemberId memberId; + u8 padding[2]; + SceNpId npId; + SceNpMatching2FlagAttr flagFilter; + SceNpMatching2FlagAttr newFlagAttr; + vm::psv::ptr newJoinedSessionInfo; + u32 newJoinedSessionInfoNum; + vm::psv::ptr newLobbyMemberBinAttrInternal; + u32 newLobbyMemberBinAttrInternalNum; +}; + + +struct SceNpMatching2LobbyMessageInfo +{ + bool filtered; + SceNpMatching2CastType castType; + u8 padding[2]; + vm::psv::ptr dst; + vm::psv::ptr srcMember; + vm::psv::ptr msg; + u32 msgLen; +}; + + +struct SceNpMatching2LobbyInvitationInfo +{ + SceNpMatching2CastType castType; + u8 padding[3]; + vm::psv::ptr dst; + vm::psv::ptr srcMember; + SceNpMatching2InvitationData invitationData; +}; + +union SceNpMatching2SignalingConnectionInfo +{ + u32 rtt; + u32 bandwidth; + SceNpId npId; + struct + { + SceNetInAddr addr; + u16 port; + u8 padding[2]; + + } address; + u32 packetLoss; +}; + +struct SceNpMatching2SignalingNetInfo +{ + u32 size; + SceNetInAddr localAddr; + SceNetInAddr mappedAddr; + s32 natStatus; +}; + +// Functions + +s32 sceNpMatching2Init( + const u32 poolSize, + const s32 threadPriority, + const s32 cpuAffinityMask, + const u32 threadStackSize) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2Term() +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2CreateContext( + vm::psv::ptr npId, + vm::psv::ptr commId, + vm::psv::ptr passPhrase, + vm::psv::ptr ctxId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2DestroyContext(const SceNpMatching2ContextId ctxId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2ContextStart(const SceNpMatching2ContextId ctxId, const u64 timeout) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2AbortContextStart(const SceNpMatching2ContextId ctxId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2ContextStop(const SceNpMatching2ContextId ctxId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SetDefaultRequestOptParam(const SceNpMatching2ContextId ctxId, vm::psv::ptr optParam) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2RegisterRoomEventCallback(const SceNpMatching2ContextId ctxId, SceNpMatching2RoomEventCallback cbFunc, vm::psv::ptr cbFuncArg) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2RegisterRoomMessageCallback(const SceNpMatching2ContextId ctxId, SceNpMatching2RoomMessageCallback cbFunc, vm::psv::ptr cbFuncArg) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2RegisterSignalingCallback(const SceNpMatching2ContextId ctxId, SceNpMatching2SignalingCallback cbFunc, vm::psv::ptr cbFuncArg) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2RegisterContextCallback(SceNpMatching2ContextCallback cbFunc, vm::psv::ptr cbFuncArg) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2AbortRequest(const SceNpMatching2ContextId ctxId, const SceNpMatching2RequestId reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2GetMemoryInfo(vm::psv::ptr memInfo) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2GetServerLocal(const SceNpMatching2ContextId ctxId, vm::psv::ptr server) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2GetWorldInfoList( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2CreateJoinRoom( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SearchRoom( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2JoinRoom( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2LeaveRoom( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2GetSignalingOptParamLocal( + const SceNpMatching2ContextId ctxId, + const SceNpMatching2RoomId roomId, + vm::psv::ptr signalingOptParam) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SetRoomDataExternal( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2KickoutRoomMember( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SendRoomChatMessage( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SendRoomMessage( + const SceNpMatching2ContextId ctxId, + vm::psv::ptr reqParam, + vm::psv::ptr optParam, + vm::psv::ptr assignedReqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SignalingGetConnectionStatus( + SceNpMatching2ContextId ctxId, + SceNpMatching2RoomId roomId, + SceNpMatching2RoomMemberId memberId, + vm::psv::ptr connStatus, + vm::psv::ptr peerAddr, + vm::psv::ptr peerPort) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SignalingGetConnectionInfo( + SceNpMatching2ContextId ctxId, + SceNpMatching2RoomId roomId, + SceNpMatching2RoomMemberId memberId, + s32 code, + vm::psv::ptr info) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SignalingGetLocalNetInfo(vm::psv::ptr netinfo) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SignalingGetPeerNetInfo( + SceNpMatching2ContextId ctxId, + SceNpMatching2RoomId roomId, + SceNpMatching2RoomMemberId memberId, + vm::psv::ptr reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SignalingCancelPeerNetInfo( + SceNpMatching2ContextId ctxId, + SceNpMatching2SignalingRequestId reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpMatching2SignalingGetPeerNetInfoResult( + SceNpMatching2ContextId ctxId, + SceNpMatching2SignalingRequestId reqId, + vm::psv::ptr netinfo) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpMatching, #name, name) psv_log_base sceNpMatching("SceNpMatching2", []() @@ -12,35 +1310,35 @@ psv_log_base sceNpMatching("SceNpMatching2", []() sceNpMatching.on_unload = nullptr; sceNpMatching.on_stop = nullptr; - //REG_FUNC(0xEBB1FE74, sceNpMatching2Init); - //REG_FUNC(0x0124641C, sceNpMatching2Term); - //REG_FUNC(0xADF578E1, sceNpMatching2CreateContext); - //REG_FUNC(0x368AA759, sceNpMatching2DestroyContext); - //REG_FUNC(0xBB2E7559, sceNpMatching2ContextStart); - //REG_FUNC(0xF2847E3B, sceNpMatching2AbortContextStart); - //REG_FUNC(0x506454DE, sceNpMatching2ContextStop); - //REG_FUNC(0xF3A43C50, sceNpMatching2SetDefaultRequestOptParam); - //REG_FUNC(0xF486991B, sceNpMatching2RegisterRoomEventCallback); - //REG_FUNC(0xFA51949B, sceNpMatching2RegisterRoomMessageCallback); - //REG_FUNC(0xF9E35566, sceNpMatching2RegisterContextCallback); - //REG_FUNC(0x74EB6CE9, sceNpMatching2AbortRequest); - //REG_FUNC(0x7BD39E50, sceNpMatching2GetMemoryInfo); - //REG_FUNC(0x65C0FEED, sceNpMatching2GetServerLocal); - //REG_FUNC(0xC086B560, sceNpMatching2GetWorldInfoList); - //REG_FUNC(0x818A9499, sceNpMatching2CreateJoinRoom); - //REG_FUNC(0xD48BAF13, sceNpMatching2SearchRoom); - //REG_FUNC(0x33F7D5AE, sceNpMatching2JoinRoom); - //REG_FUNC(0xC8B0C9EE, sceNpMatching2LeaveRoom); - //REG_FUNC(0x495D2B46, sceNpMatching2GetSignalingOptParamLocal); - //REG_FUNC(0xE0BE0510, sceNpMatching2SendRoomChatMessage); - //REG_FUNC(0x7B908D99, sceNpMatching2SendRoomMessage); - //REG_FUNC(0x4E4C55BD, sceNpMatching2SignalingGetConnectionStatus); - //REG_FUNC(0x20598618, sceNpMatching2SignalingGetConnectionInfo); - //REG_FUNC(0x79310806, sceNpMatching2SignalingGetLocalNetInfo); - //REG_FUNC(0xF0CB1DD3, sceNpMatching2SignalingGetPeerNetInfo); - //REG_FUNC(0xADCD102C, sceNpMatching2SignalingCancelPeerNetInfo); - //REG_FUNC(0xFDC7B2C9, sceNpMatching2SignalingGetPeerNetInfoResult); - //REG_FUNC(0x1C60BC5B, sceNpMatching2RegisterSignalingCallback); - //REG_FUNC(0x8F88AC7E, sceNpMatching2SetRoomDataExternal); - //REG_FUNC(0xA8021394, sceNpMatching2KickoutRoomMember); + REG_FUNC(0xEBB1FE74, sceNpMatching2Init); + REG_FUNC(0x0124641C, sceNpMatching2Term); + REG_FUNC(0xADF578E1, sceNpMatching2CreateContext); + REG_FUNC(0x368AA759, sceNpMatching2DestroyContext); + REG_FUNC(0xBB2E7559, sceNpMatching2ContextStart); + REG_FUNC(0xF2847E3B, sceNpMatching2AbortContextStart); + REG_FUNC(0x506454DE, sceNpMatching2ContextStop); + REG_FUNC(0xF3A43C50, sceNpMatching2SetDefaultRequestOptParam); + REG_FUNC(0xF486991B, sceNpMatching2RegisterRoomEventCallback); + REG_FUNC(0xFA51949B, sceNpMatching2RegisterRoomMessageCallback); + REG_FUNC(0xF9E35566, sceNpMatching2RegisterContextCallback); + REG_FUNC(0x74EB6CE9, sceNpMatching2AbortRequest); + REG_FUNC(0x7BD39E50, sceNpMatching2GetMemoryInfo); + REG_FUNC(0x65C0FEED, sceNpMatching2GetServerLocal); + REG_FUNC(0xC086B560, sceNpMatching2GetWorldInfoList); + REG_FUNC(0x818A9499, sceNpMatching2CreateJoinRoom); + REG_FUNC(0xD48BAF13, sceNpMatching2SearchRoom); + REG_FUNC(0x33F7D5AE, sceNpMatching2JoinRoom); + REG_FUNC(0xC8B0C9EE, sceNpMatching2LeaveRoom); + REG_FUNC(0x495D2B46, sceNpMatching2GetSignalingOptParamLocal); + REG_FUNC(0xE0BE0510, sceNpMatching2SendRoomChatMessage); + REG_FUNC(0x7B908D99, sceNpMatching2SendRoomMessage); + REG_FUNC(0x4E4C55BD, sceNpMatching2SignalingGetConnectionStatus); + REG_FUNC(0x20598618, sceNpMatching2SignalingGetConnectionInfo); + REG_FUNC(0x79310806, sceNpMatching2SignalingGetLocalNetInfo); + REG_FUNC(0xF0CB1DD3, sceNpMatching2SignalingGetPeerNetInfo); + REG_FUNC(0xADCD102C, sceNpMatching2SignalingCancelPeerNetInfo); + REG_FUNC(0xFDC7B2C9, sceNpMatching2SignalingGetPeerNetInfoResult); + REG_FUNC(0x1C60BC5B, sceNpMatching2RegisterSignalingCallback); + REG_FUNC(0x8F88AC7E, sceNpMatching2SetRoomDataExternal); + REG_FUNC(0xA8021394, sceNpMatching2KickoutRoomMember); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp index 612114af70..f093ab8b31 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNpScore.cpp @@ -2,8 +2,337 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceNpCommon.h" + extern psv_log_base sceNpScore; +typedef u32 SceNpScoreBoardId; +typedef s64 SceNpScoreValue; +typedef u32 SceNpScoreRankNumber; +typedef s32 SceNpScorePcId; + +struct SceNpScoreGameInfo +{ + u32 infoSize; + u8 pad[4]; + u8 data[192]; +}; + +struct SceNpScoreComment +{ + char utf8Comment[64]; +}; + +struct SceNpScoreRankData +{ + SceNpId npId; + u8 reserved[49]; + u8 pad0[3]; + SceNpScorePcId pcId; + SceNpScoreRankNumber serialRank; + SceNpScoreRankNumber rank; + SceNpScoreRankNumber highestRank; + s32 hasGameData; + u8 pad1[4]; + SceNpScoreValue scoreValue; + u64 recordDate; +}; + +struct SceNpScorePlayerRankData +{ + s32 hasData; + u8 pad0[4]; + SceNpScoreRankData rankData; +}; + +struct SceNpScoreBoardInfo +{ + u32 rankLimit; + u32 updateMode; + u32 sortMode; + u32 uploadNumLimit; + u32 uploadSizeLimit; +}; + +struct SceNpScoreNpIdPcId +{ + SceNpId npId; + SceNpScorePcId pcId; + u8 pad[4]; +}; + +s32 sceNpScoreInit(s32 threadPriority, s32 cpuAffinityMask, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreTerm(ARMv7Context&) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreCreateTitleCtx(vm::psv::ptr titleId, vm::psv::ptr passphrase, vm::psv::ptr selfNpId) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreDeleteTitleCtx(s32 titleCtxId) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreCreateRequest(s32 titleCtxId) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreDeleteRequest(s32 reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreAbortRequest(s32 reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreSetTimeout(s32 id, s32 resolveRetry, s32 resolveTimeout, s32 connTimeout, s32 sendTimeout, s32 recvTimeout) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreSetPlayerCharacterId(s32 id, SceNpScorePcId pcId) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetBoardInfo(s32 reqId, SceNpScoreBoardId boardId, vm::psv::ptr boardInfo, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreRecordScore( + s32 reqId, + SceNpScoreBoardId boardId, + SceNpScoreValue score, + vm::psv::ptr scoreComment, + vm::psv::ptr gameInfo, + vm::psv::ptr tmpRank, + vm::psv::ptr compareDate, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreRecordGameData( + s32 reqId, + SceNpScoreBoardId boardId, + SceNpScoreValue score, + u32 totalSize, + u32 sendSize, + vm::psv::ptr data, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetGameData( + s32 reqId, + SceNpScoreBoardId boardId, + vm::psv::ptr npId, + vm::psv::ptr totalSize, + u32 recvSize, + vm::psv::ptr data, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetRankingByNpId( + s32 reqId, + SceNpScoreBoardId boardId, + vm::psv::ptr npIdArray, + u32 npIdArraySize, + vm::psv::ptr rankArray, + u32 rankArraySize, + vm::psv::ptr commentArray, + u32 commentArraySize, + vm::psv::ptr infoArray, + u32 infoArraySize, + u32 arrayNum, + vm::psv::ptr lastSortDate, + vm::psv::ptr totalRecord, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetRankingByRange( + s32 reqId, + SceNpScoreBoardId boardId, + SceNpScoreRankNumber startSerialRank, + vm::psv::ptr rankArray, + u32 rankArraySize, + vm::psv::ptr commentArray, + u32 commentArraySize, + vm::psv::ptr infoArray, + u32 infoArraySize, + u32 arrayNum, + vm::psv::ptr lastSortDate, + vm::psv::ptr totalRecord, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + + +s32 sceNpScoreGetRankingByNpIdPcId( + s32 reqId, + SceNpScoreBoardId boardId, + vm::psv::ptr idArray, + u32 idArraySize, + vm::psv::ptr rankArray, + u32 rankArraySize, + vm::psv::ptr commentArray, + u32 commentArraySize, + vm::psv::ptr infoArray, + u32 infoArraySize, + u32 arrayNum, + vm::psv::ptr lastSortDate, + vm::psv::ptr totalRecord, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreCensorComment(s32 reqId, vm::psv::ptr comment, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreSanitizeComment(s32 reqId, vm::psv::ptr comment, vm::psv::ptr sanitizedComment, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreWaitAsync(s32 id, vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNpScorePollAsync(s32 reqId, vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetBoardInfoAsync(s32 reqId, SceNpScoreBoardId boardId, vm::psv::ptr boardInfo, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreRecordScoreAsync( + s32 reqId, + SceNpScoreBoardId boardId, + SceNpScoreValue score, + vm::psv::ptr scoreComment, + vm::psv::ptr gameInfo, + vm::psv::ptr tmpRank, + vm::psv::ptr compareDate, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreRecordGameDataAsync( + s32 reqId, + SceNpScoreBoardId boardId, + SceNpScoreValue score, + u32 totalSize, + u32 sendSize, + vm::psv::ptr data, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetGameDataAsync( + s32 reqId, + SceNpScoreBoardId boardId, + vm::psv::ptr npId, + vm::psv::ptr totalSize, + u32 recvSize, + vm::psv::ptr data, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetRankingByNpIdAsync( + s32 reqId, + SceNpScoreBoardId boardId, + vm::psv::ptr npIdArray, + u32 npIdArraySize, + vm::psv::ptr rankArray, + u32 rankArraySize, + vm::psv::ptr commentArray, + u32 commentArraySize, + vm::psv::ptr infoArray, + u32 infoArraySize, + u32 arrayNum, + vm::psv::ptr lastSortDate, + vm::psv::ptr totalRecord, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetRankingByRangeAsync( + s32 reqId, + SceNpScoreBoardId boardId, + SceNpScoreRankNumber startSerialRank, + vm::psv::ptr rankArray, + u32 rankArraySize, + vm::psv::ptr commentArray, + u32 commentArraySize, + vm::psv::ptr infoArray, + u32 infoArraySize, + u32 arrayNum, + vm::psv::ptr lastSortDate, + vm::psv::ptr totalRecord, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreGetRankingByNpIdPcIdAsync( + s32 reqId, + SceNpScoreBoardId boardId, + vm::psv::ptr idArray, + u32 idArraySize, + vm::psv::ptr rankArray, + u32 rankArraySize, + vm::psv::ptr commentArray, + u32 commentArraySize, + vm::psv::ptr infoArray, + u32 infoArraySize, + u32 arrayNum, + vm::psv::ptr lastSortDate, + vm::psv::ptr totalRecord, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreCensorCommentAsync(s32 reqId, vm::psv::ptr comment, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpScoreSanitizeCommentAsync(s32 reqId, vm::psv::ptr comment, vm::psv::ptr sanitizedComment, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpScore, #name, name) psv_log_base sceNpScore("SceNpScore", []() @@ -12,33 +341,33 @@ psv_log_base sceNpScore("SceNpScore", []() sceNpScore.on_unload = nullptr; sceNpScore.on_stop = nullptr; - //REG_FUNC(0x0433069F, sceNpScoreInit); - //REG_FUNC(0x2050F98F, sceNpScoreTerm); - //REG_FUNC(0x5685F225, sceNpScoreCreateTitleCtx); - //REG_FUNC(0xD30D1993, sceNpScoreCreateRequest); - //REG_FUNC(0xF52EA88A, sceNpScoreDeleteTitleCtx); - //REG_FUNC(0xFFF24BB1, sceNpScoreDeleteRequest); - //REG_FUNC(0x320C0277, sceNpScoreRecordScore); - //REG_FUNC(0x24B09634, sceNpScoreRecordScoreAsync); - //REG_FUNC(0xC2862B67, sceNpScoreRecordGameData); - //REG_FUNC(0x40573917, sceNpScoreRecordGameDataAsync); - //REG_FUNC(0xDFAD64D3, sceNpScoreGetGameData); - //REG_FUNC(0xCE416993, sceNpScoreGetGameDataAsync); - //REG_FUNC(0x427D3412, sceNpScoreGetRankingByRange); - //REG_FUNC(0xC45E3FCD, sceNpScoreGetRankingByRangeAsync); - //REG_FUNC(0xBAE55B34, sceNpScoreGetRankingByNpId); - //REG_FUNC(0x45CD1D00, sceNpScoreGetRankingByNpIdAsync); - //REG_FUNC(0x871F28AA, sceNpScoreGetRankingByNpIdPcId); - //REG_FUNC(0xCE3A9544, sceNpScoreGetRankingByNpIdPcIdAsync); - //REG_FUNC(0xA7E93CE1, sceNpScoreAbortRequest); - //REG_FUNC(0x31733BF3, sceNpScoreWaitAsync); - //REG_FUNC(0x9F2A7AC9, sceNpScorePollAsync); - //REG_FUNC(0x00F90E7B, sceNpScoreGetBoardInfo); - //REG_FUNC(0x3CD9974E, sceNpScoreGetBoardInfoAsync); - //REG_FUNC(0xA0C94D46, sceNpScoreCensorComment); - //REG_FUNC(0xAA0BBF8E, sceNpScoreCensorCommentAsync); - //REG_FUNC(0x6FD2041A, sceNpScoreSanitizeComment); - //REG_FUNC(0x15981858, sceNpScoreSanitizeCommentAsync); - //REG_FUNC(0x5EF44841, sceNpScoreSetTimeout); - //REG_FUNC(0x53D77883, sceNpScoreSetPlayerCharacterId); + REG_FUNC(0x0433069F, sceNpScoreInit); + REG_FUNC(0x2050F98F, sceNpScoreTerm); + REG_FUNC(0x5685F225, sceNpScoreCreateTitleCtx); + REG_FUNC(0xD30D1993, sceNpScoreCreateRequest); + REG_FUNC(0xF52EA88A, sceNpScoreDeleteTitleCtx); + REG_FUNC(0xFFF24BB1, sceNpScoreDeleteRequest); + REG_FUNC(0x320C0277, sceNpScoreRecordScore); + REG_FUNC(0x24B09634, sceNpScoreRecordScoreAsync); + REG_FUNC(0xC2862B67, sceNpScoreRecordGameData); + REG_FUNC(0x40573917, sceNpScoreRecordGameDataAsync); + REG_FUNC(0xDFAD64D3, sceNpScoreGetGameData); + REG_FUNC(0xCE416993, sceNpScoreGetGameDataAsync); + REG_FUNC(0x427D3412, sceNpScoreGetRankingByRange); + REG_FUNC(0xC45E3FCD, sceNpScoreGetRankingByRangeAsync); + REG_FUNC(0xBAE55B34, sceNpScoreGetRankingByNpId); + REG_FUNC(0x45CD1D00, sceNpScoreGetRankingByNpIdAsync); + REG_FUNC(0x871F28AA, sceNpScoreGetRankingByNpIdPcId); + REG_FUNC(0xCE3A9544, sceNpScoreGetRankingByNpIdPcIdAsync); + REG_FUNC(0xA7E93CE1, sceNpScoreAbortRequest); + REG_FUNC(0x31733BF3, sceNpScoreWaitAsync); + REG_FUNC(0x9F2A7AC9, sceNpScorePollAsync); + REG_FUNC(0x00F90E7B, sceNpScoreGetBoardInfo); + REG_FUNC(0x3CD9974E, sceNpScoreGetBoardInfoAsync); + REG_FUNC(0xA0C94D46, sceNpScoreCensorComment); + REG_FUNC(0xAA0BBF8E, sceNpScoreCensorCommentAsync); + REG_FUNC(0x6FD2041A, sceNpScoreSanitizeComment); + REG_FUNC(0x15981858, sceNpScoreSanitizeCommentAsync); + REG_FUNC(0x5EF44841, sceNpScoreSetTimeout); + REG_FUNC(0x53D77883, sceNpScoreSetPlayerCharacterId); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp b/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp index 5ce2ca80ad..1aab007361 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceNpUtility.cpp @@ -2,8 +2,140 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceNpCommon.h" + extern psv_log_base sceNpUtility; +struct SceNpBandwidthTestResult +{ + double uploadBps; + double downloadBps; + s32 result; + char padding[4]; +}; + +s32 sceNpLookupInit(s32 usesAsync, s32 threadPriority, s32 cpuAffinityMask, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupTerm(ARMv7Context&) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupCreateTitleCtx(vm::psv::ptr titleId, vm::psv::ptr selfNpId) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupDeleteTitleCtx(s32 titleCtxId) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupCreateRequest(s32 titleCtxId) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupDeleteRequest(s32 reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupAbortRequest(s32 reqId) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupSetTimeout(s32 id, s32 resolveRetry, u32 resolveTimeout, u32 connTimeout, u32 sendTimeout, u32 recvTimeout) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupWaitAsync(s32 reqId, vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupPollAsync(s32 reqId, vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupNpId(s32 reqId, vm::psv::ptr onlineId, vm::psv::ptr npId, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupNpIdAsync(s32 reqId, vm::psv::ptr onlineId, vm::psv::ptr npId, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupUserProfile( + s32 reqId, + s32 avatarSizeType, + vm::psv::ptr npId, + vm::psv::ptr userInfo, + vm::psv::ptr aboutMe, + vm::psv::ptr languages, + vm::psv::ptr countryCode, + vm::psv::ptr avatarImageData, + u32 avatarImageDataMaxSize, + vm::psv::ptr avatarImageDataSize, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupUserProfileAsync( + s32 reqId, + s32 avatarSizeType, + vm::psv::ptr npId, + vm::psv::ptr userInfo, + vm::psv::ptr aboutMe, + vm::psv::ptr languages, + vm::psv::ptr countryCode, + vm::psv::ptr avatarImageData, + u32 avatarImageDataMaxSize, + vm::psv::ptr avatarImageDataSize, + vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupAvatarImage(s32 reqId, vm::psv::ptr avatarUrl, vm::psv::ptr avatarImage, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpLookupAvatarImageAsync(s32 reqId, vm::psv::ptr avatarUrl, vm::psv::ptr avatarImage, vm::psv::ptr option) +{ + throw __FUNCTION__; +} + +s32 sceNpBandwidthTestInitStart(s32 initPriority, s32 cpuAffinityMask) +{ + throw __FUNCTION__; +} + +s32 sceNpBandwidthTestGetStatus() +{ + throw __FUNCTION__; +} + +s32 sceNpBandwidthTestShutdown(vm::psv::ptr result) +{ + throw __FUNCTION__; +} + +s32 sceNpBandwidthTestAbort() +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceNpUtility, #name, name) psv_log_base sceNpUtility("SceNpUtility", []() @@ -12,24 +144,24 @@ psv_log_base sceNpUtility("SceNpUtility", []() sceNpUtility.on_unload = nullptr; sceNpUtility.on_stop = nullptr; - //REG_FUNC(0x9246A673, sceNpLookupInit); - //REG_FUNC(0x0158B61B, sceNpLookupTerm); - //REG_FUNC(0x5110E17E, sceNpLookupCreateTitleCtx); - //REG_FUNC(0x33B64699, sceNpLookupDeleteTitleCtx); - //REG_FUNC(0x9E42E922, sceNpLookupCreateRequest); - //REG_FUNC(0x8B608BF6, sceNpLookupDeleteRequest); - //REG_FUNC(0x027587C4, sceNpLookupAbortRequest); - //REG_FUNC(0xB0C9DC45, sceNpLookupSetTimeout); - //REG_FUNC(0xCF956F23, sceNpLookupWaitAsync); - //REG_FUNC(0xFCDBA234, sceNpLookupPollAsync); - //REG_FUNC(0xB1A14879, sceNpLookupNpId); - //REG_FUNC(0x5387BABB, sceNpLookupNpIdAsync); - //REG_FUNC(0x6A1BF429, sceNpLookupUserProfile); - //REG_FUNC(0xE5285E0F, sceNpLookupUserProfileAsync); - //REG_FUNC(0xFDB0AE47, sceNpLookupAvatarImage); - //REG_FUNC(0x282BD43C, sceNpLookupAvatarImageAsync); - //REG_FUNC(0x081FA13C, sceNpBandwidthTestInitStart); - //REG_FUNC(0xE0EBFBF6, sceNpBandwidthTestGetStatus); - //REG_FUNC(0x58D92EFD, sceNpBandwidthTestShutdown); - //REG_FUNC(0x32B068C4, sceNpBandwidthTestAbort); + REG_FUNC(0x9246A673, sceNpLookupInit); + REG_FUNC(0x0158B61B, sceNpLookupTerm); + REG_FUNC(0x5110E17E, sceNpLookupCreateTitleCtx); + REG_FUNC(0x33B64699, sceNpLookupDeleteTitleCtx); + REG_FUNC(0x9E42E922, sceNpLookupCreateRequest); + REG_FUNC(0x8B608BF6, sceNpLookupDeleteRequest); + REG_FUNC(0x027587C4, sceNpLookupAbortRequest); + REG_FUNC(0xB0C9DC45, sceNpLookupSetTimeout); + REG_FUNC(0xCF956F23, sceNpLookupWaitAsync); + REG_FUNC(0xFCDBA234, sceNpLookupPollAsync); + REG_FUNC(0xB1A14879, sceNpLookupNpId); + REG_FUNC(0x5387BABB, sceNpLookupNpIdAsync); + REG_FUNC(0x6A1BF429, sceNpLookupUserProfile); + REG_FUNC(0xE5285E0F, sceNpLookupUserProfileAsync); + REG_FUNC(0xFDB0AE47, sceNpLookupAvatarImage); + REG_FUNC(0x282BD43C, sceNpLookupAvatarImageAsync); + REG_FUNC(0x081FA13C, sceNpBandwidthTestInitStart); + REG_FUNC(0xE0EBFBF6, sceNpBandwidthTestGetStatus); + REG_FUNC(0x58D92EFD, sceNpBandwidthTestShutdown); + REG_FUNC(0x32B068C4, sceNpBandwidthTestAbort); }); diff --git a/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp b/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp index 6fb390fbd8..68216d7ddc 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceUlt.cpp @@ -2,8 +2,545 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "sceLibKernel.h" + extern psv_log_base sceUlt; +#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " size") + +struct _SceUltOptParamHeader +{ + s64 reserved[2]; +}; + +struct SceUltWaitingQueueResourcePoolOptParam +{ + _SceUltOptParamHeader header; + u64 reserved[14]; +}; + +CHECK_SIZE(SceUltWaitingQueueResourcePoolOptParam, 128); + +struct SceUltWaitingQueueResourcePool +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltWaitingQueueResourcePool, 256); + +struct SceUltQueueDataResourcePoolOptParam +{ + _SceUltOptParamHeader header; + u64 reserved[14]; +}; + +CHECK_SIZE(SceUltQueueDataResourcePoolOptParam, 128); + +struct SceUltQueueDataResourcePool +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltQueueDataResourcePool, 256); + +struct SceUltMutexOptParam +{ + _SceUltOptParamHeader header; + u32 attribute; + u32 reserved_0; + u64 reserved[13]; +}; + +CHECK_SIZE(SceUltMutexOptParam, 128); + +struct SceUltMutex +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltMutex, 256); + +struct SceUltConditionVariableOptParam +{ + _SceUltOptParamHeader header; + u64 reserved[14]; +}; + +CHECK_SIZE(SceUltConditionVariableOptParam, 128); + +struct SceUltConditionVariable +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltConditionVariable, 256); + +struct SceUltQueueOptParam +{ + _SceUltOptParamHeader header; + u64 reserved[14]; +}; + +CHECK_SIZE(SceUltQueueOptParam, 128); + +struct SceUltQueue +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltQueue, 256); + +struct SceUltReaderWriterLockOptParam +{ + _SceUltOptParamHeader header; + u64 reserved[14]; +}; + +CHECK_SIZE(SceUltReaderWriterLockOptParam, 128); + +struct SceUltReaderWriterLock +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltReaderWriterLock, 256); + +struct SceUltSemaphoreOptParam +{ + _SceUltOptParamHeader header; + u64 reserved[14]; +}; + +CHECK_SIZE(SceUltSemaphoreOptParam, 128); + +struct SceUltSemaphore +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltSemaphore, 256); + +struct SceUltUlthreadRuntimeOptParam +{ + _SceUltOptParamHeader header; + + u32 oneShotThreadStackSize; + s32 workerThreadPriority; + u32 workerThreadCpuAffinityMask; + u32 workerThreadAttr; + vm::psv::ptr workerThreadOptParam; + + u64 reserved[11]; +}; + +CHECK_SIZE(SceUltUlthreadRuntimeOptParam, 128); + +struct SceUltUlthreadRuntime +{ + u64 reserved[128]; +}; + +CHECK_SIZE(SceUltUlthreadRuntime, 1024); + +struct SceUltUlthreadOptParam +{ + _SceUltOptParamHeader header; + u32 attribute; + u32 reserved_0; + u64 reserved[13]; +}; + +CHECK_SIZE(SceUltUlthreadOptParam, 128); + +struct SceUltUlthread +{ + u64 reserved[32]; +}; + +CHECK_SIZE(SceUltUlthread, 256); + +typedef vm::psv::ptr SceUltUlthreadEntry; + +// Functions + +s32 _sceUltWaitingQueueResourcePoolOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +u32 sceUltWaitingQueueResourcePoolGetWorkAreaSize(u32 numThreads, u32 numSyncObjects) +{ + throw __FUNCTION__; +} + +s32 _sceUltWaitingQueueResourcePoolCreate( + vm::psv::ptr pool, + vm::psv::ptr name, + u32 numThreads, + u32 numSyncObjects, + vm::psv::ptr workArea, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltWaitingQueueResourcePoolDestroy(vm::psv::ptr pool) +{ + throw __FUNCTION__; +} + +s32 _sceUltQueueDataResourcePoolOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +u32 sceUltQueueDataResourcePoolGetWorkAreaSize(u32 numData, u32 dataSize, u32 numQueueObject) +{ + throw __FUNCTION__; +} + +s32 _sceUltQueueDataResourcePoolCreate( + vm::psv::ptr pool, + vm::psv::ptr name, + u32 numData, + u32 dataSize, + u32 numQueueObject, + vm::psv::ptr waitingQueueResourcePool, + vm::psv::ptr workArea, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltQueueDataResourcePoolDestroy(vm::psv::ptr pool) +{ + throw __FUNCTION__; +} + +u32 sceUltMutexGetStandaloneWorkAreaSize(u32 waitingQueueDepth, u32 numConditionVariable) +{ + throw __FUNCTION__; +} + +s32 _sceUltMutexOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltMutexCreate( + vm::psv::ptr mutex, + vm::psv::ptr name, + vm::psv::ptr waitingQueueResourcePool, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltMutexCreateStandalone( + vm::psv::ptr mutex, + vm::psv::ptr name, + u32 numConditionVariable, + u32 maxNumThreads, + vm::psv::ptr workArea, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltMutexLock(vm::psv::ptr mutex) +{ + throw __FUNCTION__; +} + +s32 sceUltMutexTryLock(vm::psv::ptr mutex) +{ + throw __FUNCTION__; +} + +s32 sceUltMutexUnlock(vm::psv::ptr mutex) +{ + throw __FUNCTION__; +} + +s32 sceUltMutexDestroy(vm::psv::ptr mutex) +{ + throw __FUNCTION__; +} + +s32 _sceUltConditionVariableOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltConditionVariableCreate( + vm::psv::ptr conditionVariable, + vm::psv::ptr name, + vm::psv::ptr mutex, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltConditionVariableSignal(vm::psv::ptr conditionVariable) +{ + throw __FUNCTION__; +} + +s32 sceUltConditionVariableSignalAll(vm::psv::ptr conditionVariable) +{ + throw __FUNCTION__; +} + +s32 sceUltConditionVariableWait(vm::psv::ptr conditionVariable) +{ + throw __FUNCTION__; +} + +s32 sceUltConditionVariableDestroy(vm::psv::ptr conditionVariable) +{ + throw __FUNCTION__; +} + +s32 _sceUltQueueOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +u32 sceUltQueueGetStandaloneWorkAreaSize(u32 queueDepth, + u32 dataSize, + u32 waitingQueueLength) +{ + throw __FUNCTION__; +} + +s32 _sceUltQueueCreate( + vm::psv::ptr queue, + vm::psv::ptr _name, + u32 dataSize, + vm::psv::ptr resourcePool, + vm::psv::ptr queueResourcePool, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltQueueCreateStandalone( + vm::psv::ptr queue, + vm::psv::ptr name, + u32 queueDepth, + u32 dataSize, + u32 waitingQueueLength, + vm::psv::ptr workArea, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltQueuePush(vm::psv::ptr queue, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +s32 sceUltQueueTryPush(vm::psv::ptr queue, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +s32 sceUltQueuePop(vm::psv::ptr queue, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +s32 sceUltQueueTryPop(vm::psv::ptr queue, vm::psv::ptr data) +{ + throw __FUNCTION__; +} + +s32 sceUltQueueDestroy(vm::psv::ptr queue) +{ + throw __FUNCTION__; +} + +s32 _sceUltReaderWriterLockOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltReaderWriterLockCreate( + vm::psv::ptr rwlock, + vm::psv::ptr name, + vm::psv::ptr waitingQueueResourcePool, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltReaderWriterLockCreateStandalone( + vm::psv::ptr rwlock, + vm::psv::ptr name, + u32 waitingQueueDepth, + vm::psv::ptr workArea, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +u32 sceUltReaderWriterLockGetStandaloneWorkAreaSize(u32 waitingQueueDepth) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockLockRead(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockTryLockRead(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockUnlockRead(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockLockWrite(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockTryLockWrite(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockUnlockWrite(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 sceUltReaderWriterLockDestroy(vm::psv::ptr rwlock) +{ + throw __FUNCTION__; +} + +s32 _sceUltSemaphoreOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltSemaphoreCreate( + vm::psv::ptr semaphore, + vm::psv::ptr name, + s32 numInitialResource, + vm::psv::ptr waitingQueueResourcePool, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltSemaphoreAcquire(vm::psv::ptr semaphore, s32 numResource) +{ + throw __FUNCTION__; +} + +s32 sceUltSemaphoreTryAcquire(vm::psv::ptr semaphore, s32 numResource) +{ + throw __FUNCTION__; +} + +s32 sceUltSemaphoreRelease(vm::psv::ptr semaphore, s32 numResource) +{ + throw __FUNCTION__; +} + +s32 sceUltSemaphoreDestroy(vm::psv::ptr semaphore) +{ + throw __FUNCTION__; +} + +s32 _sceUltUlthreadRuntimeOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +u32 sceUltUlthreadRuntimeGetWorkAreaSize(u32 numMaxUlthread, u32 numWorkerThread) +{ + throw __FUNCTION__; +} + +s32 _sceUltUlthreadRuntimeCreate( + vm::psv::ptr runtime, + vm::psv::ptr name, + u32 numMaxUlthread, + u32 numWorkerThread, + vm::psv::ptr workArea, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltUlthreadRuntimeDestroy(vm::psv::ptr runtime) +{ + throw __FUNCTION__; +} + +s32 _sceUltUlthreadOptParamInitialize(vm::psv::ptr optParam, u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 _sceUltUlthreadCreate( + vm::psv::ptr ulthread, + vm::psv::ptr name, + SceUltUlthreadEntry entry, + u32 arg, + vm::psv::ptr context, + u32 sizeContext, + vm::psv::ptr runtime, + vm::psv::ptr optParam, + u32 buildVersion) +{ + throw __FUNCTION__; +} + +s32 sceUltUlthreadYield() +{ + throw __FUNCTION__; +} + +s32 sceUltUlthreadExit(s32 status) +{ + throw __FUNCTION__; +} + +s32 sceUltUlthreadJoin(vm::psv::ptr ulthread, vm::psv::ptr status) +{ + throw __FUNCTION__; +} + +s32 sceUltUlthreadTryJoin(vm::psv::ptr ulthread, vm::psv::ptr status) +{ + throw __FUNCTION__; +} + +s32 sceUltUlthreadGetSelf(vm::psv::ptr> ulthread) +{ + throw __FUNCTION__; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceUlt, #name, name) psv_log_base sceUlt("SceUlt", []() @@ -12,57 +549,57 @@ psv_log_base sceUlt("SceUlt", []() sceUlt.on_unload = nullptr; sceUlt.on_stop = nullptr; - //REG_FUNC(0xEF094E35, _sceUltWaitingQueueResourcePoolOptParamInitialize); - //REG_FUNC(0x644DA029, sceUltWaitingQueueResourcePoolGetWorkAreaSize); - //REG_FUNC(0x62F9493E, _sceUltWaitingQueueResourcePoolCreate); - //REG_FUNC(0xC9E96714, sceUltWaitingQueueResourcePoolDestroy); - //REG_FUNC(0x8A4F88A2, _sceUltQueueDataResourcePoolOptParamInitialize); - //REG_FUNC(0xECDA7FEE, sceUltQueueDataResourcePoolGetWorkAreaSize); - //REG_FUNC(0x40856827, _sceUltQueueDataResourcePoolCreate); - //REG_FUNC(0x2B8D33F1, sceUltQueueDataResourcePoolDestroy); - //REG_FUNC(0x24D87E05, _sceUltMutexOptParamInitialize); - //REG_FUNC(0x5AFEC7A1, _sceUltMutexCreate); - //REG_FUNC(0x001EAC8A, sceUltMutexLock); - //REG_FUNC(0xE5936A69, sceUltMutexTryLock); - //REG_FUNC(0x897C9097, sceUltMutexUnlock); - //REG_FUNC(0xEEBD9052, sceUltMutexDestroy); - //REG_FUNC(0x0603FCC1, _sceUltConditionVariableOptParamInitialize); - //REG_FUNC(0xD76A156C, _sceUltConditionVariableCreate); - //REG_FUNC(0x9FE7CB9F, sceUltConditionVariableSignal); - //REG_FUNC(0xEBB6FC1E, sceUltConditionVariableSignalAll); - //REG_FUNC(0x2CD0F57C, sceUltConditionVariableWait); - //REG_FUNC(0x53420ED2, sceUltConditionVariableDestroy); - //REG_FUNC(0xF7A83023, _sceUltQueueOptParamInitialize); - //REG_FUNC(0x14DA1BB4, _sceUltQueueCreate); - //REG_FUNC(0xA7E78FF9, sceUltQueuePush); - //REG_FUNC(0x6D356B29, sceUltQueueTryPush); - //REG_FUNC(0x1AD58A53, sceUltQueuePop); - //REG_FUNC(0x2A1A8EA6, sceUltQueueTryPop); - //REG_FUNC(0xF37862DE, sceUltQueueDestroy); - //REG_FUNC(0xD8334A1F, _sceUltReaderWriterLockOptParamInitialize); - //REG_FUNC(0x2FB0EB32, _sceUltReaderWriterLockCreate); - //REG_FUNC(0x9AD07630, sceUltReaderWriterLockLockRead); - //REG_FUNC(0x2629C055, sceUltReaderWriterLockTryLockRead); - //REG_FUNC(0x218D4743, sceUltReaderWriterLockUnlockRead); - //REG_FUNC(0xF5F63E2C, sceUltReaderWriterLockLockWrite); - //REG_FUNC(0x944FB222, sceUltReaderWriterLockTryLockWrite); - //REG_FUNC(0x2A5741F5, sceUltReaderWriterLockUnlockWrite); - //REG_FUNC(0xB1FEB79B, sceUltReaderWriterLockDestroy); - //REG_FUNC(0x8E31B9FE, _sceUltSemaphoreOptParamInitialize); - //REG_FUNC(0xDD59562C, _sceUltSemaphoreCreate); - //REG_FUNC(0xF220D3AE, sceUltSemaphoreAcquire); - //REG_FUNC(0xAF15606D, sceUltSemaphoreTryAcquire); - //REG_FUNC(0x65376E2D, sceUltSemaphoreRelease); - //REG_FUNC(0x8EC57420, sceUltSemaphoreDestroy); - //REG_FUNC(0x8486DDE6, _sceUltUlthreadRuntimeOptParamInitialize); - //REG_FUNC(0x5435C586, sceUltUlthreadRuntimeGetWorkAreaSize); - //REG_FUNC(0x86DDA3AE, _sceUltUlthreadRuntimeCreate); - //REG_FUNC(0x4E9A745C, sceUltUlthreadRuntimeDestroy); - //REG_FUNC(0x7F373376, _sceUltUlthreadOptParamInitialize); - //REG_FUNC(0xB1290375, _sceUltUlthreadCreate); - //REG_FUNC(0xCAD57BAD, sceUltUlthreadYield); - //REG_FUNC(0x1E401DF8, sceUltUlthreadExit); - //REG_FUNC(0x63483381, sceUltUlthreadJoin); - //REG_FUNC(0xB4CF88AC, sceUltUlthreadTryJoin); - //REG_FUNC(0xA798C5D7, sceUltUlthreadGetSelf); + REG_FUNC(0xEF094E35, _sceUltWaitingQueueResourcePoolOptParamInitialize); + REG_FUNC(0x644DA029, sceUltWaitingQueueResourcePoolGetWorkAreaSize); + REG_FUNC(0x62F9493E, _sceUltWaitingQueueResourcePoolCreate); + REG_FUNC(0xC9E96714, sceUltWaitingQueueResourcePoolDestroy); + REG_FUNC(0x8A4F88A2, _sceUltQueueDataResourcePoolOptParamInitialize); + REG_FUNC(0xECDA7FEE, sceUltQueueDataResourcePoolGetWorkAreaSize); + REG_FUNC(0x40856827, _sceUltQueueDataResourcePoolCreate); + REG_FUNC(0x2B8D33F1, sceUltQueueDataResourcePoolDestroy); + REG_FUNC(0x24D87E05, _sceUltMutexOptParamInitialize); + REG_FUNC(0x5AFEC7A1, _sceUltMutexCreate); + REG_FUNC(0x001EAC8A, sceUltMutexLock); + REG_FUNC(0xE5936A69, sceUltMutexTryLock); + REG_FUNC(0x897C9097, sceUltMutexUnlock); + REG_FUNC(0xEEBD9052, sceUltMutexDestroy); + REG_FUNC(0x0603FCC1, _sceUltConditionVariableOptParamInitialize); + REG_FUNC(0xD76A156C, _sceUltConditionVariableCreate); + REG_FUNC(0x9FE7CB9F, sceUltConditionVariableSignal); + REG_FUNC(0xEBB6FC1E, sceUltConditionVariableSignalAll); + REG_FUNC(0x2CD0F57C, sceUltConditionVariableWait); + REG_FUNC(0x53420ED2, sceUltConditionVariableDestroy); + REG_FUNC(0xF7A83023, _sceUltQueueOptParamInitialize); + REG_FUNC(0x14DA1BB4, _sceUltQueueCreate); + REG_FUNC(0xA7E78FF9, sceUltQueuePush); + REG_FUNC(0x6D356B29, sceUltQueueTryPush); + REG_FUNC(0x1AD58A53, sceUltQueuePop); + REG_FUNC(0x2A1A8EA6, sceUltQueueTryPop); + REG_FUNC(0xF37862DE, sceUltQueueDestroy); + REG_FUNC(0xD8334A1F, _sceUltReaderWriterLockOptParamInitialize); + REG_FUNC(0x2FB0EB32, _sceUltReaderWriterLockCreate); + REG_FUNC(0x9AD07630, sceUltReaderWriterLockLockRead); + REG_FUNC(0x2629C055, sceUltReaderWriterLockTryLockRead); + REG_FUNC(0x218D4743, sceUltReaderWriterLockUnlockRead); + REG_FUNC(0xF5F63E2C, sceUltReaderWriterLockLockWrite); + REG_FUNC(0x944FB222, sceUltReaderWriterLockTryLockWrite); + REG_FUNC(0x2A5741F5, sceUltReaderWriterLockUnlockWrite); + REG_FUNC(0xB1FEB79B, sceUltReaderWriterLockDestroy); + REG_FUNC(0x8E31B9FE, _sceUltSemaphoreOptParamInitialize); + REG_FUNC(0xDD59562C, _sceUltSemaphoreCreate); + REG_FUNC(0xF220D3AE, sceUltSemaphoreAcquire); + REG_FUNC(0xAF15606D, sceUltSemaphoreTryAcquire); + REG_FUNC(0x65376E2D, sceUltSemaphoreRelease); + REG_FUNC(0x8EC57420, sceUltSemaphoreDestroy); + REG_FUNC(0x8486DDE6, _sceUltUlthreadRuntimeOptParamInitialize); + REG_FUNC(0x5435C586, sceUltUlthreadRuntimeGetWorkAreaSize); + REG_FUNC(0x86DDA3AE, _sceUltUlthreadRuntimeCreate); + REG_FUNC(0x4E9A745C, sceUltUlthreadRuntimeDestroy); + REG_FUNC(0x7F373376, _sceUltUlthreadOptParamInitialize); + REG_FUNC(0xB1290375, _sceUltUlthreadCreate); + REG_FUNC(0xCAD57BAD, sceUltUlthreadYield); + REG_FUNC(0x1E401DF8, sceUltUlthreadExit); + REG_FUNC(0x63483381, sceUltUlthreadJoin); + REG_FUNC(0xB4CF88AC, sceUltUlthreadTryJoin); + REG_FUNC(0xA798C5D7, sceUltUlthreadGetSelf); }); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 1e6d47a50e..8864e59975 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -340,6 +340,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index ac1531ee30..b45c4de188 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1501,5 +1501,8 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Modules + \ No newline at end of file From 2be045593a62f99d029f400033d04f7e88c18c36 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 20:41:17 +0300 Subject: [PATCH 41/94] Compilation fix --- rpcs3/Emu/ARMv7/Modules/sceNpCommon.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h index 2a40b7aee3..bd2b282301 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h +++ b/rpcs3/Emu/ARMv7/Modules/sceNpCommon.h @@ -106,10 +106,10 @@ struct SceNpDate union SceNpTicketParam { - s32 i32; - s64 i64; - u32 u32; - u64 u64; + s32 _s32; + s64 _s64; + u32 _u32; + u64 _u64; SceNpDate date; u8 data[256]; }; From 507638e6d825baa187015d49fbbe98f1db2bedc8 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 31 Jan 2015 00:36:58 +0530 Subject: [PATCH 42/94] SPURS: Update system service workload to use lock line reservations --- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 412 ++++++++++++-------- 3 files changed, 255 insertions(+), 161 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index d6ecbe64b0..ce0036e4a5 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -511,7 +511,7 @@ public: void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); } void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); } - void RegisterHleFuncion(u32 addr, std::function function) + void RegisterHleFunction(u32 addr, std::function function) { m_addr_to_hle_function_map[addr] = function; WriteLS32(addr, 0x00000003); // STOP 3 diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 62349f276d..83dffb54e7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -182,7 +182,7 @@ s64 spursInit( { auto spu = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, num, spurs.addr(), 0, 0); #ifndef PRX_DEBUG_XXX - spu->RegisterHleFuncion(spurs->m.spuImg.entry_point, spursKernelMain); + spu->RegisterHleFunction(spurs->m.spuImg.entry_point, spursKernelMain); #endif spurs->m.spus[num] = spu->GetId(); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 898638894c..e6921057c1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -17,6 +17,7 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status); bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag); u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask); u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll = true); +void spursHalt(); // // SPURS Kernel functions @@ -111,6 +112,12 @@ u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll) { return rv._u32[3]; } +// Halt the SPU +void spursHalt(SPUThread & spu) { + spu.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + spu.Stop(); +} + ////////////////////////////////////////////////////////////////////////////// // SPURS kernel functions ////////////////////////////////////////////////////////////////////////////// @@ -130,7 +137,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { do { // DMA and lock the first 0x80 bytes of spurs spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - CellSpurs * spurs = (CellSpurs *)mgmt->tempArea; + auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Calculate the contention (number of SPUs used) for each workload u8 contention[CELL_SPURS_MAX_WORKLOAD]; @@ -279,7 +286,7 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { do { // DMA and lock the first 0x80 bytes of spurs spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - CellSpurs * spurs = (CellSpurs *)mgmt->tempArea; + auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Calculate the contention (number of SPUs used) for each workload u8 contention[CELL_SPURS_MAX_WORKLOAD2]; @@ -408,8 +415,8 @@ bool spursKernelMain(SPUThread & spu) { SpursKernelMgmtData * mgmt = vm::get_ptr(spu.ls_offset + 0x100); bool isKernel2; - u32 pollStatus; - const CellSpurs::WorkloadInfo * wklInfo; + u32 pollStatus; + u64 wklArg; if (spu.PC == CELL_SPURS_KERNEL1_ENTRY_ADDR || spu.PC == CELL_SPURS_KERNEL2_ENTRY_ADDR) { // Entry point of SPURS kernel // Save arguments @@ -440,14 +447,15 @@ bool spursKernelMain(SPUThread & spu) { mgmt->guid[3] = 0x43A3C982; } + // Register SPURS kernel HLE functions spu.UnregisterHleFunctions(0, 0x40000); // TODO: use a symbolic constant - spu.RegisterHleFuncion(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelMain); - spu.RegisterHleFuncion(mgmt->yieldToKernelAddr, spursKernelMain); - spu.RegisterHleFuncion(mgmt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); + spu.RegisterHleFunction(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelMain); + spu.RegisterHleFunction(mgmt->yieldToKernelAddr, spursKernelMain); + spu.RegisterHleFunction(mgmt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); - // Start the system service workload - spu.RegisterHleFuncion(0xA00, spursSysServiceWorkloadEntry); - wklInfo = &mgmt->spurs->m.wklInfoSysSrv; + // Register the system HLE service workload entry point + spu.RegisterHleFunction(0xA00, spursSysServiceWorkloadEntry); + wklArg = mgmt->spurs->m.wklInfoSysSrv.arg; pollStatus = 0; } else if (spu.PC == mgmt->yieldToKernelAddr) { isKernel2 = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; @@ -460,10 +468,11 @@ bool spursKernelMain(SPUThread & spu) { spursKernel1SelectWorkload(spu); } - pollStatus = (u32)(spu.GPR[3]._u64[1]); - auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); - wklInfo = wid < CELL_SPURS_MAX_WORKLOAD ? &mgmt->spurs->m.wklInfo1[wid] : - (wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &mgmt->spurs->m.wklInfo2[wid & 0xf] : &mgmt->spurs->m.wklInfoSysSrv); + pollStatus = (u32)(spu.GPR[3]._u64[1]); + auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); + auto wklInfo = wid < CELL_SPURS_MAX_WORKLOAD ? &mgmt->spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &mgmt->spurs->m.wklInfo2[wid & 0xf] : + &mgmt->spurs->m.wklInfoSysSrv); + wklArg = wklInfo->arg; } else { assert(0); } @@ -477,7 +486,7 @@ bool spursKernelMain(SPUThread & spu) { spu.GPR[0]._u32[3] = mgmt->yieldToKernelAddr; spu.GPR[1]._u32[3] = 0x3FFB0; spu.GPR[3]._u32[3] = 0x100; - spu.GPR[4]._u64[1] = wklInfo->arg; + spu.GPR[4]._u64[1] = wklArg; spu.GPR[5]._u32[3] = pollStatus; spu.SetBranch(0xA00); return false; @@ -489,33 +498,48 @@ bool spursKernelMain(SPUThread & spu) { /// Restore scheduling parameters after a workload has been preempted by the system service workload void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt) { - if (mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] != 0xFF) { - auto wklId = mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum]; - mgmt->spurs->m.sysSrvWorkload[mgmt->spuNum] = 0xFF; + u8 wklId; - spursSysServiceUpdateWorkload(spu, mgmt); - if (wklId >= CELL_SPURS_MAX_WORKLOAD) { - mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; - mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); - } else { - mgmt->spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; - mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + if (spurs->m.sysSrvWorkload[mgmt->spuNum] == 0xFF) { + return; } - // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace - // uses the current worload id to determine the workload to which the trace belongs - auto wklIdSaved = mgmt->wklCurrentId; - mgmt->wklCurrentId = wklId; + wklId = spurs->m.sysSrvWorkload[mgmt->spuNum]; + spurs->m.sysSrvWorkload[mgmt->spuNum] = 0xFF; + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - // Trace - STOP: GUID - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = SPURS_GUID_SYS_WKL; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + spursSysServiceUpdateWorkload(spu, mgmt); - mgmt->wklCurrentId = wklIdSaved; - } + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x100); + + if (wklId >= CELL_SPURS_MAX_WORKLOAD) { + spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; + spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); + } else { + spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; + spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); + } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace + // uses the current worload id to determine the workload to which the trace belongs + auto wklIdSaved = mgmt->wklCurrentId; + mgmt->wklCurrentId = wklId; + + // Trace - STOP: GUID + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + mgmt->wklCurrentId = wklIdSaved; } /// Update the trace count for this SPU in CellSpurs @@ -528,39 +552,52 @@ void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt /// Update trace control in SPU from CellSpurs void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) { - auto sysSrvMsgUpdateTrace = mgmt->spurs->m.sysSrvMsgUpdateTrace; - mgmt->spurs->m.sysSrvMsgUpdateTrace &= ~(1 << mgmt->spuNum); - mgmt->spurs->m.xCC &= ~(1 << mgmt->spuNum); - mgmt->spurs->m.xCC |= arg2 << mgmt->spuNum; + bool notify; - bool notify = false; - if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.sysSrvMsgUpdateTrace == 0) && (mgmt->spurs->m.xCD != 0)) { - mgmt->spurs->m.xCD = 0; - notify = true; - } + u8 sysSrvMsgUpdateTrace; + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - if (arg4 && mgmt->spurs->m.xCD != 0) { - mgmt->spurs->m.xCD = 0; - notify = true; - } + sysSrvMsgUpdateTrace = spurs->m.sysSrvMsgUpdateTrace; + spurs->m.sysSrvMsgUpdateTrace &= ~(1 << mgmt->spuNum); + spurs->m.xCC &= ~(1 << mgmt->spuNum); + spurs->m.xCC |= arg2 << mgmt->spuNum; + + notify = false; + if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) && (spurs->m.sysSrvMsgUpdateTrace == 0) && (spurs->m.xCD != 0)) { + spurs->m.xCD = 0; + notify = true; + } + + if (arg4 && spurs->m.xCD != 0) { + spurs->m.xCD = 0; + notify = true; + } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); // Get trace parameters from CellSpurs and store them in the LS if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) || (arg3 != 0)) { - if (mgmt->traceMsgCount != 0xFF || mgmt->spurs->m.traceBuffer.addr() == 0) { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.traceBuffer), 0x80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x80 - offsetof(CellSpurs, m.traceBuffer)); + + if (mgmt->traceMsgCount != 0xFF || spurs->m.traceBuffer.addr() == 0) { spursSysServiceUpdateTraceCount(spu, mgmt); } else { - mgmt->traceMsgCount = mgmt->spurs->m.traceBuffer->count[mgmt->spuNum]; + spursDma(spu, MFC_GET_CMD, spurs->m.traceBuffer.addr() & 0xFFFFFFFC, 0x2C00/*LSA*/, 0x80/*size*/, mgmt->dmaTagId); + auto traceBuffer = vm::get_ptr(spu.ls_offset + 0x2C00); + mgmt->traceMsgCount = traceBuffer->count[mgmt->spuNum]; } - mgmt->traceBuffer = mgmt->spurs->m.traceBuffer.addr() + (mgmt->spurs->m.traceStartIndex[mgmt->spuNum] << 4); - mgmt->traceMaxCount = mgmt->spurs->m.traceStartIndex[1] - mgmt->spurs->m.traceStartIndex[0]; + mgmt->traceBuffer = spurs->m.traceBuffer.addr() + (spurs->m.traceStartIndex[mgmt->spuNum] << 4); + mgmt->traceMaxCount = spurs->m.traceStartIndex[1] - spurs->m.traceStartIndex[0]; if (mgmt->traceBuffer == 0) { mgmt->traceMsgCount = 0; } } if (notify) { - // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 2, 0); + // TODO: sys_spu_thread_send_event(spurs->m.spuPort, 2, 0); } } @@ -568,81 +605,108 @@ void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownBitSet) { // Mark the workloads in wklShutdownBitSet as completed and also generate a bit set of the completed // workloads that have a shutdown completion hook registered - u32 wklNotifyBitSet = 0; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - if (wklShutdownBitSet & (0x80000000u >> i)) { - mgmt->spurs->m.wklEvent1[i] |= 0x01; - if (mgmt->spurs->m.wklEvent1[i] & 0x02 || mgmt->spurs->m.wklEvent1[i] & 0x10) { - wklNotifyBitSet |= 0x80000000u >> i; - } - } + u32 wklNotifyBitSet; + u8 spuPort; + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - if (wklShutdownBitSet & (0x8000 >> i)) { - mgmt->spurs->m.wklEvent2[i] |= 0x01; - if (mgmt->spurs->m.wklEvent2[i] & 0x02 || mgmt->spurs->m.wklEvent2[i] & 0x10) { - wklNotifyBitSet |= 0x8000 >> i; + wklNotifyBitSet = 0; + spuPort = spurs->m.spuPort;; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + if (wklShutdownBitSet & (0x80000000u >> i)) { + spurs->m.wklEvent1[i] |= 0x01; + if (spurs->m.wklEvent1[i] & 0x02 || spurs->m.wklEvent1[i] & 0x10) { + wklNotifyBitSet |= 0x80000000u >> i; + } + } + + if (wklShutdownBitSet & (0x8000 >> i)) { + spurs->m.wklEvent2[i] |= 0x01; + if (spurs->m.wklEvent2[i] & 0x02 || spurs->m.wklEvent2[i] & 0x10) { + wklNotifyBitSet |= 0x8000 >> i; + } } } - } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); if (wklNotifyBitSet) { - // TODO: sys_spu_thread_send_event(mgmt->spurs->m.spuPort, 0, wklNotifyMask); + // TODO: sys_spu_thread_send_event(spuPort, 0, wklNotifyMask); } } /// Update workload information in the SPU from CellSpurs void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) { + auto spurs = vm::get_ptr(spu.ls_offset + 0x100); + spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklInfo1), 0x30000/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklInfo2), 0x30200/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + } + u32 wklShutdownBitSet = 0; mgmt->wklRunnable1 = 0; mgmt->wklRunnable2 = 0; for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + auto wklInfo1 = vm::get_ptr(spu.ls_offset + 0x30000); + // Copy the priority of the workload for this SPU and its unique id to the LS - mgmt->priority[i] = mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - mgmt->spurs->m.wklInfo1[i].priority[mgmt->spuNum]; - mgmt->wklUniqueId[i] = mgmt->spurs->m.wklInfo1[i].uniqueId.read_relaxed(); + mgmt->priority[i] = wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[mgmt->spuNum]; + mgmt->wklUniqueId[i] = wklInfo1[i].uniqueId.read_relaxed(); - // Update workload status and runnable flag based on the workload state - auto wklStatus = mgmt->spurs->m.wklStatus1[i]; - if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { - mgmt->spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum; - mgmt->wklRunnable1 |= 0x8000 >> i; - } else { - mgmt->spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum); - } + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + auto wklInfo2 = vm::get_ptr(spu.ls_offset + 0x30200); - // If the workload is shutting down and if this is the last SPU from which it is being removed then - // add it to the shutdown bit set - if (mgmt->spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus1[i] == 0)) { - mgmt->spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); - wklShutdownBitSet |= 0x80000000u >> i; - } - } - - if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { // Copy the priority of the workload for this SPU to the LS - if (mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) { - mgmt->priority[i] |= (0x10 - mgmt->spurs->m.wklInfo2[i].priority[mgmt->spuNum]) << 4; + if (wklInfo2[i].priority[mgmt->spuNum]) { + mgmt->priority[i] |= (0x10 - wklInfo2[i].priority[mgmt->spuNum]) << 4; } + } + } + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { // Update workload status and runnable flag based on the workload state - wklStatus = mgmt->spurs->m.wklStatus2[i]; - if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { - mgmt->spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum; - mgmt->wklRunnable2 |= 0x8000 >> i; + auto wklStatus = spurs->m.wklStatus1[i]; + if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum; + mgmt->wklRunnable1 |= 0x8000 >> i; } else { - mgmt->spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum); + spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum); } // If the workload is shutting down and if this is the last SPU from which it is being removed then // add it to the shutdown bit set - if (mgmt->spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (mgmt->spurs->m.wklStatus2[i] == 0)) { - mgmt->spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); - wklShutdownBitSet |= 0x8000 >> i; + if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (spurs->m.wklStatus1[i] == 0)) { + spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownBitSet |= 0x80000000u >> i; + } + } + + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + // Update workload status and runnable flag based on the workload state + wklStatus = spurs->m.wklStatus2[i]; + if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum; + mgmt->wklRunnable2 |= 0x8000 >> i; + } else { + spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (spurs->m.wklStatus2[i] == 0)) { + spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownBitSet |= 0x8000 >> i; + } } } } - } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); if (wklShutdownBitSet) { spursSysServiceUpdateEvent(spu, mgmt, wklShutdownBitSet); @@ -651,57 +715,85 @@ void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) /// Process any messages void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { - LV2_LOCK(0); + bool updateTrace = false; + bool updateWorkload = false; + bool terminate = false; + + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + // Terminate request + if (spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { + spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); + terminate = true; + } + + // Update workload message + if (spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { + spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); + updateWorkload = true; + } + + // Update trace message + if (spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { + updateTrace = true; + } + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); // Process update workload message - if (mgmt->spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { - mgmt->spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); + if (updateWorkload) { spursSysServiceUpdateWorkload(spu, mgmt); } // Process update trace message - if (mgmt->spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { + if (updateTrace) { spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0); } // Process terminate request - if (mgmt->spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { - mgmt->spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); + if (terminate) { // TODO: Rest of the terminate processing } } /// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { + // Monitor only lock line reservation lost events + spu.WriteChannel(SPU_WrEventMask, u128::from32r(SPU_EVENT_LR)); + + bool shouldExit; while (true) { - Emu.GetCoreMutex().lock(); + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Find the number of SPUs that are idling in this SPURS instance u32 nIdlingSpus = 0; for (u32 i = 0; i < 8; i++) { - if (mgmt->spurs->m.spuIdling & (1 << i)) { + if (spurs->m.spuIdling & (1 << i)) { nIdlingSpus++; } } - bool allSpusIdle = nIdlingSpus == mgmt->spurs->m.nSpus ? true: false; - bool exitIfNoWork = mgmt->spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; + bool allSpusIdle = nIdlingSpus == spurs->m.nSpus ? true: false; + bool exitIfNoWork = spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; + shouldExit = allSpusIdle && exitIfNoWork; // Check if any workloads can be scheduled bool foundReadyWorkload = false; - if (mgmt->spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { foundReadyWorkload = true; } else { - if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { + if (spurs->m.flags1 & SF1_32_WORKLOADS) { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { u32 j = i & 0x0F; u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; - u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : mgmt->spurs->m.wklMaxContention[j].read_relaxed() >> 4; - u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklCurrentContention[j] & 0x0F : mgmt->spurs->m.wklCurrentContention[j] >> 4; - u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : mgmt->spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); - u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->spurs->m.wklReadyCount1[j].read_relaxed() : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4; + u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklCurrentContention[j] & 0x0F : spurs->m.wklCurrentContention[j] >> 4; + u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); if (runnable && priority > 0 && maxContention > contention) { if (wklFlag || wklSignal || readyCount > contention) { @@ -713,14 +805,14 @@ void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { } else { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { u8 runnable = mgmt->wklRunnable1 & (0x8000 >> i); - u8 wklSignal = mgmt->spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); - u8 wklFlag = mgmt->spurs->m.wklFlag.flag.read_relaxed() == 0 ? mgmt->spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = mgmt->spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklReadyCount1[i].read_relaxed(); - u8 idleSpuCount = mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : mgmt->spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); + u8 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed(); + u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); u8 requestCount = readyCount + idleSpuCount; - if (runnable && mgmt->priority[i] != 0 && mgmt->spurs->m.wklMaxContention[i].read_relaxed() > mgmt->spurs->m.wklCurrentContention[i]) { - if (wklFlag || wklSignal || (readyCount != 0 && requestCount > mgmt->spurs->m.wklCurrentContention[i])) { + if (runnable && mgmt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > spurs->m.wklCurrentContention[i]) { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->m.wklCurrentContention[i])) { foundReadyWorkload = true; break; } @@ -729,33 +821,29 @@ void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { } } + bool spuIdling = spurs->m.spuIdling & (1 << mgmt->spuNum) ? true : false; + if (foundReadyWorkload && shouldExit == false) { + spurs->m.spuIdling &= ~(1 << mgmt->spuNum); + } else { + spurs->m.spuIdling |= 1 << mgmt->spuNum; + } + // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. - if ((mgmt->spurs->m.spuIdling & (1 << mgmt->spuNum)) && (allSpusIdle == false || exitIfNoWork == false) && foundReadyWorkload == false) { - // The system service blocks by making a reservation and waiting on the reservation lost event. This is unfortunately - // not yet completely implemented in rpcs3. So we busy wait here. - //u128 r; - //spu.ReadChannel(r, 0); - - Emu.GetCoreMutex().unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - Emu.GetCoreMutex().lock(); + if (spuIdling && shouldExit == false && foundReadyWorkload == false) { + // The system service blocks by making a reservation and waiting on the lock line reservation lost event. + u128 r; + spu.ReadChannel(r, SPU_RdEventStat); + spu.WriteChannel(SPU_WrEventAck, u128::from32r(SPU_EVENT_LR)); } - if ((allSpusIdle == true && exitIfNoWork == true) || foundReadyWorkload == false) { - mgmt->spurs->m.spuIdling |= 1 << mgmt->spuNum; - } else { - mgmt->spurs->m.spuIdling &= ~(1 << mgmt->spuNum); + auto dmaSuccess = spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + if (dmaSuccess && (shouldExit || foundReadyWorkload)) { + break; } + } - Emu.GetCoreMutex().unlock(); - - if (allSpusIdle == false || exitIfNoWork == false) { - if (foundReadyWorkload == true) { - return; - } - } else { - // TODO: exit spu thread group - } + if (shouldExit) { + // TODO: exit spu thread group } } @@ -764,22 +852,31 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); if (mgmt->spurs.addr() % CellSpurs::align) { - assert(0); + spursHalt(spu); + return; } // Initialise the system service if this is the first time its being started on this SPU if (mgmt->sysSrvInitialised == 0) { mgmt->sysSrvInitialised = 1; - LV2_LOCK(0); - if (mgmt->spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { - assert(0); - } + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - mgmt->spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; - mgmt->traceBuffer = 0; - mgmt->traceMsgCount = -1; + do { + spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + CellSpurs * spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + // Halt if already initialised + if (spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { + spursHalt(spu); + return; + } + + spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + mgmt->traceBuffer = 0; + mgmt->traceMsgCount = -1; spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0); spursSysServiceCleanupAfterPreemption(spu, mgmt); @@ -818,6 +915,8 @@ poll: pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; pkt.data.stop = SPURS_GUID_SYS_WKL; cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); break; } @@ -849,10 +948,6 @@ bool spursSysServiceWorkloadEntry(SPUThread & spu) { auto arg = spu.GPR[4]._u64[1]; auto pollStatus = spu.GPR[5]._u32[3]; - spu.GPR[1]._u32[3] = 0x3FFD0; - *(vm::ptr::make(spu.GPR[1]._u32[3])) = 0x3FFF0; - memset(vm::get_ptr(spu.ls_offset + 0x3FFE0), 0, 32); - if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { spursSysServiceWorkloadMain(spu, pollStatus); } else { @@ -860,7 +955,6 @@ bool spursSysServiceWorkloadEntry(SPUThread & spu) { // system service workload. Need to implement this. } - // TODO: Ensure that this function always returns to the SPURS kernel return false; } From 4ea1b8cffc8a0f9e4c54cb0dcb18f90986d461ff Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 30 Jan 2015 23:01:13 +0300 Subject: [PATCH 43/94] Fixed TLS for PPU threads --- rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 6 ++ rpcs3/Emu/Cell/PPUThread.cpp | 6 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 60 ++++++++++++++++++++ rpcs3/Loader/ELF64.cpp | 3 +- 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index abb831ae32..b833a38c5f 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -18,6 +18,8 @@ namespace sce_libc_func { sceLibc.Error("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso); + LV2_LOCK(0); + g_atexit.insert(g_atexit.begin(), [func, arg, dso](ARMv7Context& context) { func(context, arg); @@ -28,6 +30,8 @@ namespace sce_libc_func { sceLibc.Error("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso); + LV2_LOCK(0); + g_atexit.insert(g_atexit.begin(), [func, arg, dso](ARMv7Context& context) { func(context, arg); @@ -38,6 +42,8 @@ namespace sce_libc_func { sceLibc.Error("exit()"); + LV2_LOCK(0); + for (auto func : g_atexit) { func(context); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 9e5588276a..9a221b00c6 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -15,6 +15,9 @@ u64 rotate_mask[64][64]; +extern u32 ppu_get_tls(u32 thread); +extern void ppu_free_tls(u32 thread); + PPUThread& GetCurrentPPUThread() { PPCThread* thread = GetCurrentPPCThread(); @@ -32,6 +35,7 @@ PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU) PPUThread::~PPUThread() { + ppu_free_tls(GetId()); } void PPUThread::DoReset() @@ -92,7 +96,7 @@ void PPUThread::InitRegs() GPR[2] = rtoc; //GPR[11] = entry; //GPR[12] = Emu.GetMallocPageSize(); - GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; + GPR[13] = ppu_get_tls(GetId()) + 0x7000; // 0x7000 is usually subtracted from r13 to access first TLS element (details are not clear) LR = Emu.GetCPUThreadExit(); CTR = PC; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 1629d3fb05..c523ca64f1 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -23,11 +23,62 @@ Module *sysPrxForUser = nullptr; +u32 g_tls_size; // size of every thread's storage +u32 g_tls_start; // start of TLS memory area +u32 g_tls_image_addr; // address of TLS initialization area +u32 g_tls_image_size; // size of TLS initialization area + +const u32 TLS_MAX = 256; +std::array, TLS_MAX> g_tls_owners; + void sys_initialize_tls() { sysPrxForUser->Log("sys_initialize_tls()"); } +u32 ppu_get_tls(u32 thread) +{ + if (!g_tls_start) + { + g_tls_size = vm::cast(Emu.GetTLSMemsz(), "Emu.GetTLSMemsz"); // (not an address for vm::cast, but fine) + g_tls_start = vm::cast(Memory.Alloc(g_tls_size * TLS_MAX, 4096)); // memory for up to TLS_MAX threads + g_tls_image_addr = vm::cast(Emu.GetTLSAddr(), "Emu.GetTLSAddr"); + g_tls_image_size = vm::cast(Emu.GetTLSFilesz(), "Emu.GetTLSFilesz"); + + sysPrxForUser->Warning("TLS initialized (g_tls_size=0x%x, g_tls_start=0x%x, g_tls_image_addr=0x%x, g_tls_image_size=0x%x)", g_tls_size, g_tls_start, g_tls_image_addr, g_tls_image_size); + } + + for (auto& v : g_tls_owners) + { + u32 old = 0; + if (v.compare_exchange_strong(old, thread)) + { + const u32 addr = g_tls_start + (&v - g_tls_owners.data()) * g_tls_size; // get TLS address + memset(vm::get_ptr(addr), 0, g_tls_size); // fill TLS area with zeros + memcpy(vm::get_ptr(addr), vm::get_ptr(g_tls_image_addr), g_tls_image_size); // initialize from TLS image + return addr; + } + else if (old == thread) + { + return g_tls_start + (&v - g_tls_owners.data()) * g_tls_size; // if already initialized, return TLS address again + } + } + + throw "Out of TLS memory"; +} + +void ppu_free_tls(u32 thread) +{ + for (auto& v : g_tls_owners) + { + u32 old = thread; + if (v.compare_exchange_strong(old, 0)) + { + return; + } + } +} + int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size) { sysPrxForUser->Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size); @@ -365,6 +416,15 @@ void sysPrxForUser_init(Module *pxThis) { sysPrxForUser = pxThis; + g_tls_size = 0; + g_tls_start = 0; + g_tls_image_addr = 0; + g_tls_image_size = 0; + for (auto& v : g_tls_owners) + { + v.store(0, std::memory_order_relaxed); + } + // Setup random number generator srand(time(NULL)); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index c71e8cb5f7..de2a78c0a6 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -356,7 +356,7 @@ namespace loader ppu_thr_stop_data[1] = BLR(); Emu.SetCPUThreadStop(ppu_thr_stop_data.addr()); - vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); + //vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); /* //TODO static const int branch_size = 6 * 4; @@ -423,7 +423,6 @@ namespace loader case 0x00000007: //TLS Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value()); - LOG_ERROR(LOADER, "TLS: addr=0x%x, filesz=0x%x, memsz=0x%x", Emu.GetTLSAddr(), Emu.GetTLSFilesz(), Emu.GetTLSMemsz()); break; case 0x60000001: //LOOS+1 From f7b7c234b7d745e41f35ff8cce2350b623875562 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 31 Jan 2015 01:32:07 +0530 Subject: [PATCH 44/94] SPURS: Implement some SPU thread functions used by the system service module --- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 83 ++++++++++++++++++++++++++++++ rpcs3/Emu/SysCalls/lv2/sys_spu.h | 6 +++ 2 files changed, 89 insertions(+) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 29cdb9bd39..b6d29837e2 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -1099,3 +1099,86 @@ s32 sys_raw_spu_get_spu_cfg(u32 id, vm::ptr value) *value = (u32)t->cfg.value; return CELL_OK; } + +void sys_spu_thread_exit(SPUThread & spu, s32 status) +{ + // Cancel any pending status update requests + u128 r; + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(0)); + while (spu.GetChannelCount(MFC_RdTagStat) != 1); + spu.ReadChannel(r, MFC_RdTagStat); + + // Wait for all pending DMA operations to complete + spu.WriteChannel(MFC_WrTagMask, u128::from32r(0xFFFFFFFF)); + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(MFC_TAG_UPDATE_ALL)); + spu.ReadChannel(r, MFC_RdTagStat); + + spu.WriteChannel(SPU_WrOutMbox, u128::from32r(status)); + spu.StopAndSignal(0x102); +} + +void sys_spu_thread_group_exit(SPUThread & spu, s32 status) +{ + // Cancel any pending status update requests + u128 r; + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(0)); + while (spu.GetChannelCount(MFC_RdTagStat) != 1); + spu.ReadChannel(r, MFC_RdTagStat); + + // Wait for all pending DMA operations to complete + spu.WriteChannel(MFC_WrTagMask, u128::from32r(0xFFFFFFFF)); + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(MFC_TAG_UPDATE_ALL)); + spu.ReadChannel(r, MFC_RdTagStat); + + spu.WriteChannel(SPU_WrOutMbox, u128::from32r(status)); + spu.StopAndSignal(0x101); +} + +s32 sys_spu_thread_send_event(SPUThread & spu, u8 spup, u32 data0, u32 data1) +{ + if (spup > 0x3F) + { + return CELL_EINVAL; + } + + if (spu.GetChannelCount(SPU_RdInMbox)) + { + return CELL_EBUSY; + } + + spu.WriteChannel(SPU_WrOutMbox, u128::from32r(data1)); + spu.WriteChannel(SPU_WrOutIntrMbox, u128::from32r((spup << 24) | (data0 & 0x00FFFFFF))); + + u128 r; + spu.ReadChannel(r, SPU_RdInMbox); + return r._u32[3]; +} + +s32 sys_spu_thread_switch_system_module(SPUThread & spu, u32 status) +{ + if (spu.GetChannelCount(SPU_RdInMbox)) + { + return CELL_EBUSY; + } + + // Cancel any pending status update requests + u128 r; + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(0)); + while (spu.GetChannelCount(MFC_RdTagStat) != 1); + spu.ReadChannel(r, MFC_RdTagStat); + + // Wait for all pending DMA operations to complete + spu.WriteChannel(MFC_WrTagMask, u128::from32r(0xFFFFFFFF)); + spu.WriteChannel(MFC_WrTagUpdate, u128::from32r(MFC_TAG_UPDATE_ALL)); + spu.ReadChannel(r, MFC_RdTagStat); + + do + { + spu.WriteChannel(SPU_WrOutMbox, u128::from32r(status)); + spu.StopAndSignal(0x120); + spu.ReadChannel(r, SPU_RdInMbox); + } + while (r._u32[3] == CELL_EBUSY); + + return r._u32[3]; +} diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index e71c606bf7..e129455758 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -204,3 +204,9 @@ s32 sys_raw_spu_get_int_stat(u32 id, u32 class_id, vm::ptr stat); s32 sys_raw_spu_read_puint_mb(u32 id, vm::ptr value); s32 sys_raw_spu_set_spu_cfg(u32 id, u32 value); s32 sys_raw_spu_get_spu_cfg(u32 id, vm::ptr value); + +// SPU Calls +void sys_spu_thread_exit(SPUThread & spu, s32 status); +void sys_spu_thread_group_exit(SPUThread & spu, s32 status); +s32 sys_spu_thread_send_event(SPUThread & spu, u8 spup, u32 data0, u32 data1); +s32 sys_spu_thread_switch_system_module(SPUThread & spu, u32 status); From 140a42fbcb16f13a3f27fd7ff1ba4ecb1edd5255 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 31 Jan 2015 00:30:46 +0300 Subject: [PATCH 45/94] Bugfix --- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index c523ca64f1..063655cc72 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -48,20 +48,24 @@ u32 ppu_get_tls(u32 thread) sysPrxForUser->Warning("TLS initialized (g_tls_size=0x%x, g_tls_start=0x%x, g_tls_image_addr=0x%x, g_tls_image_size=0x%x)", g_tls_size, g_tls_start, g_tls_image_addr, g_tls_image_size); } - for (auto& v : g_tls_owners) + for (u32 i = 0; i < TLS_MAX; i++) + { + if (g_tls_owners[i] == thread) + { + return g_tls_start + i * g_tls_size; // if already initialized, return TLS address + } + } + + for (u32 i = 0; i < TLS_MAX; i++) { u32 old = 0; - if (v.compare_exchange_strong(old, thread)) + if (g_tls_owners[i].compare_exchange_strong(old, thread)) { - const u32 addr = g_tls_start + (&v - g_tls_owners.data()) * g_tls_size; // get TLS address - memset(vm::get_ptr(addr), 0, g_tls_size); // fill TLS area with zeros + const u32 addr = g_tls_start + i * g_tls_size; // get TLS address + memset(vm::get_ptr(addr), 0, g_tls_size); // fill TLS area with zeros memcpy(vm::get_ptr(addr), vm::get_ptr(g_tls_image_addr), g_tls_image_size); // initialize from TLS image return addr; } - else if (old == thread) - { - return g_tls_start + (&v - g_tls_owners.data()) * g_tls_size; // if already initialized, return TLS address again - } } throw "Out of TLS memory"; From d8bed3b0ced0bc219658ad90148f68e1caa6a5bd Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sat, 31 Jan 2015 03:35:03 +0530 Subject: [PATCH 46/94] SPURS: Implement some portions of the taskset PM --- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 6 +- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 130 ++++++++++++++++---- 2 files changed, 110 insertions(+), 26 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 4d77a06402..08fff45abf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -155,9 +155,11 @@ enum SpursWorkloadConstants : u64 // GUID SPURS_GUID_SYS_WKL = 0x1BB841BF38F89D33ull, + SPURS_GUID_TASKSET_PM = 0x836E915B2E654143ull, // Image addresses SPURS_IMG_ADDR_SYS_SRV_WORKLOAD = 0x100, + SPURS_IMG_ADDR_TASKSET_PM = 0x200, }; enum CellSpursModulePollStatus @@ -209,6 +211,8 @@ enum SpursTaskConstants CELL_SPURS_TASK_ATTRIBUTE_REVISION = 1, CELL_SPURS_TASKSET_ATTRIBUTE_REVISION = 1, CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, + CELL_SPURS_TASKSET_PM_ENTRY_ADDR = 0xA00, + CELL_SPURS_TASKSET_PM_SYSCALL_ADDR = 0xA70, }; enum CellSpursEventFlagWaitMode @@ -917,7 +921,7 @@ struct SpursTasksetPmMgmtData be_t x27B0; // 0x27B0 vm::bptr taskset; // 0x27B8 be_t kernelMgmtAddr; // 0x27C0 - be_t yieldAddr; // 0x27C4 + be_t syscallAddr; // 0x27C4 be_t x27C8; // 0x27C8 be_t spuNum; // 0x27CC be_t dmaTagId; // 0x27D0 diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index e6921057c1..653d4ca259 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -13,6 +13,7 @@ // void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag); u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status); +void cellSpursModuleExit(SPUThread & spu); bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag); u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask); @@ -39,8 +40,16 @@ void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus); bool spursSysServiceWorkloadEntry(SPUThread & spu); // -// SPURS taskset polict module functions +// SPURS taskset policy module functions // +bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); +void spursTasksetExit(SPUThread & spu); +void spursTasksetDispatch(SPUThread & spu); +void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus); +bool spursTasksetShouldYield(SPUThread & spu); +void spursTasksetInit(SPUThread & spu, u32 pollStatus); +void spursTasksetResumeTask(SPUThread & spu); +bool spursTasksetEntry(SPUThread & spu); extern Module *cellSpurs; @@ -73,6 +82,12 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { return wklId == mgmt->wklCurrentId ? 0 : 1; } +/// Exit current workload +void cellSpursModuleExit(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + spu.SetBranch(mgmt->yieldToKernelAddr); +} + /// Execute a DMA operation bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag) { spu.WriteChannel(MFC_LSA, u128::from32r(lsa)); @@ -416,7 +431,6 @@ bool spursKernelMain(SPUThread & spu) { bool isKernel2; u32 pollStatus; - u64 wklArg; if (spu.PC == CELL_SPURS_KERNEL1_ENTRY_ADDR || spu.PC == CELL_SPURS_KERNEL2_ENTRY_ADDR) { // Entry point of SPURS kernel // Save arguments @@ -453,9 +467,9 @@ bool spursKernelMain(SPUThread & spu) { spu.RegisterHleFunction(mgmt->yieldToKernelAddr, spursKernelMain); spu.RegisterHleFunction(mgmt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); - // Register the system HLE service workload entry point - spu.RegisterHleFunction(0xA00, spursSysServiceWorkloadEntry); - wklArg = mgmt->spurs->m.wklInfoSysSrv.arg; + // DMA in the system service workload info + spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklInfoSysSrv), 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID/*tag*/); + spursDmaWaitForCompletion(spu, 0x80000000); pollStatus = 0; } else if (spu.PC == mgmt->yieldToKernelAddr) { isKernel2 = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; @@ -468,15 +482,38 @@ bool spursKernelMain(SPUThread & spu) { spursKernel1SelectWorkload(spu); } - pollStatus = (u32)(spu.GPR[3]._u64[1]); - auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); - auto wklInfo = wid < CELL_SPURS_MAX_WORKLOAD ? &mgmt->spurs->m.wklInfo1[wid] : (wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &mgmt->spurs->m.wklInfo2[wid & 0xf] : - &mgmt->spurs->m.wklInfoSysSrv); - wklArg = wklInfo->arg; + pollStatus = (u32)(spu.GPR[3]._u64[1]); + auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); + + // DMA in the workload info for the selected workload + auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? offsetof(CellSpurs, m.wklInfo1[wid]) : + wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? offsetof(CellSpurs, m.wklInfo2[wid & 0xf]) : + offsetof(CellSpurs, m.wklInfoSysSrv); + spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + wklInfoOffset, 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + spursDmaWaitForCompletion(spu, 0x80000000); } else { assert(0); } + auto wklInfo = vm::get_ptr(spu.ls_offset + 0x3FFE0); + if (mgmt->wklCurrentAddr != wklInfo->addr) { + switch (wklInfo->addr.addr()) { + case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: + spu.RegisterHleFunction(0xA00, spursSysServiceWorkloadEntry); + break; + case SPURS_IMG_ADDR_TASKSET_PM: + spu.RegisterHleFunction(0xA00, spursTasksetEntry); + break; + default: + spursDma(spu, MFC_GET_CMD, wklInfo-> addr.addr(), 0xA00/*LSA*/, wklInfo->size, CELL_SPURS_KERNEL_DMA_TAG_ID); + spursDmaWaitForCompletion(spu, 0x80000000); + break; + } + + mgmt->wklCurrentAddr = wklInfo->addr; + mgmt->wklCurrentUniqueId = wklInfo->uniqueId.read_relaxed(); + } + if (!isKernel2) { mgmt->moduleId[0] = 0; mgmt->moduleId[1] = 0; @@ -486,7 +523,7 @@ bool spursKernelMain(SPUThread & spu) { spu.GPR[0]._u32[3] = mgmt->yieldToKernelAddr; spu.GPR[1]._u32[3] = 0x3FFB0; spu.GPR[3]._u32[3] = 0x100; - spu.GPR[4]._u64[1] = wklArg; + spu.GPR[4]._u64[1] = wklInfo->arg; spu.GPR[5]._u32[3] = pollStatus; spu.SetBranch(0xA00); return false; @@ -597,7 +634,8 @@ void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 } if (notify) { - // TODO: sys_spu_thread_send_event(spurs->m.spuPort, 2, 0); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + sys_spu_thread_send_event(spu, spurs->m.spuPort, 2, 0); } } @@ -1020,6 +1058,24 @@ bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 return false; } +void spursTasksetExit(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + + // Trace - STOP + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = 0x54; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_STOP + pkt.data.stop = SPURS_GUID_TASKSET_PM; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + // Not sure why this check exists. Perhaps to check for memory corruption. + if (memcmp(mgmt->moduleId, "SPURSTASK MODULE", 16) != 0) { + spursHalt(spu); + } + + cellSpursModuleExit(spu); +} + void spursTasksetDispatch(SPUThread & spu) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); @@ -1028,7 +1084,8 @@ void spursTasksetDispatch(SPUThread & spu) { u32 isWaiting; spursTasksetProcessRequest(spu, 5, &taskId, &isWaiting); if (taskId >= CELL_SPURS_MAX_TASK) { - // TODO: spursTasksetExit(spu); + spursTasksetExit(spu); + return; } mgmt->taskId = taskId; @@ -1109,11 +1166,23 @@ void spursTasksetInit(SPUThread & spu, u32 pollStatus) { spursTasksetProcessPollStatus(spu, pollStatus); } -void spursTasksetEntry(SPUThread & spu) { +void spursTasksetResumeTask(SPUThread & spu) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - // Check if the function was invoked by the SPURS kernel or because of a syscall - if (spu.PC != 0xA70) { + // Restore task context + spu.GPR[0] = mgmt->savedContextLr; + spu.GPR[1] = mgmt->savedContextSp; + for (auto i = 0; i < 48; i++) { + spu.GPR[80 + i] = mgmt->savedContextR80ToR127[i]; + } + + spu.SetBranch(spu.GPR[0]._u32[3]); +} + +bool spursTasksetEntry(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + + if (spu.PC == CELL_SPURS_TASKSET_PM_ENTRY_ADDR) { // Called from kernel auto kernelMgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); auto arg = spu.GPR[4]._u64[1]; @@ -1123,20 +1192,31 @@ void spursTasksetEntry(SPUThread & spu) { mgmt->taskset.set(arg); memcpy(mgmt->moduleId, "SPURSTASK MODULE", 16); mgmt->kernelMgmtAddr = spu.GPR[3]._u32[3]; - mgmt->yieldAddr = 0xA70; + mgmt->syscallAddr = CELL_SPURS_TASKSET_PM_SYSCALL_ADDR; mgmt->spuNum = kernelMgmt->spuNum; mgmt->dmaTagId = kernelMgmt->dmaTagId; mgmt->taskId = 0xFFFFFFFF; + // Register SPURS takset policy module HLE functions + spu.UnregisterHleFunctions(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, 0x40000); // TODO: use a symbolic constant + spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry); + spu.RegisterHleFunction(mgmt->syscallAddr, spursTasksetEntry); + spursTasksetInit(spu, pollStatus); - // TODO: Dispatch + spursTasksetDispatch(spu); + } else if (spu.PC == CELL_SPURS_TASKSET_PM_SYSCALL_ADDR) { + // Save task context + mgmt->savedContextLr = spu.GPR[0]; + mgmt->savedContextSp = spu.GPR[1]; + for (auto i = 0; i < 48; i++) { + mgmt->savedContextR80ToR127[i] = spu.GPR[80 + i]; + } + + // TODO: Process syscall + spursTasksetResumeTask(spu); + } else { + assert(0); } - mgmt->savedContextLr = spu.GPR[0]; - mgmt->savedContextSp = spu.GPR[1]; - for (auto i = 0; i < 48; i++) { - mgmt->savedContextR80ToR127[i] = spu.GPR[80 + i]; - } - - // TODO: Process syscall + return false; } From 384cb5e4153d79896fac17d1ec4a6082227c042e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 31 Jan 2015 16:01:34 +0300 Subject: [PATCH 47/94] RSX "refactoring" reverted --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 1077 ++++++++++++++++------------- rpcs3/Emu/RSX/GL/GLGSRender.h | 41 +- rpcs3/Emu/RSX/Null/NullGSRender.h | 84 ++- rpcs3/Emu/RSX/RSXThread.cpp | 969 +++++++++++++------------- rpcs3/Emu/RSX/RSXThread.h | 46 +- 5 files changed, 1104 insertions(+), 1113 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 35ec0a7dc5..1b3df4a0bd 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -18,9 +18,9 @@ void SetGetGSFrameCallback(GetGSFrameCb value) #define DUMP_VERTEX_DATA 0 #if CMD_DEBUG - #define CMD_LOG(...) LOG_NOTICE(RSX, __VA_ARGS__) +#define CMD_LOG(...) LOG_NOTICE(RSX, __VA_ARGS__) #else - #define CMD_LOG(...) +#define CMD_LOG(...) #endif GLuint g_flip_tex, g_depth_tex, g_pbo[6]; @@ -41,7 +41,7 @@ void printGlError(GLenum err, const std::string& situation) } #if 0 - #define checkForGlError(x) /*x*/ +#define checkForGlError(x) /*x*/ #endif void GLTexture::Create() @@ -110,9 +110,9 @@ void GLTexture::Init(RSXTexture& tex) LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr); return; } - //lOG_WARNING(RSX, "texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x", + //LOG_WARNING(RSX, "texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x", // m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod); - + //TODO: safe init checkForGlError("GLTexture::Init() -> glBindTexture"); @@ -134,10 +134,11 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE }; glRemap = swizzleMaskB8; + break; } - break; case CELL_GCM_TEXTURE_A1R5G5B5: + { glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); checkForGlError("GLTexture::Init() -> glPixelStorei"); @@ -147,7 +148,8 @@ void GLTexture::Init(RSXTexture& tex) glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_A1R5G5B5)"); - break; + break; + } case CELL_GCM_TEXTURE_A4R4G4B4: { @@ -157,8 +159,8 @@ void GLTexture::Init(RSXTexture& tex) // We read it in as R4G4B4A4, so we need to remap each component. static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN }; glRemap = swizzleMaskA4R4G4B4; + break; } - break; case CELL_GCM_TEXTURE_R5G6B5: { @@ -170,8 +172,8 @@ void GLTexture::Init(RSXTexture& tex) glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G6B5)"); + break; } - break; case CELL_GCM_TEXTURE_A8R8G8B8: { @@ -195,11 +197,11 @@ void GLTexture::Init(RSXTexture& tex) } } } - + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, is_swizzled ? unswizzledPixels : pixels); checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A8R8G8B8)"); + break; } - break; case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes { @@ -207,8 +209,8 @@ void GLTexture::Init(RSXTexture& tex) glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels); checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT1)"); + break; } - break; case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes { @@ -217,7 +219,7 @@ void GLTexture::Init(RSXTexture& tex) glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels); checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT23)"); } - break; + break; case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes { @@ -225,8 +227,8 @@ void GLTexture::Init(RSXTexture& tex) glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels); checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT45)"); + break; } - break; case CELL_GCM_TEXTURE_G8B8: { @@ -235,8 +237,8 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; glRemap = swizzleMaskG8B8; + break; } - break; case CELL_GCM_TEXTURE_R6G5B5: { @@ -256,36 +258,36 @@ void GLTexture::Init(RSXTexture& tex) checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R6G5B5)"); free(unswizzledPixels); + break; } - break; case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage { glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH24_D8)"); + break; } - break; case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage { glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT)"); + break; } - break; case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number { glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH16)"); + break; } - break; case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float { glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH16_FLOAT)"); + break; } - break; case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number { @@ -300,8 +302,8 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE }; glRemap = swizzleMaskX16; + break; } - break; case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers { @@ -316,8 +318,8 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED }; glRemap = swizzleMaskX32_Y16_X16; + break; } - break; case CELL_GCM_TEXTURE_R5G5B5A1: { @@ -329,8 +331,8 @@ void GLTexture::Init(RSXTexture& tex) glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G5B5A1)"); + break; } - break; case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values { @@ -342,15 +344,15 @@ void GLTexture::Init(RSXTexture& tex) glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)"); + break; } - break; case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_FLOAT, pixels); checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT)"); + break; } - break; case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number { @@ -359,8 +361,8 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE }; glRemap = swizzleMaskX32_FLOAT; + break; } - break; case CELL_GCM_TEXTURE_D1R5G5B5: { @@ -376,8 +378,8 @@ void GLTexture::Init(RSXTexture& tex) glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_D1R5G5B5)"); + break; } - break; case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers { @@ -386,8 +388,9 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE }; glRemap = swizzleMaskX32_D8R8G8B8; + break; } - break; + case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values { @@ -402,15 +405,16 @@ void GLTexture::Init(RSXTexture& tex) static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN }; glRemap = swizzleMaskX32_Y16_X16_FLOAT; + break; } - break; - case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): + case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8: { const u32 numPixels = tex.GetWidth() * tex.GetHeight(); unswizzledPixels = (u8 *)malloc(numPixels * 4); // TODO: Speed. - for (u32 i = 0; i < numPixels; i += 2) { + for (u32 i = 0; i < numPixels; i += 2) + { unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3]; unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2]; unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0]; @@ -427,15 +431,16 @@ void GLTexture::Init(RSXTexture& tex) checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)"); free(unswizzledPixels); + break; } - break; - case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN): + case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8: { const u32 numPixels = tex.GetWidth() * tex.GetHeight(); unswizzledPixels = (u8 *)malloc(numPixels * 4); // TODO: Speed. - for (u32 i = 0; i < numPixels; i += 2) { + for (u32 i = 0; i < numPixels; i += 2) + { unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2]; unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3]; unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1]; @@ -452,13 +457,16 @@ void GLTexture::Init(RSXTexture& tex) checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)"); free(unswizzledPixels); - } - break; - - default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40); break; } + default: + { + LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format, (is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40); + break; + } + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.GetMipmap() > 1); @@ -746,7 +754,7 @@ void DrawCursorObj::InitializeShaders() " gl_Position = in_pos;\n" "}\n"; - m_fp.shader = + m_fp.shader = "#version 420\n" "\n" "in vec2 tc;\n" @@ -797,6 +805,18 @@ GLGSRender::~GLGSRender() m_frame->DeleteContext(m_context); } +void GLGSRender::Enable(bool enable, const u32 cap) +{ + if (enable) + { + glEnable(cap); + } + else + { + glDisable(cap); + } +} + extern CellGcmContextData current_context; void GLGSRender::Close() @@ -887,58 +907,58 @@ void GLGSRender::EnableVertexData(bool indexed_draw) switch (m_vertex_data[i].type) { case CELL_GCM_VERTEX_S1: - for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=2) + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 2) { dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j])); - if (!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); + if (!(((j + 2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); } - break; + break; case CELL_GCM_VERTEX_F: - for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=4) + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 4) { dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j])); - if (!(((j+4) / 4) % m_vertex_data[i].size)) dump.Write("\n"); + if (!(((j + 4) / 4) % m_vertex_data[i].size)) dump.Write("\n"); } - break; + break; case CELL_GCM_VERTEX_SF: - for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=2) + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 2) { dump.Write(wxString::Format("%.01f\n", *(float*)&m_vertex_data[i].data[j])); - if (!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); + if (!(((j + 2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); } - break; + break; case CELL_GCM_VERTEX_UB: for (u32 j = 0; j < m_vertex_data[i].data.size(); ++j) { dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j])); - if (!((j+1) % m_vertex_data[i].size)) dump.Write("\n"); + if (!((j + 1) % m_vertex_data[i].size)) dump.Write("\n"); } - break; + break; case CELL_GCM_VERTEX_S32K: - for (u32 j = 0; j < m_vertex_data[i].data.size(); j+=2) + for (u32 j = 0; j < m_vertex_data[i].data.size(); j += 2) { dump.Write(wxString::Format("%d\n", *(u16*)&m_vertex_data[i].data[j])); - if (!(((j+2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); + if (!(((j + 2) / 2) % m_vertex_data[i].size)) dump.Write("\n"); } - break; - - // case CELL_GCM_VERTEX_CMP: - + break; + + // case CELL_GCM_VERTEX_CMP: + case CELL_GCM_VERTEX_UB256: for (u32 j = 0; j < m_vertex_data[i].data.size(); ++j) { dump.Write(wxString::Format("%d\n", m_vertex_data[i].data[j])); - if (!((j+1) % m_vertex_data[i].size)) dump.Write("\n"); + if (!((j + 1) % m_vertex_data[i].size)) dump.Write("\n"); } - break; + break; default: LOG_ERROR(HLE, "Bad cv type! %d", m_vertex_data[i].type); - return; + return; } dump.Write("\n"); @@ -966,7 +986,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw) GL_FALSE, }; - if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7) + if (m_vertex_data[i].type < 1 || m_vertex_data[i].type > 7) { LOG_ERROR(RSX, "GLGSRender::EnableVertexData: Bad vertex data type (%d)!", m_vertex_data[i].type); } @@ -984,7 +1004,7 @@ void GLGSRender::EnableVertexData(bool indexed_draw) case 3: glVertexAttrib3sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; case 4: glVertexAttrib4sv(i, (GLshort*)&m_vertex_data[i].data[0]); break; } - break; + break; case CELL_GCM_VERTEX_F: switch (m_vertex_data[i].size) @@ -994,12 +1014,12 @@ void GLGSRender::EnableVertexData(bool indexed_draw) case 3: glVertexAttrib3fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; case 4: glVertexAttrib4fv(i, (GLfloat*)&m_vertex_data[i].data[0]); break; } - break; + break; case CELL_GCM_VERTEX_CMP: case CELL_GCM_VERTEX_UB: glVertexAttrib4ubv(i, (GLubyte*)&m_vertex_data[i].data[0]); - break; + break; } checkForGlError("glVertexAttrib"); @@ -1034,9 +1054,9 @@ void GLGSRender::InitVertexData() int l; GLfloat scaleOffsetMat[16] = { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; @@ -1076,7 +1096,7 @@ void GLGSRender::InitFragmentData() return; } - for (const RSXTransformConstant& c : m_fragment_constants) + for (const RSXTransformConstant& c : m_fragment_constants) { u32 id = c.id - m_cur_fragment_prog->offset; @@ -1101,15 +1121,15 @@ bool GLGSRender::LoadProgram() LOG_WARNING(RSX, "LoadProgram: m_cur_shader_prog == NULL"); return false; } - + m_cur_fragment_prog->ctrl = m_shader_ctrl; - + if (!m_cur_vertex_prog) { LOG_WARNING(RSX, "LoadProgram: m_cur_vertex_prog == NULL"); return false; } - + m_fp_buf_num = m_prog_buffer.SearchFp(*m_cur_fragment_prog, m_fragment_prog); m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog, m_vertex_prog); @@ -1391,14 +1411,14 @@ void GLGSRender::WriteColorBuffers() glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); WriteColorBufferA(); - break; + break; case CELL_GCM_SURFACE_TARGET_1: glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[1]); glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); WriteColorBufferB(); - break; + break; case CELL_GCM_SURFACE_TARGET_MRT1: for (int i = 0; i < 2; i++) @@ -1409,7 +1429,7 @@ void GLGSRender::WriteColorBuffers() glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); WriteColorBufferA(); WriteColorBufferB(); - break; + break; case CELL_GCM_SURFACE_TARGET_MRT2: for (int i = 0; i < 3; i++) @@ -1421,7 +1441,7 @@ void GLGSRender::WriteColorBuffers() WriteColorBufferA(); WriteColorBufferB(); WriteColorBufferC(); - break; + break; case CELL_GCM_SURFACE_TARGET_MRT3: for (int i = 0; i < 4; i++) @@ -1434,7 +1454,7 @@ void GLGSRender::WriteColorBuffers() WriteColorBufferB(); WriteColorBufferC(); WriteColorBufferD(); - break; + break; } } @@ -1480,7 +1500,7 @@ void GLGSRender::OnExitThread() glDeleteTextures(1, &g_flip_tex); glDeleteTextures(1, &g_depth_tex); glDeleteBuffers(6, g_pbo); - + glDisable(GL_TEXTURE_2D); glDisable(GL_VERTEX_PROGRAM_POINT_SIZE); @@ -1530,15 +1550,31 @@ void GLGSRender::InitDrawBuffers() m_rbo.Bind(4); - if (m_surface_depth_format == CELL_GCM_SURFACE_Z16) + switch (m_surface_depth_format) + { + case 0: + { + // case 0 found in BLJM60410-[Suzukaze no Melt - Days in the Sanctuary] + // [E : RSXThread]: Bad depth format! (0) + // [E : RSXThread]: glEnable: opengl error 0x0506 + // [E : RSXThread]: glDrawArrays: opengl error 0x0506 + m_rbo.Storage(GL_DEPTH_COMPONENT, RSXThread::m_width, RSXThread::m_height); + checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT)"); + break; + } + + case CELL_GCM_SURFACE_Z16: { m_rbo.Storage(GL_DEPTH_COMPONENT16, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_DEPTH_COMPONENT16)"); m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4)); checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); + break; } - else if (m_surface_depth_format == CELL_GCM_SURFACE_Z24S8) + + + case CELL_GCM_SURFACE_Z24S8: { m_rbo.Storage(GL_DEPTH24_STENCIL8, RSXThread::m_width, RSXThread::m_height); checkForGlError("m_rbo.Storage(GL_DEPTH24_STENCIL8)"); @@ -1548,6 +1584,18 @@ void GLGSRender::InitDrawBuffers() m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4)); checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); + + break; + + } + + + default: + { + LOG_ERROR(RSX, "Bad depth format! (%d)", m_surface_depth_format); + assert(0); + break; + } } for (int i = 0; i < 4; ++i) @@ -1555,6 +1603,15 @@ void GLGSRender::InitDrawBuffers() m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0 + i, m_rbo.GetId(i)); checkForGlError(fmt::Format("m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT%d)", i)); } + + //m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT, m_rbo.GetId(4)); + //checkForGlError("m_fbo.Renderbuffer(GL_DEPTH_ATTACHMENT)"); + + //if (m_surface_depth_format == 2) + //{ + // m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT, m_rbo.GetId(4)); + // checkForGlError("m_fbo.Renderbuffer(GL_STENCIL_ATTACHMENT)"); + //} } if (!m_set_surface_clip_horizontal) @@ -1568,41 +1625,56 @@ void GLGSRender::InitDrawBuffers() m_surface_clip_y = 0; m_surface_clip_h = RSXThread::m_height; } - + m_fbo.Bind(); static const GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; switch (m_surface_color_target) { - case CELL_GCM_SURFACE_TARGET_NONE: - break; + case CELL_GCM_SURFACE_TARGET_NONE: break; case CELL_GCM_SURFACE_TARGET_0: + { glDrawBuffer(draw_buffers[0]); - break; - + checkForGlError("glDrawBuffer(0)"); + break; + } + case CELL_GCM_SURFACE_TARGET_1: + { glDrawBuffer(draw_buffers[1]); - break; - + checkForGlError("glDrawBuffer(1)"); + break; + } + case CELL_GCM_SURFACE_TARGET_MRT1: + { glDrawBuffers(2, draw_buffers); - break; - + checkForGlError("glDrawBuffers(2)"); + break; + } + case CELL_GCM_SURFACE_TARGET_MRT2: + { glDrawBuffers(3, draw_buffers); - break; + checkForGlError("glDrawBuffers(3)"); + break; + } case CELL_GCM_SURFACE_TARGET_MRT3: + { glDrawBuffers(4, draw_buffers); - break; - - checkForGlError("glDrawBuffers"); + checkForGlError("glDrawBuffers(4)"); + break; + } default: + { LOG_ERROR(RSX, "Bad surface color target: %d", m_surface_color_target); - break; + break; + } + } if (m_read_buffer) @@ -1621,326 +1693,63 @@ void GLGSRender::InitDrawBuffers() } } -void GLGSRender::Enable(u32 cmd, u32 enable) +void GLGSRender::ExecCMD(u32 cmd) { - switch (cmd) - { - case NV4097_SET_DITHER_ENABLE: - enable ? glEnable(GL_DITHER) : glDisable(GL_DITHER); - break; + assert(cmd == NV4097_CLEAR_SURFACE); - case NV4097_SET_ALPHA_TEST_ENABLE: - enable ? glEnable(GL_ALPHA_TEST) : glDisable(GL_ALPHA_TEST); - break; - - case NV4097_SET_STENCIL_TEST_ENABLE: - enable ? glEnable(GL_STENCIL_TEST) : glDisable(GL_STENCIL_TEST); - break; - - case NV4097_SET_DEPTH_TEST_ENABLE: - enable ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); - break; - - case NV4097_SET_CULL_FACE_ENABLE: - enable ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE); - break; - - case NV4097_SET_BLEND_ENABLE: - enable ? glEnable(GL_BLEND) : glDisable(GL_BLEND); - break; - - case NV4097_SET_POLY_OFFSET_FILL_ENABLE: - enable ? glEnable(GL_POLYGON_OFFSET_FILL) : glDisable(GL_POLYGON_OFFSET_FILL); - break; - - case NV4097_SET_POLY_OFFSET_LINE_ENABLE: - enable ? glEnable(GL_POLYGON_OFFSET_LINE) : glDisable(GL_POLYGON_OFFSET_LINE); - break; - - case NV4097_SET_POLY_OFFSET_POINT_ENABLE: - enable ? glEnable(GL_POLYGON_OFFSET_POINT) : glDisable(GL_POLYGON_OFFSET_POINT); - break; - - case NV4097_SET_LOGIC_OP_ENABLE: - enable ? glEnable(GL_LOGIC_OP) : glDisable(GL_LOGIC_OP); - break; - - case NV4097_SET_SPECULAR_ENABLE: - enable ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING); - break; - - case NV4097_SET_LINE_SMOOTH_ENABLE: - enable ? glEnable(GL_LINE_SMOOTH) : glDisable(GL_LINE_SMOOTH); - break; - - case NV4097_SET_POLY_SMOOTH_ENABLE: - enable ? glEnable(GL_POLYGON_SMOOTH) : glDisable(GL_POLYGON_SMOOTH); - break; - - case NV4097_SET_RESTART_INDEX_ENABLE: - enable ? glEnable(GL_PRIMITIVE_RESTART) : glDisable(GL_PRIMITIVE_RESTART); - break; - - case NV4097_SET_POINT_SPRITE_CONTROL: - enable ? glEnable(GL_POINT_SPRITE) : glDisable(GL_POINT_SPRITE); - break; - - case NV4097_SET_LINE_STIPPLE: - enable ? glEnable(GL_LINE_STIPPLE) : glDisable(GL_LINE_STIPPLE); - break; - - case NV4097_SET_POLYGON_STIPPLE: - enable ? glEnable(GL_POLYGON_STIPPLE) : glDisable(GL_POLYGON_STIPPLE); - break; - - case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE: - enable ? glEnable(GL_DEPTH_BOUNDS_TEST_EXT) : glDisable(GL_DEPTH_BOUNDS_TEST_EXT); - break; - - case NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE: - enable ? glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT) : glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); - break; - - case NV4097_SET_USER_CLIP_PLANE_CONTROL: - const u32 clip_plane_0 = enable & 0xf; - const u32 clip_plane_1 = (enable >> 4) & 0xf; - const u32 clip_plane_2 = (enable >> 8) & 0xf; - const u32 clip_plane_3 = (enable >> 12) & 0xf; - const u32 clip_plane_4 = (enable >> 16) & 0xf; - const u32 clip_plane_5 = enable >> 20; - - clip_plane_0 ? glEnable(GL_CLIP_PLANE0) : glDisable(GL_CLIP_PLANE0); - clip_plane_1 ? glEnable(GL_CLIP_PLANE1) : glDisable(GL_CLIP_PLANE1); - clip_plane_2 ? glEnable(GL_CLIP_PLANE2) : glDisable(GL_CLIP_PLANE2); - clip_plane_3 ? glEnable(GL_CLIP_PLANE3) : glDisable(GL_CLIP_PLANE3); - clip_plane_4 ? glEnable(GL_CLIP_PLANE4) : glDisable(GL_CLIP_PLANE4); - clip_plane_5 ? glEnable(GL_CLIP_PLANE5) : glDisable(GL_CLIP_PLANE5); - break; - } -} - -void GLGSRender::ClearColor(u32 a, u32 r, u32 g, u32 b) -{ - glClearColor(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); - checkForGlError("glClearColor"); -} - -void GLGSRender::ClearStencil(u32 stencil) -{ - glClearStencil(stencil); - checkForGlError("glClearStencil"); -} - -void GLGSRender::ClearDepth(u32 depth) -{ - glClearDepth(depth / (float)0xffffff); - checkForGlError("glClearDepth"); -} - -void GLGSRender::ClearSurface(u32 mask) -{ InitDrawBuffers(); - GLbitfield clearMask = 0; - if (mask & 0x01) clearMask |= GL_DEPTH_BUFFER_BIT; - if (mask & 0x02) clearMask |= GL_STENCIL_BUFFER_BIT; - if (mask & 0xF0) clearMask |= GL_COLOR_BUFFER_BIT; - - glClear(clearMask); + if (m_set_color_mask) + { + glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); + checkForGlError("glColorMask"); + } + + if (m_set_scissor_horizontal && m_set_scissor_vertical) + { + glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + checkForGlError("glScissor"); + } + + GLbitfield f = 0; + + if (m_clear_surface_mask & 0x1) + { + glClearDepth(m_clear_surface_z / (float)0xffffff); + checkForGlError("glClearDepth"); + + f |= GL_DEPTH_BUFFER_BIT; + } + + if (m_clear_surface_mask & 0x2) + { + glClearStencil(m_clear_surface_s); + checkForGlError("glClearStencil"); + + f |= GL_STENCIL_BUFFER_BIT; + } + + if (m_clear_surface_mask & 0xF0) + { + glClearColor( + m_clear_surface_color_r / 255.0f, + m_clear_surface_color_g / 255.0f, + m_clear_surface_color_b / 255.0f, + m_clear_surface_color_a / 255.0f); + checkForGlError("glClearColor"); + + f |= GL_COLOR_BUFFER_BIT; + } + + glClear(f); checkForGlError("glClear"); WriteBuffers(); } -void GLGSRender::ColorMask(bool a, bool r, bool g, bool b) -{ - glColorMask(r, g, b, a); - checkForGlError("glColorMask"); -} - -void GLGSRender::AlphaFunc(u32 func, float ref) -{ - glAlphaFunc(func, ref); - checkForGlError("glAlphaFunc"); -} - -void GLGSRender::DepthFunc(u32 func) -{ - glDepthFunc(func); - checkForGlError("glDepthFunc"); -} - -void GLGSRender::DepthMask(u32 flag) -{ - glDepthMask(flag); - checkForGlError("glDepthMask"); -} - -void GLGSRender::PolygonMode(u32 face, u32 mode) -{ - switch (face) - { - case NV4097_SET_FRONT_POLYGON_MODE: - glPolygonMode(GL_FRONT, mode); - break; - case NV4097_SET_BACK_POLYGON_MODE: - glPolygonMode(GL_BACK, mode); - break; - } - checkForGlError("glPolygonMode"); -} - -void GLGSRender::PointSize(float size) -{ - glPointSize(m_point_size); - checkForGlError("glPointSize"); -} - -void GLGSRender::LogicOp(u32 opcode) -{ - glLogicOp(opcode); - checkForGlError("glLogicOp"); -} - -void GLGSRender::LineWidth(float width) -{ - glLineWidth(width); - checkForGlError("glLineWidth"); -} - -void GLGSRender::LineStipple(u16 factor, u16 pattern) -{ - glLineStipple(factor, pattern); - checkForGlError("glLineStipple"); -} - -void GLGSRender::PolygonStipple(u32 pattern) -{ - glPolygonStipple((const GLubyte*)pattern); - checkForGlError("glPolygonStipple"); -} - -void GLGSRender::PrimitiveRestartIndex(u32 index) -{ - glPrimitiveRestartIndex(index); - checkForGlError("glPrimitiveRestartIndex"); -} - -void GLGSRender::CullFace(u32 mode) -{ - glCullFace(mode); - checkForGlError("glCullFace"); -} - -void GLGSRender::FrontFace(u32 mode) -{ - glFrontFace(mode); - checkForGlError("glFrontFace"); -} - -void GLGSRender::Fogi(u32 mode) -{ - glFogi(GL_FOG_MODE, mode); - checkForGlError("glFogi(GL_FOG_MODE)"); -} - -void GLGSRender::Fogf(float start, float end) -{ - glFogf(GL_FOG_START, start); - checkForGlError("glFogf(GL_FOG_START)"); - glFogf(GL_FOG_END, end); - checkForGlError("glFogf(GL_FOG_END)"); -} - -void GLGSRender::PolygonOffset(float factor , float bias) -{ - glPolygonOffset(factor, bias); - checkForGlError("glPolygonOffset"); -} - -void GLGSRender::DepthRangef(float min, float max) -{ - glDepthRangef(min, max); - checkForGlError("glDepthRangef"); -} - -void GLGSRender::BlendEquationSeparate(u16 rgb, u16 a) -{ - glBlendEquationSeparate(rgb, a); - checkForGlError("glBlendEquationSeparate"); -} - -void GLGSRender::BlendFuncSeparate(u16 srcRGB, u16 dstRGB, u16 srcAlpha, u16 dstAlpha) -{ - glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); - checkForGlError("glBlendFuncSeparate"); -} - -void GLGSRender::BlendColor(u8 r, u8 g, u8 b, u8 a) -{ - glBlendColor(r, g, b, a); - checkForGlError("glBlendColor"); -} - -void GLGSRender::LightModeli(u32 enable) -{ - enable ? glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) : glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - checkForGlError("glLightModeli"); -} - -void GLGSRender::ShadeModel(u32 mode) -{ - glShadeModel(m_shade_mode); - checkForGlError("glShadeModel"); -} - -void GLGSRender::DepthBoundsEXT(float min, float max) -{ - glDepthBoundsEXT(min, max); - checkForGlError("glDepthBoundsEXT"); -} - -void GLGSRender::Scissor(u16 x, u16 y, u16 width, u16 height) -{ - glScissor(x, y, width, height); - checkForGlError("glScissor"); -} - -void GLGSRender::StencilOp(u32 fail, u32 zfail, u32 zpass) -{ - glStencilOp(fail, zfail, zpass); - checkForGlError("glStencilOp"); -} - -void GLGSRender::StencilMask(u32 mask) -{ - glStencilMask(mask); - checkForGlError("glStencilMask"); -} - -void GLGSRender::StencilFunc(u32 func, u32 ref, u32 mask) -{ - glStencilFunc(func, ref, mask); - checkForGlError("glStencilFunc"); -} - -void GLGSRender::StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass) -{ - mode ? glStencilOpSeparate(GL_FRONT, fail, zfail, zpass) : glStencilOpSeparate(GL_BACK, fail, zfail, zpass); -} - -void GLGSRender::StencilMaskSeparate(u32 mode, u32 mask) -{ - mode ? glStencilMaskSeparate(GL_FRONT, mask) : glStencilMaskSeparate(GL_BACK, mask); -} - -void GLGSRender::StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask) -{ - mode ? glStencilFuncSeparate(GL_FRONT, func, ref, mask) : glStencilFuncSeparate(GL_BACK, func, ref, mask); -} - void GLGSRender::ExecCMD() { + //return; if (!LoadProgram()) { LOG_ERROR(RSX, "LoadProgram failed."); @@ -1949,7 +1758,268 @@ void GLGSRender::ExecCMD() } InitDrawBuffers(); - + + if (m_set_color_mask) + { + glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); + checkForGlError("glColorMask"); + } + + if (!m_indexed_array.m_count && !m_draw_array_count) + { + u32 min_vertex_size = ~0; + for (auto &i : m_vertex_data) + { + if (!i.size) + continue; + + u32 vertex_size = i.data.size() / (i.size * i.GetTypeSize()); + + if (min_vertex_size > vertex_size) + min_vertex_size = vertex_size; + } + + m_draw_array_count = min_vertex_size; + m_draw_array_first = 0; + } + + Enable(m_set_depth_test, GL_DEPTH_TEST); + Enable(m_set_alpha_test, GL_ALPHA_TEST); + Enable(m_set_depth_bounds_test, GL_DEPTH_BOUNDS_TEST_EXT); + Enable(m_set_blend || m_set_blend_mrt1 || m_set_blend_mrt2 || m_set_blend_mrt3, GL_BLEND); + Enable(m_set_scissor_horizontal && m_set_scissor_vertical, GL_SCISSOR_TEST); + Enable(m_set_logic_op, GL_LOGIC_OP); + Enable(m_set_cull_face, GL_CULL_FACE); + Enable(m_set_dither, GL_DITHER); + Enable(m_set_stencil_test, GL_STENCIL_TEST); + Enable(m_set_line_smooth, GL_LINE_SMOOTH); + Enable(m_set_poly_smooth, GL_POLYGON_SMOOTH); + Enable(m_set_point_sprite_control, GL_POINT_SPRITE); + Enable(m_set_specular, GL_LIGHTING); + Enable(m_set_poly_offset_fill, GL_POLYGON_OFFSET_FILL); + Enable(m_set_poly_offset_line, GL_POLYGON_OFFSET_LINE); + Enable(m_set_poly_offset_point, GL_POLYGON_OFFSET_POINT); + Enable(m_set_restart_index, GL_PRIMITIVE_RESTART); + Enable(m_set_line_stipple, GL_LINE_STIPPLE); + Enable(m_set_polygon_stipple, GL_POLYGON_STIPPLE); + + if (m_set_clip_plane) + { + Enable(m_clip_plane_0, GL_CLIP_PLANE0); + Enable(m_clip_plane_1, GL_CLIP_PLANE1); + Enable(m_clip_plane_2, GL_CLIP_PLANE2); + Enable(m_clip_plane_3, GL_CLIP_PLANE3); + Enable(m_clip_plane_4, GL_CLIP_PLANE4); + Enable(m_clip_plane_5, GL_CLIP_PLANE5); + + checkForGlError("m_set_clip_plane"); + } + + checkForGlError("glEnable"); + + if (m_set_front_polygon_mode) + { + glPolygonMode(GL_FRONT, m_front_polygon_mode); + checkForGlError("glPolygonMode(Front)"); + } + + if (m_set_back_polygon_mode) + { + glPolygonMode(GL_BACK, m_back_polygon_mode); + checkForGlError("glPolygonMode(Back)"); + } + + if (m_set_point_size) + { + glPointSize(m_point_size); + checkForGlError("glPointSize"); + } + + if (m_set_poly_offset_mode) + { + glPolygonOffset(m_poly_offset_scale_factor, m_poly_offset_bias); + checkForGlError("glPolygonOffset"); + } + + if (m_set_logic_op) + { + glLogicOp(m_logic_op); + checkForGlError("glLogicOp"); + } + + if (m_set_scissor_horizontal && m_set_scissor_vertical) + { + glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + checkForGlError("glScissor"); + } + + if (m_set_two_sided_stencil_test_enable) + { + if (m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) + { + glStencilOpSeparate(GL_FRONT, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); + checkForGlError("glStencilOpSeparate"); + } + + if (m_set_stencil_mask) + { + glStencilMaskSeparate(GL_FRONT, m_stencil_mask); + checkForGlError("glStencilMaskSeparate"); + } + + if (m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) + { + glStencilFuncSeparate(GL_FRONT, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + checkForGlError("glStencilFuncSeparate"); + } + + if (m_set_back_stencil_fail && m_set_back_stencil_zfail && m_set_back_stencil_zpass) + { + glStencilOpSeparate(GL_BACK, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); + checkForGlError("glStencilOpSeparate(GL_BACK)"); + } + + if (m_set_back_stencil_mask) + { + glStencilMaskSeparate(GL_BACK, m_back_stencil_mask); + checkForGlError("glStencilMaskSeparate(GL_BACK)"); + } + + if (m_set_back_stencil_func && m_set_back_stencil_func_ref && m_set_back_stencil_func_mask) + { + glStencilFuncSeparate(GL_BACK, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); + checkForGlError("glStencilFuncSeparate(GL_BACK)"); + } + } + else + { + if (m_set_stencil_fail && m_set_stencil_zfail && m_set_stencil_zpass) + { + glStencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); + checkForGlError("glStencilOp"); + } + + if (m_set_stencil_mask) + { + glStencilMask(m_stencil_mask); + checkForGlError("glStencilMask"); + } + + if (m_set_stencil_func && m_set_stencil_func_ref && m_set_stencil_func_mask) + { + glStencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + checkForGlError("glStencilFunc"); + } + } + + // TODO: Use other glLightModel functions? + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE); + checkForGlError("glLightModeli"); + + if (m_set_shade_mode) + { + glShadeModel(m_shade_mode); + checkForGlError("glShadeModel"); + } + + if (m_set_depth_mask) + { + glDepthMask(m_depth_mask); + checkForGlError("glDepthMask"); + } + + if (m_set_depth_func) + { + glDepthFunc(m_depth_func); + checkForGlError("glDepthFunc"); + } + + if (m_set_depth_bounds) + { + glDepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max); + checkForGlError("glDepthBounds"); + } + + if (m_set_clip) + { + glDepthRangef(m_clip_min, m_clip_max); + checkForGlError("glDepthRangef"); + } + + if (m_set_line_width) + { + glLineWidth(m_line_width); + checkForGlError("glLineWidth"); + } + + if (m_set_line_stipple) + { + glLineStipple(m_line_stipple_factor, m_line_stipple_pattern); + checkForGlError("glLineStipple"); + } + + if (m_set_polygon_stipple) + { + glPolygonStipple((const GLubyte*)m_polygon_stipple_pattern); + checkForGlError("glPolygonStipple"); + } + + if (m_set_blend_equation) + { + glBlendEquationSeparate(m_blend_equation_rgb, m_blend_equation_alpha); + checkForGlError("glBlendEquationSeparate"); + } + + if (m_set_blend_sfactor && m_set_blend_dfactor) + { + glBlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha); + checkForGlError("glBlendFuncSeparate"); + } + + if (m_set_blend_color) + { + glBlendColor(m_blend_color_r, m_blend_color_g, m_blend_color_b, m_blend_color_a); + checkForGlError("glBlendColor"); + } + + if (m_set_cull_face) + { + glCullFace(m_cull_face); + checkForGlError("glCullFace"); + } + + if (m_set_front_face) + { + glFrontFace(m_front_face); + checkForGlError("glFrontFace"); + } + + if (m_set_alpha_func && m_set_alpha_ref) + { + glAlphaFunc(m_alpha_func, m_alpha_ref); + checkForGlError("glAlphaFunc"); + } + + if (m_set_fog_mode) + { + glFogi(GL_FOG_MODE, m_fog_mode); + checkForGlError("glFogi(GL_FOG_MODE)"); + } + + if (m_set_fog_params) + { + glFogf(GL_FOG_START, m_fog_param0); + checkForGlError("glFogf(GL_FOG_START)"); + glFogf(GL_FOG_END, m_fog_param1); + checkForGlError("glFogf(GL_FOG_END)"); + } + + if (m_set_restart_index) + { + glPrimitiveRestartIndex(m_restart_index); + checkForGlError("glPrimitiveRestartIndex"); + } + if (m_indexed_array.m_count && m_draw_array_count) { LOG_WARNING(RSX, "m_indexed_array.m_count && draw_array_count"); @@ -2005,16 +2075,16 @@ void GLGSRender::ExecCMD() case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr); checkForGlError("glDrawElements #4"); - break; + break; case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: glDrawElements(m_draw_mode - 1, m_indexed_array.m_count, GL_UNSIGNED_SHORT, nullptr); checkForGlError("glDrawElements #2"); - break; + break; default: LOG_ERROR(RSX, "Bad indexed array type (%d)", m_indexed_array.m_type); - break; + break; } DisableVertexData(); @@ -2028,102 +2098,130 @@ void GLGSRender::ExecCMD() checkForGlError("glDrawArrays"); DisableVertexData(); } - + WriteBuffers(); } void GLGSRender::Flip() { - static u8* src_buffer = nullptr; - static u32 width = 0; - static u32 height = 0; - GLenum format = GL_RGBA; - - if (m_read_buffer) + // Set scissor to FBO size + if (m_set_scissor_horizontal && m_set_scissor_vertical) { - format = GL_BGRA; - CellGcmDisplayInfo* buffers = vm::get_ptr(m_gcm_buffers_addr); - u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); + glScissor(0, 0, RSXThread::m_width, RSXThread::m_height); + checkForGlError("glScissor"); + } - if (Memory.IsGoodAddr(addr)) + switch (m_surface_color_target) + { + case CELL_GCM_SURFACE_TARGET_0: + case CELL_GCM_SURFACE_TARGET_1: + case CELL_GCM_SURFACE_TARGET_MRT1: + case CELL_GCM_SURFACE_TARGET_MRT2: + case CELL_GCM_SURFACE_TARGET_MRT3: + { + // Fast path for non-MRT using glBlitFramebuffer. + GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); + // Renderbuffer is upside turn , swapped srcY0 and srcY1 + GLfbo::Blit(0, RSXThread::m_height, RSXThread::m_width, 0, 0, 0, RSXThread::m_width, RSXThread::m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + break; + + case CELL_GCM_SURFACE_TARGET_NONE: + { + // Slow path for MRT/None target using glReadPixels. + static u8* src_buffer = nullptr; + static u32 width = 0; + static u32 height = 0; + GLenum format = GL_RGBA; + + if (m_read_buffer) { - width = buffers[m_gcm_current_buffer].width; - height = buffers[m_gcm_current_buffer].height; - src_buffer = vm::get_ptr(addr); + format = GL_BGRA; + CellGcmDisplayInfo* buffers = vm::get_ptr(m_gcm_buffers_addr); + u32 addr = GetAddress(buffers[m_gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); + + if (Memory.IsGoodAddr(addr)) + { + width = buffers[m_gcm_current_buffer].width; + height = buffers[m_gcm_current_buffer].height; + src_buffer = vm::get_ptr(addr); + } + else + { + src_buffer = nullptr; + } + } + else if (m_fbo.IsCreated()) + { + format = GL_RGBA; + static std::vector pixels; + pixels.resize(RSXThread::m_width * RSXThread::m_height * 4); + m_fbo.Bind(GL_READ_FRAMEBUFFER); + glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[5]); + glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); + glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0); + checkForGlError("Flip(): glReadPixels(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8)"); + GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); + if (packed) + { + memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4); + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + checkForGlError("Flip(): glUnmapBuffer"); + } + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + + src_buffer = pixels.data(); + width = RSXThread::m_width; + height = RSXThread::m_height; } else { src_buffer = nullptr; } - } - else if (m_fbo.IsCreated()) - { - format = GL_RGBA; - static std::vector pixels; - pixels.resize(RSXThread::m_width * RSXThread::m_height * 4); - m_fbo.Bind(GL_READ_FRAMEBUFFER); - glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[5]); - glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); - glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0); - checkForGlError("Flip(): glReadPixels(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8)"); - GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); - if (packed) + + if (src_buffer) { - memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4); - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - checkForGlError("Flip(): glUnmapBuffer"); + glDisable(GL_STENCIL_TEST); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + glDisable(GL_CLIP_PLANE4); + glDisable(GL_CLIP_PLANE5); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_flip_tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, 1, 0, 1, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); + + m_program.UnUse(); + m_program.Use(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); + + glColor3f(1, 1, 1); + glBegin(GL_QUADS); + glTexCoord2i(0, 1); + glVertex2i(0, 0); + glTexCoord2i(1, 1); + glVertex2i(1, 0); + glTexCoord2i(1, 0); + glVertex2i(1, 1); + glTexCoord2i(0, 0); + glVertex2i(0, 1); + glEnd(); } - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - - src_buffer = pixels.data(); - width = RSXThread::m_width; - height = RSXThread::m_height; } - else - { - src_buffer = nullptr; - } - - if (src_buffer) - { - glDisable(GL_STENCIL_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); - glDisable(GL_CLIP_PLANE4); - glDisable(GL_CLIP_PLANE5); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, g_flip_tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_INT_8_8_8_8, src_buffer); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 1, 0, 1, 0, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0); - - m_program.UnUse(); - m_program.Use(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); - - glColor3f(1, 1, 1); - glBegin(GL_QUADS); - glTexCoord2i(0, 1); - glVertex2i(0, 0); - glTexCoord2i(1, 1); - glVertex2i(1, 0); - glTexCoord2i(1, 0); - glVertex2i(1, 1); - glTexCoord2i(0, 0); - glVertex2i(0, 1); - glEnd(); + break; } // Draw Objects @@ -2133,7 +2231,14 @@ void GLGSRender::Flip() } m_frame->Flip(m_context); - + + // Restore scissor + if (m_set_scissor_horizontal && m_set_scissor_vertical) + { + glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + checkForGlError("glScissor"); + } + } u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, u32 log2_depth) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 7ab9f406d1..a509664ded 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -21,7 +21,7 @@ u32 LinearToSwizzleAddress(u32 x, u32 y, u32 z, u32 log2_width, u32 log2_height, class GLTexture { u32 m_id; - + public: GLTexture() : m_id(0) { @@ -166,11 +166,12 @@ public: virtual ~GLGSRender(); private: - void EnableVertexData(bool indexed_draw=false); + void EnableVertexData(bool indexed_draw = false); void DisableVertexData(); void InitVertexData(); void InitFragmentData(); + void Enable(bool enable, const u32 cap); virtual void Close(); bool LoadProgram(); void WriteBuffers(); @@ -189,41 +190,7 @@ protected: virtual void OnInitThread(); virtual void OnExitThread(); virtual void OnReset(); + virtual void ExecCMD(u32 cmd); virtual void ExecCMD(); - virtual void Enable(u32 cmd, u32 enable); - virtual void ClearColor(u32 a, u32 r, u32 g, u32 b); - virtual void ClearStencil(u32 stencil); - virtual void ClearDepth(u32 depth); - virtual void ClearSurface(u32 mask); - virtual void ColorMask(bool a, bool r, bool g, bool b); - virtual void AlphaFunc(u32 func, float ref); - virtual void DepthFunc(u32 func); - virtual void DepthMask(u32 flag); - virtual void PolygonMode(u32 face, u32 mode); - virtual void PointSize(float size); - virtual void LogicOp(u32 opcode); - virtual void LineWidth(float width); - virtual void LineStipple(u16 factor, u16 pattern); - virtual void PolygonStipple(u32 pattern); - virtual void PrimitiveRestartIndex(u32 index); - virtual void CullFace(u32 mode); - virtual void FrontFace(u32 mode); - virtual void Fogi(u32 mode); - virtual void Fogf(float start, float end); - virtual void PolygonOffset(float factor, float bias); - virtual void DepthRangef(float min, float max); - virtual void BlendEquationSeparate(u16 rgb, u16 a); - virtual void BlendFuncSeparate(u16 srcRGB, u16 dstRGB, u16 srcAlpha, u16 dstAlpha); - virtual void BlendColor(u8 r, u8 g, u8 b, u8 a); - virtual void LightModeli(u32 enable); - virtual void ShadeModel(u32 mode); - virtual void DepthBoundsEXT(float min, float max); - virtual void Scissor(u16 x, u16 y, u16 width, u16 height); - virtual void StencilOp(u32 fail, u32 zfail, u32 zpass); - virtual void StencilMask(u32 mask); - virtual void StencilFunc(u32 func, u32 ref, u32 mask); - virtual void StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass); - virtual void StencilMaskSeparate(u32 mode, u32 mask); - virtual void StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask); virtual void Flip(); }; diff --git a/rpcs3/Emu/RSX/Null/NullGSRender.h b/rpcs3/Emu/RSX/Null/NullGSRender.h index 53786c3b8e..33875cbabe 100644 --- a/rpcs3/Emu/RSX/Null/NullGSRender.h +++ b/rpcs3/Emu/RSX/Null/NullGSRender.h @@ -6,50 +6,44 @@ class NullGSRender { public: - NullGSRender() {} - virtual ~NullGSRender() {} + NullGSRender() + { + } + + virtual ~NullGSRender() + { + } private: - virtual void OnInit() {} - virtual void OnInitThread() {} - virtual void OnExitThread() {} - virtual void OnReset() {} - virtual void Enable(u32 cmd, u32 enable) {} - virtual void ClearColor(u32 a, u32 r, u32 g, u32 b) {} - virtual void ClearStencil(u32 stencil) {} - virtual void ClearDepth(u32 depth) {} - virtual void ClearSurface(u32 mask) {} - virtual void ColorMask(bool a, bool r, bool g, bool b) {} - virtual void ExecCMD() {} - virtual void AlphaFunc(u32 func, float ref) {} - virtual void DepthFunc(u32 func) {} - virtual void DepthMask(u32 flag) {} - virtual void PolygonMode(u32 face, u32 mode) {} - virtual void PointSize(float size) {} - virtual void LogicOp(u32 opcode) {} - virtual void LineWidth(float width) {} - virtual void LineStipple(u16 factor, u16 pattern) {} - virtual void PolygonStipple(u32 pattern) {} - virtual void PrimitiveRestartIndex(u32 index) {} - virtual void CullFace(u32 mode) {} - virtual void FrontFace(u32 mode) {} - virtual void Fogi(u32 mode) {} - virtual void Fogf(float start, float end) {} - virtual void PolygonOffset(float factor, float bias) {} - virtual void DepthRangef(float min, float max) {} - virtual void BlendEquationSeparate(u16 rgb, u16 a) {} - virtual void BlendFuncSeparate(u16 srcRGB, u16 dstRGB, u16 srcAlpha, u16 dstAlpha) {} - virtual void BlendColor(u8 r, u8 g, u8 b, u8 a) {} - virtual void LightModeli(u32 enable) {} - virtual void ShadeModel(u32 mode) {} - virtual void DepthBoundsEXT(float min, float max) {} - virtual void Scissor(u16 x, u16 y, u16 width, u16 height) {} - virtual void StencilOp(u32 fail, u32 zfail, u32 zpass) {} - virtual void StencilMask(u32 mask) {} - virtual void StencilFunc(u32 func, u32 ref, u32 mask) {} - virtual void StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass) {} - virtual void StencilMaskSeparate(u32 mode, u32 mask) {} - virtual void StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask) {} - virtual void Flip() {} - virtual void Close() {} -}; + virtual void OnInit() + { + } + + virtual void OnInitThread() + { + } + + virtual void OnExitThread() + { + } + + virtual void OnReset() + { + } + + virtual void ExecCMD(u32 cmd) + { + } + + virtual void ExecCMD() + { + } + + virtual void Flip() + { + } + + virtual void Close() + { + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 906b0281c3..2c7f2086ba 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -25,32 +25,32 @@ void RSXThread::NativeRescale(float width, float height) m_height_scale = 1080 / height * 2.0f; m_width = 1920; m_height = 1080; + break; } - break; case 2: // 1280x720 window size { m_width_scale = 1280 / width * 2.0f; m_height_scale = 720 / height * 2.0f; m_width = 1280; m_height = 720; + break; } - break; case 4: // 720x480 window size { m_width_scale = 720 / width * 2.0f; m_height_scale = 480 / height * 2.0f; m_width = 720; m_height = 480; + break; } - break; case 5: // 720x576 window size { m_width_scale = 720 / width * 2.0f; m_height_scale = 576 / height * 2.0f; m_width = 720; m_height = 576; + break; } - break; } } @@ -58,7 +58,7 @@ u32 GetAddress(u32 offset, u32 location) { u32 res = 0; - switch(location) + switch (location) { case CELL_GCM_LOCATION_LOCAL: { @@ -70,22 +70,19 @@ u32 GetAddress(u32 offset, u32 location) res = (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check? if (res == 0) { - LOG_ERROR(RSX, "GetAddress(offset=0x%x): RSXIO memory not mapped", offset); - Emu.Pause(); - break; + throw fmt::format("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped", offset, location); } if (Emu.GetGSManager().GetRender().m_strict_ordering[offset >> 20]) { _mm_mfence(); // probably doesn't have any effect on current implementation } + break; } default: { - LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x): invalid location", offset, location); - Emu.Pause(); - break; + throw fmt::format("GetAddress(offset=0x%x, location=0x%x): invalid location", offset, location); } } @@ -112,7 +109,7 @@ void RSXVertexData::Reset() data.clear(); } -void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) +void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex = 0) { if (!addr) return; @@ -125,29 +122,29 @@ void RSXVertexData::Load(u32 start, u32 count, u32 baseOffset, u32 baseIndex=0) auto src = vm::get_ptr(addr + baseOffset + stride * (i + baseIndex)); u8* dst = &data[i * tsize * size]; - switch(tsize) + switch (tsize) { case 1: { - memcpy(dst, src, size); // may be dangerous + memcpy(dst, src, size); + break; } - break; case 2: { const u16* c_src = (const u16*)src; u16* c_dst = (u16*)dst; for (u32 j = 0; j < size; ++j) *c_dst++ = re16(*c_src++); + break; } - break; case 4: { const u32* c_src = (const u32*)src; u32* c_dst = (u32*)dst; for (u32 j = 0; j < size; ++j) *c_dst++ = re32(*c_src++); + break; } - break; } } } @@ -199,7 +196,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, cons case_16(offset + 16*step, step) #define case_range(n, offset, step) \ case_##n(offset, step) \ - index = (cmd - offset) / step; + index = (cmd - offset) / step void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count) { @@ -217,14 +214,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_used_gcm_commands.insert(cmd); - switch(cmd) + switch (cmd) { // NV406E case NV406E_SET_REFERENCE: { m_ctrl->ref.exchange(be_t::make(ARGS(0))); + break; } - break; case NV406E_SET_CONTEXT_DMA_SEMAPHORE: { @@ -232,16 +229,16 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV406E_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0)); } + break; } - break; case NV4097_SET_SEMAPHORE_OFFSET: case NV406E_SEMAPHORE_OFFSET: { m_set_semaphore_offset = true; m_semaphore_offset = ARGS(0); + break; } - break; case NV406E_SEMAPHORE_ACQUIRE: { @@ -249,8 +246,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0)); } + break; } - break; case NV406E_SEMAPHORE_RELEASE: case NV4097_TEXTURE_READ_SEMAPHORE_RELEASE: @@ -260,8 +257,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_semaphore_offset = false; vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, ARGS(0)); } + break; } - break; case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE: { @@ -273,8 +270,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const vm::write32(Memory.RSXCMDMem.GetStartAddr() + m_semaphore_offset, value); } + break; } - break; // NV4097 case 0x0003fead: @@ -311,30 +308,30 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const return; } - std::this_thread::sleep_for (std::chrono::milliseconds((s64)(1000.0 / limit - m_timer_sync.GetElapsedTimeInMilliSec()))); + std::this_thread::sleep_for(std::chrono::milliseconds((s64)(1000.0 / limit - m_timer_sync.GetElapsedTimeInMilliSec()))); m_timer_sync.Start(); }; sync(); //Emu.Pause(); + break; } - break; case NV4097_NO_OPERATION: { // Nothing to do here + break; } - break; - + case NV4097_SET_CONTEXT_DMA_REPORT: { if (ARGS(0)) { LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_REPORT: 0x%x", ARGS(0)); } + break; } - break; case NV4097_NOTIFY: { @@ -342,8 +339,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_NOTIFY: 0x%x", ARGS(0)); } + break; } - break; case NV4097_WAIT_FOR_IDLE: { @@ -351,8 +348,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_WAIT_FOR_IDLE: 0x%x", ARGS(0)); } + break; } - break; case NV4097_PM_TRIGGER: { @@ -360,64 +357,64 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_PM_TRIGGER: 0x%x", ARGS(0)); } + break; } - break; // Texture - case_range(16, NV4097_SET_TEXTURE_FORMAT, 0x20) - case_range(16, NV4097_SET_TEXTURE_OFFSET, 0x20) - case_range(16, NV4097_SET_TEXTURE_FILTER, 0x20) - case_range(16, NV4097_SET_TEXTURE_ADDRESS, 0x20) - case_range(16, NV4097_SET_TEXTURE_IMAGE_RECT, 32) - case_range(16, NV4097_SET_TEXTURE_BORDER_COLOR, 0x20) - case_range(16, NV4097_SET_TEXTURE_CONTROL0, 0x20) - case_range(16, NV4097_SET_TEXTURE_CONTROL1, 0x20) + case_range(16, NV4097_SET_TEXTURE_FORMAT, 0x20); + case_range(16, NV4097_SET_TEXTURE_OFFSET, 0x20); + case_range(16, NV4097_SET_TEXTURE_FILTER, 0x20); + case_range(16, NV4097_SET_TEXTURE_ADDRESS, 0x20); + case_range(16, NV4097_SET_TEXTURE_IMAGE_RECT, 32); + case_range(16, NV4097_SET_TEXTURE_BORDER_COLOR, 0x20); + case_range(16, NV4097_SET_TEXTURE_CONTROL0, 0x20); + case_range(16, NV4097_SET_TEXTURE_CONTROL1, 0x20); { // Done using methodRegisters in RSXTexture.cpp + break; } - break; - case_range(16, NV4097_SET_TEX_COORD_CONTROL, 4) + case_range(16, NV4097_SET_TEX_COORD_CONTROL, 4); { LOG_WARNING(RSX, "TODO: NV4097_SET_TEX_COORD_CONTROL"); + break; } - break; - case_range(16, NV4097_SET_TEXTURE_CONTROL3, 4) + case_range(16, NV4097_SET_TEXTURE_CONTROL3, 4); { RSXTexture& tex = m_textures[index]; const u32 a0 = ARGS(0); u32 pitch = a0 & 0xFFFFF; u16 depth = a0 >> 20; tex.SetControl3(depth, pitch); + break; } - break; - - // Vertex Texture - case_range(4, NV4097_SET_VERTEX_TEXTURE_FORMAT, 0x20) - case_range(4, NV4097_SET_VERTEX_TEXTURE_OFFSET, 0x20) - case_range(4, NV4097_SET_VERTEX_TEXTURE_FILTER, 0x20) - case_range(4, NV4097_SET_VERTEX_TEXTURE_ADDRESS, 0x20) - case_range(4, NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT, 0x20) - case_range(4, NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR, 0x20) - case_range(4, NV4097_SET_VERTEX_TEXTURE_CONTROL0, 0x20) + + // Vertex Texture + case_range(4, NV4097_SET_VERTEX_TEXTURE_FORMAT, 0x20); + case_range(4, NV4097_SET_VERTEX_TEXTURE_OFFSET, 0x20); + case_range(4, NV4097_SET_VERTEX_TEXTURE_FILTER, 0x20); + case_range(4, NV4097_SET_VERTEX_TEXTURE_ADDRESS, 0x20); + case_range(4, NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT, 0x20); + case_range(4, NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR, 0x20); + case_range(4, NV4097_SET_VERTEX_TEXTURE_CONTROL0, 0x20); { // Done using methodRegisters in RSXTexture.cpp + break; } - break; - case_range(4, NV4097_SET_VERTEX_TEXTURE_CONTROL3, 0x20) + case_range(4, NV4097_SET_VERTEX_TEXTURE_CONTROL3, 0x20); { RSXVertexTexture& tex = m_vertex_textures[index]; const u32 a0 = ARGS(0); u32 pitch = a0 & 0xFFFFF; u16 depth = a0 >> 20; tex.SetControl3(depth, pitch); + break; } - break; - // Vertex data - case_range(16, NV4097_SET_VERTEX_DATA4UB_M, 4) + // Vertex data + case_range(16, NV4097_SET_VERTEX_DATA4UB_M, 4); { const u32 a0 = ARGS(0); u8 v0 = a0; @@ -434,17 +431,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_vertex_data[index].data.push_back(v3); //LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA4UB_M: index = %d, v0 = 0x%x, v1 = 0x%x, v2 = 0x%x, v3 = 0x%x", index, v0, v1, v2, v3); + break; } - break; - case_range(16, NV4097_SET_VERTEX_DATA2F_M, 8) + case_range(16, NV4097_SET_VERTEX_DATA2F_M, 8); { const u32 a0 = ARGS(0); const u32 a1 = ARGS(1); float v0 = (float&)a0; float v1 = (float&)a1; - + m_vertex_data[index].Reset(); m_vertex_data[index].type = CELL_GCM_VERTEX_F; m_vertex_data[index].size = 2; @@ -454,10 +451,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const (float&)m_vertex_data[index].data[pos + sizeof(float) * 1] = v1; //LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA2F_M: index = %d, v0 = %f, v1 = %f", index, v0, v1); + break; } - break; - case_range(16, NV4097_SET_VERTEX_DATA4F_M, 16) + case_range(16, NV4097_SET_VERTEX_DATA4F_M, 16); { const u32 a0 = ARGS(0); const u32 a1 = ARGS(1); @@ -480,10 +477,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const (float&)m_vertex_data[index].data[pos + sizeof(float) * 3] = v3; //LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA4F_M: index = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f", index, v0, v1, v2, v3); + break; } - break; - case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_OFFSET, 4) + case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_OFFSET, 4); { const u32 addr = GetAddress(ARGS(0) & 0x7fffffff, ARGS(0) >> 31); @@ -491,10 +488,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_vertex_data[index].data.clear(); //LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA_ARRAY_OFFSET: num=%d, addr=0x%x", index, addr); + break; } - break; - case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4) + case_range(16, NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, 4); { const u32 a0 = ARGS(0); u16 frequency = a0 >> 16; @@ -510,8 +507,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const //LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA_ARRAY_FORMAT: index=%d, frequency=%d, stride=%d, size=%d, type=%d", index, frequency, stride, size, type); + break; } - break; // Vertex Attribute case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: @@ -522,8 +519,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const } //VertexData[0].prog.attributeInputMask = ARGS(0); + break; } - break; case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: { @@ -534,16 +531,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const //VertexData[0].prog.attributeOutputMask = ARGS(0); //FragmentData.prog.attributeInputMask = ARGS(0)/* & ~0x20*/; + break; } - break; // Color Mask case NV4097_SET_COLOR_MASK: { - const u32 mask = ARGS(0); - ColorMask(mask & 0x1000000, mask & 0x1000000, mask & 0x1000000, mask & 0x0000001); + const u32 a0 = ARGS(0); + + m_set_color_mask = true; + m_color_mask_a = a0 & 0x1000000 ? true : false; + m_color_mask_r = a0 & 0x0010000 ? true : false; + m_color_mask_g = a0 & 0x0000100 ? true : false; + m_color_mask_b = a0 & 0x0000001 ? true : false; + break; } - break; case NV4097_SET_COLOR_MASK_MRT: { @@ -551,118 +553,105 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_COLOR_MASK_MRT: 0x%x", mask); } + break; } - break; // Alpha testing case NV4097_SET_ALPHA_TEST_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_alpha_test = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_ALPHA_FUNC: { - const u32 value = ARGS(0); - m_alpha_func = value; + m_set_alpha_func = true; + m_alpha_func = ARGS(0); - // Sanity check here for invalid alpha func - if (m_alpha_func) + if (count == 2) { - AlphaFunc(m_alpha_func, m_alpha_ref); + m_set_alpha_ref = true; + const u32 a1 = ARGS(1); + m_alpha_ref = (float&)a1; } + break; } - break; case NV4097_SET_ALPHA_REF: { - const u32 value = ARGS(0); - m_alpha_ref = (float&)value; - - // Sanity check here for invalid alpha func - if (m_alpha_func) - { - AlphaFunc(m_alpha_func, m_alpha_ref); - } + m_set_alpha_ref = true; + const u32 a0 = ARGS(0); + m_alpha_ref = (float&)a0; + break; } - break; // Cull face case NV4097_SET_CULL_FACE_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_cull_face = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_CULL_FACE: { - const u32 value = ARGS(0); - CullFace(value); + m_cull_face = ARGS(0); + break; } - break; // Front face case NV4097_SET_FRONT_FACE: { - const u32 value = ARGS(0); - //FrontFace(value); + m_front_face = ARGS(0); + break; } - break; // Blending case NV4097_SET_BLEND_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_blend = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_BLEND_ENABLE_MRT: { m_set_blend_mrt1 = ARGS(0) & 0x02 ? true : false; m_set_blend_mrt2 = ARGS(0) & 0x04 ? true : false; m_set_blend_mrt3 = ARGS(0) & 0x08 ? true : false; + break; } - break; case NV4097_SET_BLEND_FUNC_SFACTOR: { - const u32 value = ARGS(0); m_set_blend_sfactor = true; - m_blend_sfactor_rgb = value & 0xffff; - m_blend_sfactor_alpha = value >> 16; + m_blend_sfactor_rgb = ARGS(0) & 0xffff; + m_blend_sfactor_alpha = ARGS(0) >> 16; if (count == 2) { - const u32 value1 = ARGS(1); - m_blend_dfactor_rgb = value1 & 0xffff; - m_blend_dfactor_alpha = value1 >> 16; - BlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha); + m_set_blend_dfactor = true; + m_blend_dfactor_rgb = ARGS(1) & 0xffff; + m_blend_dfactor_alpha = ARGS(1) >> 16; } + break; } - break; case NV4097_SET_BLEND_FUNC_DFACTOR: { - const u32 value = ARGS(0); - m_blend_dfactor_rgb = value & 0xffff; - m_blend_dfactor_alpha = value >> 16; - - if (m_set_blend_sfactor) - { - BlendFuncSeparate(m_blend_sfactor_rgb, m_blend_dfactor_rgb, m_blend_sfactor_alpha, m_blend_dfactor_alpha); - } + m_set_blend_dfactor = true; + m_blend_dfactor_rgb = ARGS(0) & 0xffff; + m_blend_dfactor_alpha = ARGS(0) >> 16; + break; } - break; case NV4097_SET_BLEND_COLOR: { - const u32 value = ARGS(0); - BlendColor(value & 0xff, (value >> 8) & 0xff, (value >> 16) & 0xff, (value >> 24) & 0xff); + m_set_blend_color = true; + m_blend_color_r = ARGS(0) & 0xff; + m_blend_color_g = (ARGS(0) >> 8) & 0xff; + m_blend_color_b = (ARGS(0) >> 16) & 0xff; + m_blend_color_a = (ARGS(0) >> 24) & 0xff; + break; } - break; case NV4097_SET_BLEND_COLOR2: { @@ -670,15 +659,16 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO : NV4097_SET_BLEND_COLOR2: 0x%x", value); } + break; } - break; case NV4097_SET_BLEND_EQUATION: { - const u32 value = ARGS(0); - BlendEquationSeparate(value & 0xffff, value >> 16); + m_set_blend_equation = true; + m_blend_equation_rgb = ARGS(0) & 0xffff; + m_blend_equation_alpha = ARGS(0) >> 16; + break; } - break; case NV4097_SET_REDUCE_DST_COLOR: { @@ -686,43 +676,37 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_REDUCE_DST_COLOR: 0x%x", value); } + break; } - break; // Depth bound testing case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_depth_bounds_test = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_DEPTH_BOUNDS_MIN: { - const u32 value = ARGS(0); m_set_depth_bounds = true; - m_depth_bounds_min = (float&)value; + const u32 a0 = ARGS(0); + m_depth_bounds_min = (float&)a0; if (count == 2) { - const u32 value1 = ARGS(1); - m_depth_bounds_max = (float&)value1; - DepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max); + const u32 a1 = ARGS(1); + m_depth_bounds_max = (float&)a1; } + break; } - break; case NV4097_SET_DEPTH_BOUNDS_MAX: { - const u32 value = ARGS(0); - m_depth_bounds_max = (float&)value; - - if (m_set_depth_bounds) - { - DepthBoundsEXT(m_depth_bounds_min, m_depth_bounds_max); - } + m_set_depth_bounds = true; + const u32 a0 = ARGS(0); + m_depth_bounds_max = (float&)a0; + break; } - break; // Viewport case NV4097_SET_VIEWPORT_HORIZONTAL: @@ -739,8 +723,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const } //LOG_NOTICE(RSX, "NV4097_SET_VIEWPORT_HORIZONTAL: x=%d, y=%d, w=%d, h=%d", m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); + break; } - break; case NV4097_SET_VIEWPORT_VERTICAL: { @@ -749,124 +733,120 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_viewport_h = ARGS(0) >> 16; //LOG_NOTICE(RSX, "NV4097_SET_VIEWPORT_VERTICAL: y=%d, h=%d", m_viewport_y, m_viewport_h); + break; } - break; case NV4097_SET_VIEWPORT_SCALE: case NV4097_SET_VIEWPORT_OFFSET: { // Done in Vertex Shader + break; } - break; // Clipping case NV4097_SET_CLIP_MIN: { - const u32 value = ARGS(0); - m_clip_min = (float&)value; - DepthRangef(m_clip_min, m_clip_max); + const u32 a0 = ARGS(0); + const u32 a1 = ARGS(1); + + m_set_clip = true; + m_clip_min = (float&)a0; + m_clip_max = (float&)a1; + + //LOG_NOTICE(RSX, "NV4097_SET_CLIP_MIN: clip_min=%.01f, clip_max=%.01f", m_clip_min, m_clip_max); + break; } - break; case NV4097_SET_CLIP_MAX: { - const u32 value = ARGS(0); - m_clip_max = (float&)value; - DepthRangef(m_clip_min, m_clip_max); + const u32 a0 = ARGS(0); + + m_set_clip = true; + m_clip_max = (float&)a0; + + //LOG_NOTICE(RSX, "NV4097_SET_CLIP_MAX: clip_max=%.01f", m_clip_max); + break; } - break; // Depth testing case NV4097_SET_DEPTH_TEST_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_depth_test = ARGS(0) ? true : false; + break; } - break; - + case NV4097_SET_DEPTH_FUNC: { - const u32 value = ARGS(0); - // Sanity check here for invalid depth func - if (value) - { - DepthFunc(value); - } + m_set_depth_func = true; + m_depth_func = ARGS(0); + break; } - break; case NV4097_SET_DEPTH_MASK: { - const u32 value = ARGS(0); - DepthMask(value); + m_set_depth_mask = true; + m_depth_mask = ARGS(0); + break; } - break; // Polygon mode/offset case NV4097_SET_FRONT_POLYGON_MODE: { - const u32 value = ARGS(0); - PolygonMode(cmd, value); + m_set_front_polygon_mode = true; + m_front_polygon_mode = ARGS(0); + break; } - break; case NV4097_SET_BACK_POLYGON_MODE: { - const u32 value = ARGS(0); - PolygonMode(cmd, value); + m_set_back_polygon_mode = true; + m_back_polygon_mode = ARGS(0); + break; } - break; - + case NV4097_SET_POLY_OFFSET_FILL_ENABLE: { - Enable(cmd, ARGS(0)); + m_set_poly_offset_fill = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_POLY_OFFSET_LINE_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_poly_offset_line = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_POLY_OFFSET_POINT_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_poly_offset_point = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_POLYGON_OFFSET_SCALE_FACTOR: { - Enable(NV4097_SET_DEPTH_TEST_ENABLE, 1); - - const u32 value = ARGS(0); + m_set_depth_test = true; m_set_poly_offset_mode = true; - m_poly_offset_scale_factor = (float&)value; + + const u32 a0 = ARGS(0); + m_poly_offset_scale_factor = (float&)a0; if (count == 2) { - const u32 value1 = ARGS(1); - m_poly_offset_bias = (float&)value1; - PolygonOffset(m_poly_offset_scale_factor, m_poly_offset_bias); + const u32 a1 = ARGS(1); + m_poly_offset_bias = (float&)a1; } + break; } - break; case NV4097_SET_POLYGON_OFFSET_BIAS: { - Enable(NV4097_SET_DEPTH_TEST_ENABLE, 1); + m_set_depth_test = true; + m_set_poly_offset_mode = true; - const u32 value = ARGS(0); - m_poly_offset_bias = (float&)value; - - if (m_set_poly_offset_mode) - { - PolygonOffset(m_poly_offset_scale_factor, m_poly_offset_bias); - } + const u32 a0 = ARGS(0); + m_poly_offset_bias = (float&)a0; + break; } - break; case NV4097_SET_CYLINDRICAL_WRAP: { @@ -874,8 +854,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CYLINDRICAL_WRAP: 0x%x", ARGS(0)); } + break; } - break; // Clearing case NV4097_CLEAR_ZCULL_SURFACE: @@ -886,33 +866,42 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if (a0 & 0x02) m_clear_surface_s = m_clear_s; m_clear_surface_mask |= a0 & 0x3; + break; } - break; case NV4097_CLEAR_SURFACE: { - const u32 mask = ARGS(0); + const u32 a0 = ARGS(0); - ClearSurface(mask); + if (a0 & 0x01) m_clear_surface_z = m_clear_z; + if (a0 & 0x02) m_clear_surface_s = m_clear_s; + if (a0 & 0x10) m_clear_surface_color_r = m_clear_color_r; + if (a0 & 0x20) m_clear_surface_color_g = m_clear_color_g; + if (a0 & 0x40) m_clear_surface_color_b = m_clear_color_b; + if (a0 & 0x80) m_clear_surface_color_a = m_clear_color_a; + + m_clear_surface_mask = a0; + ExecCMD(NV4097_CLEAR_SURFACE); + break; } - break; case NV4097_SET_ZSTENCIL_CLEAR_VALUE: { - const u32 value = ARGS(0); - - ClearStencil(value & 0xff); - ClearDepth(value >> 8); + const u32 a0 = ARGS(0); + m_clear_s = a0 & 0xff; + m_clear_z = a0 >> 8; + break; } - break; case NV4097_SET_COLOR_CLEAR_VALUE: { const u32 color = ARGS(0); - - ClearColor((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + m_clear_color_a = (color >> 24) & 0xff; + m_clear_color_r = (color >> 16) & 0xff; + m_clear_color_g = (color >> 8) & 0xff; + m_clear_color_b = color & 0xff; + break; } - break; case NV4097_SET_CLEAR_RECT_HORIZONTAL: { @@ -920,8 +909,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", value); } + break; } - break; case NV4097_SET_CLEAR_RECT_VERTICAL: { @@ -929,8 +918,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", value); } + break; } - break; // Arrays case NV4097_INLINE_ARRAY: @@ -939,12 +928,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NNV4097_INLINE_ARRAY: 0x%x", value); } + break; } - break; case NV4097_DRAW_ARRAYS: { - for (u32 c=0; c> 4; + break; } - break; case NV4097_DRAW_INDEX_ARRAY: { @@ -985,24 +974,24 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 index; switch(m_indexed_array.m_type) { - case 0: - { - int pos = (int)m_indexed_array.m_data.size(); - m_indexed_array.m_data.resize(m_indexed_array.m_data.size() + 4); - index = vm::read32(m_indexed_array.m_addr + i * 4); - *(u32*)&m_indexed_array.m_data[pos] = index; - //LOG_WARNING(RSX, "index 4: %d", *(u32*)&m_indexed_array.m_data[pos]); - } + case 0: + { + int pos = (int)m_indexed_array.m_data.size(); + m_indexed_array.m_data.resize(m_indexed_array.m_data.size() + 4); + index = vm::read32(m_indexed_array.m_addr + i * 4); + *(u32*)&m_indexed_array.m_data[pos] = index; + //LOG_WARNING(RSX, "index 4: %d", *(u32*)&m_indexed_array.m_data[pos]); + } break; - case 1: - { - int pos = (int)m_indexed_array.m_data.size(); - m_indexed_array.m_data.resize(m_indexed_array.m_data.size() + 2); - index = vm::read16(m_indexed_array.m_addr + i * 2); - //LOG_WARNING(RSX, "index 2: %d", index); - *(u16*)&m_indexed_array.m_data[pos] = index; - } + case 1: + { + int pos = (int)m_indexed_array.m_data.size(); + m_indexed_array.m_data.resize(m_indexed_array.m_data.size() + 2); + index = vm::read16(m_indexed_array.m_addr + i * 2); + //LOG_WARNING(RSX, "index 2: %d", index); + *(u16*)&m_indexed_array.m_data[pos] = index; + } break; } @@ -1012,27 +1001,27 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_indexed_array.m_count += _count; } + break; } - break; case NV4097_SET_VERTEX_DATA_BASE_OFFSET: { m_vertex_data_base_offset = ARGS(0); - if (count >= 2) + if (count >= 2) { m_vertex_data_base_index = ARGS(1); } //LOG_WARNING(RSX, "NV4097_SET_VERTEX_DATA_BASE_OFFSET: 0x%x", m_vertex_data_base_offset); + break; } - break; case NV4097_SET_VERTEX_DATA_BASE_INDEX: { m_vertex_data_base_index = ARGS(0); + break; } - break; case NV4097_SET_BEGIN_END: { @@ -1068,8 +1057,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { End(); } + break; } - break; // Shader case NV4097_SET_SHADER_PROGRAM: @@ -1080,21 +1069,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_cur_fragment_prog->offset = a0 & ~0x3; m_cur_fragment_prog->addr = GetAddress(m_cur_fragment_prog->offset, (a0 & 0x3) - 1); m_cur_fragment_prog->ctrl = 0x40; + break; } - break; case NV4097_SET_SHADER_CONTROL: { m_shader_ctrl = ARGS(0); + break; } - break; case NV4097_SET_SHADE_MODE: { - const u32 value = ARGS(0); - ShadeModel(value); + m_set_shade_mode = true; + m_shade_mode = ARGS(0); + break; } - break; case NV4097_SET_SHADER_PACKER: { @@ -1110,8 +1099,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_shader_window_height = a0 & 0xfff; m_shader_window_origin = (a0 >> 12) & 0xf; m_shader_window_pixel_centers = a0 >> 16; + break; } - break; // Transform case NV4097_SET_TRANSFORM_PROGRAM_LOAD: @@ -1129,20 +1118,20 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_LOAD: start = %d", start); } } + break; } - break; case NV4097_SET_TRANSFORM_PROGRAM_START: { const u32 start = ARGS(0); - if (start) + if (start) { LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM_START: start = %d", start); } + break; } - break; - case_range(32, NV4097_SET_TRANSFORM_PROGRAM, 4) + case_range(32, NV4097_SET_TRANSFORM_PROGRAM, 4); { //LOG_WARNING(RSX, "NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count); @@ -1156,11 +1145,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { m_cur_vertex_prog->data.push_back(ARGS(i)); } + break; } - break; case NV4097_SET_TRANSFORM_TIMEOUT: - + { // TODO: // (cmd)[1] = CELL_GCM_ENDIAN_SWAP((count) | ((registerCount) << 16)); \ @@ -1171,7 +1160,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const } //m_cur_vertex_prog->Decompile(); - break; + break; + } case NV4097_SET_TRANSFORM_BRANCH_BITS: { @@ -1179,8 +1169,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_TRANSFORM_BRANCH_BITS: 0x%x", value); } + break; } - break; case NV4097_SET_TRANSFORM_CONSTANT_LOAD: { @@ -1203,8 +1193,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const //LOG_NOTICE(RSX, "NV4097_SET_TRANSFORM_CONSTANT_LOAD: [%d : %d] = (%f, %f, %f, %f)", i, id, c.x, c.y, c.z, c.w); } + break; } - break; // Invalidation case NV4097_INVALIDATE_L2: @@ -1213,20 +1203,20 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_INVALIDATE_L2: 0x%x", value); } + break; } - break; case NV4097_INVALIDATE_VERTEX_CACHE_FILE: { // Nothing to do here + break; } - break; case NV4097_INVALIDATE_VERTEX_FILE: { // Nothing to do here + break; } - break; case NV4097_INVALIDATE_ZCULL: { @@ -1234,190 +1224,165 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_INVALIDATE_ZCULL: 0x%x", value); } + break; } - break; // Logic Ops case NV4097_SET_LOGIC_OP_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_logic_op = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_LOGIC_OP: { - const u32 value = ARGS(0); - LogicOp(value); + m_logic_op = ARGS(0); + break; } - break; - + // Dithering case NV4097_SET_DITHER_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_dither = ARGS(0) ? true : false; + break; } - break; // Stencil testing case NV4097_SET_STENCIL_TEST_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, ARGS(0)); + m_set_stencil_test = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_TWO_SIDED_STENCIL_TEST_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, ARGS(0)); + m_set_two_sided_stencil_test_enable = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_TWO_SIDE_LIGHT_EN: { - const u32 value = ARGS(0); - LightModeli(value); + m_set_two_side_light_enable = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_STENCIL_MASK: { - const u32 value = ARGS(0); m_set_stencil_mask = true; - StencilMask(value); + m_stencil_mask = ARGS(0); + break; } - break; case NV4097_SET_STENCIL_FUNC: { - if (count == 3) + m_set_stencil_func = true; + m_stencil_func = ARGS(0); + + if (count >= 2) { - m_set_stencil_func = true; - m_stencil_func = ARGS(0); + m_set_stencil_func_ref = true; m_stencil_func_ref = ARGS(1); - m_stencil_func_mask = ARGS(2); - StencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); + + if (count >= 3) + { + m_set_stencil_func_mask = true; + m_stencil_func_mask = ARGS(2); + } } + break; } - break; case NV4097_SET_STENCIL_FUNC_REF: { + m_set_stencil_func_ref = true; m_stencil_func_ref = ARGS(0); - - if (m_set_stencil_func) - { - StencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - } + break; } - break; case NV4097_SET_STENCIL_FUNC_MASK: { + m_set_stencil_func_mask = true; m_stencil_func_mask = ARGS(0); - - if (m_set_stencil_func) - { - StencilFunc(m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); - } + break; } - break; case NV4097_SET_STENCIL_OP_FAIL: { - if (count == 3) + m_set_stencil_fail = true; + m_stencil_fail = ARGS(0); + + if (count >= 2) { - m_set_stencil_op_fail = true; - m_stencil_fail = ARGS(0); + m_set_stencil_zfail = true; m_stencil_zfail = ARGS(1); - m_stencil_zpass = ARGS(2); - StencilOp(m_stencil_fail, m_stencil_zfail, m_stencil_zpass); + + if (count >= 3) + { + m_set_stencil_zpass = true; + m_stencil_zpass = ARGS(2); + } } + break; } - break; case NV4097_SET_BACK_STENCIL_MASK: { + m_set_back_stencil_mask = true; m_back_stencil_mask = ARGS(0); - - StencilMaskSeparate(0, m_back_stencil_mask); // GL_BACK - - if (m_set_stencil_mask) - { - StencilMaskSeparate(1, m_stencil_mask); // GL_FRONT - } + break; } - break; case NV4097_SET_BACK_STENCIL_FUNC: { - if (count == 3) + m_set_back_stencil_func = true; + m_back_stencil_func = ARGS(0); + + if (count >= 2) { - m_set_back_stencil_func = true; - m_back_stencil_func = ARGS(0); + m_set_back_stencil_func_ref = true; m_back_stencil_func_ref = ARGS(1); - m_back_stencil_func_mask = ARGS(2); - StencilFuncSeparate(0, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); // GL_BACK - if (m_set_stencil_func) + + if (count >= 3) { - StencilFuncSeparate(1, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); // GL_FRONT + m_set_back_stencil_func_mask = true; + m_back_stencil_func_mask = ARGS(2); } } + break; } - break; case NV4097_SET_BACK_STENCIL_FUNC_REF: { + m_set_back_stencil_func_ref = true; m_back_stencil_func_ref = ARGS(0); - - if (m_set_back_stencil_func) - { - StencilFuncSeparate(0, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); // GL_BACK - - if (m_set_stencil_func) - { - StencilFuncSeparate(1, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); // GL_FRONT - } - } - + break; } - break; case NV4097_SET_BACK_STENCIL_FUNC_MASK: { + m_set_back_stencil_func_mask = true; m_back_stencil_func_mask = ARGS(0); - - if (m_set_back_stencil_func) - { - StencilFuncSeparate(0, m_back_stencil_func, m_back_stencil_func_ref, m_back_stencil_func_mask); // GL_BACK - - if (m_set_stencil_func) - { - StencilFuncSeparate(1, m_stencil_func, m_stencil_func_ref, m_stencil_func_mask); // GL_FRONT - } - } + break; } - break; case NV4097_SET_BACK_STENCIL_OP_FAIL: { - if (count == 3) - { - m_back_stencil_fail = ARGS(0); - m_back_stencil_zfail = ARGS(1); - m_back_stencil_zpass = ARGS(2); - StencilOpSeparate(0, m_back_stencil_fail, m_back_stencil_zfail, m_back_stencil_zpass); // GL_BACK + m_set_stencil_fail = true; + m_stencil_fail = ARGS(0); - if (m_set_stencil_op_fail) + if (count >= 2) + { + m_set_back_stencil_zfail = true; + m_back_stencil_zfail = ARGS(1); + + if (count >= 3) { - StencilOpSeparate(1, m_stencil_fail, m_stencil_zfail, m_stencil_zpass); // GL_FRONT + m_set_back_stencil_zpass = true; + m_back_stencil_zpass = ARGS(2); } } - + break; } - break; case NV4097_SET_SCULL_CONTROL: { @@ -1425,31 +1390,30 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_SCULL_CONTROL: 0x%x", value); } + break; } - break; // Primitive restart index case NV4097_SET_RESTART_INDEX_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_restart_index = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_RESTART_INDEX: { - const u32 value = ARGS(0); - PrimitiveRestartIndex(value); + m_restart_index = ARGS(0); + break; } - break; // Point size case NV4097_SET_POINT_SIZE: { - const u32 value = ARGS(0); - PointSize((float&)value); + m_set_point_size = true; + const u32 a0 = ARGS(0); + m_point_size = (float&)a0; + break; } - break; // Point sprite case NV4097_SET_POINT_PARAMS_ENABLE: @@ -1458,57 +1422,48 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", value); } + break; } - break; case NV4097_SET_POINT_SPRITE_CONTROL: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_point_sprite_control = ARGS(0) ? true : false; // TODO: //(cmd)[1] = CELL_GCM_ENDIAN_SWAP((enable) | ((rmode) << 1) | (texcoordMask)); + break; } - break; // Lighting case NV4097_SET_SPECULAR_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_specular = ARGS(0) ? true : false; + break; } - break; // Scissor case NV4097_SET_SCISSOR_HORIZONTAL: { - const u32 value = ARGS(0); m_set_scissor_horizontal = true; - m_scissor_x = value & 0xffff; - m_scissor_w = value >> 16; + m_scissor_x = ARGS(0) & 0xffff; + m_scissor_w = ARGS(0) >> 16; if (count == 2) { - const u32 value1 = ARGS(1); - m_scissor_y = value1 & 0xffff; - m_scissor_h = value1 >> 16; - Scissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + m_set_scissor_vertical = true; + m_scissor_y = ARGS(1) & 0xffff; + m_scissor_h = ARGS(1) >> 16; } + break; } - break; case NV4097_SET_SCISSOR_VERTICAL: { - const u32 value = ARGS(0); - m_scissor_y = value & 0xffff; - m_scissor_h = value >> 16; - - if (m_set_scissor_horizontal) - { - Scissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); - } + m_set_scissor_vertical = true; + m_scissor_y = ARGS(0) & 0xffff; + m_scissor_h = ARGS(0) >> 16; + break; } - break; // Depth/Color buffer usage case NV4097_SET_SURFACE_FORMAT: @@ -1536,56 +1491,56 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_height = buffers[m_gcm_current_buffer].height; NativeRescale((float)m_width, (float)m_height); + break; } - break; case NV4097_SET_SURFACE_COLOR_TARGET: { m_surface_color_target = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_COLOR_AOFFSET: { m_surface_offset_a = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_COLOR_BOFFSET: { m_surface_offset_b = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_COLOR_COFFSET: { m_surface_offset_c = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_COLOR_DOFFSET: { m_surface_offset_d = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_ZETA_OFFSET: { m_surface_offset_z = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_PITCH_A: { m_surface_pitch_a = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_PITCH_B: { m_surface_pitch_b = ARGS(0); + break; } - break; case NV4097_SET_SURFACE_PITCH_C: { @@ -1599,8 +1554,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_surface_pitch_d = ARGS(1); m_surface_offset_c = ARGS(2); m_surface_offset_d = ARGS(3); + break; } - break; case NV4097_SET_SURFACE_PITCH_D: { @@ -1611,8 +1566,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_ERROR(RSX, "NV4097_SET_SURFACE_PITCH_D: Bad count (%d)", count); break; } + break; } - break; case NV4097_SET_SURFACE_PITCH_Z: { @@ -1623,8 +1578,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_ERROR(RSX, "NV4097_SET_SURFACE_PITCH_Z: Bad count (%d)", count); break; } + break; } - break; case NV4097_SET_CONTEXT_DMA_COLOR_A: { @@ -1636,15 +1591,15 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_ERROR(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_A: Bad count (%d)", count); break; } + break; } - break; case NV4097_SET_CONTEXT_DMA_COLOR_B: { m_set_context_dma_color_b = true; m_context_dma_color_b = ARGS(0); + break; } - break; case NV4097_SET_CONTEXT_DMA_COLOR_C: { @@ -1656,8 +1611,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_context_dma_color_d = true; m_context_dma_color_d = ARGS(1); } + break; } - break; case NV4097_SET_CONTEXT_DMA_COLOR_D: { @@ -1665,15 +1620,15 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_COLOR_D: 0x%x", ARGS(0)); } + break; } - break; case NV4097_SET_CONTEXT_DMA_ZETA: { m_set_context_dma_z = true; m_context_dma_z = ARGS(0); + break; } - break; case NV4097_SET_CONTEXT_DMA_SEMAPHORE: { @@ -1681,8 +1636,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", value); } + break; } - break; case NV4097_SET_CONTEXT_DMA_NOTIFIES: { @@ -1690,8 +1645,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", value); } + break; } - break; case NV4097_SET_SURFACE_CLIP_HORIZONTAL: { @@ -1708,8 +1663,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_surface_clip_y = a1; m_surface_clip_h = a1 >> 16; } + break; } - break; case NV4097_SET_SURFACE_CLIP_VERTICAL: { @@ -1717,8 +1672,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_set_surface_clip_vertical = true; m_surface_clip_y = a0; m_surface_clip_h = a0 >> 16; + break; } - break; // Anti-aliasing case NV4097_SET_ANTI_ALIASING_CONTROL: @@ -1729,78 +1684,76 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u8 alphaToCoverage = (a0 >> 4) & 0xf; const u8 alphaToOne = (a0 >> 8) & 0xf; const u16 sampleMask = a0 >> 16; - + if (a0) { LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: 0x%x", a0); } + break; } - break; // Line/Polygon smoothing case NV4097_SET_LINE_SMOOTH_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_line_smooth = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_POLY_SMOOTH_ENABLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_poly_smooth = ARGS(0) ? true : false; + break; } - break; // Line width case NV4097_SET_LINE_WIDTH: { - const u32 value = ARGS(0); - LineWidth((float)value / 8.0f); + m_set_line_width = true; + const u32 a0 = ARGS(0); + m_line_width = (float)a0 / 8.0f; + break; } - break; // Line/Polygon stipple case NV4097_SET_LINE_STIPPLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_line_stipple = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_LINE_STIPPLE_PATTERN: { - const u32 value = ARGS(0); - LineStipple(value & 0xffff, value >> 16); + m_set_line_stipple = true; + const u32 a0 = ARGS(0); + m_line_stipple_factor = a0 & 0xffff; + m_line_stipple_pattern = a0 >> 16; + break; } - break; case NV4097_SET_POLYGON_STIPPLE: { - const u32 value = ARGS(0); - Enable(cmd, value); + m_set_polygon_stipple = ARGS(0) ? true : false; + break; } - break; case NV4097_SET_POLYGON_STIPPLE_PATTERN: { - u32 pattern[32]; for (u32 i = 0; i < 32; i++) { - pattern[i] = ARGS(i); - PolygonStipple(pattern[i]); + m_polygon_stipple_pattern[i] = ARGS(i); } + break; } - break; // Zcull case NV4097_SET_ZCULL_EN: { - const u32 value = ARGS(0); - Enable(NV4097_SET_DEPTH_TEST_ENABLE, value & 0x1); - Enable(NV4097_SET_STENCIL_TEST_ENABLE, value & 0x2); + const u32 a0 = ARGS(0); + + m_set_depth_test = a0 & 0x1 ? true : false; + m_set_stencil_test = a0 & 0x2 ? true : false; + break; } - break; case NV4097_SET_ZCULL_CONTROL0: { @@ -1808,17 +1761,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_CONTROL0: 0x%x", value); } + break; } - break; - + case NV4097_SET_ZCULL_CONTROL1: { if (u32 value = ARGS(0)) { LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_CONTROL1: 0x%x", value); } + break; } - break; case NV4097_SET_ZCULL_STATS_ENABLE: { @@ -1826,8 +1779,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", value); } + break; } - break; case NV4097_ZCULL_SYNC: { @@ -1835,8 +1788,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV4097_ZCULL_SYNC: 0x%x", value); } + break; } - break; // Reports case NV4097_GET_REPORT: @@ -1855,12 +1808,12 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case CELL_GCM_ZCULL_STATS3: value = 0; LOG_WARNING(RSX, "NV4097_GET_REPORT: Unimplemented type %d", type); - break; + break; default: value = 0; LOG_ERROR(RSX, "NV4097_GET_REPORT: Bad type %d", type); - break; + break; } // Get timestamp, and convert it from microseconds to nanoseconds @@ -1870,14 +1823,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const vm::write64(m_local_mem_addr + offset + 0x0, timestamp); vm::write32(m_local_mem_addr + offset + 0x8, value); vm::write32(m_local_mem_addr + offset + 0xc, 0); + break; } - break; case NV4097_CLEAR_REPORT_VALUE: { const u32 type = ARGS(0); - switch(type) + switch (type) { case CELL_GCM_ZPASS_PIXEL_CNT: LOG_WARNING(RSX, "TODO: NV4097_CLEAR_REPORT_VALUE: ZPASS_PIXEL_CNT"); @@ -1888,33 +1841,41 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const default: LOG_ERROR(RSX, "NV4097_CLEAR_REPORT_VALUE: Bad type: %d", type); break; - } + } + break; } - break; // Clip Plane case NV4097_SET_USER_CLIP_PLANE_CONTROL: { - const u32 value = ARGS(0); - Enable(cmd, value); + const u32 a0 = ARGS(0); + m_set_clip_plane = true; + m_clip_plane_0 = (a0 & 0xf) ? true : false; + m_clip_plane_1 = ((a0 >> 4)) & 0xf ? true : false; + m_clip_plane_2 = ((a0 >> 8)) & 0xf ? true : false; + m_clip_plane_3 = ((a0 >> 12)) & 0xf ? true : false; + m_clip_plane_4 = ((a0 >> 16)) & 0xf ? true : false; + m_clip_plane_5 = (a0 >> 20) ? true : false; + break; } - break; // Fog case NV4097_SET_FOG_MODE: { - const u32 value = ARGS(0); - Fogi(value); + m_set_fog_mode = true; + m_fog_mode = ARGS(0); + break; } - break; case NV4097_SET_FOG_PARAMS: { - const u32 start = ARGS(0); - const u32 end = ARGS(1); - Fogf((float&)start, (float&)end); + m_set_fog_params = true; + const u32 a0 = ARGS(0); + const u32 a1 = ARGS(1); + m_fog_param0 = (float&)a0; + m_fog_param1 = (float&)a1; + break; } - break; // Zmin_max case NV4097_SET_ZMIN_MAX_CONTROL: @@ -1924,8 +1885,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u8 cullIgnoreW = (ARGS(0) >> 8) & 0xf; LOG_WARNING(RSX, "TODO: NV4097_SET_ZMIN_MAX_CONTROL: cullNearFarEnable=%d, zclampEnable=%d, cullIgnoreW=%d", cullNearFarEnable, zclampEnable, cullIgnoreW); + break; } - break; case NV4097_SET_WINDOW_OFFSET: { @@ -1933,16 +1894,16 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u16 y = ARGS(0) >> 16; LOG_WARNING(RSX, "TODO: NV4097_SET_WINDOW_OFFSET: x=%d, y=%d", x, y); + break; } - break; case NV4097_SET_FREQUENCY_DIVIDER_OPERATION: { m_set_frequency_divider_operation = ARGS(0); - + LOG_WARNING(RSX, "TODO: NV4097_SET_FREQUENCY_DIVIDER_OPERATION: %d", m_set_frequency_divider_operation); + break; } - break; case NV4097_SET_RENDER_ENABLE: { @@ -1950,16 +1911,16 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u8 mode = ARGS(0) >> 24; LOG_WARNING(RSX, "TODO: NV4097_SET_RENDER_ENABLE: Offset=0x%06x, Mode=0x%x", offset, mode); + break; } - break; case NV4097_SET_ZPASS_PIXEL_COUNT_ENABLE: { const u32 enable = ARGS(0); LOG_WARNING(RSX, "TODO: NV4097_SET_ZPASS_PIXEL_COUNT_ENABLE: %d", enable); + break; } - break; // NV0039 case NV0039_SET_CONTEXT_DMA_BUFFER_IN: @@ -1968,8 +1929,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u32 dstContext = ARGS(1); m_context_dma_buffer_in_src = srcContext; m_context_dma_buffer_in_dst = dstContext; + break; } - break; case NV0039_OFFSET_IN: { @@ -1984,7 +1945,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u32 notify = ARGS(7); // The existing GCM commands use only the value 0x1 for inFormat and outFormat - if (inFormat != 0x01 || outFormat != 0x01) + if (inFormat != 0x01 || outFormat != 0x01) { LOG_ERROR(RSX, "NV0039_OFFSET_IN: Unsupported format: inFormat=%d, outFormat=%d", inFormat, outFormat); } @@ -1998,8 +1959,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_ERROR(RSX, "NV0039_OFFSET_IN: bad offset(in=0x%x, out=0x%x), pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", inOffset, outOffset, inPitch, outPitch, lineLength, lineCount, inFormat, outFormat, notify); } + break; } - break; case NV0039_OFFSET_OUT: // [E : RSXThread]: TODO: unknown/illegal method [0x00002310](0x0) { @@ -2012,8 +1973,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_ERROR(RSX, "TODO: NV0039_OFFSET_OUT: offset=0x%x", offset); } + break; } - break; case NV0039_PITCH_IN: { @@ -2021,8 +1982,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV0039_PITCH_IN: 0x%x", value); } + break; } - break; case NV0039_BUFFER_NOTIFY: { @@ -2030,29 +1991,29 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV0039_BUFFER_NOTIFY: 0x%x", value); } + break; } - break; // NV3062 case NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN: { m_context_dma_img_dst = ARGS(0); + break; } - break; case NV3062_SET_OFFSET_DESTIN: { m_dst_offset = ARGS(0); + break; } - break; case NV3062_SET_COLOR_FORMAT: { m_color_format = ARGS(0); m_color_format_src_pitch = ARGS(1); m_color_format_dst_pitch = ARGS(1) >> 16; + break; } - break; // NV309E case NV309E_SET_CONTEXT_DMA_IMAGE: @@ -2061,8 +2022,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_WARNING(RSX, "TODO: NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", value); } + break; } - break; case NV309E_SET_FORMAT: { @@ -2072,8 +2033,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u32 offset = ARGS(1); LOG_WARNING(RSX, "TODO: NV309E_SET_FORMAT: Format:0x%x, Width:%d, Height:%d, Offset:0x%x", format, width, height, offset); + break; } - break; // NV308A case NV308A_POINT: @@ -2081,8 +2042,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u32 a0 = ARGS(0); m_point_x = a0 & 0xffff; m_point_y = a0 >> 16; + break; } - break; case NV308A_COLOR: { @@ -2125,15 +2086,15 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_fragment_constants.push_back(c); //LOG_WARNING(RSX, "NV308A_COLOR: [%d]: %f, %f, %f, %f", c.id, c.x, c.y, c.z, c.w); + break; } - break; // NV3089 case NV3089_SET_CONTEXT_DMA_IMAGE: { m_context_dma_img_src = ARGS(0); + break; } - break; case NV3089_SET_CONTEXT_SURFACE: { @@ -2141,8 +2102,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { LOG_ERROR(RSX, "NV3089_SET_CONTEXT_SURFACE: Unsupported surface (0x%x)", ARGS(0)); } + break; } - break; case NV3089_IMAGE_IN_SIZE: { @@ -2174,8 +2135,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const //(u32&)pixels_dst[dst_offset] = (u32&)pixels_src[src_offset]; } } + break; } - break; case NV3089_SET_COLOR_CONVERSION: { @@ -2194,8 +2155,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_color_conv_dtdy = ARGS(8); LOG_WARNING(RSX, "TODO: NV3089_SET_COLOR_CONVERSION"); + break; } - break; case GCM_SET_USER_COMMAND: { @@ -2205,8 +2166,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { cb(CPU, cause); }); + break; } - break; // Note: What is this? NV4097 offsets? case 0x000002c8: @@ -2216,7 +2177,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case 0x000002e8: case 0x000002f0: case 0x000002f8: - break; + break; // The existing GCM commands don't use any of the following NV4097 / NV0039 / NV3062 / NV309E / NV308A / NV3089 methods case NV4097_SET_WINDOW_CLIP_TYPE: @@ -2224,8 +2185,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV4097_SET_WINDOW_CLIP_VERTICAL: { LOG_WARNING(RSX, "Unused NV4097 method 0x%x detected!", cmd); + break; } - break; case NV0039_SET_CONTEXT_DMA_BUFFER_OUT: case NV0039_PITCH_OUT: @@ -2236,8 +2197,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV0039_SET_CONTEXT_DMA_NOTIFIES: { LOG_WARNING(RSX, "Unused NV0039 method 0x%x detected!", cmd); + break; } - break; case NV3062_SET_OBJECT: case NV3062_SET_CONTEXT_DMA_NOTIFIES: @@ -2246,8 +2207,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV3062_SET_OFFSET_SOURCE: { LOG_WARNING(RSX, "Unused NV3062 method 0x%x detected!", cmd); + break; } - break; case NV308A_SET_OBJECT: case NV308A_SET_CONTEXT_DMA_NOTIFIES: @@ -2265,16 +2226,16 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV308A_SIZE_IN: { LOG_WARNING(RSX, "Unused NV308A method 0x%x detected!", cmd); + break; } - break; case NV309E_SET_OBJECT: case NV309E_SET_CONTEXT_DMA_NOTIFIES: case NV309E_SET_OFFSET: { LOG_WARNING(RSX, "Unused NV309E method 0x%x detected!", cmd); + break; } - break; case NV3089_SET_OBJECT: case NV3089_SET_CONTEXT_DMA_NOTIFIES: @@ -2295,20 +2256,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case NV3089_IMAGE_IN: { LOG_WARNING(RSX, "Unused NV3089 methods 0x%x detected!", cmd); + break; } - break; default: { std::string log = GetMethodName(cmd); log += "("; - for (u32 i=0; i lock(m_cs_main); - inc=1; + inc = 1; u32 get = m_ctrl->get.read_sync(); u32 put = m_ctrl->put.read_sync(); @@ -2405,12 +2367,12 @@ void RSXThread::Task() const u32 cmd = ReadIO32(get); const u32 count = (cmd >> 18) & 0x7ff; - + if (Ini.RSXLogging.GetValue()) { LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd); } - + if (cmd & CELL_GCM_METHOD_FLAG_JUMP) { u32 offs = cmd & 0x1fffffff; @@ -2418,7 +2380,6 @@ void RSXThread::Task() m_ctrl->get.exchange(be_t::make(offs)); continue; } - if (cmd & CELL_GCM_METHOD_FLAG_CALL) { m_call_stack.push(get + 4); @@ -2427,7 +2388,6 @@ void RSXThread::Task() m_ctrl->get.exchange(be_t::make(offs)); continue; } - if (cmd == CELL_GCM_METHOD_FLAG_RETURN) { u32 get = m_call_stack.top(); @@ -2436,7 +2396,6 @@ void RSXThread::Task() m_ctrl->get.exchange(be_t::make(get)); continue; } - if (cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) { //LOG_WARNING(RSX, "rsx non increment cmd! 0x%x", cmd); diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index c0f412f648..9732c8a418 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -90,7 +90,7 @@ struct RSXTransformConstant } }; -class RSXThread : public ThreadBase +class RSXThread : public ThreadBase { public: static const uint m_textures_count = 16; @@ -498,7 +498,7 @@ protected: m_front_face = 0x0901; // GL_CCW m_cull_face = 0x0405; // GL_BACK m_alpha_func = 0x0207; // GL_ALWAYS - m_alpha_ref = 0.0; + m_alpha_ref = 0.0f; m_logic_op = 0x1503; // GL_COPY m_shade_mode = 0x1D01; // GL_SMOOTH m_depth_mask = 1; @@ -523,7 +523,7 @@ protected: m_vertex_data_base_index = 0; // Construct Stipple Pattern - for (size_t i = 0; i < 32; i++) + for (size_t i = 0; i < 32; i++) { m_polygon_stipple_pattern[i] = 0xFFFFFFFF; } @@ -629,54 +629,20 @@ protected: u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr); void DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count); void NativeRescale(float width, float height); - + virtual void OnInit() = 0; virtual void OnInitThread() = 0; virtual void OnExitThread() = 0; virtual void OnReset() = 0; virtual void ExecCMD() = 0; - virtual void Enable(u32 cmd, u32 enable) = 0; - virtual void ClearColor(u32 a, u32 r, u32 g, u32 b) = 0; - virtual void ClearStencil(u32 stencil) = 0; - virtual void ClearDepth(u32 depth) = 0; - virtual void ClearSurface(u32 mask) = 0; - virtual void ColorMask(bool a, bool r, bool g, bool b) = 0; - virtual void AlphaFunc(u32 func, float ref) = 0; - virtual void DepthFunc(u32 func) = 0; - virtual void DepthMask(u32 flag) = 0; - virtual void PolygonMode(u32 face, u32 mode) = 0; - virtual void PointSize(float size) = 0; - virtual void LogicOp(u32 opcode) = 0; - virtual void LineWidth(float width) = 0; - virtual void LineStipple(u16 factor, u16 pattern) = 0; - virtual void PolygonStipple(u32 pattern) = 0; - virtual void PrimitiveRestartIndex(u32 index) = 0; - virtual void CullFace(u32 mode) = 0; - virtual void FrontFace(u32 mode) = 0; - virtual void Fogi(u32 mode) = 0; - virtual void Fogf(float start, float end) = 0; - virtual void PolygonOffset(float factor, float bias) = 0; - virtual void DepthRangef(float min, float max) = 0; - virtual void BlendEquationSeparate(u16 rgb, u16 a) = 0; - virtual void BlendFuncSeparate(u16 srcRGB, u16 dstRGB, u16 srcAlpha, u16 dstAlpha) = 0; - virtual void BlendColor(u8 r, u8 g, u8 b, u8 a) = 0; - virtual void LightModeli(u32 enable) = 0; - virtual void ShadeModel(u32 mode) = 0; - virtual void DepthBoundsEXT(float min, float max) = 0; - virtual void Scissor(u16 x, u16 y, u16 width, u16 height) = 0; - virtual void StencilOp(u32 fail, u32 zfail, u32 zpass) = 0; - virtual void StencilMask(u32 mask) = 0; - virtual void StencilFunc(u32 func, u32 ref, u32 mask) = 0; - virtual void StencilOpSeparate(u32 mode, u32 fail, u32 zfail, u32 zpass) = 0; - virtual void StencilMaskSeparate(u32 mode, u32 mask) = 0; - virtual void StencilFuncSeparate(u32 mode, u32 func, u32 ref, u32 mask) = 0; + virtual void ExecCMD(u32 cmd) = 0; virtual void Flip() = 0; void LoadVertexData(u32 first, u32 count) { for (u32 i = 0; i < m_vertex_count; ++i) { - if(!m_vertex_data[i].IsEnabled()) continue; + if (!m_vertex_data[i].IsEnabled()) continue; m_vertex_data[i].Load(first, count, m_vertex_data_base_offset, m_vertex_data_base_index); } From 61a5459ccb48a25e499e1a6a82df64c3ac47e60e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 31 Jan 2015 19:44:26 +0300 Subject: [PATCH 48/94] TLS for ARMv7 threads --- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 + rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 14 ++-- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 69 ++++++++++++++++++++ rpcs3/Emu/ARMv7/ARMv7Thread.h | 1 + rpcs3/Emu/Cell/PPUThread.cpp | 27 +------- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 28 +++----- rpcs3/Emu/System.h | 22 +++---- rpcs3/Loader/ELF32.cpp | 11 +++- rpcs3/Loader/ELF64.cpp | 5 +- 9 files changed, 115 insertions(+), 64 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 962f5dcc19..1316a26786 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -111,6 +111,8 @@ struct ARMv7Context } ITSTATE; + u32 TLS; + u32 R_ADDR; u64 R_DATA; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index ea01bcecc9..78c17f4fda 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -336,15 +336,17 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (ConditionPassed(context, cond)) { - if (cp == 15 && opc1 == 0 && cn == 13 && cm == 0 && opc2 == 3) - { - LOG_ERROR(ARMv7, "TODO: TLS requested"); + // APSR flags are written if t = 15 - if (t < 15) + if (t < 15 && cp == 15 && opc1 == 0 && cn == 13 && cm == 0 && opc2 == 3) + { + if (!context.TLS) { - context.GPR[t] = 0; - return; + throw "TLS not initialized"; } + + context.GPR[t] = context.TLS; + return; } throw fmt::format("Bad instruction: mrc p%d,%d,r%d,c%d,c%d,%d", cp, opc1, t, cn, cm, opc2); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 0b9710ffe2..3495376c79 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -30,6 +30,69 @@ void ARMv7Context::fast_call(u32 addr) return thread.FastCall(addr); } +#define TLS_MAX 128 + +u32 g_armv7_tls_start; + +std::array, TLS_MAX> g_armv7_tls_owners; + +void armv7_init_tls() +{ + g_armv7_tls_start = Emu.GetTLSMemsz() ? vm::cast(Memory.PSV.RAM.AllocAlign(Emu.GetTLSMemsz() * TLS_MAX, 4096)) : 0; + + for (auto& v : g_armv7_tls_owners) + { + v.store(0, std::memory_order_relaxed); + } +} + +u32 armv7_get_tls(u32 thread) +{ + if (!Emu.GetTLSMemsz()) + { + return 0; + } + + for (u32 i = 0; i < TLS_MAX; i++) + { + if (g_armv7_tls_owners[i] == thread) + { + return g_armv7_tls_start + i * Emu.GetTLSMemsz(); // if already initialized, return TLS address + } + } + + for (u32 i = 0; i < TLS_MAX; i++) + { + u32 old = 0; + if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread)) + { + const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address + memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros + memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + return addr; + } + } + + throw "Out of TLS memory"; +} + +void armv7_free_tls(u32 thread) +{ + if (!Emu.GetTLSMemsz()) + { + return; + } + + for (auto& v : g_armv7_tls_owners) + { + u32 old = thread; + if (v.compare_exchange_strong(old, 0)) + { + return; + } + } +} + ARMv7Thread::ARMv7Thread() : CPUThread(CPU_THREAD_ARMv7) , context(*this) @@ -39,6 +102,11 @@ ARMv7Thread::ARMv7Thread() { } +ARMv7Thread::~ARMv7Thread() +{ + armv7_free_tls(GetId()); +} + void ARMv7Thread::InitRegs() { memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); @@ -47,6 +115,7 @@ void ARMv7Thread::InitRegs() context.ISET = Thumb; context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; + context.TLS = armv7_get_tls(GetId()); } void ARMv7Thread::InitStack() diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index 2dd26772e7..c806f4b6c4 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -12,6 +12,7 @@ public: //const char* m_last_instr_name; ARMv7Thread(); + ~ARMv7Thread(); //void update_code(const u32 address) //{ diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 9a221b00c6..e064a54feb 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -55,7 +55,7 @@ void PPUThread::DoReset() XER.XER = 0; FPSCR.FPSCR = 0; VSCR.VSCR = 0; - VRSAVE = 0; + VRSAVE = 0; cycle = 0; } @@ -65,33 +65,8 @@ void PPUThread::InitRegs() const u32 pc = entry ? vm::read32(entry) : 0; const u32 rtoc = entry ? vm::read32(entry + 4) : 0; - //ConLog.Write("entry = 0x%x", entry); - //ConLog.Write("rtoc = 0x%x", rtoc); - SetPc(pc); - /* - const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); - - if(thread_num < 0) - { - LOG_ERROR(PPU, "GetThreadNumById failed."); - Emu.Pause(); - return; - } - */ - - /* - const s32 tls_size = Emu.GetTLSFilesz() * thread_num; - - if(tls_size >= Emu.GetTLSMemsz()) - { - LOG_ERROR(PPU, "Out of TLS memory."); - Emu.Pause(); - return; - } - */ - GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200; GPR[2] = rtoc; //GPR[11] = entry; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 063655cc72..2a8d3cc699 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -23,12 +23,10 @@ Module *sysPrxForUser = nullptr; -u32 g_tls_size; // size of every thread's storage -u32 g_tls_start; // start of TLS memory area -u32 g_tls_image_addr; // address of TLS initialization area -u32 g_tls_image_size; // size of TLS initialization area +#define TLS_MAX 128 + +u32 g_tls_start; // start of TLS memory area -const u32 TLS_MAX = 256; std::array, TLS_MAX> g_tls_owners; void sys_initialize_tls() @@ -40,19 +38,16 @@ u32 ppu_get_tls(u32 thread) { if (!g_tls_start) { - g_tls_size = vm::cast(Emu.GetTLSMemsz(), "Emu.GetTLSMemsz"); // (not an address for vm::cast, but fine) - g_tls_start = vm::cast(Memory.Alloc(g_tls_size * TLS_MAX, 4096)); // memory for up to TLS_MAX threads - g_tls_image_addr = vm::cast(Emu.GetTLSAddr(), "Emu.GetTLSAddr"); - g_tls_image_size = vm::cast(Emu.GetTLSFilesz(), "Emu.GetTLSFilesz"); - - sysPrxForUser->Warning("TLS initialized (g_tls_size=0x%x, g_tls_start=0x%x, g_tls_image_addr=0x%x, g_tls_image_size=0x%x)", g_tls_size, g_tls_start, g_tls_image_addr, g_tls_image_size); + g_tls_start = vm::cast(Memory.MainMem.AllocAlign(Emu.GetTLSMemsz() * TLS_MAX, 4096)); // memory for up to TLS_MAX threads + sysPrxForUser->Notice("Thread Local Storage initialized (g_tls_start=0x%x, size = 0x%x)\n*** TLS segment addr: 0x%08x\n*** TLS segment size: 0x%08x", + g_tls_start, Emu.GetTLSMemsz(), Emu.GetTLSAddr(), Emu.GetTLSFilesz()); } for (u32 i = 0; i < TLS_MAX; i++) { if (g_tls_owners[i] == thread) { - return g_tls_start + i * g_tls_size; // if already initialized, return TLS address + return g_tls_start + i * Emu.GetTLSMemsz(); // if already initialized, return TLS address } } @@ -61,9 +56,9 @@ u32 ppu_get_tls(u32 thread) u32 old = 0; if (g_tls_owners[i].compare_exchange_strong(old, thread)) { - const u32 addr = g_tls_start + i * g_tls_size; // get TLS address - memset(vm::get_ptr(addr), 0, g_tls_size); // fill TLS area with zeros - memcpy(vm::get_ptr(addr), vm::get_ptr(g_tls_image_addr), g_tls_image_size); // initialize from TLS image + const u32 addr = g_tls_start + i * Emu.GetTLSMemsz(); // get TLS address + memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros + memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image return addr; } } @@ -420,10 +415,7 @@ void sysPrxForUser_init(Module *pxThis) { sysPrxForUser = pxThis; - g_tls_size = 0; g_tls_start = 0; - g_tls_image_addr = 0; - g_tls_image_size = 0; for (auto& v : g_tls_owners) { v.store(0, std::memory_order_relaxed); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index a4901089b3..d9615e2613 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -28,9 +28,9 @@ struct VFS; struct EmuInfo { private: - u64 tls_addr; - u64 tls_filesz; - u64 tls_memsz; + u32 tls_addr; + u32 tls_filesz; + u32 tls_memsz; sys_process_param_info proc_param; @@ -50,16 +50,16 @@ public: proc_param.primary_prio = be_t::make(0x50); } - void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) + void SetTLSData(u32 addr, u32 filesz, u32 memsz) { tls_addr = addr; tls_filesz = filesz; tls_memsz = memsz; } - u64 GetTLSAddr() const { return tls_addr; } - u64 GetTLSFilesz() const { return tls_filesz; } - u64 GetTLSMemsz() const { return tls_memsz; } + u32 GetTLSAddr() const { return tls_addr; } + u32 GetTLSFilesz() const { return tls_filesz; } + u32 GetTLSMemsz() const { return tls_memsz; } }; class ModuleInitializer @@ -173,7 +173,7 @@ public: m_modules_init.push_back(std::move(m)); } - void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) + void SetTLSData(u32 addr, u32 filesz, u32 memsz) { m_info.SetTLSData(addr, filesz, memsz); } @@ -195,9 +195,9 @@ public: EmuInfo& GetInfo() { return m_info; } - u64 GetTLSAddr() const { return m_info.GetTLSAddr(); } - u64 GetTLSFilesz() const { return m_info.GetTLSFilesz(); } - u64 GetTLSMemsz() const { return m_info.GetTLSMemsz(); } + u32 GetTLSAddr() const { return m_info.GetTLSAddr(); } + u32 GetTLSFilesz() const { return m_info.GetTLSFilesz(); } + u32 GetTLSMemsz() const { return m_info.GetTLSMemsz(); } u32 GetMallocPageSize() { return m_info.GetProcParam().malloc_pagesize; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 01232eb579..9c7f19d0c2 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -11,6 +11,8 @@ #include "Emu/ARMv7/PSVFuncList.h" #include "Emu/System.h" +extern void armv7_init_tls(); + namespace loader { namespace handlers @@ -235,9 +237,13 @@ namespace loader } else if (!strcmp(name.c_str(), ".tbss")) { - LOG_NOTICE(LOADER, ".tbss analysis"); + LOG_NOTICE(LOADER, ".tbss analysis..."); + const u32 img_addr = shdr.data_le.sh_addr; // start address of TLS initialization image + const u32 img_size = (&shdr)[1].data_le.sh_addr - img_addr; // calculate its size as the difference between sections + const u32 tls_size = shdr.data_le.sh_size; // full size of TLS - LOG_ERROR(LOADER, "TLS: size=0x%08x", shdr.data_le.sh_size); + LOG_WARNING(LOADER, "TLS: img_addr=0x%08x, img_size=0x%x, tls_size=0x%x", img_addr, img_size, tls_size); + Emu.SetTLSData(img_addr, img_size, tls_size); } else if (!strcmp(name.c_str(), ".sceRefs.rodata")) { @@ -314,6 +320,7 @@ namespace loader } } + armv7_init_tls(); armv7_decoder_initialize(code_start, code_end); arm7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index de2a78c0a6..ac64afc207 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -422,7 +422,10 @@ namespace loader break; case 0x00000007: //TLS - Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value()); + Emu.SetTLSData( + vm::cast(phdr.p_vaddr.addr(), "TLS: phdr.p_vaddr"), + vm::cast(phdr.p_filesz.value(), "TLS: phdr.p_filesz"), + vm::cast(phdr.p_memsz.value(), "TLS: phdr.p_memsz")); break; case 0x60000001: //LOOS+1 From 61342946a4a84271a398f3f48bfd1ed60e91f69d Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Sun, 1 Feb 2015 02:16:06 +0530 Subject: [PATCH 49/94] SPURS: Implement some portions of taskset pm --- rpcs3/Emu/Cell/SPUInterpreter.h | 5 +- rpcs3/Emu/Cell/SPUThread.h | 9 + rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 34 ++- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 235 +++++++++++++++++--- 4 files changed, 235 insertions(+), 48 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 151eb4e436..8351911153 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -1373,10 +1373,7 @@ private: } void FSCRWR(u32 rt, u32 ra) { - CPU.FPSCR._u32[3] = CPU.GPR[ra]._u32[3] & 0x00000F07; - CPU.FPSCR._u32[2] = CPU.GPR[ra]._u32[2] & 0x00003F07; - CPU.FPSCR._u32[1] = CPU.GPR[ra]._u32[1] & 0x00003F07; - CPU.FPSCR._u32[0] = CPU.GPR[ra]._u32[0] & 0x00000F07; + CPU.FPSCR.Write(CPU.GPR[ra]); } void DFTSV(u32 rt, u32 ra, s32 i7) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index ce0036e4a5..cfd45d6c0e 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -248,6 +248,15 @@ public: { _u32[1+slice] |= exceptions; } + + // Write the FPSCR + void Write(u128 & r) + { + _u32[3] = r._u32[3] & 0x00000F07; + _u32[2] = r._u32[2] & 0x00003F07; + _u32[1] = r._u32[1] & 0x00003F07; + _u32[0] = r._u32[0] & 0x00000F07; + } }; union SPU_SNRConfig_hdr diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 08fff45abf..85df5fb582 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -40,6 +40,7 @@ enum { CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901, CELL_SPURS_TASK_ERROR_INVAL = 0x80410902, + CELL_SPURS_TASK_ERROR_NOSYS = 0x80410903, CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904, CELL_SPURS_TASK_ERROR_SRCH = 0x80410905, CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907, @@ -213,6 +214,17 @@ enum SpursTaskConstants CELL_SPURS_TASK_EXECUTION_CONTEXT_SIZE = 1024, CELL_SPURS_TASKSET_PM_ENTRY_ADDR = 0xA00, CELL_SPURS_TASKSET_PM_SYSCALL_ADDR = 0xA70, + + // Task syscall numbers + CELL_SPURS_TASK_SYSCALL_EXIT = 0, + CELL_SPURS_TASK_SYSCALL_YIELD = 1, + CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL = 2, + CELL_SPURS_TASK_SYSCALL_POLL = 3, + CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG = 4, + + // Task poll status + CELL_SPURS_TASK_POLL_FOUND_TASK = 1, + CELL_SPURS_TASK_POLL_FOUND_WORKLOAD = 2, }; enum CellSpursEventFlagWaitMode @@ -627,10 +639,10 @@ struct CellSpursTaskset struct TaskInfo { - CellSpursTaskArgument args; - vm::bptr elf_addr; - be_t context_save_storage_and_alloc_ls_blocks; // This is (context_save_storage_addr | allocated_ls_blocks) - CellSpursTaskLsPattern ls_pattern; + CellSpursTaskArgument args; // 0x00 + vm::bptr elf_addr; // 0x10 + be_t context_save_storage_and_alloc_ls_blocks; // 0x18 This is (context_save_storage_addr | allocated_ls_blocks) + CellSpursTaskLsPattern ls_pattern; // 0x20 }; static_assert(sizeof(TaskInfo) == 0x30, "Wrong TaskInfo size"); @@ -656,7 +668,7 @@ struct CellSpursTaskset u8 x72; // 0x72 u8 last_scheduled_task; // 0x73 be_t wid; // 0x74 - u8 unk1[8]; // 0x78 + be_t x78; // 0x78 TaskInfo task_info[128]; // 0x80 vm::bptr exception_handler; // 0x1880 vm::bptr exception_handler_arg; // 0x1888 @@ -765,7 +777,7 @@ struct CellSpursTaskset2 u8 x72; // 0x72 u8 last_scheduled_task; // 0x73 be_t wid; // 0x74 - u8 unk1[8]; // 0x78 + be_t x78; // 0x78 TaskInfo task_info[128]; // 0x80 vm::bptr exception_handler; // 0x1880 vm::bptr exception_handler_arg; // 0x1888 @@ -773,9 +785,9 @@ struct CellSpursTaskset2 u32 unk2; // 0x1894 u32 event_flag_id1; // 0x1898 u32 event_flag_id2; // 0x189C - u8 unk3[0xE8]; // 0x18A0 - u64 task_exit_code[256]; // 0x1988 - u8 unk4[0x778]; // 0x2188 + u8 unk3[0x1980 - 0x18A0]; // 0x18A0 + be_t task_exit_code[128]; // 0x1980 + u8 unk4[0x2900 - 0x2180]; // 0x2180 } m; static_assert(sizeof(_CellSpursTaskset2) == size, "Wrong _CellSpursTaskset2 size"); @@ -939,8 +951,8 @@ struct SpursTasksetPmMgmtData be_t lowestLoadSegmentAddr; // 0x2FBC be_t x2FC0; // 0x2FC0 be_t x2FC8; // 0x2FC8 - be_t x2FD0; // 0x2FD0 - be_t taskExitCode; // 0x2FD4 + be_t taskExitCode; // 0x2FD0 + be_t x2FD4; // 0x2FD4 u8 x2FD8[0x3000 - 0x2FD8]; // 0x2FD8 }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 653d4ca259..7118eadbd5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -18,7 +18,7 @@ void cellSpursModuleExit(SPUThread & spu); bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag); u32 spursDmaGetCompletionStatus(SPUThread & spu, u32 tagMask); u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll = true); -void spursHalt(); +void spursHalt(SPUThread & spu); // // SPURS Kernel functions @@ -44,9 +44,10 @@ bool spursSysServiceWorkloadEntry(SPUThread & spu); // bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); void spursTasksetExit(SPUThread & spu); +void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs); void spursTasksetDispatch(SPUThread & spu); void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus); -bool spursTasksetShouldYield(SPUThread & spu); +bool spursTasksetPollStatus(SPUThread & spu); void spursTasksetInit(SPUThread & spu, u32 pollStatus); void spursTasksetResumeTask(SPUThread & spu); bool spursTasksetEntry(SPUThread & spu); @@ -1018,6 +1019,8 @@ bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 // TODO: Implement cases s32 delta = 0; switch (request + 1) { + case -1: + break; case 0: break; case 1: @@ -1033,7 +1036,7 @@ bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 case 6: break; default: - assert(0); + spursHalt(spu); break; } @@ -1076,9 +1079,24 @@ void spursTasksetExit(SPUThread & spu) { cellSpursModuleExit(spu); } +void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); + + spu.GPR[2].clear(); + spu.GPR[3] = u128::from64(taskArgs.u64[0], taskArgs.u64[1]); + spu.GPR[4]._u64[1] = taskset->m.args; + spu.GPR[4]._u64[0] = taskset->m.spurs.addr(); + for (auto i = 5; i < 128; i++) { + spu.GPR[i].clear(); + } + + spu.SetBranch(mgmt->savedContextLr.value()._u32[3]); +} + void spursTasksetDispatch(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); u32 taskId; u32 isWaiting; @@ -1089,7 +1107,13 @@ void spursTasksetDispatch(SPUThread & spu) { } mgmt->taskId = taskId; - u64 elfAddr = mgmt->taskset->m.task_info[taskId].elf_addr.addr() & 0xFFFFFFFFFFFFFFF8ull; + + // DMA in the task info for the selected task + spursDma(spu, MFC_GET_CMD, mgmt->taskset.addr() + offsetof(CellSpursTaskset, m.task_info[taskId]), 0x2780/*LSA*/, sizeof(CellSpursTaskset::TaskInfo), mgmt->dmaTagId); + spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); + auto elfAddr = taskInfo->elf_addr.addr().value(); + taskInfo->elf_addr.set(taskInfo->elf_addr.addr() & 0xFFFFFFFFFFFFFFF8ull); // Trace - Task: Incident=dispatch CellSpursTracePacket pkt; @@ -1097,37 +1121,84 @@ void spursTasksetDispatch(SPUThread & spu) { pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; pkt.data.task.incident = CELL_SPURS_TRACE_TASK_DISPATCH; pkt.data.task.taskId = taskId; - cellSpursModulePutTrace(&pkt, 0x1F); + cellSpursModulePutTrace(&pkt, CELL_SPURS_KERNEL_DMA_TAG_ID); if (isWaiting == 0) { - } + // If we reach here it means that the task is being started and not being resumed + mgmt->lowestLoadSegmentAddr = CELL_SPURS_TASK_TOP; - if (mgmt->taskset->m.enable_clear_ls) { - memset(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); - } + // TODO: Load elf + // TODO: halt if rc of Load elf != CELL_OK - // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area - if (mgmt->taskset->m.task_info[taskId].ls_pattern.u64[0] != 0xFFFFFFFFFFFFFFFFull || - (mgmt->taskset->m.task_info[taskId].ls_pattern.u64[0] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { - // Load the ELF - // TODO: Load ELF - } + spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); - // Load save context from main memory to LS - u64 context_save_storage = mgmt->taskset->m.task_info[taskId].context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; - for (auto i = 6; i < 128; i++) { - bool shouldLoad = mgmt->taskset->m.task_info[taskId].ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; - if (shouldLoad) { - memcpy(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), - vm::get_ptr((u32)context_save_storage + 0x400 + ((i - 6) << 11)), 0x800); + mgmt->tasksetMgmtAddr = 0x2700; + mgmt->x2FC0 = 0; + mgmt->taskExitCode = isWaiting; + mgmt->x2FD4 = elfAddr & 5; // TODO: Figure this out + + if ((elfAddr & 5) == 1) { + spursDma(spu, MFC_GET_CMD, mgmt->taskset.addr() + offsetof(CellSpursTaskset2, m.task_exit_code[taskId]), 0x2FC0/*LSA*/, 0x10/*size*/, mgmt->dmaTagId); } - } - // Trace - GUID - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; - pkt.data.guid = 0; // TODO: Put GUID of taskId here - cellSpursModulePutTrace(&pkt, 0x1F); + // Trace - GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; + pkt.data.guid = 0; // TODO: Put GUID of taskId here + cellSpursModulePutTrace(&pkt, 0x1F); + + if (elfAddr & 2) { // TODO: Figure this out + spu.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); + spu.Stop(); + return; + } + + spursTasksetStartTask(spu, taskInfo->args); + } else { + if (taskset->m.enable_clear_ls) { + memset(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); + } + + // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well + if (taskInfo->ls_pattern.u64[0] != 0xFFFFFFFFFFFFFFFFull || + (taskInfo->ls_pattern.u64[1] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { + // Load the ELF + // TODO: Load ELF + // TODO: halt if rc of Load elf != CELL_OK + } + + // Load saved context from main memory to LS + u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; + for (auto i = 6; i < 128; i++) { + bool shouldLoad = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; + if (shouldLoad) { + // TODO: Combine DMA requests for consecutive blocks into a single request + spursDma(spu, MFC_GET_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, mgmt->dmaTagId); + } + } + + spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + + // Restore saved registers + spu.FPSCR.Write(mgmt->savedContextFpscr.value()); + spu.WriteChannel(MFC_WrTagMask, u128::from32r(mgmt->savedWriteTagGroupQueryMask)); + spu.WriteChannel(SPU_WrEventMask, u128::from32r(mgmt->savedSpuWriteEventMask)); + + // Trace - GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_GUID; + pkt.data.guid = 0; // TODO: Put GUID of taskId here + cellSpursModulePutTrace(&pkt, 0x1F); + + if (elfAddr & 2) { // TODO: Figure this out + spu.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); + spu.Stop(); + return; + } + + spu.GPR[3].clear(); + spursTasksetResumeTask(spu); + } } void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { @@ -1136,7 +1207,7 @@ void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { } } -bool spursTasksetShouldYield(SPUThread & spu) { +bool spursTasksetPollStatus(SPUThread & spu) { u32 pollStatus; if (cellSpursModulePollStatus(spu, &pollStatus)) { @@ -1179,6 +1250,99 @@ void spursTasksetResumeTask(SPUThread & spu) { spu.SetBranch(spu.GPR[0]._u32[3]); } +s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); + + // If the 0x10 bit is set in syscallNum then its the 2nd version of the + // syscall (e.g. cellSpursYield2 instead of cellSpursYield) and so don't wait + // for DMA completion + if ((syscallNum & 0x10) == 0) { + spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + syscallNum &= 0x0F; + } + + s32 rc = 0; + u32 incident = 0; + switch (syscallNum) { + case CELL_SPURS_TASK_SYSCALL_EXIT: + if (mgmt->x2FD4 == 4 || (mgmt->x2FC0 & 0xFFFFFFFF) != 0) { // TODO: Figure this out + if (mgmt->x2FD4 != 4) { + spursTasksetProcessRequest(spu, 0, nullptr, nullptr); + } + + auto a = mgmt->x2FD4 == 4 ? taskset->m.x78 : mgmt->x2FC0; + auto b = mgmt->x2FD4 == 4 ? 0 : mgmt->x2FC8; + // TODO: onTaskExit(a, mgmt->taskId, mgmt->taskExitCode, b) + } + + incident = CELL_SPURS_TRACE_TASK_EXIT; + break; + case CELL_SPURS_TASK_SYSCALL_YIELD: + if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, 3, nullptr, nullptr)) { + // If we reach here then it means that either another task can be scheduled or another workload can be scheduled + // Save the context of the current task + // TODO: rc = saveContext + if (rc == CELL_OK) { + spursTasksetProcessRequest(spu, 1, nullptr, nullptr); + incident = CELL_SPURS_TRACE_TASK_YIELD; + } + } + break; + case CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL: + if (spursTasksetProcessRequest(spu, -1, nullptr, nullptr)) { + // TODO: rc = saveContext + if (rc == CELL_OK) { + if (spursTasksetProcessRequest(spu, 2, nullptr, nullptr) == false) { + incident = CELL_SPURS_TRACE_TASK_WAIT; + } + } + } + break; + case CELL_SPURS_TASK_SYSCALL_POLL: + rc = spursTasksetPollStatus(spu) ? CELL_SPURS_TASK_POLL_FOUND_WORKLOAD : 0; + rc |= spursTasksetProcessRequest(spu, 3, nullptr, nullptr) ? CELL_SPURS_TASK_POLL_FOUND_TASK : 0; + break; + case CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG: + if (args == 0) { // TODO: Figure this out + spursHalt(spu); + } + + if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, 4, nullptr, nullptr) != true) { + // TODO: rc = saveContext + if (rc == CELL_OK) { + spursTasksetProcessRequest(spu, 1, nullptr, nullptr); + incident = CELL_SPURS_TRACE_TASK_WAIT; + } + } + break; + default: + rc = CELL_SPURS_TASK_ERROR_NOSYS; + break; + } + + if (incident) { + // Trace - TASK + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; + pkt.data.task.incident = incident; + pkt.data.task.taskId = mgmt->taskId; + cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + + // Clear the GUID of the task + memset(vm::get_ptr(spu.ls_offset + mgmt->lowestLoadSegmentAddr), 0, 0x10); + + if (spursTasksetPollStatus(spu)) { + spursTasksetExit(spu); + } + + spursTasksetDispatch(spu); + } + + return rc; +} + bool spursTasksetEntry(SPUThread & spu) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); @@ -1188,6 +1352,7 @@ bool spursTasksetEntry(SPUThread & spu) { auto arg = spu.GPR[4]._u64[1]; auto pollStatus = spu.GPR[5]._u32[3]; + // Initialise memory and save args memset(mgmt, 0, sizeof(*mgmt)); mgmt->taskset.set(arg); memcpy(mgmt->moduleId, "SPURSTASK MODULE", 16); @@ -1212,8 +1377,12 @@ bool spursTasksetEntry(SPUThread & spu) { mgmt->savedContextR80ToR127[i] = spu.GPR[80 + i]; } - // TODO: Process syscall - spursTasksetResumeTask(spu); + spu.GPR[3]._u32[3] = spursTasksetProcessSyscall(spu, spu.GPR[3]._u32[3], spu.GPR[4]._u32[3]); + + // Resume the previously executing task if the syscall did not cause a context switch + if (spu.m_is_branch == false) { + spursTasksetResumeTask(spu); + } } else { assert(0); } From 8a945a1a52b47b686871978de245b092d7d1a578 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 1 Feb 2015 10:09:24 +0300 Subject: [PATCH 50/94] Fixes --- rpcs3/Emu/ARMv7/ARMv7Context.h | 35 +++++++++++--------- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 12 ++++--- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 6 ++-- rpcs3/Emu/Cell/SPUThread.cpp | 2 ++ rpcs3/Emu/Memory/Memory.cpp | 2 +- rpcs3/Emu/Memory/vm_ref.h | 2 ++ rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 7 +++- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 6 ++-- 8 files changed, 43 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 1316a26786..692592e5ec 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -37,6 +37,25 @@ struct ARMv7Context }; u32 LR; + + union + { + struct + { + u32 reserved0 : 16; + u32 GE : 4; + u32 reserved1 : 4; + u32 dummy : 3; + u32 Q : 1; // Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result + u32 V : 1; // Overflow condition code flag + u32 C : 1; // Carry condition code flag + u32 Z : 1; // Zero condition code flag + u32 N : 1; // Negative condition code flag + }; + + u32 APSR; + + } APSR; }; struct @@ -45,22 +64,6 @@ struct ARMv7Context }; }; - union - { - struct - { - u32 N : 1; //Negative condition code flag - u32 Z : 1; //Zero condition code flag - u32 C : 1; //Carry condition code flag - u32 V : 1; //Overflow condition code flag - u32 Q : 1; //Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result - u32 dummy : 27; - }; - - u32 APSR; - - } APSR; - union { struct diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 78c17f4fda..6ea768832b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -316,10 +316,10 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 switch (type) { - case T1: - case A1: + case T1: case A1: + case T2: case A2: { - cond = context.ITSTATE.advance(); + cond = type == A1 ? code.data >> 28 : context.ITSTATE.advance(); t = (code.data & 0xf000) >> 12; cp = (code.data & 0xf00) >> 8; opc1 = (code.data & 0xe00000) >> 21; @@ -327,8 +327,8 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 cn = (code.data & 0xf0000) >> 16; cm = (code.data & 0xf); - reject(cp - 10 < 2, "Advanced SIMD and VFP"); - reject(t == 13 && type == T1, "UNPREDICTABLE"); + reject(cp - 10 < 2 && (type == T1 || type == A1), "Advanced SIMD and VFP"); + reject(t == 13 && (type == T1 || type == T2), "UNPREDICTABLE"); break; } default: throw __FUNCTION__; @@ -340,6 +340,8 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (t < 15 && cp == 15 && opc1 == 0 && cn == 13 && cm == 0 && opc2 == 3) { + // Read CP15 User Read-only Thread ID Register (seems used as TLS address) + if (!context.TLS) { throw "TLS not initialized"; diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 3495376c79..1a968dd858 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -48,7 +48,7 @@ void armv7_init_tls() u32 armv7_get_tls(u32 thread) { - if (!Emu.GetTLSMemsz()) + if (!Emu.GetTLSMemsz() || !thread) { return 0; } @@ -67,8 +67,8 @@ u32 armv7_get_tls(u32 thread) if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread)) { const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address - memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros return addr; } } @@ -112,7 +112,7 @@ void ARMv7Thread::InitRegs() memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); context.APSR.APSR = 0; context.IPSR.IPSR = 0; - context.ISET = Thumb; + //context.ISET = Thumb; context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index c4cf028f8f..1c861da43c 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -99,6 +99,8 @@ void SPUThread::InitRegs() m_event_mask = 0; m_events = 0; + + R_ADDR = 0; } void SPUThread::DoRun() diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 84f75c6fff..502694ff93 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -131,7 +131,7 @@ void MemoryBase::Init(MemoryType type) case Memory_PSV: MemoryBlocks.push_back(PSV.RAM.SetRange(0x81000000, 0x10000000)); - MemoryBlocks.push_back(UserMemory = PSV.Userspace.SetRange(0x91000000, 0x10000000)); + MemoryBlocks.push_back(UserMemory = PSV.Userspace.SetRange(0x91000000, 0x2F000000)); break; case Memory_PSP: diff --git a/rpcs3/Emu/Memory/vm_ref.h b/rpcs3/Emu/Memory/vm_ref.h index 5788457c3b..f7256cedff 100644 --- a/rpcs3/Emu/Memory/vm_ref.h +++ b/rpcs3/Emu/Memory/vm_ref.h @@ -10,6 +10,8 @@ namespace vm public: typedef T type; + static_assert(!std::is_pointer::value, "vm::_ref_base<> error: invalid type (pointer)"); + static_assert(!std::is_reference::value, "vm::_ref_base<> error: invalid type (reference)"); typedef typename remove_be_t::type le_type; typedef typename to_be_t::type be_type; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 2a8d3cc699..3fc79e4256 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -42,6 +42,11 @@ u32 ppu_get_tls(u32 thread) sysPrxForUser->Notice("Thread Local Storage initialized (g_tls_start=0x%x, size = 0x%x)\n*** TLS segment addr: 0x%08x\n*** TLS segment size: 0x%08x", g_tls_start, Emu.GetTLSMemsz(), Emu.GetTLSAddr(), Emu.GetTLSFilesz()); } + + if (!thread) + { + return 0; + } for (u32 i = 0; i < TLS_MAX; i++) { @@ -57,8 +62,8 @@ u32 ppu_get_tls(u32 thread) if (g_tls_owners[i].compare_exchange_strong(old, thread)) { const u32 addr = g_tls_start + i * Emu.GetTLSMemsz(); // get TLS address - memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros return addr; } } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 29cdb9bd39..f3fb23b383 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -85,10 +85,10 @@ SPUThread* spu_thread_initialize(std::shared_ptr& group, u32 spu_n sys_spu.Todo("Unsupported SPU Thread options (0x%x)", option); } - u32 spu_ep = (u32)img.entry_point; + const u32 spu_ep = img.entry_point; // Copy SPU image: // TODO: use segment info - u32 spu_offset = (u32)Memory.Alloc(256 * 1024, 4096); + const u32 spu_offset = vm::cast(Memory.MainMem.AllocAlign(256 * 1024, 4096)); memcpy(vm::get_ptr(spu_offset), vm::get_ptr(img.addr), 256 * 1024); SPUThread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_SPU)); @@ -218,7 +218,7 @@ s32 sys_spu_thread_group_destroy(u32 id) std::shared_ptr t = Emu.GetCPU().GetThread(group_info->list[i]); if (t) { - Memory.Free(((SPUThread*)t.get())->GetOffset()); + Memory.MainMem.Free(((SPUThread*)t.get())->GetOffset()); Emu.GetCPU().RemoveThread(group_info->list[i]); } } From e5dd03dbcb042c93f00a112f4b5e0f661245cd81 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 1 Feb 2015 16:52:34 +0300 Subject: [PATCH 51/94] ARMv7: argc, argv setting, LDRSB_IMM, bugfixes --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 3 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 61 ++++++++++++++++++++++++++-- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 61 ++++++++++++++++++++++++++-- rpcs3/Emu/ARMv7/ARMv7Thread.h | 56 ++++--------------------- rpcs3/Emu/CPU/CPUThread.cpp | 11 ----- rpcs3/Emu/CPU/CPUThread.h | 11 +++-- rpcs3/Emu/Cell/PPCThread.cpp | 15 ------- rpcs3/Emu/Cell/PPCThread.h | 3 -- rpcs3/Emu/Cell/PPUThread.cpp | 18 ++++++++ rpcs3/Emu/Cell/PPUThread.h | 6 ++- rpcs3/Emu/Cell/SPUThread.cpp | 11 +++++ rpcs3/Emu/Cell/SPUThread.h | 2 + rpcs3/Emu/Memory/vm.cpp | 22 ++++++++-- rpcs3/Loader/ELF32.cpp | 2 +- 14 files changed, 184 insertions(+), 98 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index fac6873a33..ce2dbb6914 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include #include "Utilities/Log.h" +#include "Emu/Memory/Memory.h" #include "ARMv7Thread.h" #include "ARMv7Interpreter.h" #include "ARMv7Opcodes.h" @@ -1262,7 +1263,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) addr += 16; } - LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", g_opct.size()); + LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); } u32 ARMv7Decoder::DecodeMemory(const u32 address) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 6ea768832b..c204351616 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -191,7 +191,7 @@ namespace ARMv7_instrs template T AddWithCarry(T x, T y, bool carry_in, bool& carry_out, bool& overflow) { - const T sign_mask = (T)1 << (sizeof(T) - 1); + const T sign_mask = (T)1 << (sizeof(T) * 8 - 1); T result = x + y; carry_out = ((x & y) | ((x ^ y) & ~result)) & sign_mask; @@ -823,6 +823,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en if (ConditionPassed(context, cond)) { + //LOG_NOTICE(ARMv7, "Branch to 0x%x (cond=0x%x)", context.thread.PC + jump, cond); context.thread.SetBranch(context.thread.PC + jump); } } @@ -1174,6 +1175,7 @@ void ARMv7_instrs::CMP_REG(ARMv7Context& context, const ARMv7Code code, const AR } case T3: { + cond = context.ITSTATE.advance(); n = (code.data & 0xf0000) >> 16; m = (code.data & 0xf); shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); @@ -1187,13 +1189,17 @@ void ARMv7_instrs::CMP_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + const u32 m_value = context.read_gpr(m); + const u32 n_value = context.read_gpr(n); bool carry, overflow; - const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, true); - const u32 res = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); + const u32 shifted = Shift(m_value, shift_t, shift_n, true); + const u32 res = AddWithCarry(n_value, ~shifted, true, carry, overflow); context.APSR.N = res >> 31; context.APSR.Z = res == 0; context.APSR.C = carry; context.APSR.V = overflow; + + //LOG_NOTICE(ARMv7, "CMP: r%d=0x%08x <> r%d=0x%08x, shifted=0x%08x, res=0x%08x", n, n_value, m, m_value, shifted, res); } } @@ -1619,11 +1625,60 @@ void ARMv7_instrs::LDRH_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(t == 15, "PLI"); + reject(n == 15, "LDRSB (literal)"); + reject(t == 13, "UNPREDICTABLE"); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(t == 15 && index && !add && !wback, "PLI"); + reject(n == 15, "LDRSB (literal)"); + reject(index && add && !wback, "LDRSBT"); + reject(!index && !wback, "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + const s8 value = vm::psv::read8(addr); + + context.write_gpr(t, value); // sign-extend + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::LDRSB_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 1a968dd858..f58acfd0d3 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -120,10 +120,19 @@ void ARMv7Thread::InitRegs() void ARMv7Thread::InitStack() { - if(!m_stack_addr) + if (!m_stack_addr) { - m_stack_size = 0x10000; - m_stack_addr = (u32)Memory.Alloc(0x10000, 1); + assert(m_stack_size); + m_stack_addr = vm::cast(Memory.Alloc(m_stack_size, 4096)); + } +} + +void ARMv7Thread::CloseStack() +{ + if (m_stack_addr) + { + Memory.Free(m_stack_addr); + m_stack_addr = 0; } } @@ -218,7 +227,7 @@ void ARMv7Thread::FastStop() m_status = Stopped; } -arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) { thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); @@ -229,3 +238,47 @@ arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 argc = 0; } + +cpu_thread& armv7_thread::args(std::initializer_list values) +{ + assert(argc == 0); + + if (!values.size()) + { + return *this; + } + + std::vector argv_data; + u32 argv_size = 0; + + for (auto& arg : values) + { + const u32 arg_size = vm::cast(arg.size(), "arg.size()"); // get arg size + + for (char c : arg) + { + argv_data.push_back(c); // append characters + } + + argv_data.push_back('\0'); // append null terminator + + argv_size += arg_size + 1; + argc++; + } + + argv = vm::cast(Memory.PSV.RAM.AllocAlign(argv_size, 4096)); // allocate arg list + memcpy(vm::get_ptr(argv), argv_data.data(), argv_size); // copy arg list + + return *this; +} + +cpu_thread& armv7_thread::run() +{ + thread->Run(); + + // set arguments + static_cast(thread)->context.GPR[0] = argc; + static_cast(thread)->context.GPR[1] = argv; + + return *this; +} diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index c806f4b6c4..a8a0f75311 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -1,29 +1,19 @@ #pragma once #include "Emu/CPU/CPUThread.h" -#include "Emu/Memory/Memory.h" #include "ARMv7Context.h" class ARMv7Thread : public CPUThread { public: ARMv7Context context; - //u32 m_arg; - //u8 m_last_instr_size; - //const char* m_last_instr_name; ARMv7Thread(); ~ARMv7Thread(); - //void update_code(const u32 address) - //{ - // code.code0 = vm::psv::read16(address & ~1); - // code.code1 = vm::psv::read16(address + 2 & ~1); - // m_arg = address & 0x1 ? code.code1 << 16 | code.code0 : code.data; - //} - public: virtual void InitRegs(); virtual void InitStack(); + virtual void CloseStack(); u32 GetStackArg(u32 pos); void FastCall(u32 addr); void FastStop(); @@ -42,48 +32,16 @@ protected: virtual void DoCode(); }; -class arm7_thread : cpu_thread + +class armv7_thread : cpu_thread { - static const u32 stack_align = 0x10; - vm::ptr argv; + u32 argv; u32 argc; - vm::ptr envp; public: - arm7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + armv7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); - cpu_thread& args(std::initializer_list values) override - { - if (!values.size()) - return *this; + cpu_thread& args(std::initializer_list values) override; - //assert(argc == 0); - - //envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main)); - //*envp = 0; - //argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main)); - - for (auto &arg : values) - { - //u32 arg_size = align(u32(arg.size() + 1), stack_align); - //u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main); - - //std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); - - //argv[argc++] = arg_addr; - } - - return *this; - } - - cpu_thread& run() override - { - thread->Run(); - - //static_cast(thread)->GPR[0] = argc; - //static_cast(thread)->GPR[1] = argv.addr(); - //static_cast(thread)->GPR[2] = envp.addr(); - - return *this; - } + cpu_thread& run() override; }; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index a69ec8338a..b2224af9c0 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -64,17 +64,6 @@ void CPUThread::Reset() DoReset(); } -void CPUThread::CloseStack() -{ - if(m_stack_addr) - { - Memory.StackMem.Free(m_stack_addr); - m_stack_addr = 0; - } - - m_stack_size = 0; -} - void CPUThread::SetId(const u32 id) { m_id = id; diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index dd79700c65..35010483cc 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -1,8 +1,7 @@ #pragma once - #include "Utilities/Thread.h" -enum CPUThreadType :unsigned char +enum CPUThreadType : unsigned char { CPU_THREAD_PPU, CPU_THREAD_SPU, @@ -46,10 +45,10 @@ protected: bool m_trace_call_stack; public: - virtual void InitRegs()=0; + virtual void InitRegs() = 0; - virtual void InitStack()=0; - virtual void CloseStack(); + virtual void InitStack() = 0; + virtual void CloseStack() = 0; u32 GetStackAddr() const { return m_stack_addr; } u32 GetStackSize() const { return m_stack_size; } @@ -271,4 +270,4 @@ public: { return thread->GetId(); } -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/Cell/PPCThread.cpp b/rpcs3/Emu/Cell/PPCThread.cpp index 4248fd58a8..4d77900d90 100644 --- a/rpcs3/Emu/Cell/PPCThread.cpp +++ b/rpcs3/Emu/Cell/PPCThread.cpp @@ -25,18 +25,3 @@ PPCThread::~PPCThread() void PPCThread::DoReset() { } - -void PPCThread::InitStack() -{ - if(m_stack_addr) return; - if(m_stack_size == 0) m_stack_size = 0x10000; - m_stack_addr = (u32)Memory.StackMem.AllocAlign(m_stack_size, 0x100); - /* - m_stack_point += m_stack_size - 0x10; - m_stack_point &= -0x10; - vm::write64(m_stack_point, 0); - m_stack_point -= 0x60; - vm::write64(m_stack_point, m_stack_point + 0x60); - */ -} - diff --git a/rpcs3/Emu/Cell/PPCThread.h b/rpcs3/Emu/Cell/PPCThread.h index 99471f7a80..2c3fa5c05b 100644 --- a/rpcs3/Emu/Cell/PPCThread.h +++ b/rpcs3/Emu/Cell/PPCThread.h @@ -4,9 +4,6 @@ class PPCThread : public CPUThread { public: - virtual void InitRegs()=0; - virtual void InitStack(); - virtual std::string GetThreadName() const { return fmt::format("%s[0x%08x]", GetFName(), PC); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index e064a54feb..e6d229583a 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -80,6 +80,24 @@ void PPUThread::InitRegs() TB = 0; } +void PPUThread::InitStack() +{ + if (!m_stack_addr) + { + assert(m_stack_size); + m_stack_addr = vm::cast(Memory.StackMem.AllocAlign(m_stack_size, 4096)); + } +} + +void PPUThread::CloseStack() +{ + if (m_stack_addr) + { + Memory.StackMem.Free(m_stack_addr); + m_stack_addr = 0; + } +} + void PPUThread::DoRun() { switch(Ini.CPUDecoderMode.GetValue()) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 51722f1645..820b244c2b 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -799,8 +799,10 @@ public: } public: - virtual void InitRegs(); - virtual void Task(); + virtual void InitRegs() override; + virtual void InitStack() override; + virtual void CloseStack() override; + virtual void Task() override; u64 GetStackArg(s32 i); u64 FastCall2(u32 addr, u32 rtoc); void FastStop(); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 1c861da43c..f5faf9fff1 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -103,6 +103,17 @@ void SPUThread::InitRegs() R_ADDR = 0; } +void SPUThread::InitStack() +{ + m_stack_size = 0x1000; // this value is wrong + m_stack_addr = m_offset + 0x40000 - m_stack_size; // stack is the part of SPU Local Storage +} + +void SPUThread::CloseStack() +{ + // nothing to do here +} + void SPUThread::DoRun() { switch(Ini.SPUDecoderMode.GetValue()) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 50d70b1c7f..c2e2cc2f03 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -568,6 +568,8 @@ public: public: virtual void InitRegs(); + virtual void InitStack(); + virtual void CloseStack(); virtual void Task(); void FastCall(u32 ls_addr); void FastStop(); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 2c23ecdb66..69e42e62cb 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -2,6 +2,7 @@ #include "Memory.h" #include "Emu/CPU/CPUThread.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/ARMv7/ARMv7Thread.h" namespace vm { @@ -167,13 +168,14 @@ namespace vm u32 stack_push(CPUThread& CPU, u32 size, u32 align_v, u32& old_pos) { + assert(align_v); + switch (CPU.GetType()) { case CPU_THREAD_PPU: { PPUThread& PPU = static_cast(CPU); - assert(align_v); old_pos = (u32)PPU.GPR[1]; PPU.GPR[1] -= align(size, 8); // room minimal possible size PPU.GPR[1] &= ~(align_v - 1); // fix stack alignment @@ -199,8 +201,22 @@ namespace vm case CPU_THREAD_ARMv7: { - assert(!"stack_push(): ARMv7 not supported"); - return 0; + ARMv7Context& context = static_cast(CPU).context; + + old_pos = context.SP; + context.SP -= align(size, 4); // room minimal possible size + context.SP &= ~(align_v - 1); // fix stack alignment + + if (context.SP < CPU.GetStackAddr()) + { + // stack overflow + context.SP = old_pos; + return 0; + } + else + { + return context.SP; + } } default: diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 9c7f19d0c2..c622308f3d 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -323,7 +323,7 @@ namespace loader armv7_init_tls(); armv7_decoder_initialize(code_start, code_end); - arm7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); + armv7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").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; From ba6ac5019ea6e022d08060c730ae0cc9af1a0c6d Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Mon, 2 Feb 2015 01:32:40 +0530 Subject: [PATCH 52/94] SPURS: Implement some portions of taskset policy manager --- rpcs3/Emu/Cell/SPUInterpreter.h | 5 +- rpcs3/Emu/Cell/SPUThread.h | 9 + rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 34 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 16 +- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 380 ++++++++++++++++---- rpcs3/Loader/ELF32.cpp | 7 +- rpcs3/Loader/ELF32.h | 2 +- 7 files changed, 345 insertions(+), 108 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 8351911153..7c56b4c9ac 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -1316,10 +1316,7 @@ private: void FSCRRD(u32 rt) { - CPU.GPR[rt]._u32[3] = CPU.FPSCR._u32[3]; - CPU.GPR[rt]._u32[2] = CPU.FPSCR._u32[2]; - CPU.GPR[rt]._u32[1] = CPU.FPSCR._u32[1]; - CPU.GPR[rt]._u32[0] = CPU.FPSCR._u32[0]; + CPU.FPSCR.Read(CPU.GPR[rt]); } void FESD(u32 rt, u32 ra) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index cfd45d6c0e..ff5012f146 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -257,6 +257,15 @@ public: _u32[1] = r._u32[1] & 0x00003F07; _u32[0] = r._u32[0] & 0x00000F07; } + + // Read the FPSCR + void Read(u128 & r) + { + r._u32[3] = _u32[3]; + r._u32[2] = _u32[2]; + r._u32[1] = _u32[1]; + r._u32[0] = _u32[0]; + } }; union SPU_SNRConfig_hdr diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 83dffb54e7..b8088daaff 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2602,8 +2602,8 @@ s64 spursCreateTaskset(vm::ptr spurs, vm::ptr tasks cellSpursAddWorkloadWithAttribute(spurs, vm::ptr::make(wid.addr()), vm::ptr::make(wkl_attr.addr())); // TODO: Check return code - taskset->m.x72 = 0x80; - taskset->m.wid = wid.value(); + taskset->m.wkl_flag_wait_task = 0x80; + taskset->m.wid = wid.value(); // TODO: cellSpursSetExceptionEventHandler(spurs, wid, hook, taskset); // TODO: Check return code @@ -2801,11 +2801,9 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: u32 tmp_task_id; for (tmp_task_id = 0; tmp_task_id < CELL_SPURS_MAX_TASK; tmp_task_id++) { - u32 l = tmp_task_id >> 5; - u32 b = tmp_task_id & 0x1F; - if ((taskset->m.enabled_set[l] & (0x80000000 >> b)) == 0) + if (!taskset->m.enabled.value()._bit[tmp_task_id]) { - taskset->m.enabled_set[l] |= 0x80000000 >> b; + taskset->m.enabled.value()._bit[tmp_task_id] = true; break; } } @@ -2840,10 +2838,10 @@ s64 cellSpursCreateTask(vm::ptr taskset, vm::ptr taskID, #endif } -s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID) +s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskId) { #ifdef PRX_DEBUG - cellSpurs->Warning("_cellSpursSendSignal(taskset_addr=0x%x, taskID=%d)", taskset.addr(), taskID); + cellSpurs->Warning("_cellSpursSendSignal(taskset_addr=0x%x, taskId=%d)", taskset.addr(), taskId); return GetCurrentPPUThread().FastCall2(libsre + 0x124CC, libsre_rtoc); #else if (!taskset) @@ -2856,29 +2854,23 @@ s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID) return CELL_SPURS_TASK_ERROR_ALIGN; } - if (taskID >= CELL_SPURS_MAX_TASK || taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD2) + if (taskId >= CELL_SPURS_MAX_TASK || taskset->m.wid >= CELL_SPURS_MAX_WORKLOAD2) { return CELL_SPURS_TASK_ERROR_INVAL; } - auto word = taskID >> 5; - auto mask = 0x80000000u >> (taskID & 0x1F); - auto disabled = taskset->m.enabled_set[word] & mask ? false : true; - auto running = taskset->m.running_set[word]; - auto ready = taskset->m.ready_set[word]; - auto ready2 = taskset->m.ready2_set[word]; - auto waiting = taskset->m.waiting_set[word]; - auto signalled = taskset->m.signal_received_set[word]; - auto enabled = taskset->m.enabled_set[word]; - auto invalid = (ready & ready2) || (running & waiting) || ((running | ready | ready2 | waiting | signalled) & ~enabled) || disabled; + auto _0 = be_t::make(u128::from32(0)); + auto disabled = taskset->m.enabled.value()._bit[taskId] ? false : true; + auto invalid = (taskset->m.ready & taskset->m.pending_ready) != _0 || (taskset->m.running & taskset->m.waiting) != _0 || disabled || + ((taskset->m.running | taskset->m.ready | taskset->m.pending_ready | taskset->m.waiting | taskset->m.signalled) & be_t::make(~taskset->m.enabled.value())) != _0; if (invalid) { return CELL_SPURS_TASK_ERROR_SRCH; } - auto shouldSignal = waiting & ~signalled & mask ? true : false; - taskset->m.signal_received_set[word] |= mask; + auto shouldSignal = (taskset->m.waiting & be_t::make(~taskset->m.signalled.value()) & be_t::make(u128::fromBit(taskId))) != _0 ? true : false; + ((u128)taskset->m.signalled)._bit[taskId] = true; if (shouldSignal) { cellSpursSendWorkloadSignal(vm::ptr::make((u32)taskset->m.spurs.addr()), taskset->m.wid); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 85df5fb582..f1a4793e13 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -655,17 +655,17 @@ struct CellSpursTaskset // Real data struct _CellSpursTaskset { - be_t running_set[4]; // 0x00 - be_t ready_set[4]; // 0x10 - be_t ready2_set[4]; // 0x20 - TODO: Find out what this is - be_t enabled_set[4]; // 0x30 - be_t signal_received_set[4]; // 0x40 - be_t waiting_set[4]; // 0x50 + be_t running; // 0x00 + be_t ready; // 0x10 + be_t pending_ready; // 0x20 + be_t enabled; // 0x30 + be_t signalled; // 0x40 + be_t waiting; // 0x50 vm::bptr spurs; // 0x60 be_t args; // 0x68 u8 enable_clear_ls; // 0x70 u8 x71; // 0x71 - u8 x72; // 0x72 + u8 wkl_flag_wait_task; // 0x72 u8 last_scheduled_task; // 0x73 be_t wid; // 0x74 be_t x78; // 0x78 @@ -948,7 +948,7 @@ struct SpursTasksetPmMgmtData be_t savedWriteTagGroupQueryMask; // 0x2FB0 be_t savedSpuWriteEventMask; // 0x2FB4 be_t tasksetMgmtAddr; // 0x2FB8 - be_t lowestLoadSegmentAddr; // 0x2FBC + be_t guidAddr; // 0x2FBC be_t x2FC0; // 0x2FC0 be_t x2FC8; // 0x2FC8 be_t taskExitCode; // 0x2FD0 diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 7118eadbd5..c7902f7240 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -7,6 +7,8 @@ #include "Emu/SysCalls/lv2/sys_lwcond.h" #include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/SysCalls/Modules/cellSpurs.h" +#include "Loader/ELF32.h" +#include "Emu/FS/vfsStreamMemory.h" // // SPURS utility functions @@ -42,7 +44,8 @@ bool spursSysServiceWorkloadEntry(SPUThread & spu); // // SPURS taskset policy module functions // -bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); +s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); +s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments); void spursTasksetExit(SPUThread & spu); void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs); void spursTasksetDispatch(SPUThread & spu); @@ -50,6 +53,9 @@ void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus); bool spursTasksetPollStatus(SPUThread & spu); void spursTasksetInit(SPUThread & spu, u32 pollStatus); void spursTasksetResumeTask(SPUThread & spu); +s32 spursTasketSaveTaskContext(SPUThread & spu); +void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args); +s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args); bool spursTasksetEntry(SPUThread & spu); extern Module *cellSpurs; @@ -1001,64 +1007,216 @@ bool spursSysServiceWorkloadEntry(SPUThread & spu) { // SPURS taskset policy module functions ////////////////////////////////////////////////////////////////////////////// -bool spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting) { +enum SpursTasksetRequest { + SPURS_TASKSET_REQUEST_POLL_SIGNAL = -1, + SPURS_TASKSET_REQUEST_DESTROY_TASK = 0, + SPURS_TASKSET_REQUEST_YIELD_TASK = 1, + SPURS_TASKSET_REQUEST_WAIT_SIGNAL = 2, + SPURS_TASKSET_REQUEST_POLL = 3, + SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG = 4, + SPURS_TASKSET_REQUEST_SELECT_TASK = 5, + SPURS_TASKSET_REQUEST_RECV_WKL_FLAG = 6, +}; + +s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting) { auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - // Verify taskset state is valid - for (auto i = 0; i < 4; i ++) { - if ((mgmt->taskset->m.waiting_set[i] & mgmt->taskset->m.running_set[i]) || - (mgmt->taskset->m.ready_set[i] & mgmt->taskset->m.ready2_set[i]) || - ((mgmt->taskset->m.running_set[i] | mgmt->taskset->m.ready_set[i] | - mgmt->taskset->m.ready2_set[i] | mgmt->taskset->m.signal_received_set[i] | - mgmt->taskset->m.waiting_set[i]) & ~mgmt->taskset->m.enabled_set[i])) { - assert(0); - } - } - - // TODO: Implement cases - s32 delta = 0; - switch (request + 1) { - case -1: - break; - case 0: - break; - case 1: - break; - case 2: - break; - case 3: - break; - case 4: - break; - case 5: - break; - case 6: - break; - default: - spursHalt(spu); - break; - } - - // Set the ready count of the workload to the number of ready tasks + s32 rc = CELL_OK; + s32 numNewlyReadyTasks; do { - s32 readyCount = kernelMgmt->wklCurrentId >= CELL_SPURS_MAX_WORKLOAD ? - kernelMgmt->spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].read_relaxed() : - kernelMgmt->spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].read_relaxed(); + spursDma(spu, MFC_GETLLAR_CMD, mgmt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); - auto newReadyCount = readyCount + delta > 0xFF ? 0xFF : readyCount + delta < 0 ? 0 : readyCount + delta; - - if (kernelMgmt->wklCurrentId >= CELL_SPURS_MAX_WORKLOAD) { - kernelMgmt->spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].write_relaxed(newReadyCount); - } else { - kernelMgmt->spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].write_relaxed(newReadyCount); + // Verify taskset state is valid + auto _0 = be_t::make(u128::from32(0)); + if ((taskset->m.waiting & taskset->m.running) != _0 || (taskset->m.ready & taskset->m.pending_ready) != _0 || + ((taskset->m.running | taskset->m.ready | taskset->m.pending_ready | taskset->m.signalled | taskset->m.waiting) & be_t::make(~taskset->m.enabled.value())) != _0) { + spursHalt(spu); + return CELL_OK; } - delta += readyCount; - } while (delta > 0); + // Find the number of tasks that have become ready since the last iteration + auto newlyReadyTasks = (taskset->m.signalled | taskset->m.pending_ready).value() & ~taskset->m.ready.value(); + numNewlyReadyTasks = 0; + for (auto i = 0; i < 128; i++) { + if (newlyReadyTasks._bit[i]) { + numNewlyReadyTasks++; + } + } - // TODO: Implement return - return false; + u128 readyButNotRunning; + u8 selectedTaskId; + auto running = taskset->m.running.value(); + auto waiting = taskset->m.waiting.value(); + auto enabled = taskset->m.enabled.value(); + auto signalled = (taskset->m.signalled & (taskset->m.ready | taskset->m.pending_ready)).value(); + auto ready = (taskset->m.signalled | taskset->m.ready | taskset->m.pending_ready).value(); + + switch (request) { + case SPURS_TASKSET_REQUEST_POLL_SIGNAL: + rc = signalled._bit[mgmt->taskId] ? 1 : 0; + signalled._bit[mgmt->taskId] = false; + break; + case SPURS_TASKSET_REQUEST_DESTROY_TASK: + numNewlyReadyTasks--; + running._bit[mgmt->taskId] = false; + enabled._bit[mgmt->taskId] = false; + signalled._bit[mgmt->taskId] = false; + ready._bit[mgmt->taskId] = false; + break; + case SPURS_TASKSET_REQUEST_YIELD_TASK: + running._bit[mgmt->taskId] = false; + waiting._bit[mgmt->taskId] = true; + break; + case SPURS_TASKSET_REQUEST_WAIT_SIGNAL: + if (signalled._bit[mgmt->taskId]) { + numNewlyReadyTasks--; + running._bit[mgmt->taskId] = false; + waiting._bit[mgmt->taskId] = true; + signalled._bit[mgmt->taskId] = false; + ready._bit[mgmt->taskId] = false; + } + break; + case SPURS_TASKSET_REQUEST_POLL: + readyButNotRunning = ready & ~running; + if (taskset->m.wkl_flag_wait_task < CELL_SPURS_MAX_TASK) { + readyButNotRunning = readyButNotRunning & ~(u128::fromBit(taskset->m.wkl_flag_wait_task)); + } + + rc = readyButNotRunning != _0 ? 1 : 0; + break; + case SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG: + if (taskset->m.wkl_flag_wait_task == 0x81) { + // A workload flag is already pending so consume it + taskset->m.wkl_flag_wait_task = 0x80; + rc = 0; + } else if (taskset->m.wkl_flag_wait_task == 0x80) { + // No tasks are waiting for the workload flag. Mark this task as waiting for the workload flag. + taskset->m.wkl_flag_wait_task = mgmt->taskId; + running._bit[mgmt->taskId] = false; + waiting._bit[mgmt->taskId] = true; + rc = 1; + numNewlyReadyTasks--; + } else { + // Another task is already waiting for the workload signal + rc = CELL_SPURS_TASK_ERROR_BUSY; + } + break; + case SPURS_TASKSET_REQUEST_SELECT_TASK: + readyButNotRunning = ready & ~running; + if (taskset->m.wkl_flag_wait_task < CELL_SPURS_MAX_TASK) { + readyButNotRunning = readyButNotRunning & ~(u128::fromBit(taskset->m.wkl_flag_wait_task)); + } + + // Select a task from the readyButNotRunning set to run. Start from the task after the last scheduled task to ensure fairness. + for (selectedTaskId = taskset->m.last_scheduled_task + 1; selectedTaskId < 128; selectedTaskId++) { + if (readyButNotRunning._bit[selectedTaskId]) { + break; + } + } + + if (selectedTaskId == 128) { + for (selectedTaskId = 0; selectedTaskId < taskset->m.last_scheduled_task + 1; selectedTaskId++) { + if (readyButNotRunning._bit[selectedTaskId]) { + break; + } + } + + if (selectedTaskId == taskset->m.last_scheduled_task + 1) { + selectedTaskId = CELL_SPURS_MAX_TASK; + } + } + + *taskId = selectedTaskId; + *isWaiting = waiting._bit[selectedTaskId < CELL_SPURS_MAX_TASK ? selectedTaskId : 0] ? 1 : 0; + if (selectedTaskId != CELL_SPURS_MAX_TASK) { + taskset->m.last_scheduled_task = selectedTaskId; + running._bit[mgmt->taskId] = true; + waiting._bit[mgmt->taskId] = false; + } + break; + case SPURS_TASKSET_REQUEST_RECV_WKL_FLAG: + if (taskset->m.wkl_flag_wait_task < CELL_SPURS_MAX_TASK) { + // There is a task waiting for the workload flag + taskset->m.wkl_flag_wait_task = 0x80; + rc = 1; + numNewlyReadyTasks++; + } else { + // No tasks are waiting for the workload flag + taskset->m.wkl_flag_wait_task = 0x81; + rc = 0; + } + break; + default: + spursHalt(spu); + return CELL_OK; + } + + taskset->m.pending_ready = _0; + taskset->m.running = running; + taskset->m.waiting = waiting; + taskset->m.enabled = enabled; + taskset->m.signalled = signalled; + taskset->m.ready = ready; + } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + // Increment the ready count of the workload by the number of tasks that have become ready + do { + spursDma(spu, MFC_GETLLAR_CMD, kernelMgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + s32 readyCount = kernelMgmt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].read_relaxed(); + readyCount += numNewlyReadyTasks; + readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount; + + if (kernelMgmt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) { + spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].write_relaxed(readyCount); + } else { + spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].write_relaxed(readyCount); + } + } while (spursDma(spu, MFC_PUTLLC_CMD, kernelMgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + return rc; +} + +s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments) { + if (elfAddr == 0 || (elfAddr & 0x0F) != 0) { + return CELL_SPURS_TASK_ERROR_INVAL; + } + + vfsStreamMemory stream(elfAddr); + loader::handlers::elf32 loader; + auto rc = loader.init(stream); + if (rc != loader::handler::ok) { + return CELL_SPURS_TASK_ERROR_NOEXEC; + } + + u32 _lowestLoadAddr = CELL_SPURS_TASK_BOTTOM; + for (auto & phdr : loader.m_phdrs) { + if (phdr.data_be.p_paddr >= CELL_SPURS_TASK_BOTTOM) { + break; + } + + if (phdr.data_be.p_type == 1/*PT_LOAD*/) { + if (skipWriteableSegments == false || (phdr.data_be.p_flags & 2/*PF_W*/) == 0) { + if (phdr.data_be.p_vaddr < CELL_SPURS_TASK_TOP || + phdr.data_be.p_vaddr + phdr.data_be.p_memsz > CELL_SPURS_TASK_BOTTOM) { + return CELL_SPURS_TASK_ERROR_FAULT; + } + + _lowestLoadAddr = _lowestLoadAddr > phdr.data_be.p_vaddr ? phdr.data_be.p_vaddr : _lowestLoadAddr; + } + } + } + + loader.load_data(spu.ls_offset, skipWriteableSegments); + *entryPoint = loader.m_ehdr.data_be.e_entry; + if (*lowestLoadAddr) { + *lowestLoadAddr = _lowestLoadAddr; + } + + return CELL_OK; } void spursTasksetExit(SPUThread & spu) { @@ -1100,7 +1258,7 @@ void spursTasksetDispatch(SPUThread & spu) { u32 taskId; u32 isWaiting; - spursTasksetProcessRequest(spu, 5, &taskId, &isWaiting); + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_SELECT_TASK, &taskId, &isWaiting); if (taskId >= CELL_SPURS_MAX_TASK) { spursTasksetExit(spu); return; @@ -1125,13 +1283,19 @@ void spursTasksetDispatch(SPUThread & spu) { if (isWaiting == 0) { // If we reach here it means that the task is being started and not being resumed - mgmt->lowestLoadSegmentAddr = CELL_SPURS_TASK_TOP; + mgmt->guidAddr = CELL_SPURS_TASK_TOP; - // TODO: Load elf - // TODO: halt if rc of Load elf != CELL_OK + u32 entryPoint; + u32 lowestLoadAddr; + if (spursTasksetLoadElf(spu, &entryPoint, &lowestLoadAddr, taskInfo->elf_addr.addr(), false) != CELL_OK) { + spursHalt(spu); + return; + } spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + mgmt->savedContextLr.value()._u32[3] = entryPoint; + mgmt->guidAddr = lowestLoadAddr; mgmt->tasksetMgmtAddr = 0x2700; mgmt->x2FC0 = 0; mgmt->taskExitCode = isWaiting; @@ -1163,8 +1327,11 @@ void spursTasksetDispatch(SPUThread & spu) { if (taskInfo->ls_pattern.u64[0] != 0xFFFFFFFFFFFFFFFFull || (taskInfo->ls_pattern.u64[1] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { // Load the ELF - // TODO: Load ELF - // TODO: halt if rc of Load elf != CELL_OK + u32 entryPoint; + if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf_addr.addr(), true) != CELL_OK) { + spursHalt(spu); + return; + } } // Load saved context from main memory to LS @@ -1203,7 +1370,7 @@ void spursTasksetDispatch(SPUThread & spu) { void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) { - spursTasksetProcessRequest(spu, 6, nullptr, nullptr); + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_RECV_WKL_FLAG, nullptr, nullptr); } } @@ -1250,6 +1417,74 @@ void spursTasksetResumeTask(SPUThread & spu) { spu.SetBranch(spu.GPR[0]._u32[3]); } +s32 spursTasketSaveTaskContext(SPUThread & spu) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); + + spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + + if (taskInfo->context_save_storage_and_alloc_ls_blocks == 0) { + return CELL_SPURS_TASK_ERROR_STAT; + } + + u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; + u32 lsBlocks = 0; + for (auto i = 0; i < 128; i++) { + if (taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) { + lsBlocks++; + } + } + + if (lsBlocks > allocLsBlocks) { + return CELL_SPURS_TASK_ERROR_STAT; + } + + // Make sure the stack is area is specified in the ls pattern + for (auto i = (mgmt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) { + if ((taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) == 0) { + return CELL_SPURS_TASK_ERROR_STAT; + } + } + + // Get the processor context + u128 r; + spu.FPSCR.Read(r); + mgmt->savedContextFpscr = r; + spu.ReadChannel(r, SPU_RdEventMask); + mgmt->savedSpuWriteEventMask = r._u32[3]; + spu.ReadChannel(r, MFC_RdTagMask); + mgmt->savedWriteTagGroupQueryMask = r._u32[3]; + + // Store the processor context + u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; + spursDma(spu, MFC_PUT_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, mgmt->dmaTagId); + + // Save LS context + for (auto i = 6; i < 128; i++) { + bool shouldStore = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; + if (shouldStore) { + // TODO: Combine DMA requests for consecutive blocks into a single request + spursDma(spu, MFC_PUT_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, mgmt->dmaTagId); + } + } + + spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + return CELL_OK; +} + +void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args) { + auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + + spursDma(spu, MFC_GET_CMD, addr & 0xFFFFFF80, 0x10000/*LSA*/, (addr & 0x7F) << 11/*size*/, 0); + spursDmaWaitForCompletion(spu, 1); + + spu.GPR[3]._u64[1] = mgmt->taskset.addr(); + spu.GPR[4]._u32[3] = taskId; + spu.GPR[5]._u32[3] = exitCode; + spu.GPR[6]._u64[1] = args; + spu.FastCall(0x10000); +} + s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); @@ -1268,32 +1503,32 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { case CELL_SPURS_TASK_SYSCALL_EXIT: if (mgmt->x2FD4 == 4 || (mgmt->x2FC0 & 0xFFFFFFFF) != 0) { // TODO: Figure this out if (mgmt->x2FD4 != 4) { - spursTasksetProcessRequest(spu, 0, nullptr, nullptr); + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_DESTROY_TASK, nullptr, nullptr); } - auto a = mgmt->x2FD4 == 4 ? taskset->m.x78 : mgmt->x2FC0; - auto b = mgmt->x2FD4 == 4 ? 0 : mgmt->x2FC8; - // TODO: onTaskExit(a, mgmt->taskId, mgmt->taskExitCode, b) + auto addr = mgmt->x2FD4 == 4 ? taskset->m.x78 : mgmt->x2FC0; + auto args = mgmt->x2FD4 == 4 ? 0 : mgmt->x2FC8; + spursTasksetOnTaskExit(spu, addr, mgmt->taskId, mgmt->taskExitCode, args); } incident = CELL_SPURS_TRACE_TASK_EXIT; break; case CELL_SPURS_TASK_SYSCALL_YIELD: - if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, 3, nullptr, nullptr)) { + if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL, nullptr, nullptr)) { // If we reach here then it means that either another task can be scheduled or another workload can be scheduled // Save the context of the current task - // TODO: rc = saveContext + rc = spursTasketSaveTaskContext(spu); if (rc == CELL_OK) { - spursTasksetProcessRequest(spu, 1, nullptr, nullptr); + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_YIELD_TASK, nullptr, nullptr); incident = CELL_SPURS_TRACE_TASK_YIELD; } } break; case CELL_SPURS_TASK_SYSCALL_WAIT_SIGNAL: - if (spursTasksetProcessRequest(spu, -1, nullptr, nullptr)) { - // TODO: rc = saveContext + if (spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL_SIGNAL, nullptr, nullptr) == 0) { + rc = spursTasketSaveTaskContext(spu); if (rc == CELL_OK) { - if (spursTasksetProcessRequest(spu, 2, nullptr, nullptr) == false) { + if (spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_SIGNAL, nullptr, nullptr) == 0) { incident = CELL_SPURS_TRACE_TASK_WAIT; } } @@ -1301,17 +1536,16 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { break; case CELL_SPURS_TASK_SYSCALL_POLL: rc = spursTasksetPollStatus(spu) ? CELL_SPURS_TASK_POLL_FOUND_WORKLOAD : 0; - rc |= spursTasksetProcessRequest(spu, 3, nullptr, nullptr) ? CELL_SPURS_TASK_POLL_FOUND_TASK : 0; + rc |= spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_POLL, nullptr, nullptr) ? CELL_SPURS_TASK_POLL_FOUND_TASK : 0; break; case CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG: if (args == 0) { // TODO: Figure this out spursHalt(spu); } - if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, 4, nullptr, nullptr) != true) { - // TODO: rc = saveContext + if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG, nullptr, nullptr) != 1) { + rc = spursTasketSaveTaskContext(spu); if (rc == CELL_OK) { - spursTasksetProcessRequest(spu, 1, nullptr, nullptr); incident = CELL_SPURS_TRACE_TASK_WAIT; } } @@ -1331,7 +1565,7 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); // Clear the GUID of the task - memset(vm::get_ptr(spu.ls_offset + mgmt->lowestLoadSegmentAddr), 0, 0x10); + memset(vm::get_ptr(spu.ls_offset + mgmt->guidAddr), 0, 0x10); if (spursTasksetPollStatus(spu)) { spursTasksetExit(spu); diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index cb9be62759..a24e64c05f 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -247,7 +247,7 @@ namespace loader return ok; } - handler::error_code elf32::load_data(u32 offset) + handler::error_code elf32::load_data(u32 offset, bool skip_writeable) { Elf_Machine machine = (Elf_Machine)(u16)(m_ehdr.is_le() ? m_ehdr.data_le.e_machine : m_ehdr.data_be.e_machine); @@ -270,6 +270,11 @@ namespace loader return loading_error; } + if (skip_writeable == true && (phdr.data_be.p_flags & 2/*PF_W*/) != 0) + { + continue; + } + if (filesz) { m_stream->Seek(handler::get_stream_offset() + offset); diff --git a/rpcs3/Loader/ELF32.h b/rpcs3/Loader/ELF32.h index d3d37f543c..6a13b6f7cb 100644 --- a/rpcs3/Loader/ELF32.h +++ b/rpcs3/Loader/ELF32.h @@ -132,7 +132,7 @@ namespace loader error_code init(vfsStream& stream) override; error_code load() override; - error_code load_data(u32 offset); + error_code load_data(u32 offset, bool skip_writeable = false); virtual ~elf32() = default; }; From dab80497bbbd39141914a4b918732129f52c7ae2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 2 Feb 2015 00:12:40 +0300 Subject: [PATCH 53/94] ARMv7: bugfix, loader improved, scePerf --- rpcs3/Emu/ARMv7/ARMv7Context.h | 8 + rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 1 + rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 12 +- rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 18 +- rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp | 9 +- rpcs3/Emu/ARMv7/Modules/scePerf.cpp | 222 +++++++++++++++++++++-- rpcs3/Loader/ELF32.cpp | 108 +++++++++-- 7 files changed, 330 insertions(+), 48 deletions(-) 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; From 2c70f5168a89e081f2bfde4482df94eef2426c7c Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Mon, 2 Feb 2015 09:02:38 +0530 Subject: [PATCH 54/94] SPURS: Reorder, rename and some cleanup --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 18 +- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 1599 ++++++++++--------- 3 files changed, 826 insertions(+), 795 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index b8088daaff..18eed2c944 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -26,7 +26,7 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif -bool spursKernelMain(SPUThread & spu); +bool spursKernelEntry(SPUThread & spu); s64 cellSpursLookUpTasksetAddress(vm::ptr spurs, vm::ptr taskset, u32 id); s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskID); @@ -182,7 +182,7 @@ s64 spursInit( { auto spu = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, num, spurs.addr(), 0, 0); #ifndef PRX_DEBUG_XXX - spu->RegisterHleFunction(spurs->m.spuImg.entry_point, spursKernelMain); + spu->RegisterHleFunction(spurs->m.spuImg.entry_point, spursKernelEntry); #endif spurs->m.spus[num] = spu->GetId(); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index f1a4793e13..21f011eda2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -105,8 +105,8 @@ enum SPURSKernelInterfaces CELL_SPURS_KERNEL_DMA_TAG_ID = 31, CELL_SPURS_KERNEL1_ENTRY_ADDR = 0x818, CELL_SPURS_KERNEL2_ENTRY_ADDR = 0x848, - CELL_SPURS_KERNEL1_YIELD_ADDR = 0x808, - CELL_SPURS_KERNEL2_YIELD_ADDR = 0x838, + CELL_SPURS_KERNEL1_EXIT_ADDR = 0x808, + CELL_SPURS_KERNEL2_EXIT_ADDR = 0x838, CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR = 0x290, CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR = 0x290, }; @@ -886,8 +886,8 @@ struct CellSpursTaskBinInfo CellSpursTaskLsPattern lsPattern; }; -// The SPURS kernel data store. This resides at 0x100 of the LS. -struct SpursKernelMgmtData +// The SPURS kernel context. This resides at 0x100 of the LS. +struct SpursKernelContext { u8 tempArea[0x80]; // 0x100 u8 wklLocContention[0x10]; // 0x180 @@ -900,7 +900,7 @@ struct SpursKernelMgmtData vm::bptr wklCurrentAddr; // 0x1D0 be_t wklCurrentUniqueId; // 0x1D8 be_t wklCurrentId; // 0x1DC - be_t yieldToKernelAddr; // 0x1E0 + be_t exitToKernelAddr; // 0x1E0 be_t selectWorkloadAddr; // 0x1E4 u8 moduleId[2]; // 0x1E8 u8 sysSrvInitialised; // 0x1EA @@ -923,10 +923,10 @@ struct SpursKernelMgmtData be_t guid[4]; // 0x280 }; -static_assert(sizeof(SpursKernelMgmtData) == 0x190, "Incorrect size for SpursKernelMgmtData"); +static_assert(sizeof(SpursKernelContext) == 0x190, "Incorrect size for SpursKernelContext"); -// The SPURS taskset policy module data store. This resides at 0x2700 of the LS. -struct SpursTasksetPmMgmtData +// The SPURS taskset policy module context. This resides at 0x2700 of the LS. +struct SpursTasksetContext { u8 tempAreaTaskset[0x80]; // 0x2700 u8 tempAreaTaskInfo[0x30]; // 0x2780 @@ -956,7 +956,7 @@ struct SpursTasksetPmMgmtData u8 x2FD8[0x3000 - 0x2FD8]; // 0x2FD8 }; -static_assert(sizeof(SpursTasksetPmMgmtData) == 0x900, "Incorrect size for SpursTasksetPmMgmtData"); +static_assert(sizeof(SpursTasksetContext) == 0x900, "Incorrect size for SpursTasksetContext"); s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr port, s32 isDynamic, bool wasCreated); s64 spursWakeUp(PPUThread& CPU, vm::ptr spurs); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index c7902f7240..451bfef848 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -13,7 +13,7 @@ // // SPURS utility functions // -void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag); +void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId); u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status); void cellSpursModuleExit(SPUThread & spu); @@ -27,36 +27,44 @@ void spursHalt(SPUThread & spu); // bool spursKernel1SelectWorkload(SPUThread & spu); bool spursKernel2SelectWorkload(SPUThread & spu); +void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus); +bool spursKernelWorkloadExit(SPUThread & spu); +bool spursKernelEntry(SPUThread & spu); // -// SPURS system service workload functions +// SPURS System Service functions // -void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt); -void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt); -void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4); -void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownBitSet); -void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt); -void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt); -void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt); -void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus); -bool spursSysServiceWorkloadEntry(SPUThread & spu); +bool spursSysServiceEntry(SPUThread & spu); +// TODO: Exit +void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt); +void spursSysServiceMain(SPUThread & spu, u32 pollStatus); +void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt); +void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt); +// TODO: Deactivate workload +void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelContext * ctxt, u32 wklShutdownBitSet); +void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt); +void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 arg2, u32 arg3, u32 arg4); +// TODO: Deactivate trace +// TODO: System workload entry +void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt); // -// SPURS taskset policy module functions +// SPURS Taskset Policy Module functions // -s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); -s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments); -void spursTasksetExit(SPUThread & spu); +bool spursTasksetEntry(SPUThread & spu); +bool spursTasksetSyscallEntry(SPUThread & spu); +void spursTasksetResumeTask(SPUThread & spu); void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs); -void spursTasksetDispatch(SPUThread & spu); +s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting); void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus); bool spursTasksetPollStatus(SPUThread & spu); -void spursTasksetInit(SPUThread & spu, u32 pollStatus); -void spursTasksetResumeTask(SPUThread & spu); -s32 spursTasketSaveTaskContext(SPUThread & spu); +void spursTasksetExit(SPUThread & spu); void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args); +s32 spursTasketSaveTaskContext(SPUThread & spu); +void spursTasksetDispatch(SPUThread & spu); s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args); -bool spursTasksetEntry(SPUThread & spu); +void spursTasksetInit(SPUThread & spu, u32 pollStatus); +s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments); extern Module *cellSpurs; @@ -65,16 +73,16 @@ extern Module *cellSpurs; ////////////////////////////////////////////////////////////////////////////// /// Output trace information -void cellSpursModulePutTrace(CellSpursTracePacket * packet, unsigned tag) { +void cellSpursModulePutTrace(CellSpursTracePacket * packet, u32 dmaTagId) { // TODO: Implement this } /// Check for execution right requests u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); spu.GPR[3]._u32[3] = 1; - if (mgmt->spurs->m.flags1 & SF1_32_WORKLOADS) { + if (ctxt->spurs->m.flags1 & SF1_32_WORKLOADS) { spursKernel2SelectWorkload(spu); } else { spursKernel1SelectWorkload(spu); @@ -86,13 +94,13 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) { } u32 wklId = result >> 32; - return wklId == mgmt->wklCurrentId ? 0 : 1; + return wklId == ctxt->wklCurrentId ? 0 : 1; } /// Exit current workload void cellSpursModuleExit(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); - spu.SetBranch(mgmt->yieldToKernelAddr); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); + spu.SetBranch(ctxt->exitToKernelAddr); } /// Execute a DMA operation @@ -134,7 +142,7 @@ u32 spursDmaWaitForCompletion(SPUThread & spu, u32 tagMask, bool waitForAll) { return rv._u32[3]; } -// Halt the SPU +/// Halt the SPU void spursHalt(SPUThread & spu) { spu.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); spu.Stop(); @@ -146,7 +154,7 @@ void spursHalt(SPUThread & spu) { /// Select a workload to run bool spursKernel1SelectWorkload(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); // The first and only argument to this function is a boolean that is set to false if the function // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. @@ -158,20 +166,20 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { do { // DMA and lock the first 0x80 bytes of spurs - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Calculate the contention (number of SPUs used) for each workload u8 contention[CELL_SPURS_MAX_WORKLOAD]; u8 pendingContention[CELL_SPURS_MAX_WORKLOAD]; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - contention[i] = spurs->m.wklCurrentContention[i] - mgmt->wklLocContention[i]; + contention[i] = spurs->m.wklCurrentContention[i] - ctxt->wklLocContention[i]; // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably // to prevent unnecessary jumps to the kernel if (isPoll) { - pendingContention[i] = spurs->m.wklPendingContention[i] - mgmt->wklLocPendingContention[i]; - if (i != mgmt->wklCurrentId) { + pendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + if (i != ctxt->wklCurrentId) { contention[i] += pendingContention[i]; } } @@ -180,19 +188,19 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; pollStatus = 0; - // The system service workload has the highest priority. Select the system service workload if + // The system service has the highest priority. Select the system service if // the system service message bit for this SPU is set. - if (spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - mgmt->spuIdling = 0; - if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) { + ctxt->spuIdling = 0; + if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { // Clear the message bit - spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum)); } } else { // Caclulate the scheduling weight for each workload u16 maxWeight = 0; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u16 runnable = mgmt->wklRunnable1 & (0x8000 >> i); + u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); u16 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed(); @@ -206,7 +214,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { // 4. The number of SPUs allocated to it must be less than the number of SPUs requested (i.e. readyCount) // OR the workload must be signalled // OR the workload flag is 0 and the workload is configured as the wokload flag receiver - if (runnable && mgmt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) { + if (runnable && ctxt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > contention[i]) { if (wklFlag || wklSignal || (readyCount != 0 && requestCount > contention[i])) { // The scheduling weight of the workload is formed from the following parameters in decreasing order of priority: // 1. Wokload signal set or workload flag or ready count > contention @@ -217,11 +225,11 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { // 6. Is the workload executable same as the currently loaded executable // 7. The workload id (lesser the number, more the weight) u16 weight = (wklFlag || wklSignal || (readyCount > contention[i])) ? 0x8000 : 0; - weight |= (u16)(mgmt->priority[i] & 0x7F) << 16; - weight |= i == mgmt->wklCurrentId ? 0x80 : 0x00; + weight |= (u16)(ctxt->priority[i] & 0x7F) << 16; + weight |= i == ctxt->wklCurrentId ? 0x80 : 0x00; weight |= (contention[i] > 0 && spurs->m.wklMinContention[i] > contention[i]) ? 0x40 : 0x00; weight |= ((CELL_SPURS_MAX_SPU - contention[i]) & 0x0F) << 2; - weight |= mgmt->wklUniqueId[i] == mgmt->wklCurrentId ? 0x02 : 0x00; + weight |= ctxt->wklUniqueId[i] == ctxt->wklCurrentId ? 0x02 : 0x00; weight |= 0x01; // In case of a tie the lower numbered workload is chosen @@ -237,9 +245,9 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { } // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + ctxt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { + if (!isPoll || wklSelectedId == ctxt->wklCurrentId) { // Clear workload signal for the selected workload spurs->m.wklSignal1.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); spurs->m.wklSignal2.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); @@ -260,16 +268,16 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { spurs->m.wklCurrentContention[i] = contention[i]; - mgmt->wklLocContention[i] = 0; - mgmt->wklLocPendingContention[i] = 0; + ctxt->wklLocContention[i] = 0; + ctxt->wklLocPendingContention[i] = 0; } if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - mgmt->wklLocContention[wklSelectedId] = 1; + ctxt->wklLocContention[wklSelectedId] = 1; } - mgmt->wklCurrentId = wklSelectedId; - } else if (wklSelectedId != mgmt->wklCurrentId) { + ctxt->wklCurrentId = wklSelectedId; + } else if (wklSelectedId != ctxt->wklCurrentId) { // Not called by kernel but a context switch is required // Increment the pending contention for the selected workload if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { @@ -278,14 +286,14 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { spurs->m.wklPendingContention[i] = pendingContention[i]; - mgmt->wklLocPendingContention[i] = 0; + ctxt->wklLocPendingContention[i] = 0; } if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - mgmt->wklLocPendingContention[wklSelectedId] = 1; + ctxt->wklLocPendingContention[wklSelectedId] = 1; } } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); u64 result = (u64)wklSelectedId << 32; result |= pollStatus; @@ -295,7 +303,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { /// Select a workload to run bool spursKernel2SelectWorkload(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); // The first and only argument to this function is a boolean that is set to false if the function // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. @@ -307,22 +315,22 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { do { // DMA and lock the first 0x80 bytes of spurs - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Calculate the contention (number of SPUs used) for each workload u8 contention[CELL_SPURS_MAX_WORKLOAD2]; u8 pendingContention[CELL_SPURS_MAX_WORKLOAD2]; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - contention[i] = spurs->m.wklCurrentContention[i & 0x0F] - mgmt->wklLocContention[i & 0x0F]; + contention[i] = spurs->m.wklCurrentContention[i & 0x0F] - ctxt->wklLocContention[i & 0x0F]; contention[i] = i < CELL_SPURS_MAX_WORKLOAD ? contention[i] & 0x0F : contention[i] >> 4; // If this is a poll request then the number of SPUs pending to context switch is also added to the contention presumably // to prevent unnecessary jumps to the kernel if (isPoll) { - pendingContention[i] = spurs->m.wklPendingContention[i & 0x0F] - mgmt->wklLocPendingContention[i & 0x0F]; + pendingContention[i] = spurs->m.wklPendingContention[i & 0x0F] - ctxt->wklLocPendingContention[i & 0x0F]; pendingContention[i] = i < CELL_SPURS_MAX_WORKLOAD ? pendingContention[i] & 0x0F : pendingContention[i] >> 4; - if (i != mgmt->wklCurrentId) { + if (i != ctxt->wklCurrentId) { contention[i] += pendingContention[i]; } } @@ -331,22 +339,22 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { wklSelectedId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; pollStatus = 0; - // The system service workload has the highest priority. Select the system service workload if + // The system service has the highest priority. Select the system service if // the system service message bit for this SPU is set. - if (spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) { // Not sure what this does. Possibly Mark the SPU as in use. - mgmt->spuIdling = 0; - if (!isPoll || mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + ctxt->spuIdling = 0; + if (!isPoll || ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { // Clear the message bit - spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << mgmt->spuNum)); + spurs->m.sysSrvMessage.write_relaxed(spurs->m.sysSrvMessage.read_relaxed() & ~(1 << ctxt->spuNum)); } } else { // Caclulate the scheduling weight for each workload u8 maxWeight = 0; for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { auto j = i & 0x0F; - u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); - u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; + u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4; u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; @@ -365,7 +373,7 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { // The current workload is given a sligtly higher weight presumably to reduce the number of context switches. // In case of a tie the lower numbered workload is chosen. u8 weight = priority << 4; - if (mgmt->wklCurrentId == i) { + if (ctxt->wklCurrentId == i) { weight |= 0x04; } @@ -381,9 +389,9 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { } // Not sure what this does. Possibly mark the SPU as idle/in use. - mgmt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; + ctxt->spuIdling = wklSelectedId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID ? 1 : 0; - if (!isPoll || wklSelectedId == mgmt->wklCurrentId) { + if (!isPoll || wklSelectedId == ctxt->wklCurrentId) { // Clear workload signal for the selected workload spurs->m.wklSignal1.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x8000 >> wklSelectedId))); spurs->m.wklSignal2.write_relaxed(be_t::make(spurs->m.wklSignal1.read_relaxed() & ~(0x80000000u >> wklSelectedId))); @@ -404,13 +412,13 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); - mgmt->wklLocContention[i] = 0; - mgmt->wklLocPendingContention[i] = 0; + ctxt->wklLocContention[i] = 0; + ctxt->wklLocPendingContention[i] = 0; } - mgmt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; - mgmt->wklCurrentId = wklSelectedId; - } else if (wklSelectedId != mgmt->wklCurrentId) { + ctxt->wklLocContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + ctxt->wklCurrentId = wklSelectedId; + } else if (wklSelectedId != ctxt->wklCurrentId) { // Not called by kernel but a context switch is required // Increment the pending contention for the selected workload if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { @@ -419,12 +427,12 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { spurs->m.wklPendingContention[i] = pendingContention[i] | (pendingContention[i + 0x10] << 4); - mgmt->wklLocPendingContention[i] = 0; + ctxt->wklLocPendingContention[i] = 0; } - mgmt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + ctxt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); u64 result = (u64)wklSelectedId << 32; result |= pollStatus; @@ -432,81 +440,27 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { return true; } -/// SPURS kernel main -bool spursKernelMain(SPUThread & spu) { - SpursKernelMgmtData * mgmt = vm::get_ptr(spu.ls_offset + 0x100); +/// SPURS kernel dispatch workload +void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { + SpursKernelContext * ctxt = vm::get_ptr(spu.ls_offset + 0x100); + auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - bool isKernel2; - u32 pollStatus; - if (spu.PC == CELL_SPURS_KERNEL1_ENTRY_ADDR || spu.PC == CELL_SPURS_KERNEL2_ENTRY_ADDR) { - // Entry point of SPURS kernel - // Save arguments - mgmt->spuNum = spu.GPR[3]._u32[3]; - mgmt->spurs.set(spu.GPR[4]._u64[1]); + auto pollStatus = (u32)(spu.GPR[3]._u64[1]); + auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); - isKernel2 = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - - memset(mgmt, 0, sizeof(SpursKernelMgmtData)); - - // Initialise the SPURS management area to its initial values - mgmt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID; - mgmt->wklCurrentUniqueId = 0x20; - mgmt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; - mgmt->yieldToKernelAddr = isKernel2 ? CELL_SPURS_KERNEL2_YIELD_ADDR : CELL_SPURS_KERNEL1_YIELD_ADDR; - mgmt->selectWorkloadAddr = isKernel2 ? CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR : CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR; - if (!isKernel2) { - mgmt->x1F0 = 0xF0020000; - mgmt->x200 = 0x20000; - mgmt->guid[0] = 0x423A3A02; - mgmt->guid[1] = 0x43F43A82; - mgmt->guid[2] = 0x43F26502; - mgmt->guid[3] = 0x420EB382; - } else { - mgmt->guid[0] = 0x43A08402; - mgmt->guid[1] = 0x43FB0A82; - mgmt->guid[2] = 0x435E9302; - mgmt->guid[3] = 0x43A3C982; - } - - // Register SPURS kernel HLE functions - spu.UnregisterHleFunctions(0, 0x40000); // TODO: use a symbolic constant - spu.RegisterHleFunction(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelMain); - spu.RegisterHleFunction(mgmt->yieldToKernelAddr, spursKernelMain); - spu.RegisterHleFunction(mgmt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); - - // DMA in the system service workload info - spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklInfoSysSrv), 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID/*tag*/); - spursDmaWaitForCompletion(spu, 0x80000000); - pollStatus = 0; - } else if (spu.PC == mgmt->yieldToKernelAddr) { - isKernel2 = mgmt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - - // Select next workload to run - spu.GPR[3].clear(); - if (isKernel2) { - spursKernel2SelectWorkload(spu); - } else { - spursKernel1SelectWorkload(spu); - } - - pollStatus = (u32)(spu.GPR[3]._u64[1]); - auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); - - // DMA in the workload info for the selected workload - auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? offsetof(CellSpurs, m.wklInfo1[wid]) : - wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? offsetof(CellSpurs, m.wklInfo2[wid & 0xf]) : - offsetof(CellSpurs, m.wklInfoSysSrv); - spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + wklInfoOffset, 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); - spursDmaWaitForCompletion(spu, 0x80000000); - } else { - assert(0); - } + // DMA in the workload info for the selected workload + auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? offsetof(CellSpurs, m.wklInfo1[wid]) : + wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? offsetof(CellSpurs, m.wklInfo2[wid & 0xf]) : + offsetof(CellSpurs, m.wklInfoSysSrv); + spursDma(spu, MFC_GET_CMD, ctxt->spurs.addr() + wklInfoOffset, 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + spursDmaWaitForCompletion(spu, 0x80000000); + // Load the workload to LS auto wklInfo = vm::get_ptr(spu.ls_offset + 0x3FFE0); - if (mgmt->wklCurrentAddr != wklInfo->addr) { + if (ctxt->wklCurrentAddr != wklInfo->addr) { switch (wklInfo->addr.addr()) { case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: - spu.RegisterHleFunction(0xA00, spursSysServiceWorkloadEntry); + spu.RegisterHleFunction(0xA00, spursSysServiceEntry); break; case SPURS_IMG_ADDR_TASKSET_PM: spu.RegisterHleFunction(0xA00, spursTasksetEntry); @@ -517,22 +471,81 @@ bool spursKernelMain(SPUThread & spu) { break; } - mgmt->wklCurrentAddr = wklInfo->addr; - mgmt->wklCurrentUniqueId = wklInfo->uniqueId.read_relaxed(); + ctxt->wklCurrentAddr = wklInfo->addr; + ctxt->wklCurrentUniqueId = wklInfo->uniqueId.read_relaxed(); } if (!isKernel2) { - mgmt->moduleId[0] = 0; - mgmt->moduleId[1] = 0; + ctxt->moduleId[0] = 0; + ctxt->moduleId[1] = 0; } // Run workload - spu.GPR[0]._u32[3] = mgmt->yieldToKernelAddr; + spu.GPR[0]._u32[3] = ctxt->exitToKernelAddr; spu.GPR[1]._u32[3] = 0x3FFB0; spu.GPR[3]._u32[3] = 0x100; spu.GPR[4]._u64[1] = wklInfo->arg; spu.GPR[5]._u32[3] = pollStatus; spu.SetBranch(0xA00); +} + +/// SPURS kernel workload exit +bool spursKernelWorkloadExit(SPUThread & spu) { + SpursKernelContext * ctxt = vm::get_ptr(spu.ls_offset + 0x100); + auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; + + // Select next workload to run + spu.GPR[3].clear(); + if (isKernel2) { + spursKernel2SelectWorkload(spu); + } else { + spursKernel1SelectWorkload(spu); + } + + spursKernelDispatchWorkload(spu, spu.GPR[3]._u64[1]); + return false; +} + +/// SPURS kernel entry point +bool spursKernelEntry(SPUThread & spu) { + SpursKernelContext * ctxt = vm::get_ptr(spu.ls_offset + 0x100); + + // Save arguments + ctxt->spuNum = spu.GPR[3]._u32[3]; + ctxt->spurs.set(spu.GPR[4]._u64[1]); + + auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; + + memset(ctxt, 0, sizeof(SpursKernelContext)); + + // Initialise the SPURS context to its initial values + ctxt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID; + ctxt->wklCurrentUniqueId = 0x20; + ctxt->wklCurrentId = CELL_SPURS_SYS_SERVICE_WORKLOAD_ID; + ctxt->exitToKernelAddr = isKernel2 ? CELL_SPURS_KERNEL2_EXIT_ADDR : CELL_SPURS_KERNEL1_EXIT_ADDR; + ctxt->selectWorkloadAddr = isKernel2 ? CELL_SPURS_KERNEL2_SELECT_WORKLOAD_ADDR : CELL_SPURS_KERNEL1_SELECT_WORKLOAD_ADDR; + if (!isKernel2) { + ctxt->x1F0 = 0xF0020000; + ctxt->x200 = 0x20000; + ctxt->guid[0] = 0x423A3A02; + ctxt->guid[1] = 0x43F43A82; + ctxt->guid[2] = 0x43F26502; + ctxt->guid[3] = 0x420EB382; + } else { + ctxt->guid[0] = 0x43A08402; + ctxt->guid[1] = 0x43FB0A82; + ctxt->guid[2] = 0x435E9302; + ctxt->guid[3] = 0x43A3C982; + } + + // Register SPURS kernel HLE functions + spu.UnregisterHleFunctions(0, 0x40000/*LS_BOTTOM*/); + spu.RegisterHleFunction(isKernel2 ? CELL_SPURS_KERNEL2_ENTRY_ADDR : CELL_SPURS_KERNEL1_ENTRY_ADDR, spursKernelEntry); + spu.RegisterHleFunction(ctxt->exitToKernelAddr, spursKernelWorkloadExit); + spu.RegisterHleFunction(ctxt->selectWorkloadAddr, isKernel2 ? spursKernel2SelectWorkload : spursKernel1SelectWorkload); + + // Start the system service + spursKernelDispatchWorkload(spu, ((u64)CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) << 32); return false; } @@ -540,120 +553,337 @@ bool spursKernelMain(SPUThread & spu) { // SPURS system workload functions ////////////////////////////////////////////////////////////////////////////// -/// Restore scheduling parameters after a workload has been preempted by the system service workload -void spursSysServiceCleanupAfterPreemption(SPUThread & spu, SpursKernelMgmtData * mgmt) { - u8 wklId; +/// Entry point of the system service +bool spursSysServiceEntry(SPUThread & spu) { + auto ctxt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); + auto arg = spu.GPR[4]._u64[1]; + auto pollStatus = spu.GPR[5]._u32[3]; - do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { + spursSysServiceMain(spu, pollStatus); + } else { + // TODO: If we reach here it means the current workload was preempted to start the + // system workload. Need to implement this. + } - if (spurs->m.sysSrvWorkload[mgmt->spuNum] == 0xFF) { - return; - } + return false; +} - wklId = spurs->m.sysSrvWorkload[mgmt->spuNum]; - spurs->m.sysSrvWorkload[mgmt->spuNum] = 0xFF; - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); +/// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled +void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { + // Monitor only lock line reservation lost events + spu.WriteChannel(SPU_WrEventMask, u128::from32r(SPU_EVENT_LR)); - spursSysServiceUpdateWorkload(spu, mgmt); - - do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + bool shouldExit; + while (true) { + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x100); - if (wklId >= CELL_SPURS_MAX_WORKLOAD) { - spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; - spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); - } else { - spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; - spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); + // Find the number of SPUs that are idling in this SPURS instance + u32 nIdlingSpus = 0; + for (u32 i = 0; i < 8; i++) { + if (spurs->m.spuIdling & (1 << i)) { + nIdlingSpus++; + } } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace - // uses the current worload id to determine the workload to which the trace belongs - auto wklIdSaved = mgmt->wklCurrentId; - mgmt->wklCurrentId = wklId; + bool allSpusIdle = nIdlingSpus == spurs->m.nSpus ? true: false; + bool exitIfNoWork = spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; + shouldExit = allSpusIdle && exitIfNoWork; - // Trace - STOP: GUID + // Check if any workloads can be scheduled + bool foundReadyWorkload = false; + if (spurs->m.sysSrvMessage.read_relaxed() & (1 << ctxt->spuNum)) { + foundReadyWorkload = true; + } else { + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { + u32 j = i & 0x0F; + u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); + u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; + u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4; + u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklCurrentContention[j] & 0x0F : spurs->m.wklCurrentContention[j] >> 4; + u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); + + if (runnable && priority > 0 && maxContention > contention) { + if (wklFlag || wklSignal || readyCount > contention) { + foundReadyWorkload = true; + break; + } + } + } + } else { + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + u8 runnable = ctxt->wklRunnable1 & (0x8000 >> i); + u8 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; + u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed(); + u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); + u8 requestCount = readyCount + idleSpuCount; + + if (runnable && ctxt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > spurs->m.wklCurrentContention[i]) { + if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->m.wklCurrentContention[i])) { + foundReadyWorkload = true; + break; + } + } + } + } + } + + bool spuIdling = spurs->m.spuIdling & (1 << ctxt->spuNum) ? true : false; + if (foundReadyWorkload && shouldExit == false) { + spurs->m.spuIdling &= ~(1 << ctxt->spuNum); + } else { + spurs->m.spuIdling |= 1 << ctxt->spuNum; + } + + // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. + if (spuIdling && shouldExit == false && foundReadyWorkload == false) { + // The system service blocks by making a reservation and waiting on the lock line reservation lost event. + u128 r; + spu.ReadChannel(r, SPU_RdEventStat); + spu.WriteChannel(SPU_WrEventAck, u128::from32r(SPU_EVENT_LR)); + } + + auto dmaSuccess = spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + if (dmaSuccess && (shouldExit || foundReadyWorkload)) { + break; + } + } + + if (shouldExit) { + // TODO: exit spu thread group + } +} + +/// Main function for the system service +void spursSysServiceMain(SPUThread & spu, u32 pollStatus) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); + + if (ctxt->spurs.addr() % CellSpurs::align) { + spursHalt(spu); + return; + } + + // Initialise the system service if this is the first time its being started on this SPU + if (ctxt->sysSrvInitialised == 0) { + ctxt->sysSrvInitialised = 1; + + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + + do { + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + CellSpurs * spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + // Halt if already initialised + if (spurs->m.sysSrvOnSpu & (1 << ctxt->spuNum)) { + spursHalt(spu); + return; + } + + spurs->m.sysSrvOnSpu |= 1 << ctxt->spuNum; + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + ctxt->traceBuffer = 0; + ctxt->traceMsgCount = -1; + spursSysServiceTraceUpdate(spu, ctxt, 1, 1, 0); + spursSysServiceCleanupAfterSystemWorkload(spu, ctxt); + + // Trace - SERVICE: INIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + } + + // Trace - START: Module='SYS ' CellSpursTracePacket pkt; memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = SPURS_GUID_SYS_WKL; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + pkt.header.tag = CELL_SPURS_TRACE_TAG_START; + memcpy(pkt.data.start.module, "SYS ", 4); + pkt.data.start.level = 1; // Policy module + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - mgmt->wklCurrentId = wklIdSaved; -} + while (true) { + // Process requests for the system service + spursSysServiceProcessRequests(spu, ctxt); -/// Update the trace count for this SPU in CellSpurs -void spursSysServiceUpdateTraceCount(SPUThread & spu, SpursKernelMgmtData * mgmt) { - if (mgmt->traceBuffer) { - auto traceInfo = vm::ptr::make((u32)(mgmt->traceBuffer - (mgmt->spurs->m.traceStartIndex[mgmt->spuNum] << 4))); - traceInfo->count[mgmt->spuNum] = mgmt->traceMsgCount; +poll: + if (cellSpursModulePollStatus(spu, nullptr)) { + // Trace - SERVICE: EXIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + // Trace - STOP: GUID + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + break; + } + + // If we reach here it means that either there are more system service messages to be processed + // or there are no workloads that can be scheduled. + + // If the SPU is not idling then process the remaining system service messages + if (ctxt->spuIdling == 0) { + continue; + } + + // If we reach here it means that the SPU is idling + + // Trace - SERVICE: WAIT + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; + pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); + + spursSysServiceIdleHandler(spu, ctxt); + goto poll; } } -/// Update trace control in SPU from CellSpurs -void spursSysServiceUpdateTrace(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 arg2, u32 arg3, u32 arg4) { - bool notify; +/// Process any requests +void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt) { + bool updateTrace = false; + bool updateWorkload = false; + bool terminate = false; - u8 sysSrvMsgUpdateTrace; do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - sysSrvMsgUpdateTrace = spurs->m.sysSrvMsgUpdateTrace; - spurs->m.sysSrvMsgUpdateTrace &= ~(1 << mgmt->spuNum); - spurs->m.xCC &= ~(1 << mgmt->spuNum); - spurs->m.xCC |= arg2 << mgmt->spuNum; - - notify = false; - if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) && (spurs->m.sysSrvMsgUpdateTrace == 0) && (spurs->m.xCD != 0)) { - spurs->m.xCD = 0; - notify = true; + // Terminate request + if (spurs->m.sysSrvMsgTerminate & (1 << ctxt->spuNum)) { + spurs->m.sysSrvOnSpu &= ~(1 << ctxt->spuNum); + terminate = true; } - if (arg4 && spurs->m.xCD != 0) { - spurs->m.xCD = 0; - notify = true; - } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - - // Get trace parameters from CellSpurs and store them in the LS - if (((sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) != 0) || (arg3 != 0)) { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.traceBuffer), 0x80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x80 - offsetof(CellSpurs, m.traceBuffer)); - - if (mgmt->traceMsgCount != 0xFF || spurs->m.traceBuffer.addr() == 0) { - spursSysServiceUpdateTraceCount(spu, mgmt); - } else { - spursDma(spu, MFC_GET_CMD, spurs->m.traceBuffer.addr() & 0xFFFFFFFC, 0x2C00/*LSA*/, 0x80/*size*/, mgmt->dmaTagId); - auto traceBuffer = vm::get_ptr(spu.ls_offset + 0x2C00); - mgmt->traceMsgCount = traceBuffer->count[mgmt->spuNum]; + // Update workload message + if (spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << ctxt->spuNum)) { + spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << ctxt->spuNum); + updateWorkload = true; } - mgmt->traceBuffer = spurs->m.traceBuffer.addr() + (spurs->m.traceStartIndex[mgmt->spuNum] << 4); - mgmt->traceMaxCount = spurs->m.traceStartIndex[1] - spurs->m.traceStartIndex[0]; - if (mgmt->traceBuffer == 0) { - mgmt->traceMsgCount = 0; + // Update trace message + if (spurs->m.sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) { + updateTrace = true; } + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + // Process update workload message + if (updateWorkload) { + spursSysServiceActivateWorkload(spu, ctxt); } - if (notify) { - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - sys_spu_thread_send_event(spu, spurs->m.spuPort, 2, 0); + // Process update trace message + if (updateTrace) { + spursSysServiceTraceUpdate(spu, ctxt, 1, 0, 0); + } + + // Process terminate request + if (terminate) { + // TODO: Rest of the terminate processing } } -/// Update events in CellSpurs -void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 wklShutdownBitSet) { +/// Activate a workload +void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt) { + auto spurs = vm::get_ptr(spu.ls_offset + 0x100); + spursDma(spu, MFC_GET_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo1), 0x30000/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + spursDma(spu, MFC_GET_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo2), 0x30200/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + } + + u32 wklShutdownBitSet = 0; + ctxt->wklRunnable1 = 0; + ctxt->wklRunnable2 = 0; + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + auto wklInfo1 = vm::get_ptr(spu.ls_offset + 0x30000); + + // Copy the priority of the workload for this SPU and its unique id to the LS + ctxt->priority[i] = wklInfo1[i].priority[ctxt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[ctxt->spuNum]; + ctxt->wklUniqueId[i] = wklInfo1[i].uniqueId.read_relaxed(); + + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + auto wklInfo2 = vm::get_ptr(spu.ls_offset + 0x30200); + + // Copy the priority of the workload for this SPU to the LS + if (wklInfo2[i].priority[ctxt->spuNum]) { + ctxt->priority[i] |= (0x10 - wklInfo2[i].priority[ctxt->spuNum]) << 4; + } + } + } + + do { + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + // Update workload status and runnable flag based on the workload state + auto wklStatus = spurs->m.wklStatus1[i]; + if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + spurs->m.wklStatus1[i] |= 1 << ctxt->spuNum; + ctxt->wklRunnable1 |= 0x8000 >> i; + } else { + spurs->m.wklStatus1[i] &= ~(1 << ctxt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->m.wklStatus1[i] == 0)) { + spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownBitSet |= 0x80000000u >> i; + } + } + + if (spurs->m.flags1 & SF1_32_WORKLOADS) { + // Update workload status and runnable flag based on the workload state + wklStatus = spurs->m.wklStatus2[i]; + if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { + spurs->m.wklStatus2[i] |= 1 << ctxt->spuNum; + ctxt->wklRunnable2 |= 0x8000 >> i; + } else { + spurs->m.wklStatus2[i] &= ~(1 << ctxt->spuNum); + } + + // If the workload is shutting down and if this is the last SPU from which it is being removed then + // add it to the shutdown bit set + if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { + if (((wklStatus & (1 << ctxt->spuNum)) != 0) && (spurs->m.wklStatus2[i] == 0)) { + spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); + wklShutdownBitSet |= 0x8000 >> i; + } + } + } + } + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + if (wklShutdownBitSet) { + spursSysServiceUpdateShutdownCompletionEvents(spu, ctxt, wklShutdownBitSet); + } +} + +/// Update shutdown completion events +void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelContext * ctxt, u32 wklShutdownBitSet) { // Mark the workloads in wklShutdownBitSet as completed and also generate a bit set of the completed // workloads that have a shutdown completion hook registered u32 wklNotifyBitSet; u8 spuPort; do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); wklNotifyBitSet = 0; @@ -673,334 +903,117 @@ void spursSysServiceUpdateEvent(SPUThread & spu, SpursKernelMgmtData * mgmt, u32 } } } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); if (wklNotifyBitSet) { // TODO: sys_spu_thread_send_event(spuPort, 0, wklNotifyMask); } } -/// Update workload information in the SPU from CellSpurs -void spursSysServiceUpdateWorkload(SPUThread & spu, SpursKernelMgmtData * mgmt) { - auto spurs = vm::get_ptr(spu.ls_offset + 0x100); - spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklInfo1), 0x30000/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); - if (spurs->m.flags1 & SF1_32_WORKLOADS) { - spursDma(spu, MFC_GET_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklInfo2), 0x30200/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); - } - - u32 wklShutdownBitSet = 0; - mgmt->wklRunnable1 = 0; - mgmt->wklRunnable2 = 0; - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - auto wklInfo1 = vm::get_ptr(spu.ls_offset + 0x30000); - - // Copy the priority of the workload for this SPU and its unique id to the LS - mgmt->priority[i] = wklInfo1[i].priority[mgmt->spuNum] == 0 ? 0 : 0x10 - wklInfo1[i].priority[mgmt->spuNum]; - mgmt->wklUniqueId[i] = wklInfo1[i].uniqueId.read_relaxed(); - - if (spurs->m.flags1 & SF1_32_WORKLOADS) { - auto wklInfo2 = vm::get_ptr(spu.ls_offset + 0x30200); - - // Copy the priority of the workload for this SPU to the LS - if (wklInfo2[i].priority[mgmt->spuNum]) { - mgmt->priority[i] |= (0x10 - wklInfo2[i].priority[mgmt->spuNum]) << 4; - } - } - } - - do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - // Update workload status and runnable flag based on the workload state - auto wklStatus = spurs->m.wklStatus1[i]; - if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { - spurs->m.wklStatus1[i] |= 1 << mgmt->spuNum; - mgmt->wklRunnable1 |= 0x8000 >> i; - } else { - spurs->m.wklStatus1[i] &= ~(1 << mgmt->spuNum); - } - - // If the workload is shutting down and if this is the last SPU from which it is being removed then - // add it to the shutdown bit set - if (spurs->m.wklState1[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (spurs->m.wklStatus1[i] == 0)) { - spurs->m.wklState1[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); - wklShutdownBitSet |= 0x80000000u >> i; - } - } - - if (spurs->m.flags1 & SF1_32_WORKLOADS) { - // Update workload status and runnable flag based on the workload state - wklStatus = spurs->m.wklStatus2[i]; - if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_RUNNABLE) { - spurs->m.wklStatus2[i] |= 1 << mgmt->spuNum; - mgmt->wklRunnable2 |= 0x8000 >> i; - } else { - spurs->m.wklStatus2[i] &= ~(1 << mgmt->spuNum); - } - - // If the workload is shutting down and if this is the last SPU from which it is being removed then - // add it to the shutdown bit set - if (spurs->m.wklState2[i].read_relaxed() == SPURS_WKL_STATE_SHUTTING_DOWN) { - if (((wklStatus & (1 << mgmt->spuNum)) != 0) && (spurs->m.wklStatus2[i] == 0)) { - spurs->m.wklState2[i].write_relaxed(SPURS_WKL_STATE_REMOVABLE); - wklShutdownBitSet |= 0x8000 >> i; - } - } - } - } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - - if (wklShutdownBitSet) { - spursSysServiceUpdateEvent(spu, mgmt, wklShutdownBitSet); +/// Update the trace count for this SPU +void spursSysServiceTraceSaveCount(SPUThread & spu, SpursKernelContext * ctxt) { + if (ctxt->traceBuffer) { + auto traceInfo = vm::ptr::make((u32)(ctxt->traceBuffer - (ctxt->spurs->m.traceStartIndex[ctxt->spuNum] << 4))); + traceInfo->count[ctxt->spuNum] = ctxt->traceMsgCount; } } -/// Process any messages -void spursSysServiceProcessMessages(SPUThread & spu, SpursKernelMgmtData * mgmt) { - bool updateTrace = false; - bool updateWorkload = false; - bool terminate = false; +/// Update trace control +void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 arg2, u32 arg3, u32 arg4) { + bool notify; + u8 sysSrvMsgUpdateTrace; do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - // Terminate request - if (spurs->m.sysSrvMsgTerminate & (1 << mgmt->spuNum)) { - spurs->m.sysSrvOnSpu &= ~(1 << mgmt->spuNum); - terminate = true; + sysSrvMsgUpdateTrace = spurs->m.sysSrvMsgUpdateTrace; + spurs->m.sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum); + spurs->m.xCC &= ~(1 << ctxt->spuNum); + spurs->m.xCC |= arg2 << ctxt->spuNum; + + notify = false; + if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) && (spurs->m.sysSrvMsgUpdateTrace == 0) && (spurs->m.xCD != 0)) { + spurs->m.xCD = 0; + notify = true; } - // Update workload message - if (spurs->m.sysSrvMsgUpdateWorkload.read_relaxed() & (1 << mgmt->spuNum)) { - spurs->m.sysSrvMsgUpdateWorkload &= ~(1 << mgmt->spuNum); - updateWorkload = true; + if (arg4 && spurs->m.xCD != 0) { + spurs->m.xCD = 0; + notify = true; + } + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + // Get trace parameters from CellSpurs and store them in the LS + if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0)) { + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.traceBuffer), 0x80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x80 - offsetof(CellSpurs, m.traceBuffer)); + + if (ctxt->traceMsgCount != 0xFF || spurs->m.traceBuffer.addr() == 0) { + spursSysServiceTraceSaveCount(spu, ctxt); + } else { + spursDma(spu, MFC_GET_CMD, spurs->m.traceBuffer.addr() & 0xFFFFFFFC, 0x2C00/*LSA*/, 0x80/*size*/, ctxt->dmaTagId); + auto traceBuffer = vm::get_ptr(spu.ls_offset + 0x2C00); + ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum]; } - // Update trace message - if (spurs->m.sysSrvMsgUpdateTrace & (1 << mgmt->spuNum)) { - updateTrace = true; + ctxt->traceBuffer = spurs->m.traceBuffer.addr() + (spurs->m.traceStartIndex[ctxt->spuNum] << 4); + ctxt->traceMaxCount = spurs->m.traceStartIndex[1] - spurs->m.traceStartIndex[0]; + if (ctxt->traceBuffer == 0) { + ctxt->traceMsgCount = 0; } - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - - // Process update workload message - if (updateWorkload) { - spursSysServiceUpdateWorkload(spu, mgmt); } - // Process update trace message - if (updateTrace) { - spursSysServiceUpdateTrace(spu, mgmt, 1, 0, 0); - } - - // Process terminate request - if (terminate) { - // TODO: Rest of the terminate processing + if (notify) { + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + sys_spu_thread_send_event(spu, spurs->m.spuPort, 2, 0); } } -/// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled -void spursSysServiceWaitOrExit(SPUThread & spu, SpursKernelMgmtData * mgmt) { - // Monitor only lock line reservation lost events - spu.WriteChannel(SPU_WrEventMask, u128::from32r(SPU_EVENT_LR)); +/// Restore state after executing the system workload +void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt) { + u8 wklId; - bool shouldExit; - while (true) { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + do { + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + + if (spurs->m.sysSrvWorkload[ctxt->spuNum] == 0xFF) { + return; + } + + wklId = spurs->m.sysSrvWorkload[ctxt->spuNum]; + spurs->m.sysSrvWorkload[ctxt->spuNum] = 0xFF; + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + spursSysServiceActivateWorkload(spu, ctxt); + + do { + spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x100); - // Find the number of SPUs that are idling in this SPURS instance - u32 nIdlingSpus = 0; - for (u32 i = 0; i < 8; i++) { - if (spurs->m.spuIdling & (1 << i)) { - nIdlingSpus++; - } - } - - bool allSpusIdle = nIdlingSpus == spurs->m.nSpus ? true: false; - bool exitIfNoWork = spurs->m.flags1 & SF1_EXIT_IF_NO_WORK ? true : false; - shouldExit = allSpusIdle && exitIfNoWork; - - // Check if any workloads can be scheduled - bool foundReadyWorkload = false; - if (spurs->m.sysSrvMessage.read_relaxed() & (1 << mgmt->spuNum)) { - foundReadyWorkload = true; + if (wklId >= CELL_SPURS_MAX_WORKLOAD) { + spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; + spurs->m.wklReadyCount1[wklId & 0x0F].write_relaxed(spurs->m.wklReadyCount1[wklId & 0x0F].read_relaxed() - 1); } else { - if (spurs->m.flags1 & SF1_32_WORKLOADS) { - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { - u32 j = i & 0x0F; - u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->wklRunnable1 & (0x8000 >> j) : mgmt->wklRunnable2 & (0x8000 >> j); - u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? mgmt->priority[j] & 0x0F : mgmt->priority[j] >> 4; - u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4; - u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklCurrentContention[j] & 0x0F : spurs->m.wklCurrentContention[j] >> 4; - u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); - u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); - - if (runnable && priority > 0 && maxContention > contention) { - if (wklFlag || wklSignal || readyCount > contention) { - foundReadyWorkload = true; - break; - } - } - } - } else { - for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u8 runnable = mgmt->wklRunnable1 & (0x8000 >> i); - u8 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); - u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; - u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed(); - u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); - u8 requestCount = readyCount + idleSpuCount; - - if (runnable && mgmt->priority[i] != 0 && spurs->m.wklMaxContention[i].read_relaxed() > spurs->m.wklCurrentContention[i]) { - if (wklFlag || wklSignal || (readyCount != 0 && requestCount > spurs->m.wklCurrentContention[i])) { - foundReadyWorkload = true; - break; - } - } - } - } + spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; + spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); } + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - bool spuIdling = spurs->m.spuIdling & (1 << mgmt->spuNum) ? true : false; - if (foundReadyWorkload && shouldExit == false) { - spurs->m.spuIdling &= ~(1 << mgmt->spuNum); - } else { - spurs->m.spuIdling |= 1 << mgmt->spuNum; - } + // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace + // uses the current worload id to determine the workload to which the trace belongs + auto wklIdSaved = ctxt->wklCurrentId; + ctxt->wklCurrentId = wklId; - // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. - if (spuIdling && shouldExit == false && foundReadyWorkload == false) { - // The system service blocks by making a reservation and waiting on the lock line reservation lost event. - u128 r; - spu.ReadChannel(r, SPU_RdEventStat); - spu.WriteChannel(SPU_WrEventAck, u128::from32r(SPU_EVENT_LR)); - } - - auto dmaSuccess = spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - if (dmaSuccess && (shouldExit || foundReadyWorkload)) { - break; - } - } - - if (shouldExit) { - // TODO: exit spu thread group - } -} - -/// Main function for the system service workload -void spursSysServiceWorkloadMain(SPUThread & spu, u32 pollStatus) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x100); - - if (mgmt->spurs.addr() % CellSpurs::align) { - spursHalt(spu); - return; - } - - // Initialise the system service if this is the first time its being started on this SPU - if (mgmt->sysSrvInitialised == 0) { - mgmt->sysSrvInitialised = 1; - - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - - do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - CellSpurs * spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - - // Halt if already initialised - if (spurs->m.sysSrvOnSpu & (1 << mgmt->spuNum)) { - spursHalt(spu); - return; - } - - spurs->m.sysSrvOnSpu |= 1 << mgmt->spuNum; - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); - - mgmt->traceBuffer = 0; - mgmt->traceMsgCount = -1; - spursSysServiceUpdateTrace(spu, mgmt, 1, 1, 0); - spursSysServiceCleanupAfterPreemption(spu, mgmt); - - // Trace - SERVICE: INIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_INIT; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - } - - // Trace - START: Module='SYS ' + // Trace - STOP: GUID CellSpursTracePacket pkt; memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_START; - memcpy(pkt.data.start.module, "SYS ", 4); - pkt.data.start.level = 1; // Policy module - pkt.data.start.ls = 0xA00 >> 2; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; + pkt.data.stop = SPURS_GUID_SYS_WKL; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - while (true) { - // Process messages for the system service workload - spursSysServiceProcessMessages(spu, mgmt); - -poll: - if (cellSpursModulePollStatus(spu, nullptr)) { - // Trace - SERVICE: EXIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_EXIT; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - // Trace - STOP: GUID - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_STOP; - pkt.data.stop = SPURS_GUID_SYS_WKL; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); - break; - } - - // If we reach here it means that either there are more system service messages to be processed - // or there are no workloads that can be scheduled. - - // If the SPU is not idling then process the remaining system service messages - if (mgmt->spuIdling == 0) { - continue; - } - - // If we reach here it means that the SPU is idling - - // Trace - SERVICE: WAIT - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = CELL_SPURS_TRACE_TAG_SERVICE; - pkt.data.service.incident = CELL_SPURS_TRACE_SERVICE_WAIT; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - spursSysServiceWaitOrExit(spu, mgmt); - goto poll; - } -} - -/// Entry point of the system service workload -bool spursSysServiceWorkloadEntry(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); - auto arg = spu.GPR[4]._u64[1]; - auto pollStatus = spu.GPR[5]._u32[3]; - - if (mgmt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { - spursSysServiceWorkloadMain(spu, pollStatus); - } else { - // TODO: If we reach here it means the current workload was preempted to start the - // system service workload. Need to implement this. - } - - return false; + ctxt->wklCurrentId = wklIdSaved; } ////////////////////////////////////////////////////////////////////////////// @@ -1018,14 +1031,98 @@ enum SpursTasksetRequest { SPURS_TASKSET_REQUEST_RECV_WKL_FLAG = 6, }; +/// Taskset PM entry point +bool spursTasksetEntry(SPUThread & spu) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); + auto kernelCtxt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); + + auto arg = spu.GPR[4]._u64[1]; + auto pollStatus = spu.GPR[5]._u32[3]; + + // Initialise memory and save args + memset(ctxt, 0, sizeof(*ctxt)); + ctxt->taskset.set(arg); + memcpy(ctxt->moduleId, "SPURSTASK MODULE", sizeof(ctxt->moduleId)); + ctxt->kernelMgmtAddr = spu.GPR[3]._u32[3]; + ctxt->syscallAddr = CELL_SPURS_TASKSET_PM_SYSCALL_ADDR; + ctxt->spuNum = kernelCtxt->spuNum; + ctxt->dmaTagId = kernelCtxt->dmaTagId; + ctxt->taskId = 0xFFFFFFFF; + + // Register SPURS takset policy module HLE functions + spu.UnregisterHleFunctions(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, 0x40000/*LS_BOTTOM*/); + spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry); + spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry); + + // Initialise the taskset policy module + spursTasksetInit(spu, pollStatus); + + // Dispatch + spursTasksetDispatch(spu); + return false; +} + +/// Entry point into the Taskset PM for task syscalls +bool spursTasksetSyscallEntry(SPUThread & spu) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); + + // Save task context + ctxt->savedContextLr = spu.GPR[0]; + ctxt->savedContextSp = spu.GPR[1]; + for (auto i = 0; i < 48; i++) { + ctxt->savedContextR80ToR127[i] = spu.GPR[80 + i]; + } + + // Handle the syscall + spu.GPR[3]._u32[3] = spursTasksetProcessSyscall(spu, spu.GPR[3]._u32[3], spu.GPR[4]._u32[3]); + + // Resume the previously executing task if the syscall did not cause a context switch + if (spu.m_is_branch == false) { + spursTasksetResumeTask(spu); + } + + return false; +} + +/// Resume a task +void spursTasksetResumeTask(SPUThread & spu) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); + + // Restore task context + spu.GPR[0] = ctxt->savedContextLr; + spu.GPR[1] = ctxt->savedContextSp; + for (auto i = 0; i < 48; i++) { + spu.GPR[80 + i] = ctxt->savedContextR80ToR127[i]; + } + + spu.SetBranch(spu.GPR[0]._u32[3]); +} + +/// Start a task +void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); + auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); + + spu.GPR[2].clear(); + spu.GPR[3] = u128::from64(taskArgs.u64[0], taskArgs.u64[1]); + spu.GPR[4]._u64[1] = taskset->m.args; + spu.GPR[4]._u64[0] = taskset->m.spurs.addr(); + for (auto i = 5; i < 128; i++) { + spu.GPR[i].clear(); + } + + spu.SetBranch(ctxt->savedContextLr.value()._u32[3]); +} + +/// Process a request and update the state of the taskset s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * isWaiting) { - auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto kernelCtxt = vm::get_ptr(spu.ls_offset + 0x100); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); s32 rc = CELL_OK; s32 numNewlyReadyTasks; do { - spursDma(spu, MFC_GETLLAR_CMD, mgmt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, ctxt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/); auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); // Verify taskset state is valid @@ -1055,27 +1152,27 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * switch (request) { case SPURS_TASKSET_REQUEST_POLL_SIGNAL: - rc = signalled._bit[mgmt->taskId] ? 1 : 0; - signalled._bit[mgmt->taskId] = false; + rc = signalled._bit[ctxt->taskId] ? 1 : 0; + signalled._bit[ctxt->taskId] = false; break; case SPURS_TASKSET_REQUEST_DESTROY_TASK: numNewlyReadyTasks--; - running._bit[mgmt->taskId] = false; - enabled._bit[mgmt->taskId] = false; - signalled._bit[mgmt->taskId] = false; - ready._bit[mgmt->taskId] = false; + running._bit[ctxt->taskId] = false; + enabled._bit[ctxt->taskId] = false; + signalled._bit[ctxt->taskId] = false; + ready._bit[ctxt->taskId] = false; break; case SPURS_TASKSET_REQUEST_YIELD_TASK: - running._bit[mgmt->taskId] = false; - waiting._bit[mgmt->taskId] = true; + running._bit[ctxt->taskId] = false; + waiting._bit[ctxt->taskId] = true; break; case SPURS_TASKSET_REQUEST_WAIT_SIGNAL: - if (signalled._bit[mgmt->taskId]) { + if (signalled._bit[ctxt->taskId]) { numNewlyReadyTasks--; - running._bit[mgmt->taskId] = false; - waiting._bit[mgmt->taskId] = true; - signalled._bit[mgmt->taskId] = false; - ready._bit[mgmt->taskId] = false; + running._bit[ctxt->taskId] = false; + waiting._bit[ctxt->taskId] = true; + signalled._bit[ctxt->taskId] = false; + ready._bit[ctxt->taskId] = false; } break; case SPURS_TASKSET_REQUEST_POLL: @@ -1093,9 +1190,9 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * rc = 0; } else if (taskset->m.wkl_flag_wait_task == 0x80) { // No tasks are waiting for the workload flag. Mark this task as waiting for the workload flag. - taskset->m.wkl_flag_wait_task = mgmt->taskId; - running._bit[mgmt->taskId] = false; - waiting._bit[mgmt->taskId] = true; + taskset->m.wkl_flag_wait_task = ctxt->taskId; + running._bit[ctxt->taskId] = false; + waiting._bit[ctxt->taskId] = true; rc = 1; numNewlyReadyTasks--; } else { @@ -1132,8 +1229,8 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * *isWaiting = waiting._bit[selectedTaskId < CELL_SPURS_MAX_TASK ? selectedTaskId : 0] ? 1 : 0; if (selectedTaskId != CELL_SPURS_MAX_TASK) { taskset->m.last_scheduled_task = selectedTaskId; - running._bit[mgmt->taskId] = true; - waiting._bit[mgmt->taskId] = false; + running._bit[ctxt->taskId] = true; + waiting._bit[ctxt->taskId] = false; } break; case SPURS_TASKSET_REQUEST_RECV_WKL_FLAG: @@ -1159,101 +1256,138 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * taskset->m.enabled = enabled; taskset->m.signalled = signalled; taskset->m.ready = ready; - } while (spursDma(spu, MFC_PUTLLC_CMD, mgmt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); // Increment the ready count of the workload by the number of tasks that have become ready do { - spursDma(spu, MFC_GETLLAR_CMD, kernelMgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + spursDma(spu, MFC_GETLLAR_CMD, kernelCtxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); - s32 readyCount = kernelMgmt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].read_relaxed(); + s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[kernelCtxt->wklCurrentId].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].read_relaxed(); readyCount += numNewlyReadyTasks; readyCount = readyCount < 0 ? 0 : readyCount > 0xFF ? 0xFF : readyCount; - if (kernelMgmt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) { - spurs->m.wklReadyCount1[kernelMgmt->wklCurrentId].write_relaxed(readyCount); + if (kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD) { + spurs->m.wklReadyCount1[kernelCtxt->wklCurrentId].write_relaxed(readyCount); } else { - spurs->m.wklIdleSpuCountOrReadyCount2[kernelMgmt->wklCurrentId & 0x0F].write_relaxed(readyCount); + spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].write_relaxed(readyCount); } - } while (spursDma(spu, MFC_PUTLLC_CMD, kernelMgmt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + } while (spursDma(spu, MFC_PUTLLC_CMD, kernelCtxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); return rc; } -s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments) { - if (elfAddr == 0 || (elfAddr & 0x0F) != 0) { - return CELL_SPURS_TASK_ERROR_INVAL; +/// Process pollStatus received from the SPURS kernel +void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { + if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) { + spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_RECV_WKL_FLAG, nullptr, nullptr); } - - vfsStreamMemory stream(elfAddr); - loader::handlers::elf32 loader; - auto rc = loader.init(stream); - if (rc != loader::handler::ok) { - return CELL_SPURS_TASK_ERROR_NOEXEC; - } - - u32 _lowestLoadAddr = CELL_SPURS_TASK_BOTTOM; - for (auto & phdr : loader.m_phdrs) { - if (phdr.data_be.p_paddr >= CELL_SPURS_TASK_BOTTOM) { - break; - } - - if (phdr.data_be.p_type == 1/*PT_LOAD*/) { - if (skipWriteableSegments == false || (phdr.data_be.p_flags & 2/*PF_W*/) == 0) { - if (phdr.data_be.p_vaddr < CELL_SPURS_TASK_TOP || - phdr.data_be.p_vaddr + phdr.data_be.p_memsz > CELL_SPURS_TASK_BOTTOM) { - return CELL_SPURS_TASK_ERROR_FAULT; - } - - _lowestLoadAddr = _lowestLoadAddr > phdr.data_be.p_vaddr ? phdr.data_be.p_vaddr : _lowestLoadAddr; - } - } - } - - loader.load_data(spu.ls_offset, skipWriteableSegments); - *entryPoint = loader.m_ehdr.data_be.e_entry; - if (*lowestLoadAddr) { - *lowestLoadAddr = _lowestLoadAddr; - } - - return CELL_OK; } +/// Check execution rights +bool spursTasksetPollStatus(SPUThread & spu) { + u32 pollStatus; + + if (cellSpursModulePollStatus(spu, &pollStatus)) { + return true; + } + + spursTasksetProcessPollStatus(spu, pollStatus); + return false; +} + +/// Exit the Taskset PM void spursTasksetExit(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); // Trace - STOP CellSpursTracePacket pkt; memset(&pkt, 0, sizeof(pkt)); pkt.header.tag = 0x54; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_STOP pkt.data.stop = SPURS_GUID_TASKSET_PM; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); // Not sure why this check exists. Perhaps to check for memory corruption. - if (memcmp(mgmt->moduleId, "SPURSTASK MODULE", 16) != 0) { + if (memcmp(ctxt->moduleId, "SPURSTASK MODULE", 16) != 0) { spursHalt(spu); } cellSpursModuleExit(spu); } -void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); +/// Invoked when a task exits +void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); - spu.GPR[2].clear(); - spu.GPR[3] = u128::from64(taskArgs.u64[0], taskArgs.u64[1]); - spu.GPR[4]._u64[1] = taskset->m.args; - spu.GPR[4]._u64[0] = taskset->m.spurs.addr(); - for (auto i = 5; i < 128; i++) { - spu.GPR[i].clear(); - } + spursDma(spu, MFC_GET_CMD, addr & 0xFFFFFF80, 0x10000/*LSA*/, (addr & 0x7F) << 11/*size*/, 0); + spursDmaWaitForCompletion(spu, 1); - spu.SetBranch(mgmt->savedContextLr.value()._u32[3]); + spu.GPR[3]._u64[1] = ctxt->taskset.addr(); + spu.GPR[4]._u32[3] = taskId; + spu.GPR[5]._u32[3] = exitCode; + spu.GPR[6]._u64[1] = args; + spu.FastCall(0x10000); } +/// Save the context of a task +s32 spursTasketSaveTaskContext(SPUThread & spu) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); + auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); + + spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + + if (taskInfo->context_save_storage_and_alloc_ls_blocks == 0) { + return CELL_SPURS_TASK_ERROR_STAT; + } + + u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; + u32 lsBlocks = 0; + for (auto i = 0; i < 128; i++) { + if (taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) { + lsBlocks++; + } + } + + if (lsBlocks > allocLsBlocks) { + return CELL_SPURS_TASK_ERROR_STAT; + } + + // Make sure the stack is area is specified in the ls pattern + for (auto i = (ctxt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) { + if ((taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) == 0) { + return CELL_SPURS_TASK_ERROR_STAT; + } + } + + // Get the processor context + u128 r; + spu.FPSCR.Read(r); + ctxt->savedContextFpscr = r; + spu.ReadChannel(r, SPU_RdEventMask); + ctxt->savedSpuWriteEventMask = r._u32[3]; + spu.ReadChannel(r, MFC_RdTagMask); + ctxt->savedWriteTagGroupQueryMask = r._u32[3]; + + // Store the processor context + u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; + spursDma(spu, MFC_PUT_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, ctxt->dmaTagId); + + // Save LS context + for (auto i = 6; i < 128; i++) { + bool shouldStore = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; + if (shouldStore) { + // TODO: Combine DMA requests for consecutive blocks into a single request + spursDma(spu, MFC_PUT_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); + } + } + + spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + return CELL_OK; +} + +/// Taskset dispatcher void spursTasksetDispatch(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); u32 taskId; @@ -1264,11 +1398,11 @@ void spursTasksetDispatch(SPUThread & spu) { return; } - mgmt->taskId = taskId; + ctxt->taskId = taskId; // DMA in the task info for the selected task - spursDma(spu, MFC_GET_CMD, mgmt->taskset.addr() + offsetof(CellSpursTaskset, m.task_info[taskId]), 0x2780/*LSA*/, sizeof(CellSpursTaskset::TaskInfo), mgmt->dmaTagId); - spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + spursDma(spu, MFC_GET_CMD, ctxt->taskset.addr() + offsetof(CellSpursTaskset, m.task_info[taskId]), 0x2780/*LSA*/, sizeof(CellSpursTaskset::TaskInfo), ctxt->dmaTagId); + spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); auto elfAddr = taskInfo->elf_addr.addr().value(); taskInfo->elf_addr.set(taskInfo->elf_addr.addr() & 0xFFFFFFFFFFFFFFF8ull); @@ -1283,7 +1417,7 @@ void spursTasksetDispatch(SPUThread & spu) { if (isWaiting == 0) { // If we reach here it means that the task is being started and not being resumed - mgmt->guidAddr = CELL_SPURS_TASK_TOP; + ctxt->guidAddr = CELL_SPURS_TASK_TOP; u32 entryPoint; u32 lowestLoadAddr; @@ -1292,17 +1426,17 @@ void spursTasksetDispatch(SPUThread & spu) { return; } - spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); - mgmt->savedContextLr.value()._u32[3] = entryPoint; - mgmt->guidAddr = lowestLoadAddr; - mgmt->tasksetMgmtAddr = 0x2700; - mgmt->x2FC0 = 0; - mgmt->taskExitCode = isWaiting; - mgmt->x2FD4 = elfAddr & 5; // TODO: Figure this out + ctxt->savedContextLr.value()._u32[3] = entryPoint; + ctxt->guidAddr = lowestLoadAddr; + ctxt->tasksetMgmtAddr = 0x2700; + ctxt->x2FC0 = 0; + ctxt->taskExitCode = isWaiting; + ctxt->x2FD4 = elfAddr & 5; // TODO: Figure this out if ((elfAddr & 5) == 1) { - spursDma(spu, MFC_GET_CMD, mgmt->taskset.addr() + offsetof(CellSpursTaskset2, m.task_exit_code[taskId]), 0x2FC0/*LSA*/, 0x10/*size*/, mgmt->dmaTagId); + spursDma(spu, MFC_GET_CMD, ctxt->taskset.addr() + offsetof(CellSpursTaskset2, m.task_exit_code[taskId]), 0x2FC0/*LSA*/, 0x10/*size*/, ctxt->dmaTagId); } // Trace - GUID @@ -1340,16 +1474,16 @@ void spursTasksetDispatch(SPUThread & spu) { bool shouldLoad = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; if (shouldLoad) { // TODO: Combine DMA requests for consecutive blocks into a single request - spursDma(spu, MFC_GET_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, mgmt->dmaTagId); + spursDma(spu, MFC_GET_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); } } - spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); + spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); // Restore saved registers - spu.FPSCR.Write(mgmt->savedContextFpscr.value()); - spu.WriteChannel(MFC_WrTagMask, u128::from32r(mgmt->savedWriteTagGroupQueryMask)); - spu.WriteChannel(SPU_WrEventMask, u128::from32r(mgmt->savedSpuWriteEventMask)); + spu.FPSCR.Write(ctxt->savedContextFpscr.value()); + spu.WriteChannel(MFC_WrTagMask, u128::from32r(ctxt->savedWriteTagGroupQueryMask)); + spu.WriteChannel(SPU_WrEventMask, u128::from32r(ctxt->savedSpuWriteEventMask)); // Trace - GUID memset(&pkt, 0, sizeof(pkt)); @@ -1368,125 +1502,9 @@ void spursTasksetDispatch(SPUThread & spu) { } } -void spursTasksetProcessPollStatus(SPUThread & spu, u32 pollStatus) { - if (pollStatus & CELL_SPURS_MODULE_POLL_STATUS_FLAG) { - spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_RECV_WKL_FLAG, nullptr, nullptr); - } -} - -bool spursTasksetPollStatus(SPUThread & spu) { - u32 pollStatus; - - if (cellSpursModulePollStatus(spu, &pollStatus)) { - return true; - } - - spursTasksetProcessPollStatus(spu, pollStatus); - return false; -} - -void spursTasksetInit(SPUThread & spu, u32 pollStatus) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - auto kernelMgmt = vm::get_ptr(spu.ls_offset + 0x100); - - kernelMgmt->moduleId[0] = 'T'; - kernelMgmt->moduleId[1] = 'K'; - - // Trace - START: Module='TKST' - CellSpursTracePacket pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.header.tag = 0x52; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_START - memcpy(pkt.data.start.module, "TKST", 4); - pkt.data.start.level = 2; - pkt.data.start.ls = 0xA00 >> 2; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); - - spursTasksetProcessPollStatus(spu, pollStatus); -} - -void spursTasksetResumeTask(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - - // Restore task context - spu.GPR[0] = mgmt->savedContextLr; - spu.GPR[1] = mgmt->savedContextSp; - for (auto i = 0; i < 48; i++) { - spu.GPR[80 + i] = mgmt->savedContextR80ToR127[i]; - } - - spu.SetBranch(spu.GPR[0]._u32[3]); -} - -s32 spursTasketSaveTaskContext(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); - - spursDmaWaitForCompletion(spu, 0xFFFFFFFF); - - if (taskInfo->context_save_storage_and_alloc_ls_blocks == 0) { - return CELL_SPURS_TASK_ERROR_STAT; - } - - u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; - u32 lsBlocks = 0; - for (auto i = 0; i < 128; i++) { - if (taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) { - lsBlocks++; - } - } - - if (lsBlocks > allocLsBlocks) { - return CELL_SPURS_TASK_ERROR_STAT; - } - - // Make sure the stack is area is specified in the ls pattern - for (auto i = (mgmt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) { - if ((taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) == 0) { - return CELL_SPURS_TASK_ERROR_STAT; - } - } - - // Get the processor context - u128 r; - spu.FPSCR.Read(r); - mgmt->savedContextFpscr = r; - spu.ReadChannel(r, SPU_RdEventMask); - mgmt->savedSpuWriteEventMask = r._u32[3]; - spu.ReadChannel(r, MFC_RdTagMask); - mgmt->savedWriteTagGroupQueryMask = r._u32[3]; - - // Store the processor context - u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; - spursDma(spu, MFC_PUT_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, mgmt->dmaTagId); - - // Save LS context - for (auto i = 6; i < 128; i++) { - bool shouldStore = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; - if (shouldStore) { - // TODO: Combine DMA requests for consecutive blocks into a single request - spursDma(spu, MFC_PUT_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, mgmt->dmaTagId); - } - } - - spursDmaWaitForCompletion(spu, 1 << mgmt->dmaTagId); - return CELL_OK; -} - -void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); - - spursDma(spu, MFC_GET_CMD, addr & 0xFFFFFF80, 0x10000/*LSA*/, (addr & 0x7F) << 11/*size*/, 0); - spursDmaWaitForCompletion(spu, 1); - - spu.GPR[3]._u64[1] = mgmt->taskset.addr(); - spu.GPR[4]._u32[3] = taskId; - spu.GPR[5]._u32[3] = exitCode; - spu.GPR[6]._u64[1] = args; - spu.FastCall(0x10000); -} - +/// Process a syscall request s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); // If the 0x10 bit is set in syscallNum then its the 2nd version of the @@ -1501,14 +1519,14 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { u32 incident = 0; switch (syscallNum) { case CELL_SPURS_TASK_SYSCALL_EXIT: - if (mgmt->x2FD4 == 4 || (mgmt->x2FC0 & 0xFFFFFFFF) != 0) { // TODO: Figure this out - if (mgmt->x2FD4 != 4) { + if (ctxt->x2FD4 == 4 || (ctxt->x2FC0 & 0xFFFFFFFF) != 0) { // TODO: Figure this out + if (ctxt->x2FD4 != 4) { spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_DESTROY_TASK, nullptr, nullptr); } - auto addr = mgmt->x2FD4 == 4 ? taskset->m.x78 : mgmt->x2FC0; - auto args = mgmt->x2FD4 == 4 ? 0 : mgmt->x2FC8; - spursTasksetOnTaskExit(spu, addr, mgmt->taskId, mgmt->taskExitCode, args); + auto addr = ctxt->x2FD4 == 4 ? taskset->m.x78 : ctxt->x2FC0; + auto args = ctxt->x2FD4 == 4 ? 0 : ctxt->x2FC8; + spursTasksetOnTaskExit(spu, addr, ctxt->taskId, ctxt->taskExitCode, args); } incident = CELL_SPURS_TRACE_TASK_EXIT; @@ -1561,11 +1579,11 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { memset(&pkt, 0, sizeof(pkt)); pkt.header.tag = CELL_SPURS_TRACE_TAG_TASK; pkt.data.task.incident = incident; - pkt.data.task.taskId = mgmt->taskId; - cellSpursModulePutTrace(&pkt, mgmt->dmaTagId); + pkt.data.task.taskId = ctxt->taskId; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); // Clear the GUID of the task - memset(vm::get_ptr(spu.ls_offset + mgmt->guidAddr), 0, 0x10); + memset(vm::get_ptr(spu.ls_offset + ctxt->guidAddr), 0, 0x10); if (spursTasksetPollStatus(spu)) { spursTasksetExit(spu); @@ -1577,49 +1595,62 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { return rc; } -bool spursTasksetEntry(SPUThread & spu) { - auto mgmt = vm::get_ptr(spu.ls_offset + 0x2700); +/// Initialise the Taskset PM +void spursTasksetInit(SPUThread & spu, u32 pollStatus) { + auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); + auto kernelCtxt = vm::get_ptr(spu.ls_offset + 0x100); - if (spu.PC == CELL_SPURS_TASKSET_PM_ENTRY_ADDR) { - // Called from kernel - auto kernelMgmt = vm::get_ptr(spu.ls_offset + spu.GPR[3]._u32[3]); - auto arg = spu.GPR[4]._u64[1]; - auto pollStatus = spu.GPR[5]._u32[3]; + kernelCtxt->moduleId[0] = 'T'; + kernelCtxt->moduleId[1] = 'K'; - // Initialise memory and save args - memset(mgmt, 0, sizeof(*mgmt)); - mgmt->taskset.set(arg); - memcpy(mgmt->moduleId, "SPURSTASK MODULE", 16); - mgmt->kernelMgmtAddr = spu.GPR[3]._u32[3]; - mgmt->syscallAddr = CELL_SPURS_TASKSET_PM_SYSCALL_ADDR; - mgmt->spuNum = kernelMgmt->spuNum; - mgmt->dmaTagId = kernelMgmt->dmaTagId; - mgmt->taskId = 0xFFFFFFFF; + // Trace - START: Module='TKST' + CellSpursTracePacket pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.header.tag = 0x52; // Its not clear what this tag means exactly but it seems similar to CELL_SPURS_TRACE_TAG_START + memcpy(pkt.data.start.module, "TKST", 4); + pkt.data.start.level = 2; + pkt.data.start.ls = 0xA00 >> 2; + cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - // Register SPURS takset policy module HLE functions - spu.UnregisterHleFunctions(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, 0x40000); // TODO: use a symbolic constant - spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry); - spu.RegisterHleFunction(mgmt->syscallAddr, spursTasksetEntry); + spursTasksetProcessPollStatus(spu, pollStatus); +} - spursTasksetInit(spu, pollStatus); - spursTasksetDispatch(spu); - } else if (spu.PC == CELL_SPURS_TASKSET_PM_SYSCALL_ADDR) { - // Save task context - mgmt->savedContextLr = spu.GPR[0]; - mgmt->savedContextSp = spu.GPR[1]; - for (auto i = 0; i < 48; i++) { - mgmt->savedContextR80ToR127[i] = spu.GPR[80 + i]; - } - - spu.GPR[3]._u32[3] = spursTasksetProcessSyscall(spu, spu.GPR[3]._u32[3], spu.GPR[4]._u32[3]); - - // Resume the previously executing task if the syscall did not cause a context switch - if (spu.m_is_branch == false) { - spursTasksetResumeTask(spu); - } - } else { - assert(0); +/// Load an ELF +s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments) { + if (elfAddr == 0 || (elfAddr & 0x0F) != 0) { + return CELL_SPURS_TASK_ERROR_INVAL; } - return false; + vfsStreamMemory stream(elfAddr); + loader::handlers::elf32 loader; + auto rc = loader.init(stream); + if (rc != loader::handler::ok) { + return CELL_SPURS_TASK_ERROR_NOEXEC; + } + + u32 _lowestLoadAddr = CELL_SPURS_TASK_BOTTOM; + for (auto & phdr : loader.m_phdrs) { + if (phdr.data_be.p_paddr >= CELL_SPURS_TASK_BOTTOM) { + break; + } + + if (phdr.data_be.p_type == 1/*PT_LOAD*/) { + if (skipWriteableSegments == false || (phdr.data_be.p_flags & 2/*PF_W*/) == 0) { + if (phdr.data_be.p_vaddr < CELL_SPURS_TASK_TOP || + phdr.data_be.p_vaddr + phdr.data_be.p_memsz > CELL_SPURS_TASK_BOTTOM) { + return CELL_SPURS_TASK_ERROR_FAULT; + } + + _lowestLoadAddr = _lowestLoadAddr > phdr.data_be.p_vaddr ? phdr.data_be.p_vaddr : _lowestLoadAddr; + } + } + } + + loader.load_data(spu.ls_offset, skipWriteableSegments); + *entryPoint = loader.m_ehdr.data_be.e_entry; + if (*lowestLoadAddr) { + *lowestLoadAddr = _lowestLoadAddr; + } + + return CELL_OK; } From 23c7028b2acf2bc18e657d6613e7ebfd42b6a6eb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 2 Feb 2015 12:14:49 +0300 Subject: [PATCH 55/94] ARMv7: ARM encoding introduced; bugfixes --- Utilities/GNU.h | 6 + Utilities/Log.h | 2 +- Utilities/StrFmt.cpp | 3 +- Utilities/StrFmt.h | 11 +- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 +- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 132 ++++++++++++++------ rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 31 ++--- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 8 +- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 4 +- rpcs3/Emu/ARMv7/Modules/sceRtc.cpp | 4 +- rpcs3/Emu/Memory/vm.cpp | 7 +- rpcs3/Emu/SysCalls/LogBase.h | 14 +-- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 12 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 13 +- rpcs3/Loader/ELF32.cpp | 17 ++- 16 files changed, 161 insertions(+), 109 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index b1988b4dfa..a8db7f8703 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -14,6 +14,12 @@ #define __noinline __attribute__((noinline)) #endif +#ifdef _WIN32 +#define __safebuffers __declspec(safebuffers) +#else +#define __safebuffers +#endif + template void strcpy_trunc(char(&dst)[size], const std::string& src) { diff --git a/Utilities/Log.h b/Utilities/Log.h index d1710f05cf..5ff8504ce7 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -132,5 +132,5 @@ void log_message(Log::LogType type, Log::LogSeverity sev, std::string text); template __noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args) { - log_message(type, sev, fmt::detail::format(fmt, strlen(fmt), fmt::do_unveil(args)...)); + log_message(type, sev, fmt::detail::format(fmt, fmt::do_unveil(args)...)); } diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 0b8410e2f4..2de4fc889f 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -144,8 +144,9 @@ size_t fmt::detail::get_fmt_precision(const char* fmt, size_t len) return 1; } -std::string fmt::detail::format(const char* fmt, size_t len) +std::string fmt::detail::format(const char* fmt) { + const size_t len = strlen(fmt); const size_t fmt_start = get_fmt_start(fmt, len); if (fmt_start != len) { diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 3bc464fcb8..f7474efa25 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -429,16 +429,17 @@ namespace fmt } }; - std::string format(const char* fmt, size_t len); // terminator + std::string format(const char* fmt); // terminator template - std::string format(const char* fmt, size_t len, const T& arg, Args... args) + std::string format(const char* fmt, const T& arg, Args... args) { + const size_t len = strlen(fmt); const size_t fmt_start = get_fmt_start(fmt, len); const size_t fmt_len = get_fmt_len(fmt + fmt_start, len - fmt_start); const size_t fmt_end = fmt_start + fmt_len; - return std::string(fmt, fmt_start) + get_fmt::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, len - fmt_end, args...); + return std::string(fmt, fmt_start) + get_fmt::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, args...); } }; @@ -551,9 +552,9 @@ namespace fmt Other features are not supported. */ template - __forceinline std::string format(const char* fmt, Args... args) + __forceinline __safebuffers std::string format(const char* fmt, Args... args) { - return detail::format(fmt, strlen(fmt), do_unveil(args)...); + return detail::format(fmt, do_unveil(args)...); } //convert a wxString to a std::string encoded in utf8 diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index fa9e04c64d..5ca662939f 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -137,7 +137,7 @@ struct ARMv7Context } else { - write_pc(value & ~1); + write_pc(value); } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index ce2dbb6914..2c0c976697 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1159,9 +1159,44 @@ struct ARMv7_op4t_table_t } } } + + const ARMv7_opcode_t* HACK() + { + for (auto& opcode : table) + { + if (opcode->func == ARMv7_instrs::HACK) + { + return opcode; + } + } + + throw "HACK instruction not found"; + } } g_op4t; +struct ARMv7_op4arm_table_t +{ + std::vector table; + + ARMv7_op4arm_table_t() + { + for (auto& opcode : ARMv7_opcode_table) + { + if (opcode.type >= A1) + { + if (opcode.code & ~opcode.mask) + { + LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%08x, code=0x%08x)", opcode.name, opcode.mask, opcode.code); + } + + table.push_back(&opcode); + } + } + } + +} g_op4arm; + std::unordered_map g_opct; void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) @@ -1231,16 +1266,21 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); - // possibly a call to imported function: - if (target >= end_addr && ((target - end_addr) % 16) == 0 && vm::psv::read16(target) == 0xf870) - { - const u32 instr = vm::psv::read32(target); + const u32 instr = vm::psv::read32(target); - // check if not "unimplemented" - if (instr >> 16) + // possibly a call to imported function: + if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090) + { + // check if implemented + if (const u32 func = (instr & 0xfff00) >> 4 | (instr & 0xf)) { - // replace BLX with "hack" instruction directly, it can help to see where it was called from - vm::psv::write32(addr, instr); + // replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from + vm::psv::write32(addr, 0xf870 | func << 16); + g_opct[0xf8700000 | func] = g_op4t.HACK(); + } + else + { + // leave as is if unimplemented } } else @@ -1257,50 +1297,60 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) addr += found->length; } - while (vm::psv::read16(addr) == 0xf870) - { - g_opct[0xf8700000 | vm::psv::read16(addr + 2)] = g_op4t.table[0]; - addr += 16; - } - LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); } u32 ARMv7Decoder::DecodeMemory(const u32 address) { - if (address & 0x1) - { - throw "ARMv7Decoder::DecodeMemory() failed (something is wrong with instruction set)"; - } - ARMv7Code code = {}; - code.code0 = vm::psv::read16(address); - if (auto opcode = g_op2t.data[code.code0]) + if (m_ctx.ISET == Thumb) { - (*opcode->func)(m_ctx, code, opcode->type); - return 2; + code.code0 = vm::psv::read16(address); + + if (auto opcode = g_op2t.data[code.code0]) + { + (*opcode->func)(m_ctx, code, opcode->type); + return 2; + } + + code.code1 = code.code0; + code.code0 = vm::psv::read16(address + 2); + + auto op = g_opct.find(code.data); + if (op != g_opct.end()) + { + (*op->second->func)(m_ctx, code, op->second->type); + return 4; + } + + //for (auto opcode : g_op4t.table) + //{ + // if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) + // { + // (*opcode->func)(m_ctx, code, opcode->type); + // return 4; + // } + //} } - - code.code1 = code.code0; - code.code0 = vm::psv::read16(address + 2); - - auto op = g_opct.find(code.data); - if (op != g_opct.end()) + else if (m_ctx.ISET == ARM) { - (*op->second->func)(m_ctx, code, op->second->type); - return 4; + code.data = vm::psv::read32(address); + + for (auto opcode : g_op4arm.table) + { + if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) + { + (*opcode->func)(m_ctx, code, opcode->type); + return 4; + } + } } - - //for (auto opcode : g_op4t.table) - //{ - // if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) - // { - // (*opcode->func)(m_ctx, code, opcode->type); - // return 4; - // } - //} - + else + { + throw "ARMv7Decoder::DecodeMemory() failed (invalid instruction set set)"; + } + ARMv7_instrs::UNK(m_ctx, code); return 4; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index c204351616..d7b1c9adf8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -280,7 +280,14 @@ namespace ARMv7_instrs void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) { - throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); + if (context.ISET == Thumb) + { + throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); + } + else + { + throw fmt::format("Unknown/illegal opcode: 0x%08x", code.data); + } } void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -976,16 +983,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (ConditionPassed(context, cond)) { context.LR = newLR; - if (target & 1) - { - context.ISET = Thumb; - context.thread.SetBranch(target & ~1); - } - else - { - context.ISET = ARM; - context.thread.SetBranch(target); - } + context.write_pc(target); } } @@ -1014,16 +1012,7 @@ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_e if (ConditionPassed(context, cond)) { - if (target & 1) - { - context.ISET = Thumb; - context.thread.SetBranch(target & ~1); - } - else - { - context.ISET = ARM; - context.thread.SetBranch(target); - } + context.write_pc(target); } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 6e1cec6fa8..9fe72a3d49 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -12,7 +12,8 @@ void ARMv7Context::write_pc(u32 value) { - thread.SetBranch(value); + ISET = value & 1 ? Thumb : ARM; + thread.SetBranch(value & ~1); } u32 ARMv7Context::read_pc() @@ -109,10 +110,11 @@ ARMv7Thread::~ARMv7Thread() void ARMv7Thread::InitRegs() { - memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); + memset(context.GPR, 0, sizeof(context.GPR)); context.APSR.APSR = 0; context.IPSR.IPSR = 0; - //context.ISET = Thumb; + context.ISET = PC & 1 ? Thumb : ARM; // select instruction set + context.thread.SetPc(PC & ~1); // and fix PC context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index dbbce2e151..d7bd58c79a 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -48,12 +48,12 @@ s32 sceKernelCreateThread( ARMv7Thread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7)); const auto id = new_thread.GetId(); - new_thread.SetEntry(entry.addr() ^ 1); + new_thread.SetEntry(entry.addr()); new_thread.SetPrio(initPriority); new_thread.SetStackSize(stackSize); new_thread.SetName(pName.get_ptr()); - sceLibKernel.Error("*** New ARMv7 Thread [%s] (entry=0x%x)^1: id -> 0x%x", pName.get_ptr(), entry, id); + sceLibKernel.Warning("*** New ARMv7 Thread [%s] (entry=0x%x): id -> 0x%x", pName.get_ptr(), entry, id); new_thread.Run(); return id; diff --git a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp index 96d44a3686..9b81d86072 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp @@ -59,7 +59,7 @@ s32 sceRtcCheckValid(vm::psv::ptr pTime) throw __FUNCTION__; } -s32 sceRtcSetTime_t(vm::psv::ptr pTime, time_t iTime) +s32 sceRtcSetTime_t(vm::psv::ptr pTime, u32 iTime) { throw __FUNCTION__; } @@ -69,7 +69,7 @@ s32 sceRtcSetTime64_t(vm::psv::ptr pTime, u64 ullTime) throw __FUNCTION__; } -s32 sceRtcGetTime_t(vm::psv::ptr pTime, vm::psv::ptr piTime) +s32 sceRtcGetTime_t(vm::psv::ptr pTime, vm::psv::ptr piTime) { throw __FUNCTION__; } diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 69e42e62cb..04d3a0f90a 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -69,7 +69,7 @@ namespace vm void error(const u64 addr, const char* func) { - throw fmt::format("%s(): invalid address 0x%llx", func, addr); + throw fmt::format("%s(): failed to cast 0x%llx (too big value)", func, addr); } namespace ps3 @@ -249,7 +249,10 @@ namespace vm case CPU_THREAD_ARMv7: { - assert(!"stack_pop(): ARMv7 not supported"); + ARMv7Context& context = static_cast(CPU).context; + + assert(context.SP == addr); + context.SP = old_pos; return; } diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index 7f496d6c6e..82e569e808 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -17,9 +17,9 @@ class LogBase void LogOutput(LogType type, const std::string& text) const; template - __noinline void LogPrepare(LogType type, const char* fmt, size_t len, Targs... args) const + __noinline void LogPrepare(LogType type, const char* fmt, Targs... args) const { - LogOutput(type, fmt::detail::format(fmt, len, args...)); + LogOutput(type, fmt::detail::format(fmt, args...)); } public: @@ -38,7 +38,7 @@ public: template __forceinline void Notice(const char* fmt, Targs... args) const { - LogPrepare(LogNotice, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogNotice, fmt, fmt::do_unveil(args)...); } template @@ -53,25 +53,25 @@ public: template __forceinline void Success(const char* fmt, Targs... args) const { - LogPrepare(LogSuccess, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogSuccess, fmt, fmt::do_unveil(args)...); } template __forceinline void Warning(const char* fmt, Targs... args) const { - LogPrepare(LogWarning, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogWarning, fmt, fmt::do_unveil(args)...); } template __forceinline void Error(const char* fmt, Targs... args) const { - LogPrepare(LogError, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogError, fmt, fmt::do_unveil(args)...); } template __forceinline void Todo(const char* fmt, Targs... args) const { - LogPrepare(LogTodo, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogTodo, fmt, fmt::do_unveil(args)...); } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 18724020af..79ad2d72bc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -372,7 +372,7 @@ s32 cellSaveDataListSave2( for (u32 i=0; iresult < 0) { @@ -629,7 +629,7 @@ s32 cellSaveDataFixedLoad2( for (u32 i = 0; iresult < 0) { @@ -826,7 +826,7 @@ s32 cellSaveDataListAutoSave( //for (u32 i = 0; i queue, vm::ptr buffer, u32 siz queue->m_depth = depth; queue->m_buffer = buffer; queue->m_direction = direction; - *queue->m_hs1 = {}; - *queue->m_hs2 = {}; + memset(queue->m_hs1, 0, sizeof(queue->m_hs1)); + memset(queue->m_hs2, 0, sizeof(queue->m_hs2)); queue->m_eaSignal = eaSignal; if (direction == CELL_SYNC_QUEUE_ANY2ANY) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 99555c70cf..f38865db09 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -217,6 +217,7 @@ int cellVideoOutGetConfiguration(u32 videoOut, vm::ptrresolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId; config->format = Emu.GetGSManager().GetInfo().mode.format; config->aspect = Emu.GetGSManager().GetInfo().mode.aspect; - *config->reserved = {}; config->pitch = Emu.GetGSManager().GetInfo().mode.pitch; return CELL_VIDEO_OUT_SUCCEEDED; case CELL_VIDEO_OUT_SECONDARY: - *config = {}; // ??? return CELL_VIDEO_OUT_SUCCEEDED; } @@ -478,22 +477,25 @@ int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptrWarning("cellAudioOutGetState(audioOut=0x%x, deviceIndex=0x%x, state_addr=0x%x)", audioOut, deviceIndex, state.addr()); + *state = {}; + switch(audioOut) { case CELL_AUDIO_OUT_PRIMARY: state->state = Emu.GetAudioManager().GetState(); state->encoder = Emu.GetAudioManager().GetInfo().mode.encoder; - *state->reserved = {}; state->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer; state->soundMode.type = Emu.GetAudioManager().GetInfo().mode.type; state->soundMode.channel = Emu.GetAudioManager().GetInfo().mode.channel; state->soundMode.fs = Emu.GetAudioManager().GetInfo().mode.fs; state->soundMode.reserved = 0; state->soundMode.layout = Emu.GetAudioManager().GetInfo().mode.layout; + return CELL_AUDIO_OUT_SUCCEEDED; case CELL_AUDIO_OUT_SECONDARY: - *state = { CELL_AUDIO_OUT_OUTPUT_STATE_DISABLED }; + state->state = CELL_AUDIO_OUT_OUTPUT_STATE_DISABLED; + return CELL_AUDIO_OUT_SUCCEEDED; } @@ -534,19 +536,18 @@ int cellAudioOutGetConfiguration(u32 audioOut, vm::ptrWarning("cellAudioOutGetConfiguration(audioOut=%d, config_addr=0x%x, option_addr=0x%x)", audioOut, config.addr(), option.addr()); if (option) *option = {}; + *config = {}; switch(audioOut) { case CELL_AUDIO_OUT_PRIMARY: config->channel = Emu.GetAudioManager().GetInfo().mode.channel; config->encoder = Emu.GetAudioManager().GetInfo().mode.encoder; - *config->reserved = {}; config->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer; return CELL_AUDIO_OUT_SUCCEEDED; case CELL_AUDIO_OUT_SECONDARY: - *config = {}; return CELL_AUDIO_OUT_SUCCEEDED; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index bf36001a51..89112c8692 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -104,6 +104,10 @@ namespace loader vm::psv::ptr sceLibcHeapDelayedAlloc; u32 unk2; + u32 unk3; + + vm::psv::ptr __sce_libcmallocreplace; + vm::psv::ptr __sce_libcnewreplace; }; struct psv_process_param_t @@ -233,18 +237,14 @@ namespace loader LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); } - // writing Thumb code (temporarily, because it should be ARM) - vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) - vm::psv::write16(addr + 2, (u16)get_psv_func_index(func)); // function index - vm::psv::write16(addr + 4, 0x4770); // BX LR - vm::psv::write16(addr + 6, 0); // null + const u32 code = get_psv_func_index(func); + vm::psv::write32(addr + 0, 0xe0700090 | (code & 0xfff0) << 4 | (code & 0xf)); // HACK instruction (ARM) } else { LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr); - vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) - vm::psv::write16(addr + 2, 0); // index 0 (unimplemented stub) + vm::psv::write32(addr + 0, 0xe0700090); // HACK instruction (ARM), unimplemented stub (code 0) vm::psv::write32(addr + 4, nid); // nid } @@ -404,8 +404,7 @@ namespace loader 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(); + armv7_thread(entry, 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; From bd65f8107495186d6f0f0a2b0ae585dda666c1c3 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Mon, 2 Feb 2015 11:21:35 +0100 Subject: [PATCH 56/94] Fix some small mistakes * replace_first and replace_all were in the wrong namespace, so they could not be linked * replace_all did not work correctly (would loop indefinately) * cellGcmUnmapIoAddress did not shif the size, so it would run past the end of the mmap array * fsstat did use a 32-bit size on Windows, so files >4 gigs would return "stat failed" --- Utilities/StrFmt.cpp | 9 +++++---- Utilities/StrFmt.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 1 + rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 12 +++++++++--- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 0b8410e2f4..8760fddd69 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -157,7 +157,7 @@ std::string fmt::detail::format(const char* fmt, size_t len) extern const std::string fmt::placeholder = "???"; -std::string replace_first(const std::string& src, const std::string& from, const std::string& to) +std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to) { auto pos = src.find(from); @@ -169,11 +169,12 @@ std::string replace_first(const std::string& src, const std::string& from, const return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length()); } -std::string replace_all(std::string src, const std::string& from, const std::string& to) +std::string fmt::replace_all(const std::string &src, const std::string& from, const std::string& to) { - for (auto pos = src.find(from); pos != std::string::npos; src.find(from, pos + 1)) + std::string target = src; + for (auto pos = target.find(from); pos != std::string::npos; pos = target.find(from, pos + 1)) { - src = (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length()); + target = (pos ? target.substr(0, pos) + to : to) + std::string(target.c_str() + pos + from.length()); pos += to.length(); } diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 3bc464fcb8..001dbaa742 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -123,7 +123,7 @@ namespace fmt } std::string replace_first(const std::string& src, const std::string& from, const std::string& to); - std::string replace_all(std::string src, const std::string& from, const std::string& to); + std::string replace_all(const std::string &src, const std::string& from, const std::string& to); template std::string replace_all(std::string src, const std::pair(&list)[list_size]) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index de40d05383..292ca71c30 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1004,6 +1004,7 @@ s32 cellGcmUnmapIoAddress(u64 io) { u64 ea; io = io >> 20; + size = size >> 20; ea = offsetTable.eaAddress[io]; for (u32 i = 0; i path, vm::ptr sb) Emu.GetVFS().GetDevice(_path, real_path); + int stat_result; +#ifdef _WIN32 + struct _stat64 buf; + stat_result = _stat64(real_path.c_str(), &buf); +#elif struct stat buf; - - if (int result = stat(real_path.c_str(), &buf)) + stat_result = stat(real_path.c_str(), &buf); +#endif + if (stat_result) { - sys_fs->Error("cellFsStat(): stat('%s') failed -> 0x%x", real_path.c_str(), result); + sys_fs->Error("cellFsStat(): stat('%s') failed -> 0x%x", real_path.c_str(), stat_result); } else { From 13d2f8fa59b477bcfe32dae1e4dba2b014d24ec3 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Mon, 2 Feb 2015 11:33:49 +0100 Subject: [PATCH 57/94] re-enable threadlist in GUI This used to crash so it was removed. However I think this is a cruicial feature. This is the only way to observe the stack-frames, registers and disasm around the PC in a user friendly way. The reason this caused crashes was that we got a reference to a std::vector and iterated over it in one thread while another thread could modify it (and thereby invalidating the iterators). The way I "fixed" it is to just copy the `std::vector>` and iterate over the copy. This obviously has some overhead (locking the shared_ptr counters and incrementing them). It also allows entities other than the Thread manager to keep the Thread objects frome being deleted but that should not be a problem. --- rpcs3/Emu/CPU/CPUThreadManager.h | 2 +- rpcs3/Gui/InterpreterDisAsm.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThreadManager.h b/rpcs3/Emu/CPU/CPUThreadManager.h index 66fef8b377..9724b4ab34 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.h +++ b/rpcs3/Emu/CPU/CPUThreadManager.h @@ -18,7 +18,7 @@ public: CPUThread& AddThread(CPUThreadType type); void RemoveThread(const u32 id); - //std::vector>& GetThreads() { return m_threads; } + std::vector> GetThreads() { return m_threads; } s32 GetThreadNumById(CPUThreadType type, u32 id); std::shared_ptr GetThread(u32 id); std::shared_ptr GetThread(u32 id, CPUThreadType type); diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index 1a62a4224c..b16742f078 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -108,12 +108,12 @@ void InterpreterDisAsmFrame::UpdateUnitList() { m_choice_units->Freeze(); m_choice_units->Clear(); - //auto& thrs = Emu.GetCPU().GetThreads(); + auto thrs = Emu.GetCPU().GetThreads(); - //for (auto& t : thrs) - //{ - // m_choice_units->Append(t->GetFName(), t.get()); - //} + for (auto& t : thrs) + { + m_choice_units->Append(t->GetFName(), t.get()); + } m_choice_units->Thaw(); } From 67342781b7a91ac4d0737279c6e6d1ea565b3c7b Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Tue, 3 Feb 2015 02:13:32 +0530 Subject: [PATCH 58/94] SPURS: Fix some issues --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 78 +++++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 56 ++++++++------- 2 files changed, 95 insertions(+), 39 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 18eed2c944..dad4f10484 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2588,7 +2588,7 @@ s64 spursCreateTaskset(vm::ptr spurs, vm::ptr tasks taskset->m.size = size; vm::var wkl_attr; - _cellSpursWorkloadAttributeInitialize(wkl_attr, 1 /*revision*/, 0x33 /*sdk_version*/, vm::ptr::make(16) /*pm*/, 0x1E40 /*pm_size*/, + _cellSpursWorkloadAttributeInitialize(wkl_attr, 1 /*revision*/, 0x33 /*sdk_version*/, vm::ptr::make(SPURS_IMG_ADDR_TASKSET_PM), 0x1E40 /*pm_size*/, taskset.addr(), priority, 8 /*min_contention*/, max_contention); // TODO: Check return code @@ -2768,14 +2768,16 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: if (ls_pattern.addr() != 0) { u32 ls_blocks = 0; - for (u32 i = 0; i < 2; i++) + for (auto i = 0; i < 64; i++) { - for (u32 j = 0; j < 64; j++) + if (ls_pattern->u64[0] & ((u64)1 << i)) { - if (ls_pattern->u64[0] & ((u64)1 << j)) - { - ls_blocks++; - } + ls_blocks++; + } + + if (ls_pattern->u64[1] & ((u64)1 << i)) + { + ls_blocks++; } } @@ -2803,7 +2805,9 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: { if (!taskset->m.enabled.value()._bit[tmp_task_id]) { - taskset->m.enabled.value()._bit[tmp_task_id] = true; + auto enabled = taskset->m.enabled.value(); + enabled._bit[tmp_task_id] = true; + taskset->m.enabled = enabled; break; } } @@ -2818,23 +2822,73 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: for (u32 i = 0; i < 2; i++) { taskset->m.task_info[tmp_task_id].args.u64[i] = arg != 0 ? arg->u64[i] : 0; - taskset->m.task_info[tmp_task_id].ls_pattern.u64[i] = ls_pattern != 0 ? ls_pattern->u64[i] : 0; + if (ls_pattern.addr()) + { + taskset->m.task_info[tmp_task_id].ls_pattern.u64[i] = ls_pattern->u64[i]; + } } *task_id = tmp_task_id; return CELL_OK; } -s64 cellSpursCreateTask(vm::ptr taskset, vm::ptr taskID, u32 elf_addr, u32 context_addr, u32 context_size, vm::ptr lsPattern, +s64 spursTaskStart(vm::ptr taskset, u32 taskId) +{ + auto pendingReady = taskset->m.pending_ready.value(); + pendingReady._bit[taskId] = true; + taskset->m.pending_ready = pendingReady; + + cellSpursSendWorkloadSignal(vm::ptr::make((u32)taskset->m.spurs.addr()), taskset->m.wid); + auto rc = cellSpursWakeUp(GetCurrentPPUThread(), vm::ptr::make((u32)taskset->m.spurs.addr())); + if (rc != CELL_OK) + { + if (rc == CELL_SPURS_POLICY_MODULE_ERROR_STAT) + { + rc = CELL_SPURS_TASK_ERROR_STAT; + } + else + { + assert(0); + } + } + + return rc; +} + +s64 cellSpursCreateTask(vm::ptr taskset, vm::ptr taskId, u32 elf_addr, u32 context_addr, u32 context_size, vm::ptr lsPattern, vm::ptr argument) { cellSpurs->Warning("cellSpursCreateTask(taskset_addr=0x%x, taskID_addr=0x%x, elf_addr_addr=0x%x, context_addr_addr=0x%x, context_size=%d, lsPattern_addr=0x%x, argument_addr=0x%x)", - taskset.addr(), taskID.addr(), elf_addr, context_addr, context_size, lsPattern.addr(), argument.addr()); + taskset.addr(), taskId.addr(), elf_addr, context_addr, context_size, lsPattern.addr(), argument.addr()); #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x12414, libsre_rtoc); #else - return spursCreateTask(taskset, taskID, vm::ptr::make(elf_addr), vm::ptr::make(context_addr), context_size, lsPattern, argument); + if (!taskset) + { + return CELL_SPURS_TASK_ERROR_NULL_POINTER; + } + + if (taskset.addr() % CellSpursTaskset::align) + { + return CELL_SPURS_TASK_ERROR_ALIGN; + } + + vm::var tmpTaskId; + auto rc = spursCreateTask(taskset, tmpTaskId, vm::ptr::make(elf_addr), vm::ptr::make(context_addr), context_size, lsPattern, argument); + if (rc != CELL_OK) + { + return rc; + } + + rc = spursTaskStart(taskset, tmpTaskId); + if (rc != CELL_OK) + { + return rc; + } + + *taskId = tmpTaskId; + return CELL_OK; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 451bfef848..aa1b25a081 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -116,7 +116,9 @@ bool spursDma(SPUThread & spu, u32 cmd, u64 ea, u32 lsa, u32 size, u32 tag) { u128 rv; spu.ReadChannel(rv, MFC_RdAtomicStat); - return rv._u32[3] ? true : false; + auto success = rv._u32[3] ? true : false; + success = cmd == MFC_PUTLLC_CMD ? !success : success; + return success; } return true; @@ -442,11 +444,11 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { /// SPURS kernel dispatch workload void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { - SpursKernelContext * ctxt = vm::get_ptr(spu.ls_offset + 0x100); - auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); + auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - auto pollStatus = (u32)(spu.GPR[3]._u64[1]); - auto wid = (u32)(spu.GPR[3]._u64[1] >> 32); + auto pollStatus = (u32)widAndPollStatus; + auto wid = (u32)(widAndPollStatus >> 32); // DMA in the workload info for the selected workload auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? offsetof(CellSpurs, m.wklInfo1[wid]) : @@ -491,8 +493,8 @@ void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { /// SPURS kernel workload exit bool spursKernelWorkloadExit(SPUThread & spu) { - SpursKernelContext * ctxt = vm::get_ptr(spu.ls_offset + 0x100); - auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); + auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; // Select next workload to run spu.GPR[3].clear(); @@ -508,7 +510,8 @@ bool spursKernelWorkloadExit(SPUThread & spu) { /// SPURS kernel entry point bool spursKernelEntry(SPUThread & spu) { - SpursKernelContext * ctxt = vm::get_ptr(spu.ls_offset + 0x100); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); + memset(ctxt, 0, sizeof(SpursKernelContext)); // Save arguments ctxt->spuNum = spu.GPR[3]._u32[3]; @@ -516,8 +519,6 @@ bool spursKernelEntry(SPUThread & spu) { auto isKernel2 = ctxt->spurs->m.flags1 & SF1_32_WORKLOADS ? true : false; - memset(ctxt, 0, sizeof(SpursKernelContext)); - // Initialise the SPURS context to its initial values ctxt->dmaTagId = CELL_SPURS_KERNEL_DMA_TAG_ID; ctxt->wklCurrentUniqueId = 0x20; @@ -565,7 +566,8 @@ bool spursSysServiceEntry(SPUThread & spu) { // TODO: If we reach here it means the current workload was preempted to start the // system workload. Need to implement this. } - + + cellSpursModuleExit(spu); return false; } @@ -599,11 +601,11 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { if (spurs->m.flags1 & SF1_32_WORKLOADS) { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD2; i++) { u32 j = i & 0x0F; - u8 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); + u16 runnable = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->wklRunnable1 & (0x8000 >> j) : ctxt->wklRunnable2 & (0x8000 >> j); u8 priority = i < CELL_SPURS_MAX_WORKLOAD ? ctxt->priority[j] & 0x0F : ctxt->priority[j] >> 4; u8 maxContention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklMaxContention[j].read_relaxed() & 0x0F : spurs->m.wklMaxContention[j].read_relaxed() >> 4; u8 contention = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklCurrentContention[j] & 0x0F : spurs->m.wklCurrentContention[j] >> 4; - u8 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); + u16 wklSignal = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklSignal1.read_relaxed() & (0x8000 >> j) : spurs->m.wklSignal2.read_relaxed() & (0x8000 >> j); u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 readyCount = i < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[j].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[j].read_relaxed(); @@ -616,8 +618,8 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { } } else { for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { - u8 runnable = ctxt->wklRunnable1 & (0x8000 >> i); - u8 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); + u16 runnable = ctxt->wklRunnable1 & (0x8000 >> i); + u16 wklSignal = spurs->m.wklSignal1.read_relaxed() & (0x8000 >> i); u8 wklFlag = spurs->m.wklFlag.flag.read_relaxed() == 0 ? spurs->m.wklFlagReceiver.read_relaxed() == i ? 1 : 0 : 0; u8 readyCount = spurs->m.wklReadyCount1[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklReadyCount1[i].read_relaxed(); u8 idleSpuCount = spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed() > CELL_SPURS_MAX_SPU ? CELL_SPURS_MAX_SPU : spurs->m.wklIdleSpuCountOrReadyCount2[i].read_relaxed(); @@ -676,7 +678,7 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) { do { spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - CellSpurs * spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); // Halt if already initialised if (spurs->m.sysSrvOnSpu & (1 << ctxt->spuNum)) { @@ -1167,7 +1169,7 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * waiting._bit[ctxt->taskId] = true; break; case SPURS_TASKSET_REQUEST_WAIT_SIGNAL: - if (signalled._bit[ctxt->taskId]) { + if (signalled._bit[ctxt->taskId] == false) { numNewlyReadyTasks--; running._bit[ctxt->taskId] = false; waiting._bit[ctxt->taskId] = true; @@ -1229,8 +1231,8 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * *isWaiting = waiting._bit[selectedTaskId < CELL_SPURS_MAX_TASK ? selectedTaskId : 0] ? 1 : 0; if (selectedTaskId != CELL_SPURS_MAX_TASK) { taskset->m.last_scheduled_task = selectedTaskId; - running._bit[ctxt->taskId] = true; - waiting._bit[ctxt->taskId] = false; + running._bit[selectedTaskId] = true; + waiting._bit[selectedTaskId] = false; } break; case SPURS_TASKSET_REQUEST_RECV_WKL_FLAG: @@ -1343,7 +1345,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; u32 lsBlocks = 0; for (auto i = 0; i < 128; i++) { - if (taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) { + if (taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i)) { lsBlocks++; } } @@ -1354,7 +1356,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { // Make sure the stack is area is specified in the ls pattern for (auto i = (ctxt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) { - if ((taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i)) == 0) { + if ((taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i)) == 0) { return CELL_SPURS_TASK_ERROR_STAT; } } @@ -1374,7 +1376,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { // Save LS context for (auto i = 6; i < 128; i++) { - bool shouldStore = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; + bool shouldStore = taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i) ? true : false; if (shouldStore) { // TODO: Combine DMA requests for consecutive blocks into a single request spursDma(spu, MFC_PUT_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); @@ -1417,6 +1419,7 @@ void spursTasksetDispatch(SPUThread & spu) { if (isWaiting == 0) { // If we reach here it means that the task is being started and not being resumed + memset(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP), 0, CELL_SPURS_TASK_BOTTOM - CELL_SPURS_TASK_TOP); ctxt->guidAddr = CELL_SPURS_TASK_TOP; u32 entryPoint; @@ -1428,7 +1431,7 @@ void spursTasksetDispatch(SPUThread & spu) { spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); - ctxt->savedContextLr.value()._u32[3] = entryPoint; + ctxt->savedContextLr = u128::from32r(entryPoint); ctxt->guidAddr = lowestLoadAddr; ctxt->tasksetMgmtAddr = 0x2700; ctxt->x2FC0 = 0; @@ -1512,12 +1515,11 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { // for DMA completion if ((syscallNum & 0x10) == 0) { spursDmaWaitForCompletion(spu, 0xFFFFFFFF); - syscallNum &= 0x0F; } s32 rc = 0; u32 incident = 0; - switch (syscallNum) { + switch (syscallNum & 0x0F) { case CELL_SPURS_TASK_SYSCALL_EXIT: if (ctxt->x2FD4 == 4 || (ctxt->x2FC0 & 0xFFFFFFFF) != 0) { // TODO: Figure this out if (ctxt->x2FD4 != 4) { @@ -1587,9 +1589,9 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { if (spursTasksetPollStatus(spu)) { spursTasksetExit(spu); + } else { + spursTasksetDispatch(spu); } - - spursTasksetDispatch(spu); } return rc; From 5225ca8fc2154c506cb91bdfdb56cf38087fdef2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 3 Feb 2015 00:00:05 +0300 Subject: [PATCH 59/94] ARMv7: branch instrs fixed, new instructions BIC_IMM, BIC_REG, RSB_IMM, LDR_LIT, STRB_REG, STRH_REG Fixed initial stack size --- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 290 ++++++++++++++++++++--- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 8 +- rpcs3/Emu/ARMv7/ARMv7Thread.h | 2 +- rpcs3/Emu/ARMv7/Modules/psv_event_flag.h | 1 + rpcs3/Emu/ARMv7/Modules/psv_sema.h | 1 + rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 126 +++++----- rpcs3/Emu/ARMv7/PSVObjectList.h | 34 ++- rpcs3/Emu/Memory/vm.cpp | 6 +- rpcs3/Loader/ELF32.cpp | 4 +- 9 files changed, 367 insertions(+), 105 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index d7b1c9adf8..6ec1bbebf1 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -228,9 +228,9 @@ namespace ARMv7_instrs } } - u32 ThumbExpandImm(ARMv7Context& context, u32 imm12) + u32 ThumbExpandImm(u32 imm12) { - bool carry = context.APSR.C; + bool carry; return ThumbExpandImm_C(imm12, carry, carry); } @@ -418,7 +418,7 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR d = (code.data & 0xf00) >> 8; n = (code.data & 0xf0000) >> 16; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMN (immediate)"); reject(n == 13, "ADD (SP plus immediate)"); @@ -567,7 +567,7 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMN (immediate)"); reject(d == 15, "UNPREDICTABLE"); @@ -770,14 +770,14 @@ void ARMv7_instrs::ASR_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, jump; + u32 cond, imm32; switch (type) { case T1: { cond = (code.data >> 8) & 0xf; - jump = 4 + sign<9, u32>((code.data & 0xff) << 1); + imm32 = sign<9, u32>((code.data & 0xff) << 1); reject(cond == 14, "UNDEFINED"); reject(cond == 15, "SVC"); @@ -787,7 +787,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en case T2: { cond = context.ITSTATE.advance(); - jump = 4 + sign<12, u32>((code.data & 0x7ff) << 1); + imm32 = sign<12, u32>((code.data & 0x7ff) << 1); reject(context.ITSTATE, "UNPREDICTABLE"); break; @@ -799,7 +799,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en const u32 s = (code.data >> 26) & 0x1; const u32 j1 = (code.data >> 13) & 0x1; const u32 j2 = (code.data >> 11) & 0x1; - jump = 4 + sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (code.data & 0x3f0000) >> 4 | (code.data & 0x7ff) << 1); + imm32 = sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (code.data & 0x3f0000) >> 4 | (code.data & 0x7ff) << 1); } reject(cond >= 14, "Related encodings"); @@ -813,7 +813,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en const u32 s = (code.data >> 26) & 0x1; const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - jump = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + imm32 = sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); } reject(context.ITSTATE, "UNPREDICTABLE"); @@ -822,7 +822,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en case A1: { cond = code.data >> 28; - jump = 1 + 4 + sign<26, u32>((code.data & 0xffffff) << 2); + imm32 = sign<26, u32>((code.data & 0xffffff) << 2); break; } default: throw __FUNCTION__; @@ -830,8 +830,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en if (ConditionPassed(context, cond)) { - //LOG_NOTICE(ARMv7, "Branch to 0x%x (cond=0x%x)", context.thread.PC + jump, cond); - context.thread.SetBranch(context.thread.PC + jump); + context.thread.SetBranch(context.read_pc() + imm32); } } @@ -857,20 +856,86 @@ void ARMv7_instrs::BFI(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags, carry = context.APSR.C; + u32 cond, d, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) & ~imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::BIC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = context.read_gpr(n) & ~shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::BIC_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -895,19 +960,18 @@ void ARMv7_instrs::BKPT(ARMv7Context& context, const ARMv7Code code, const ARMv7 void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, imm32, newLR; + u32 cond, imm32; switch (type) { case T1: { cond = context.ITSTATE.advance(); - newLR = (context.thread.PC + 4) | 1; { const u32 s = (code.data >> 26) & 0x1; const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - imm32 = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + imm32 = sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); } reject(context.ITSTATE, "UNPREDICTABLE"); @@ -916,8 +980,7 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e case A1: { cond = code.data >> 28; - newLR = (context.thread.PC + 4) - 4; - imm32 = 4 + sign<26, u32>((code.data & 0xffffff) << 2); + imm32 = sign<26, u32>((code.data & 0xffffff) << 2); break; } default: throw __FUNCTION__; @@ -925,8 +988,16 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e if (ConditionPassed(context, cond)) { - context.LR = newLR; - context.thread.SetBranch(context.thread.PC + imm32); + if (context.ISET == ARM) + { + context.LR = context.read_pc() - 4; + context.thread.SetBranch((context.read_pc() & ~3) + imm32); + } + else + { + context.LR = context.read_pc() | 1; + context.thread.SetBranch(context.read_pc() + imm32); + } } } @@ -939,7 +1010,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ case T1: { cond = context.ITSTATE.advance(); - newLR = (context.thread.PC + 2) | 1; // ??? + newLR = (context.thread.PC + 2) | 1; { const u32 m = (code.data >> 3) & 0xf; reject(m == 15, "UNPREDICTABLE"); @@ -957,7 +1028,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ const u32 s = (code.data >> 26) & 0x1; const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1; const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; - target = (context.thread.PC + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); + target = ~3 & context.thread.PC + 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); } reject(context.ITSTATE, "UNPREDICTABLE"); @@ -966,15 +1037,15 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ case A1: { cond = code.data >> 28; - newLR = (context.thread.PC + 4) - 4; + newLR = context.thread.PC + 4; target = context.read_gpr(code.data & 0xf); break; } case A2: { cond = 0xe; // always true - newLR = (context.thread.PC + 4) - 4; - target = (context.thread.PC + 4 | 1) + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23); + newLR = context.thread.PC + 4; + target = 1 | context.thread.PC + 8 + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23); break; } default: throw __FUNCTION__; @@ -1038,7 +1109,7 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7 if ((context.read_gpr(n) == 0) ^ nonzero) { - context.thread.SetBranch(context.thread.PC + 2 + imm32); + context.thread.SetBranch(context.read_pc() + imm32); } } @@ -1115,7 +1186,7 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR { cond = context.ITSTATE.advance(); n = (code.data & 0xf0000) >> 16; - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(n == 15, "UNPREDICTABLE"); break; @@ -1127,11 +1198,14 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); + const u32 n_value = context.read_gpr(n); + const u32 res = AddWithCarry(n_value, ~imm32, true, carry, overflow); context.APSR.N = res >> 31; context.APSR.Z = res == 0; context.APSR.C = carry; context.APSR.V = overflow; + + //LOG_NOTICE(ARMv7, "CMP: r%d=0x%08x <> 0x%08x, res=0x%08x", n, n_value, imm32, res); } } @@ -1369,11 +1443,40 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, imm32; + bool add; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x700) >> 8; + imm32 = (code.data & 0xff) << 2; + add = true; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + imm32 = (code.data & 0xfff); + add = (code.data & 0x800000); + + reject(t == 15 && context.ITSTATE, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + const u32 data = vm::psv::read32(addr); + context.write_gpr(t, data); + } } void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2544,11 +2647,48 @@ void ARMv7_instrs::RRX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry, overflow; + const u32 result = AddWithCarry(~context.read_gpr(n), imm32, true, carry, overflow); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + context.APSR.V = overflow; + } + } } void ARMv7_instrs::RSB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3167,11 +3307,57 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, m, shift_t, shift_n; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + m = (code.data & 0x1c0) >> 6; + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write8(addr, (u8)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } @@ -3205,11 +3391,57 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, m, shift_t, shift_n; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + m = (code.data & 0x1c0) >> 6; + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write16(addr, (u16)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } @@ -3302,7 +3534,7 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR d = (code.data & 0xf00) >> 8; n = (code.data & 0xf0000) >> 16; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMP (immediate)"); reject(n == 13, "SUB (SP minus immediate)"); @@ -3429,7 +3661,7 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; set_flags = (code.data & 0x100000); - imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); reject(d == 15 && set_flags, "CMP (immediate)"); reject(d == 15, "UNPREDICTABLE"); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 9fe72a3d49..12b7c7b0b3 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -18,7 +18,7 @@ void ARMv7Context::write_pc(u32 value) u32 ARMv7Context::read_pc() { - return thread.PC; + return ISET == ARM ? thread.PC + 8 : thread.PC + 4; } u32 ARMv7Context::get_stack_arg(u32 pos) @@ -230,14 +230,14 @@ void ARMv7Thread::FastStop() m_status = Stopped; } -armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio) { thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); thread->SetName(name); thread->SetEntry(entry); - thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize); - thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); + thread->SetStackSize(stack_size); + thread->SetPrio(prio); argc = 0; } diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index a8a0f75311..5bbc4a564c 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -39,7 +39,7 @@ class armv7_thread : cpu_thread u32 argc; public: - armv7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio); cpu_thread& args(std::initializer_list values) override; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h index bc1cb2d4e9..ad69269a1a 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h @@ -2,6 +2,7 @@ struct psv_event_flag_t { + s32 id; char name[32]; u32 attr; u32 pattern; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema.h b/rpcs3/Emu/ARMv7/Modules/psv_sema.h index 30b3fa6c4c..83b3b99b24 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema.h @@ -2,6 +2,7 @@ struct psv_sema_t { + s32 id; char name[32]; u32 attr; s32 value; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index d280e3dc24..cf3725a3f9 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -2,6 +2,7 @@ #include "Utilities/Log.h" #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/ARMv7Thread.h" #include "Emu/ARMv7/ARMv7Callback.h" extern psv_log_base sceLibc; @@ -12,6 +13,70 @@ typedef void(atexit_func_t)(vm::psv::ptr); std::vector> g_atexit; +std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g_count, u32 f_count, u32 v_count) +{ + std::string result; + + for (char c = *fmt++; c; c = *fmt++) + { + switch (c) + { + case '%': + { + const auto start = fmt - 1; + const bool number_sign = *fmt == '#' ? fmt++, true : false; + + switch (*fmt++) + { + case '%': + { + result += '%'; + continue; + } + case 'd': + case 'i': + { + // signed decimal + const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + + result += fmt::to_sdec(value); + continue; + } + case 'x': + { + // hexadecimal + const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + + if (number_sign && value) + { + result += "0x"; + } + + result += fmt::to_hex(value); + continue; + } + case 's': + { + // string + auto string = vm::psv::ptr::make(context.get_next_gpr_arg(g_count, f_count, v_count)); + + result += string.get_ptr(); + continue; + } + default: + { + throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); + } + } + } + } + + result += c; + } + + return result; +} + namespace sce_libc_func { void __cxa_atexit(vm::psv::ptr func, vm::psv::ptr arg, vm::psv::ptr dso) @@ -59,62 +124,6 @@ namespace sce_libc_func }); } - std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g_count, u32 f_count, u32 v_count) - { - std::string result; - - for (char c = *fmt++; c; c = *fmt++) - { - switch (c) - { - case '%': - { - const auto start = fmt - 1; - const bool number_sign = *fmt == '#' ? fmt++, true : false; - - switch (*fmt++) - { - case '%': - { - result += '%'; - continue; - } - case 'd': - case 'i': - { - // signed decimal - const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count); - - result += fmt::to_sdec(value); - continue; - } - case 'x': - { - // hexadecimal - const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count); - - if (number_sign && value) - { - result += "0x"; - } - - result += fmt::to_hex(value); - continue; - } - default: - { - throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); - } - } - } - } - - result += c; - } - - return result; - } - void printf(ARMv7Context& context, vm::psv::ptr fmt) // va_args... { sceLibc.Warning("printf(fmt=0x%x)", fmt); @@ -158,11 +167,12 @@ namespace sce_libc_func ::memset(dst.get_ptr(), value, size); } - void _Assert(vm::psv::ptr text, vm::psv::ptr func) + void _Assert(ARMv7Context& context, vm::psv::ptr text, vm::psv::ptr func) { - sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func); + sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func); LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr()); + LOG_NOTICE(ARMv7, context.thread.RegsToString()); Emu.Pause(); } } diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index d25c6e39ce..278bc521dd 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -25,8 +25,18 @@ template class psv_object_list_t // Class for managing object data { std::array, 0x8000> m_data; + std::atomic m_hint; // guessing next free position std::mutex m_mutex; // TODO: remove it when shared_ptr atomic ops are fully available +public: + psv_object_list_t() : m_hint(0) {} + + psv_object_list_t(const psv_object_list_t&) = delete; + psv_object_list_t(psv_object_list_t&&) = delete; + + psv_object_list_t& operator =(const psv_object_list_t&) = delete; + psv_object_list_t& operator =(psv_object_list_t&&) = delete; + public: static const u32 uid_class = type; @@ -60,18 +70,18 @@ public: { std::lock_guard lock(m_mutex); - for (auto& value : m_data) + for (u32 i = 0, j = m_hint % m_data.size(); i < m_data.size(); i++, j = (j + 1) % m_data.size()) { - // find an empty position and move the pointer - //std::shared_ptr old_ptr = nullptr; - //if (std::atomic_compare_exchange_strong(&value, &old_ptr, data)) - if (!value) + // find an empty position and copy the pointer + if (!m_data[j]) { - value = data; + m_data[j] = data; + m_hint = j + 1; // guess next position psv_uid_t id = psv_uid_t::make(1); // odd number id.type = uid_class; // set type - id.number = &value - m_data.data(); // set position - return id.uid; + id.number = j; // set position + data->id = id.uid; // save UID + return id.uid; // return UID } } @@ -86,12 +96,14 @@ public: return nullptr; } + const u32 pos = psv_uid_t::make(uid).number; + std::lock_guard lock(m_mutex); std::shared_ptr old_ptr = nullptr; - m_data[psv_uid_t::make(uid).number].swap(old_ptr); + m_data[pos].swap(old_ptr); + m_hint = pos; return old_ptr; - //return std::atomic_exchange>(&m_data[psv_uid_t::make(uid).number], nullptr); } // remove all objects @@ -103,6 +115,8 @@ public: { value = nullptr; } + + m_hint = 0; } }; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 04d3a0f90a..9a5f9eec9e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -63,7 +63,11 @@ namespace vm return res; } - assert(!real_pointer); + if (real_pointer) + { + throw fmt::format("vm::get_addr(0x%016llx) failed: not a part of virtual memory", (u64)real_pointer); + } + return 0; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 89112c8692..1d0ea7a16e 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -401,8 +401,8 @@ namespace loader armv7_decoder_initialize(code_start, code_end); 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; + const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 256 * 1024; + const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 160; armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run(); break; From 8ce1de036adeefe5874731be57b2a7ce48e74179 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Mon, 2 Feb 2015 22:38:05 +0100 Subject: [PATCH 60/94] fix #elif with no condition --- rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index f140555ddc..38ea4fc729 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -239,7 +239,7 @@ s32 cellFsStat(vm::ptr path, vm::ptr sb) #ifdef _WIN32 struct _stat64 buf; stat_result = _stat64(real_path.c_str(), &buf); -#elif +#else struct stat buf; stat_result = stat(real_path.c_str(), &buf); #endif From 0191955ab67d178f6b27526853a63ed800b049d9 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Tue, 3 Feb 2015 11:03:49 +0530 Subject: [PATCH 61/94] SPURS: Fix more issues --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 6 ++++-- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 21 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index dad4f10484..2d37755f48 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2923,8 +2923,10 @@ s64 _cellSpursSendSignal(vm::ptr taskset, u32 taskId) return CELL_SPURS_TASK_ERROR_SRCH; } - auto shouldSignal = (taskset->m.waiting & be_t::make(~taskset->m.signalled.value()) & be_t::make(u128::fromBit(taskId))) != _0 ? true : false; - ((u128)taskset->m.signalled)._bit[taskId] = true; + auto shouldSignal = (taskset->m.waiting & be_t::make(~taskset->m.signalled.value()) & be_t::make(u128::fromBit(taskId))) != _0 ? true : false; + auto signalled = taskset->m.signalled.value(); + signalled._bit[taskId] = true; + taskset->m.signalled = signalled; if (shouldSignal) { cellSpursSendWorkloadSignal(vm::ptr::make((u32)taskset->m.spurs.addr()), taskset->m.wid); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index aa1b25a081..bbcc00e056 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -270,6 +270,7 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { spurs->m.wklCurrentContention[i] = contention[i]; + spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i]; ctxt->wklLocContention[i] = 0; ctxt->wklLocPendingContention[i] = 0; } @@ -294,6 +295,12 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { if (wklSelectedId != CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) { ctxt->wklLocPendingContention[wklSelectedId] = 1; } + } else { + // Not called by kernel and no context switch is required + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + ctxt->wklLocPendingContention[i] = 0; + } } } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); @@ -414,6 +421,7 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { for (auto i = 0; i < (CELL_SPURS_MAX_WORKLOAD2 >> 1); i++) { spurs->m.wklCurrentContention[i] = contention[i] | (contention[i + 0x10] << 4); + spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i]; ctxt->wklLocContention[i] = 0; ctxt->wklLocPendingContention[i] = 0; } @@ -433,6 +441,12 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { } ctxt->wklLocPendingContention[wklSelectedId & 0x0F] = wklSelectedId < CELL_SPURS_MAX_WORKLOAD ? 0x01 : wklSelectedId < CELL_SPURS_MAX_WORKLOAD2 ? 0x10 : 0; + } else { + // Not called by kernel and no context switch is required + for (auto i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { + spurs->m.wklPendingContention[i] = spurs->m.wklPendingContention[i] - ctxt->wklLocPendingContention[i]; + ctxt->wklLocPendingContention[i] = 0; + } } } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); @@ -1461,8 +1475,8 @@ void spursTasksetDispatch(SPUThread & spu) { } // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well - if (taskInfo->ls_pattern.u64[0] != 0xFFFFFFFFFFFFFFFFull || - (taskInfo->ls_pattern.u64[1] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { + if (taskInfo->ls_pattern.u64[1] != 0xFFFFFFFFFFFFFFFFull || + (taskInfo->ls_pattern.u64[0] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { // Load the ELF u32 entryPoint; if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf_addr.addr(), true) != CELL_OK) { @@ -1473,8 +1487,9 @@ void spursTasksetDispatch(SPUThread & spu) { // Load saved context from main memory to LS u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; + spursDma(spu, MFC_GET_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, ctxt->dmaTagId); for (auto i = 6; i < 128; i++) { - bool shouldLoad = taskInfo->ls_pattern.u64[i < 64 ? 1 : 0] & (0x8000000000000000ull >> i) ? true : false; + bool shouldLoad = taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i) ? true : false; if (shouldLoad) { // TODO: Combine DMA requests for consecutive blocks into a single request spursDma(spu, MFC_GET_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); From 2494fcf8d842d0e69d49361f859854f1ace641c7 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 3 Feb 2015 17:48:20 +0300 Subject: [PATCH 62/94] ARMv7: new instructions, bugfix LDRD_LIT, LDRH_IMM, LDRH_LIT, LSR_IMM, ORR_IMM, STRD_IMM, STRD_REG, UMULL --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 11 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 390 ++++++++++++++++++----- rpcs3/Emu/ARMv7/Modules/psv_event_flag.h | 4 +- rpcs3/Emu/ARMv7/Modules/psv_sema.h | 3 +- rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp | 6 +- rpcs3/Emu/ARMv7/PSVObjectList.h | 11 +- 6 files changed, 342 insertions(+), 83 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 2c0c976697..09ac2275d8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1105,6 +1105,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = struct ARMv7_op2_table_t { const ARMv7_opcode_t* data[0x10000]; + u32 null_ops; ARMv7_op2_table_t() { @@ -1123,6 +1124,8 @@ struct ARMv7_op2_table_t } } + null_ops = 0x10000; + for (u32 i = 0; i < 0x10000; i++) { data[i] = nullptr; @@ -1132,6 +1135,7 @@ struct ARMv7_op2_table_t if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i))) { data[i] = opcode; + null_ops--; break; } } @@ -1201,11 +1205,12 @@ std::unordered_map g_opct; void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) { - // 1. Find every 4-byte thumb instruction and cache it + // 1. Find every 4-byte Thumb instruction and cache it // 2. If some instruction is not recognized, print the error // 3. Possibly print disasm - g_opct.clear(); + //g_opct.clear(); + //g_opct.reserve(end_addr - addr); while (addr < end_addr) { @@ -1297,7 +1302,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) addr += found->length; } - LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); + LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld, g_op2t.null_ops=0x%x", (u64)g_opct.size(), g_op2t.null_ops); } u32 ARMv7Decoder::DecodeMemory(const u32 address) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 6ec1bbebf1..eabed09520 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -444,20 +444,17 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.read_gpr(n), imm32, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), imm32, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) + imm32); - } } } @@ -512,21 +509,18 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, true); + const u32 result = AddWithCarry(context.read_gpr(n), shifted, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), shifted, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) + shifted); - } } } @@ -589,20 +583,17 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.SP, imm32, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.SP, imm32, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.SP + imm32); - } } } @@ -652,21 +643,18 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 result = AddWithCarry(context.SP, shifted, false, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.SP, shifted, false, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.SP + context.read_gpr(m)); - } } } @@ -1549,7 +1537,7 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A cond = context.ITSTATE.advance(); t = (code.data & 0x7); n = (code.data & 0x38) >> 3; - imm32 = (code.data & 0x7c0) >> 4; + imm32 = (code.data & 0x7c0) >> 6; index = true; add = true; wback = false; @@ -1657,7 +1645,6 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); const u64 value = vm::psv::read64(addr); - context.write_gpr(t, (u32)(value)); context.write_gpr(t2, (u32)(value >> 32)); @@ -1670,11 +1657,35 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, t2, imm32; + bool add; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + t2 = (code.data & 0xf00) >> 8; + imm32 = (code.data & 0xff) << 2; + add = (code.data & 0x800000); + + reject(!(code.data & 0x1000000), "Related encodings"); // ??? + reject(t == 13 || t == 15 || t2 == 13 || t2 == 15 || t == t2, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + const u64 value = vm::psv::read64(addr); + context.write_gpr(t, (u32)(value)); + context.write_gpr(t2, (u32)(value >> 32)); + } } void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1689,11 +1700,70 @@ void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = (code.data & 0x7c0) >> 5; + index = true; + add = true; + wback = false; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(t == 15, "Unallocated memory hints"); + reject(n == 15, "LDRH (literal)"); + reject(t == 13, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(n == 15, "LDRH (literal)"); + reject(t == 15 && index && !add && !wback, "Unallocated memory hints"); + reject(index && add && !wback, "LDRHT"); + reject(!index && !wback, "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + context.write_gpr(t, vm::psv::read16(addr)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::LDRH_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1891,7 +1961,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR cond = context.ITSTATE.advance(); d = (code.data & 0x7); m = (code.data & 0x38) >> 3; - shift_n = (code.data & 0x7c0) >> 6; + DecodeImmShift(0, (code.data & 0x7c0) >> 6, &shift_n); reject(!shift_n, "MOV (register)"); break; @@ -1902,7 +1972,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR d = (code.data & 0xf00) >> 8; m = (code.data & 0xf); set_flags = (code.data & 0x100000); - shift_n = (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6; + DecodeImmShift(0, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); reject(!shift_n, "MOV (register)"); reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); @@ -1917,6 +1987,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR bool carry; const u32 res = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); context.write_gpr(d, res); + if (set_flags) { context.APSR.N = res >> 31; @@ -1960,6 +2031,7 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR bool carry; const u32 res = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); context.write_gpr(d, res); + if (set_flags) { context.APSR.N = res >> 31; @@ -1972,11 +2044,47 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::LSR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, m, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + DecodeImmShift(1, (code.data & 0x7c0) >> 6, &shift_n); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + DecodeImmShift(1, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 result = Shift_C(context.read_gpr(m), SRType_LSR, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::LSR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2049,6 +2157,7 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { context.write_gpr(d, imm32); + if (set_flags) { context.APSR.N = imm32 >> 31; @@ -2102,12 +2211,13 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { - const u32 res = context.read_gpr(m); - context.write_gpr(d, res); + const u32 result = context.read_gpr(m); + context.write_gpr(d, result); + if (set_flags) { - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; //context.APSR.C = ? } } @@ -2319,11 +2429,39 @@ void ARMv7_instrs::ORN_REG(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, n, imm32; + bool set_flags, carry = context.APSR.C; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(n == 15, "MOV (immediate)"); + reject(d == 13 || d == 15 || n == 13, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) | imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3252,7 +3390,7 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A cond = context.ITSTATE.advance(); t = (code.data & 0x7); n = (code.data & 0x38) >> 3; - imm32 = (code.data & 0x7c0) >> 4; + imm32 = (code.data & 0x7c0) >> 6; index = true; add = true; wback = false; @@ -3363,11 +3501,43 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, t2, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + t2 = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff) << 2; + index = (code.data & 0x1000000); + add = (code.data & 0x800000); + wback = (code.data & 0x200000); + + reject(!index && !wback, "Related encodings"); + reject(wback && (n == t || n == t2), "UNPREDICTABLE"); + reject(n == 15 || t == 13 || t == 15 || t2 == 13 || t2 == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 n_value = context.read_gpr(n); + const u32 offset = add ? n_value + imm32 : n_value - imm32; + const u32 addr = index ? offset : n_value; + vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset); + } + } } void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3382,11 +3552,67 @@ void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + imm32 = (code.data & 0x7c0) >> 5; + index = true; + add = true; + wback = false; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(n == 15, "UNDEFINED"); + reject(t == 13 || t == 15, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(index && add && !wback, "STRHT"); + reject(n == 15 || (!index && !wback), "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + + vm::psv::write16(addr, (u16)context.read_gpr(t)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3560,20 +3786,17 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) - imm32); - } } } @@ -3614,21 +3837,18 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 result = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.read_gpr(n) - shifted); - } } } @@ -3683,20 +3903,17 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + bool carry, overflow; + const u32 result = AddWithCarry(context.SP, ~imm32, true, carry, overflow); + context.write_gpr(d, result); + if (set_flags) { - bool carry, overflow; - const u32 res = AddWithCarry(context.SP, ~imm32, true, carry, overflow); - context.write_gpr(d, res); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; } - else - { - context.write_gpr(d, context.SP - imm32); - } } } @@ -3960,11 +4177,40 @@ void ARMv7_instrs::UMLAL(ARMv7Context& context, const ARMv7Code code, const ARMv void ARMv7_instrs::UMULL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d0, d1, n, m; + bool set_flags; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d0 = (code.data & 0xf000) >> 12; + d1 = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = false; + + reject(d0 == 13 || d0 == 15 || d1 == 13 || d1 == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + reject(d0 == d1, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u64 result = (u64)context.read_gpr(n) * (u64)context.read_gpr(m); + context.write_gpr(d1, (u32)(result >> 32)); + context.write_gpr(d0, (u32)(result)); + + if (set_flags) + { + context.APSR.N = result >> 63 != 0; + context.APSR.Z = result == 0; + } + } } void ARMv7_instrs::UQADD16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h index ad69269a1a..44f1c8214b 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_event_flag.h @@ -2,7 +2,6 @@ struct psv_event_flag_t { - s32 id; char name[32]; u32 attr; u32 pattern; @@ -17,6 +16,9 @@ private: public: psv_event_flag_t(const char* name, u32 attr, u32 pattern); + void on_init(s32 id) {} + void on_stop() {} + }; extern psv_object_list_t g_psv_ef_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_sema.h b/rpcs3/Emu/ARMv7/Modules/psv_sema.h index 83b3b99b24..95608c3c04 100644 --- a/rpcs3/Emu/ARMv7/Modules/psv_sema.h +++ b/rpcs3/Emu/ARMv7/Modules/psv_sema.h @@ -2,7 +2,6 @@ struct psv_sema_t { - s32 id; char name[32]; u32 attr; s32 value; @@ -18,6 +17,8 @@ private: public: psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value); + void on_init(s32 id) {} + void on_stop() {} }; diff --git a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp index a845595c87..51158c0226 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceSysmodule.cpp @@ -6,21 +6,21 @@ extern psv_log_base sceSysmodule; s32 sceSysmoduleLoadModule(u16 id) { - sceSysmodule.Error("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id); + sceSysmodule.Warning("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id); return SCE_OK; // loading succeeded } s32 sceSysmoduleUnloadModule(u16 id) { - sceSysmodule.Error("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id); + sceSysmodule.Warning("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id); return SCE_OK; // unloading succeeded } s32 sceSysmoduleIsLoaded(u16 id) { - sceSysmodule.Error("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id); + sceSysmodule.Warning("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id); return SCE_OK; // module is loaded } diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.h b/rpcs3/Emu/ARMv7/PSVObjectList.h index 278bc521dd..5be66688e0 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.h +++ b/rpcs3/Emu/ARMv7/PSVObjectList.h @@ -80,7 +80,7 @@ public: psv_uid_t id = psv_uid_t::make(1); // odd number id.type = uid_class; // set type id.number = j; // set position - data->id = id.uid; // save UID + data->on_init(id.uid); // save UID return id.uid; // return UID } } @@ -111,9 +111,14 @@ public: { std::lock_guard lock(m_mutex); - for (auto& value : m_data) + for (auto& object : m_data) { - value = nullptr; + if (object) + { + object->on_stop(); + } + + object = nullptr; } m_hint = 0; From d5bbea097badf32a2c3dcc002dd22b39f6055364 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 4 Feb 2015 00:34:18 +0300 Subject: [PATCH 63/94] ARMv7: new instructions, bugfix ADC_IMM, ADR, AND_IMM, EOR_REG, LDRB_REG --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 4 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 186 ++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 09ac2275d8..f143458d48 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -151,8 +151,8 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM), ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM), - ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM), - ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM), + ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )), + ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM, SKIP_IF( BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0 )), ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM), ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT), ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index eabed09520..94c5f79e83 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -364,11 +364,40 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, n, imm32; + bool set_flags; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff)); + + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry, overflow; + const u32 result = AddWithCarry(context.read_gpr(n), imm32, context.APSR.C, carry, overflow); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + context.APSR.V = overflow; + } + } } void ARMv7_instrs::ADC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -661,21 +690,87 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ADR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, imm32; + bool add; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x700) >> 8; + imm32 = (code.data & 0xff) << 2; + add = true; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + imm32 = (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff); + add = false; + + reject(d == 13 || d == 15, "UNPREDICTABLE"); + break; + } + case T3: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + imm32 = (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff); + add = true; + + reject(d == 13 || d == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 base = context.read_pc() & ~3; + const u32 result = add ? base + imm32 : base - imm32; + context.write_gpr(d, result); + } } void ARMv7_instrs::AND_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, n, imm32; + bool set_flags, carry = context.APSR.C; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(d == 15 && set_flags, "TST (immediate)"); + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) & imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::AND_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1275,11 +1370,51 @@ void ARMv7_instrs::EOR_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 15 && set_flags, "TEQ (register)"); + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = context.read_gpr(n) ^ shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::EOR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1496,8 +1631,8 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR index = true; add = true; wback = false; - shift_t = (code.data & 0x30) >> 4; - shift_n = 0; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; reject(n == 15, "LDR (literal)"); reject(m == 13 || m == 15, "UNPREDICTABLE"); @@ -1583,7 +1718,6 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - context.write_gpr(t, vm::psv::read8(addr)); if (wback) @@ -1604,11 +1738,57 @@ void ARMv7_instrs::LDRB_LIT(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, m, shift_t, shift_n; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0x7); + n = (code.data & 0x38) >> 3; + m = (code.data & 0x1c0) >> 6; + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + index = true; + add = true; + wback = false; + shift_t = SRType_LSL; + shift_n = (code.data & 0x30) >> 4; + + reject(t == 15, "PLD"); + reject(n == 15, "LDRB (literal)"); + reject(t == 13 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; + const u32 addr = index ? offset_addr : context.read_gpr(n); + context.write_gpr(t, vm::psv::read8(addr)); + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } From e3f55a75a32cabfe7814fcc4c4cedc7be8cb15c3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 4 Feb 2015 15:16:10 +0300 Subject: [PATCH 64/94] TTY output improved; ARMv7: new instructions ADC_REG, MVN_REG, ORR_REG, ROR_IMM, ROR_REG, TST_IMM, armv7_fmt improved --- Utilities/Log.cpp | 6 +- Utilities/StrFmt.cpp | 33 +++- Utilities/StrFmt.h | 2 + rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 130 ++++++++------- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 230 +++++++++++++++++++++++++++ rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 4 + rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 97 +++++++++-- 7 files changed, 426 insertions(+), 76 deletions(-) diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 44ed7dedf7..0b49521e09 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -109,7 +109,11 @@ struct FileListener : LogListener if (mPrependChannelName) { text.insert(0, gTypeNameTable[static_cast(msg.mType)].mName); - + + if (msg.mType == Log::TTY) + { + text = fmt::escape(text) + "\n"; + } } mFile.Write(text); } diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 6ae236b922..a4a43b8624 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -179,7 +179,7 @@ std::string fmt::replace_all(const std::string &src, const std::string& from, co pos += to.length(); } - return src; + return target; } //TODO: move this wx Stuff somewhere else @@ -339,3 +339,34 @@ std::string fmt::tolower(std::string source) return source; } + +std::string fmt::toupper(std::string source) +{ + std::transform(source.begin(), source.end(), source.begin(), ::toupper); + + return source; +} + +std::string fmt::escape(std::string source) +{ + const std::pair escape_list[] = + { + { "\\", "\\\\" }, + { "\a", "\\a" }, + { "\b", "\\b" }, + { "\f", "\\f" }, + { "\n", "\\n" }, + { "\r", "\\r" }, + { "\t", "\\t" }, + { "\v", "\\v" }, + }; + + source = fmt::replace_all(source, escape_list); + + for (char c = 0; c < 32; c++) + { + source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c)); + } + + return source; +} diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index bd4059ab86..4015d5077b 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -579,4 +579,6 @@ namespace fmt std::string merge(std::vector source, const std::string& separator); std::string merge(std::initializer_list> sources, const std::string& separator); std::string tolower(std::string source); + std::string toupper(std::string source); + std::string escape(std::string source); } diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index f143458d48..cbc6a5d553 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -30,137 +30,147 @@ struct ARMv7_opcode_t const ARMv7_opcode_t ARMv7_opcode_table[] = { - ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK), // "Undefined" Thumb opcode used + ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK, nullptr), // "Undefined" Thumb opcode used ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode used - ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM, nullptr), ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM), - ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG), + ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr), ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR), - ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM), - ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM), + ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM, nullptr), + ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM, nullptr), ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )), ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )), ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM), - ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG), + ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG, nullptr), ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )), ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )), ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR), - ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI), - ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI), + ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI, nullptr), + ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI, nullptr), ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI, SKIP_IF( BF(8, 11) == 15 && BT(20) )), - ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI), + ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI, nullptr), ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI), - ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR), + ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR, nullptr), ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR, SKIP_IF( BF(3, 6) == 13 )), - ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR), + ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR, nullptr), ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR), - ARMv7_OP2(0xf800, 0xa000, T1, ADR), - ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR), - ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR), + ARMv7_OP2(0xf800, 0xa000, T1, ADR, nullptr), + ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR, nullptr), + ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR, nullptr), ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR), ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR), - ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0000, 0x0200, 0x0000, A1, AND_IMM), - ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG), + ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0010, 0x0000, 0x0000, A1, AND_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0000, 0x0010, A1, AND_RSR), - ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM), - ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM), + ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM, nullptr), + ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM, nullptr), ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM), - ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG), - ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG), + ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG, nullptr), + ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG, nullptr), ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG), - ARMv7_OP2(0xf000, 0xd000, T1, B), - ARMv7_OP2(0xf800, 0xe000, T2, B), - ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B), - ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B), + ARMv7_OP2(0xf000, 0xd000, T1, B, SKIP_IF( BF(9, 11) == 0x7 )), + ARMv7_OP2(0xf800, 0xe000, T2, B, nullptr), + ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B, SKIP_IF( BF(23, 25) == 0x7 )), + ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B, nullptr), ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B), - ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC), + ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC, nullptr), ARMv7_OP4(0x0fe0, 0x007f, 0x07c0, 0x001f, A1, BFC), - ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI), + + ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0x0fe0, 0x0070, 0x07c0, 0x0010, A1, BFI), - ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM), + ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM, nullptr), ARMv7_OP4(0x0fe0, 0x0000, 0x03c0, 0x0000, A1, BIC_IMM), - ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG), + ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG, nullptr), ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR), - ARMv7_OP2(0xff00, 0xbe00, T1, BKPT), + ARMv7_OP2(0xff00, 0xbe00, T1, BKPT, nullptr), ARMv7_OP4(0x0ff0, 0x00f0, 0x0120, 0x0070, A1, BKPT), - ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL), + ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL, nullptr), ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL), - ARMv7_OP2(0xff80, 0x4780, T1, BLX), - ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX), + ARMv7_OP2(0xff80, 0x4780, T1, BLX, nullptr), + ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX, nullptr), ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX), ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX), - ARMv7_OP2(0xff87, 0x4700, T1, BX), + ARMv7_OP2(0xff87, 0x4700, T1, BX, nullptr), ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff10, A1, BX), - ARMv7_OP2(0xf500, 0xb100, T1, CB_Z), + ARMv7_OP2(0xf500, 0xb100, T1, CB_Z, nullptr), - ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ), + ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ, nullptr), ARMv7_OP4(0x0fff, 0x0ff0, 0x016f, 0x0f10, A1, CLZ), - ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM), + ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM, nullptr), ARMv7_OP4(0x0ff0, 0xf000, 0x0370, 0x0000, A1, CMN_IMM), - ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG), - ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG), + ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG, nullptr), + ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG, nullptr), ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG), ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR), - ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM), - ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM), + ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM, nullptr), + ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM, nullptr), ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM), - ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG), - ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG), - ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG), + ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG, nullptr), + ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG, nullptr), + ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG, nullptr), ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG), ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR), - ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM), + ARMv7_OP4(0xffff, 0xfff0, 0xf3af, 0x80f0, T1, DBG, nullptr), + ARMv7_OP4(0x0fff, 0xfff0, 0x0320, 0xf0f0, A1, DBG), + + ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f50, T1, DMB, nullptr), + ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf050, A1, DMB), + + ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f40, T1, DSB, nullptr), + ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf040, A1, DSB), + + ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0000, 0x0220, 0x0000, A1, EOR_IMM), - ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG), + ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG, nullptr), + ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )), ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR), ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )), - ARMv7_OP2(0xf800, 0xc800, T1, LDM), - ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM), + ARMv7_OP2(0xf800, 0xc800, T1, LDM, nullptr), + ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM, SKIP_IF( BT(21) && BF(16, 19) == 13 )), ARMv7_OP4(0x0fd0, 0x0000, 0x0890, 0x0000, A1, LDM), ARMv7_OP4(0x0fd0, 0x0000, 0x0810, 0x0000, A1, LDMDA), - ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB), + ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB, nullptr), ARMv7_OP4(0x0fd0, 0x0000, 0x0910, 0x0000, A1, LDMDB), ARMv7_OP4(0x0fd0, 0x0000, 0x0990, 0x0000, A1, LDMIB), - ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM), - ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM), + ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM, nullptr), + ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM, nullptr), ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM, SKIP_IF( BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0 )), ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM), - ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT), - ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT), + ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT, nullptr), + ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT, nullptr), ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT), - ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG), - ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG), + ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG, nullptr), + ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0x0e50, 0x0010, 0x0610, 0x0000, A1, LDR_REG), - + ARMv7_OP2(0xf800, 0x7800, T1, LDRB_IMM), ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, LDRB_IMM), ARMv7_OP4(0xfff0, 0x0800, 0xf810, 0x0800, T3, LDRB_IMM), @@ -280,7 +290,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfbe0, 0x8000, 0xf040, 0x0000, T1, ORR_IMM), ARMv7_OP4(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM), ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG), - ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG), + ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG, SKIP_IF( BF(16, 19) == 15 )), ARMv7_OP4(0x0fe0, 0x0010, 0x0180, 0x0000, A1, ORR_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0180, 0x0010, A1, ORR_RSR), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 94c5f79e83..aede0d0488 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -402,11 +402,51 @@ void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ADC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry, overflow; + const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); + const u32 result = AddWithCarry(context.read_gpr(n), shifted, context.APSR.C, carry, overflow); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + context.APSR.V = overflow; + } + } } void ARMv7_instrs::ADC_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1359,6 +1399,34 @@ void ARMv7_instrs::CMP_RSR(ARMv7Context& context, const ARMv7Code code, const AR } +void ARMv7_instrs::DBG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) +{ + switch (type) + { + case A1: throw __FUNCTION__; + default: throw __FUNCTION__; + } +} + +void ARMv7_instrs::DMB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) +{ + switch (type) + { + case A1: throw __FUNCTION__; + default: throw __FUNCTION__; + } +} + +void ARMv7_instrs::DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) +{ + switch (type) + { + case A1: throw __FUNCTION__; + default: throw __FUNCTION__; + } +} + + void ARMv7_instrs::EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { switch (type) @@ -2541,11 +2609,49 @@ void ARMv7_instrs::MVN_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::MVN_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = ~shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::MVN_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2646,11 +2752,51 @@ void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m, shift_t, shift_n; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + shift_t = SRType_LSL; + shift_n = 0; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(n == 15, "ROR (immediate)"); + reject(d == 13 || d == 15 || n == 13 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry); + const u32 result = context.read_gpr(n) | shifted; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::ORR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -2936,20 +3082,84 @@ void ARMv7_instrs::REVSH(ARMv7Context& context, const ARMv7Code code, const ARMv void ARMv7_instrs::ROR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, m, shift_n; + bool set_flags; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + const u32 shift_t = DecodeImmShift(3, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); + + reject(shift_t == SRType_RRX, "RRX"); + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 result = Shift_C(context.read_gpr(m), SRType_ROR, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::ROR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags = !context.ITSTATE; + u32 cond, d, n, m; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = n = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + break; + } + case T2: + { + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + m = (code.data & 0xf); + set_flags = (code.data & 0x100000); + + reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + bool carry; + const u32 shift_n = context.read_gpr(m) & 0xff; + const u32 result = Shift_C(context.read_gpr(n), SRType_ROR, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } @@ -4212,11 +4422,31 @@ void ARMv7_instrs::TEQ_RSR(ARMv7Context& context, const ARMv7Code code, const AR void ARMv7_instrs::TST_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool carry = context.APSR.C; + u32 cond, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0xf0000) >> 16; + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) & imm32; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } } void ARMv7_instrs::TST_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 2a18646d42..01521ce9d5 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -79,6 +79,10 @@ namespace ARMv7_instrs void CMP_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void CMP_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void DBG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void DMB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); + void EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); void EOR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index cf3725a3f9..3e5b21c44e 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -24,12 +24,63 @@ std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g case '%': { const auto start = fmt - 1; - const bool number_sign = *fmt == '#' ? fmt++, true : false; - switch (*fmt++) + // read flags + const bool plus_sign = *fmt == '+' ? fmt++, true : false; + const bool minus_sign = *fmt == '-' ? fmt++, true : false; + const bool space_sign = *fmt == ' ' ? fmt++, true : false; + const bool number_sign = *fmt == '#' ? fmt++, true : false; + const bool zero_padding = *fmt == '0' ? fmt++, true : false; + + // read width + const u32 width = [&]() -> u32 + { + u32 width = 0; + + if (*fmt == '*') + { + fmt++; + return context.get_next_gpr_arg(g_count, f_count, v_count); + } + + while (*fmt - '0' < 10) + { + width = width * 10 + (*fmt++ - '0'); + } + + return width; + }(); + + // read precision + const u32 prec = [&]() -> u32 + { + u32 prec = 0; + + if (*fmt != '.') + { + return 0; + } + + if (*++fmt == '*') + { + fmt++; + return context.get_next_gpr_arg(g_count, f_count, v_count); + } + + while (*fmt - '0' < 10) + { + prec = prec * 10 + (*fmt++ - '0'); + } + + return prec; + }(); + + switch (char cf = *fmt++) { case '%': { + if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; + result += '%'; continue; } @@ -39,20 +90,38 @@ std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g // signed decimal const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; + result += fmt::to_sdec(value); continue; } case 'x': + case 'X': { // hexadecimal const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count); + if (plus_sign || minus_sign || space_sign || prec) break; + if (number_sign && value) { - result += "0x"; + result += cf == 'x' ? "0x" : "0X"; } - result += fmt::to_hex(value); + const std::string& hex = cf == 'x' ? fmt::to_hex(value) : fmt::toupper(fmt::to_hex(value)); + + if (hex.length() >= width) + { + result += hex; + } + else if (zero_padding) + { + result += std::string(width - hex.length(), '0') + hex; + } + else + { + result += hex + std::string(width - hex.length(), ' '); + } continue; } case 's': @@ -60,14 +129,14 @@ std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr fmt, u32 g // string auto string = vm::psv::ptr::make(context.get_next_gpr_arg(g_count, f_count, v_count)); + if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break; + result += string.get_ptr(); continue; } - default: - { - throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); - } } + + throw fmt::format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr()); } } @@ -127,21 +196,21 @@ namespace sce_libc_func void printf(ARMv7Context& context, vm::psv::ptr fmt) // va_args... { sceLibc.Warning("printf(fmt=0x%x)", fmt); + sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr()); - sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); + const std::string& result = armv7_fmt(context, fmt, 1, 0, 0); + sceLibc.Log("*** -> '%s'", result); - LOG_NOTICE(TTY, armv7_fmt(context, fmt, 1, 0, 0)); + LOG_NOTICE(TTY, result); } void sprintf(ARMv7Context& context, vm::psv::ptr str, vm::psv::ptr fmt) // va_args... { sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt); - - sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); + sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr()); const std::string& result = armv7_fmt(context, fmt, 2, 0, 0); - - sceLibc.Notice("*** res -> '%s'", result); + sceLibc.Log("*** -> '%s'", result); ::memcpy(str.get_ptr(), result.c_str(), result.size() + 1); } From daaa5059e9da18efeabd2e94e71159786f735092 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Wed, 4 Feb 2015 20:59:34 +0530 Subject: [PATCH 65/94] SPURS: Fixed more issues --- Utilities/BEType.h | 20 ++++++++++--- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 32 +++++++-------------- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 7 ++--- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 15 ++++------ 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 4965eac336..8cf5e9a89c 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -1,5 +1,7 @@ #pragma once +#define IS_LE_MACHINE + union _CRT_ALIGN(16) u128 { u64 _u64[2]; @@ -136,16 +138,28 @@ union _CRT_ALIGN(16) u128 } }; + // Index 0 returns the MSB and index 127 returns the LSB bit_element operator [] (u32 index) { assert(index < 128); - return bit_element(data[index / 64], 1ull << (index % 64)); + +#ifdef IS_LE_MACHINE + return bit_element(data[1 - (index >> 6)], 0x8000000000000000ull >> (index & 0x3F)); +#else + return bit_element(data[index >> 6], 0x8000000000000000ull >> (index & 0x3F)); +#endif } + // Index 0 returns the MSB and index 127 returns the LSB const bool operator [] (u32 index) const { assert(index < 128); - return (data[index / 64] & (1ull << (index % 64))) != 0; + +#ifdef IS_LE_MACHINE + return (data[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0; +#else + return (data[index >> 6] & (0x8000000000000000ull >> (index & 0x3F))) != 0; +#endif } } _bit; @@ -509,8 +523,6 @@ struct be_storage_t typedef u128 type; }; -#define IS_LE_MACHINE - template class be_t { diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 2d37755f48..18eaca3722 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -34,9 +34,9 @@ s64 spursCreateLv2EventQueue(vm::ptr spurs, u32& queue_id, vm::ptr> queue; - s32 res = cb_call, vm::ptr, vm::ptr, s32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, + s32 res = cb_call, vm::ptr>, vm::ptr, s32, u32>(GetCurrentPPUThread(), libsre + 0xB14C, libsre_rtoc, spurs, queue, port, size, vm::read32(libsre_rtoc - 0x7E2C)); - queue_id = queue; + queue_id = queue.value(); return res; #endif @@ -2768,14 +2768,9 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: if (ls_pattern.addr() != 0) { u32 ls_blocks = 0; - for (auto i = 0; i < 64; i++) + for (auto i = 0; i < 128; i++) { - if (ls_pattern->u64[0] & ((u64)1 << i)) - { - ls_blocks++; - } - - if (ls_pattern->u64[1] & ((u64)1 << i)) + if (ls_pattern->_u128.value()._bit[i]) { ls_blocks++; } @@ -2786,7 +2781,8 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: return CELL_SPURS_TASK_ERROR_INVAL; } - if (ls_pattern->u32[0] & 0xFC000000) + u128 _0 = u128::from32(0); + if ((ls_pattern->_u128.value() & u128::from32r(0xFC000000)) != _0) { // Prevent save/restore to SPURS management area return CELL_SPURS_TASK_ERROR_INVAL; @@ -2819,13 +2815,10 @@ s64 spursCreateTask(vm::ptr taskset, vm::ptr task_id, vm: taskset->m.task_info[tmp_task_id].elf_addr.set(elf_addr.addr()); taskset->m.task_info[tmp_task_id].context_save_storage_and_alloc_ls_blocks = (context_addr.addr() | alloc_ls_blocks); - for (u32 i = 0; i < 2; i++) + taskset->m.task_info[tmp_task_id].args = *arg; + if (ls_pattern.addr()) { - taskset->m.task_info[tmp_task_id].args.u64[i] = arg != 0 ? arg->u64[i] : 0; - if (ls_pattern.addr()) - { - taskset->m.task_info[tmp_task_id].ls_pattern.u64[i] = ls_pattern->u64[i]; - } + taskset->m.task_info[tmp_task_id].ls_pattern = *ls_pattern; } *task_id = tmp_task_id; @@ -3162,12 +3155,7 @@ s64 _cellSpursTaskAttribute2Initialize(vm::ptr attribut for (s32 c = 0; c < 4; c++) { - attribute->lsPattern.u32[c] = 0; - } - - for (s32 i = 0; i < 2; i++) - { - attribute->lsPattern.u64[i] = 0; + attribute->lsPattern._u128 = u128::from64r(0); } attribute->name_addr = 0; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 3188d3238c..348c795653 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -413,6 +413,7 @@ struct CellSpurs be_t arg; // spu argument be_t size; atomic_t uniqueId; // The unique id is the same for all workloads with the same addr + u8 pad[3]; u8 priority[8]; }; @@ -622,14 +623,12 @@ struct CellSpursEventFlag union CellSpursTaskArgument { - be_t u32[4]; - be_t u64[2]; + be_t _u128; }; union CellSpursTaskLsPattern { - be_t u32[4]; - be_t u64[2]; + be_t _u128; }; struct CellSpursTaskset diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index bbcc00e056..9070a8ce8e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -1120,7 +1120,7 @@ void spursTasksetStartTask(SPUThread & spu, CellSpursTaskArgument & taskArgs) { auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); spu.GPR[2].clear(); - spu.GPR[3] = u128::from64(taskArgs.u64[0], taskArgs.u64[1]); + spu.GPR[3] = taskArgs._u128; spu.GPR[4]._u64[1] = taskset->m.args; spu.GPR[4]._u64[0] = taskset->m.spurs.addr(); for (auto i = 5; i < 128; i++) { @@ -1359,7 +1359,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { u32 allocLsBlocks = taskInfo->context_save_storage_and_alloc_ls_blocks & 0x7F; u32 lsBlocks = 0; for (auto i = 0; i < 128; i++) { - if (taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i)) { + if (taskInfo->ls_pattern._u128.value()._bit[i]) { lsBlocks++; } } @@ -1370,7 +1370,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { // Make sure the stack is area is specified in the ls pattern for (auto i = (ctxt->savedContextSp.value()._u32[3]) >> 11; i < 128; i++) { - if ((taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i)) == 0) { + if (taskInfo->ls_pattern._u128.value()._bit[i] == false) { return CELL_SPURS_TASK_ERROR_STAT; } } @@ -1390,8 +1390,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { // Save LS context for (auto i = 6; i < 128; i++) { - bool shouldStore = taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i) ? true : false; - if (shouldStore) { + if (taskInfo->ls_pattern._u128.value()._bit[i]) { // TODO: Combine DMA requests for consecutive blocks into a single request spursDma(spu, MFC_PUT_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); } @@ -1475,8 +1474,7 @@ void spursTasksetDispatch(SPUThread & spu) { } // If the entire LS is saved then there is no need to load the ELF as it will be be saved in the context save area as well - if (taskInfo->ls_pattern.u64[1] != 0xFFFFFFFFFFFFFFFFull || - (taskInfo->ls_pattern.u64[0] | 0xFC00000000000000ull) != 0xFFFFFFFFFFFFFFFFull) { + if (taskInfo->ls_pattern._u128.value() != u128::from64r(0x03FFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull)) { // Load the ELF u32 entryPoint; if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf_addr.addr(), true) != CELL_OK) { @@ -1489,8 +1487,7 @@ void spursTasksetDispatch(SPUThread & spu) { u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; spursDma(spu, MFC_GET_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, ctxt->dmaTagId); for (auto i = 6; i < 128; i++) { - bool shouldLoad = taskInfo->ls_pattern.u64[i < 64 ? 0 : 1] & (0x8000000000000000ull >> i) ? true : false; - if (shouldLoad) { + if (taskInfo->ls_pattern._u128.value()._bit[i]) { // TODO: Combine DMA requests for consecutive blocks into a single request spursDma(spu, MFC_GET_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); } From 819c955cca888368546f195d11aff3d4c2c5d026 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Feb 2015 02:52:47 +0300 Subject: [PATCH 66/94] ARMv7: partial disasm functionality, bugfix --- Utilities/Log.cpp | 6 +- Utilities/StrFmt.cpp | 4 +- rpcs3/Emu/ARMv7/ARMv7Context.h | 28 +- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 2 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 671 ++++++++++++++++++++++++--- rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 3 +- rpcs3/Emu/ARMv7/PSVFuncList.cpp | 21 +- rpcs3/Emu/ARMv7/PSVFuncList.h | 6 +- rpcs3/Emu/System.cpp | 10 + 9 files changed, 651 insertions(+), 100 deletions(-) diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 0b49521e09..5aaf98579d 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -112,7 +112,11 @@ struct FileListener : LogListener if (msg.mType == Log::TTY) { - text = fmt::escape(text) + "\n"; + text = fmt::escape(text); + if (text[text.length() - 1] != '\n') + { + text += '\n'; + } } } mFile.Write(text); diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index a4a43b8624..f3f74a327d 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -355,7 +355,7 @@ std::string fmt::escape(std::string source) { "\a", "\\a" }, { "\b", "\\b" }, { "\f", "\\f" }, - { "\n", "\\n" }, + { "\n", "\\n\n" }, { "\r", "\\r" }, { "\t", "\\t" }, { "\v", "\\v" }, @@ -365,7 +365,7 @@ std::string fmt::escape(std::string source) for (char c = 0; c < 32; c++) { - source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c)); + if (c != '\n') source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c)); } return source; diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 5ca662939f..78c0ab0e43 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -10,17 +10,15 @@ enum ARMv7InstructionSet ThumbEE }; +enum armv7_debug_flags : u32 +{ + DF_DISASM = 1 << 0, + DF_PRINT = 1 << 1, + DF_NO_EXE = 1 << 2, +}; + struct ARMv7Context { - ARMv7Thread& thread; - - ARMv7Context(ARMv7Thread& thread) : thread(thread) {} - - void write_pc(u32 value); - u32 read_pc(); - u32 get_stack_arg(u32 pos); - void fast_call(u32 addr); - union { u32 GPR[15]; @@ -127,6 +125,18 @@ struct ARMv7Context std::array counters; + ARMv7Thread& thread; + + u32 debug; // debug flags + std::string debug_str; + + ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(DF_DISASM | DF_PRINT) {} + + void write_pc(u32 value); + u32 read_pc(); + u32 get_stack_arg(u32 pos); + void fast_call(u32 addr); + void write_gpr(u32 n, u32 value) { assert(n < 16); diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index cbc6a5d553..4ae428e985 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -35,7 +35,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM, nullptr), ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM), - ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG, nullptr), + ARMv7_OP2(0xffc0, 0x4140, T1, ADC_REG, nullptr), ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr), ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR), diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index aede0d0488..1d1add9481 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include #include "Utilities/Log.h" #include "Emu/System.h" #include "Emu/Memory/Memory.h" @@ -10,6 +11,8 @@ #define reject(cond, info) { if (cond) Error(__FUNCTION__, code, type, #cond, info); } +std::map g_armv7_dump; + namespace ARMv7_instrs { template @@ -63,7 +66,7 @@ namespace ARMv7_instrs SRType DecodeImmShift(u32 type, u32 imm5, u32* shift_n) { - SRType shift_t = SRType_None; + SRType shift_t; switch (type) { @@ -80,25 +83,28 @@ namespace ARMv7_instrs shift_t = SRType_ROR; if (shift_n) *shift_n = imm5; } break; + + default: throw __FUNCTION__; } return shift_t; } - SRType DecodeRegShift(u8 type) - { - SRType shift_t = SRType_None; + //SRType DecodeRegShift(u8 type) + //{ + // SRType shift_t; - switch (type) - { - case 0: shift_t = SRType_LSL; break; - case 1: shift_t = SRType_LSR; break; - case 2: shift_t = SRType_ASR; break; - case 3: shift_t = SRType_ROR; break; - } + // switch (type) + // { + // case 0: shift_t = SRType_LSL; break; + // case 1: shift_t = SRType_LSR; break; + // case 2: shift_t = SRType_ASR; break; + // case 3: shift_t = SRType_ROR; break; + // default: throw __FUNCTION__; + // } - return shift_t; - } + // return shift_t; + //} u32 LSL_C(u32 x, s32 shift, bool& carry_out) { @@ -129,7 +135,7 @@ namespace ARMv7_instrs s32 ASR_C(s32 x, s32 shift, bool& carry_out) { assert(shift > 0); - carry_out = shift <= 32 ? x & (1 << (shift - 1)) : false; + carry_out = shift <= 32 ? x & (1 << (shift - 1)) : x < 0; return shift < 32 ? x >> shift : x >> 31; } @@ -142,8 +148,9 @@ namespace ARMv7_instrs u32 ROR_C(u32 x, s32 shift, bool& carry_out) { assert(shift); - carry_out = x & (1 << (shift - 1)); - return x >> shift | x << (32 - shift); + const u32 result = x >> shift | x << (32 - shift); + carry_out = result >> 31; + return result; } u32 ROR_(u32 x, s32 shift) @@ -230,7 +237,7 @@ namespace ARMv7_instrs u32 ThumbExpandImm(u32 imm12) { - bool carry; + bool carry = false; return ThumbExpandImm_C(imm12, carry, carry); } @@ -240,13 +247,13 @@ namespace ARMv7_instrs switch (cond >> 1) { - case 0: result = context.APSR.Z == 1; break; - case 1: result = context.APSR.C == 1; break; - case 2: result = context.APSR.N == 1; break; - case 3: result = context.APSR.V == 1; break; - case 4: result = context.APSR.C == 1 && context.APSR.Z == 0; break; - case 5: result = context.APSR.N == context.APSR.V; break; - case 6: result = context.APSR.N == context.APSR.V && context.APSR.Z == 0; break; + case 0: result = (context.APSR.Z == 1); break; + case 1: result = (context.APSR.C == 1); break; + case 2: result = (context.APSR.N == 1); break; + case 3: result = (context.APSR.V == 1); break; + case 4: result = (context.APSR.C == 1) && (context.APSR.Z == 0); break; + case 5: result = (context.APSR.N == context.APSR.V); break; + case 6: result = (context.APSR.N == context.APSR.V) && (context.APSR.Z == 0); break; case 7: return true; } @@ -276,6 +283,137 @@ namespace ARMv7_instrs throw fmt::format("%s(%s) error: %s (%s)", func, format_encoding(type), info, cond); } + + bool process_debug(ARMv7Context& context) + { + if (context.debug & DF_PRINT) + { + auto pos = context.debug_str.find(' '); + if (pos != std::string::npos && pos < 8) + { + context.debug_str.insert(pos, 8 - pos, ' '); + } + + context.debug_str = fmt::format("0x%08x: %s", context.thread.PC, context.debug_str); + + LV2_LOCK(0); + + auto found = g_armv7_dump.find(context.thread.PC); + if (found != g_armv7_dump.end()) + { + if (found->second != context.debug_str) + { + throw context.debug_str; + } + } + else + { + g_armv7_dump[context.thread.PC] = context.debug_str; + } + } + + if (context.debug & DF_NO_EXE) + { + return true; + } + + return false; + } + + const char* fmt_cond(u32 cond) + { + switch (cond) + { + case 0: return "eq"; + case 1: return "ne"; + case 2: return "cs"; + case 3: return "cc"; + case 4: return "mi"; + case 5: return "pl"; + case 6: return "vs"; + case 7: return "vc"; + case 8: return "hi"; + case 9: return "ls"; + case 10: return "ge"; + case 11: return "lt"; + case 12: return "gt"; + case 13: return "le"; + case 14: return ""; + default: return "???"; + } + } + + const char* fmt_it(u32 state) + { + switch (state & ~0x10) + { + case 0x8: return ""; + + case 0x4: return state & 0x10 ? "e" : "t"; + case 0xc: return state & 0x10 ? "t" : "e"; + + case 0x2: return state & 0x10 ? "ee" : "tt"; + case 0x6: return state & 0x10 ? "et" : "te"; + case 0xa: return state & 0x10 ? "te" : "et"; + case 0xe: return state & 0x10 ? "tt" : "ee"; + + case 0x1: return state & 0x10 ? "eee" : "ttt"; + case 0x3: return state & 0x10 ? "eet" : "tte"; + case 0x5: return state & 0x10 ? "ete" : "tet"; + case 0x7: return state & 0x10 ? "ett" : "tee"; + case 0x9: return state & 0x10 ? "tee" : "ett"; + case 0xb: return state & 0x10 ? "tet" : "ete"; + case 0xd: return state & 0x10 ? "tte" : "eet"; + case 0xf: return state & 0x10 ? "ttt" : "eee"; + + default: return "???"; + } + } + + const char* fmt_reg(u32 reg) + { + switch (reg) + { + case 0: return "r0"; + case 1: return "r1"; + case 2: return "r2"; + case 3: return "r3"; + case 4: return "r4"; + case 5: return "r5"; + case 6: return "r6"; + case 7: return "r7"; + case 8: return "r8"; + case 9: return "r9"; + case 10: return "r10"; + case 11: return "r11"; + case 12: return "r12"; + case 13: return "sp"; + case 14: return "lr"; + case 15: return "pc"; + default: return "???"; + } + } + + std::string fmt_shift(u32 type, u32 amount) + { + assert(type != SRType_RRX || amount == 1); + assert(amount <= 32); + + if (amount) + { + switch (type) + { + case SRType_LSL: return ",lsl #" + fmt::to_udec(amount); + case SRType_LSR: return ",lsr #" + fmt::to_udec(amount); + case SRType_ASR: return ",asr #" + fmt::to_udec(amount); + case SRType_ROR: return ",ror #" + fmt::to_udec(amount); + case SRType_RRX: return ",rrx"; + default: return ",?????"; + } + } + + return{}; + } } void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) @@ -311,6 +449,12 @@ void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("hack%s %s", fmt_cond(cond), get_psv_func_by_index(func)->name); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { execute_psv_func_by_index(context, func); @@ -341,6 +485,12 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mrc%s p%d,%d,r%d,c%d,c%d,%d", fmt_cond(cond), cp, opc1, t, cn, cm, opc2); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { // APSR flags are written if t = 15 @@ -358,7 +508,7 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 return; } - throw fmt::format("Bad instruction: mrc p%d,%d,r%d,c%d,c%d,%d", cp, opc1, t, cn, cm, opc2); + throw fmt::format("Bad instruction: mrc%s p%d,%d,r%d,c%d,c%d,%d", fmt_cond(cond), cp, opc1, t, cn, cm, opc2); } } @@ -384,6 +534,12 @@ void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -432,6 +588,12 @@ void ARMv7_instrs::ADC_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -511,6 +673,12 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -576,6 +744,12 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -650,6 +824,12 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -710,6 +890,12 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spr)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -767,10 +953,17 @@ void ARMv7_instrs::ADR(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + const u32 base = context.read_pc() & ~3; + const u32 result = add ? base + imm32 : base - imm32; + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adr%s r%d, 0x%08x", fmt_cond(cond), d, result); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - const u32 base = context.read_pc() & ~3; - const u32 result = add ? base + imm32 : base - imm32; context.write_gpr(d, result); } } @@ -799,6 +992,12 @@ void ARMv7_instrs::AND_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) & imm32; @@ -846,6 +1045,12 @@ void ARMv7_instrs::AND_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -951,6 +1156,12 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("b%s 0x%08x", fmt_cond(cond), context.read_pc() + imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.thread.SetBranch(context.read_pc() + imm32); @@ -999,6 +1210,12 @@ void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) & ~imm32; @@ -1045,6 +1262,12 @@ void ARMv7_instrs::BIC_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -1109,18 +1332,19 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e default: throw __FUNCTION__; } + const u32 lr = context.ISET == ARM ? context.read_pc() - 4 : context.read_pc() | 1; + const u32 pc = context.ISET == ARM ? (context.read_pc() & ~3) + imm32 : context.read_pc() + imm32; + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bl%s 0x%08x", fmt_cond(cond), pc); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - if (context.ISET == ARM) - { - context.LR = context.read_pc() - 4; - context.thread.SetBranch((context.read_pc() & ~3) + imm32); - } - else - { - context.LR = context.read_pc() | 1; - context.thread.SetBranch(context.read_pc() + imm32); - } + context.LR = lr; + context.thread.SetBranch(pc); } } @@ -1174,6 +1398,21 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) + { + context.debug_str = fmt::format("blx%s ", fmt_cond(cond)); + switch (type) + { + case T1: context.debug_str += fmt_reg((code.data >> 3) & 0xf); break; + case T2: context.debug_str += fmt::format("0x%08x", target); break; + default: context.debug_str += "???"; + } + } + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.LR = newLR; @@ -1183,14 +1422,14 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { - u32 cond, target; + u32 cond, m; switch (type) { case T1: { cond = context.ITSTATE.advance(); - target = context.read_gpr((code.data >> 3) & 0xf); + m = (code.data >> 3) & 0xf; reject(context.ITSTATE, "UNPREDICTABLE"); break; @@ -1198,15 +1437,21 @@ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_e case A1: { cond = code.data >> 28; - target = context.read_gpr(code.data & 0xf); + m = (code.data & 0xf); break; } default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bx%s %s", fmt_cond(cond), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - context.write_pc(target); + context.write_pc(context.read_gpr(m)); } } @@ -1230,6 +1475,12 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cb%sz 0x%08x", nonzero ? "n" : "", context.read_pc() + imm32); + if (process_debug(context)) return; + } + if ((context.read_gpr(n) == 0) ^ nonzero) { context.thread.SetBranch(context.read_pc() + imm32); @@ -1257,6 +1508,12 @@ void ARMv7_instrs::CLZ(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("clz%s %s,%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.write_gpr(d, cntlz32(context.read_gpr(m))); @@ -1318,13 +1575,19 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; const u32 n_value = context.read_gpr(n); - const u32 res = AddWithCarry(n_value, ~imm32, true, carry, overflow); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + const u32 result = AddWithCarry(n_value, ~imm32, true, carry, overflow); + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; @@ -1373,15 +1636,21 @@ void ARMv7_instrs::CMP_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,%s%s", fmt_cond(cond), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { + bool carry, overflow; const u32 m_value = context.read_gpr(m); const u32 n_value = context.read_gpr(n); - bool carry, overflow; const u32 shifted = Shift(m_value, shift_t, shift_n, true); - const u32 res = AddWithCarry(n_value, ~shifted, true, carry, overflow); - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + const u32 result = AddWithCarry(n_value, ~shifted, true, carry, overflow); + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; context.APSR.V = overflow; @@ -1469,6 +1738,12 @@ void ARMv7_instrs::EOR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("eor%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -1501,19 +1776,25 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e { case T1: { - const u32 mask = code.data & 0xf; + const u32 mask = (code.data & 0xf); const u32 first = (code.data & 0xf0) >> 4; reject(mask == 0, "Related encodings"); reject(first == 15, "UNPREDICTABLE"); reject(first == 14 && BitCount(mask) != 1, "UNPREDICTABLE"); reject(context.ITSTATE, "UNPREDICTABLE"); + + context.ITSTATE.IT = code.data & 0xff; break; } default: throw __FUNCTION__; } - context.ITSTATE.IT = code.data & 0xff; + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("IT%s %s", fmt_it(context.ITSTATE.shift_state), fmt_cond(context.ITSTATE.condition)); + if (process_debug(context)) return; + } } @@ -1618,11 +1899,16 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - context.write_gpr(t, vm::psv::read32(addr)); if (wback) @@ -1661,6 +1947,12 @@ void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (lit)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 base = context.read_pc() & ~3; @@ -1711,19 +2003,23 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - const u32 data = vm::psv::read32(addr); + context.write_gpr(t, vm::psv::read32(addr)); if (wback) { context.write_gpr(n, offset_addr); } - - context.write_gpr(t, data); } } @@ -1782,6 +2078,12 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; @@ -1845,6 +2147,12 @@ void ARMv7_instrs::LDRB_REG(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); @@ -1888,6 +2196,12 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; @@ -1926,6 +2240,12 @@ void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (lit)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 base = context.read_pc() & ~3; @@ -2000,11 +2320,16 @@ void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrh%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - context.write_gpr(t, vm::psv::read16(addr)); if (wback) @@ -2076,6 +2401,12 @@ void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrsb%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; @@ -2158,14 +2489,19 @@ void ARMv7_instrs::LDREX(ARMv7Context& context, const ARMv7Code code, const ARMv default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrex%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 addr = context.read_gpr(n) + imm32; const u32 value = vm::psv::read32(addr); - + context.write_gpr(t, value); context.R_ADDR = addr; context.R_DATA = value; - context.write_gpr(t, value); } } @@ -2230,16 +2566,22 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("lsl%s%s %s,%s,#%d", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), shift_n); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; - const u32 res = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); - context.write_gpr(d, res); + const u32 result = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); + context.write_gpr(d, result); if (set_flags) { - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; } } @@ -2274,16 +2616,22 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("lsl%s%s %s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; - const u32 res = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); - context.write_gpr(d, res); + const u32 result = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); + context.write_gpr(d, result); if (set_flags) { - context.APSR.N = res >> 31; - context.APSR.Z = res == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; } } @@ -2320,6 +2668,12 @@ void ARMv7_instrs::LSR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("lsr%s%s %s,%s,#%d", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), shift_n); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -2382,7 +2736,7 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR case T2: { cond = context.ITSTATE.advance(); - set_flags = code.data & 0x100000; + set_flags = (code.data & 0x100000); d = (code.data >> 8) & 0xf; imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); @@ -2402,14 +2756,21 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mov%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { - context.write_gpr(d, imm32); + const u32 result = imm32; + context.write_gpr(d, result); if (set_flags) { - context.APSR.N = imm32 >> 31; - context.APSR.Z = imm32 == 0; + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; context.APSR.C = carry; } } @@ -2457,6 +2818,12 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mov%s%s %s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(m); @@ -2466,7 +2833,7 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR { context.APSR.N = result >> 31; context.APSR.Z = result == 0; - //context.APSR.C = ? + //context.APSR.C = carry; } } } @@ -2490,6 +2857,12 @@ void ARMv7_instrs::MOVT(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("movt%s %s,#0x%x", fmt_cond(cond), fmt_reg(d), imm16); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.write_gpr(d, (context.read_gpr(d) & 0xffff) | (imm16 << 16)); @@ -2556,6 +2929,12 @@ void ARMv7_instrs::MUL(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mul%s%s %s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 op1 = context.read_gpr(n); @@ -2593,6 +2972,12 @@ void ARMv7_instrs::MVN_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = ~imm32; @@ -2638,6 +3023,12 @@ void ARMv7_instrs::MVN_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -2688,6 +3079,12 @@ void ARMv7_instrs::NOP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("nop%s", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { } @@ -2736,6 +3133,12 @@ void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) | imm32; @@ -2783,6 +3186,12 @@ void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -2870,6 +3279,12 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("pop%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { u32 written = 0; @@ -2935,6 +3350,12 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("push%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { u32 read = 0; @@ -3103,6 +3524,12 @@ void ARMv7_instrs::ROR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ror%s%s %s,%s,#%d", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), shift_n); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -3134,6 +3561,7 @@ void ARMv7_instrs::ROR_REG(ARMv7Context& context, const ARMv7Code code, const AR } case T2: { + cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; n = (code.data & 0xf0000) >> 16; m = (code.data & 0xf); @@ -3146,6 +3574,12 @@ void ARMv7_instrs::ROR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ror%s%s %s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry; @@ -3203,6 +3637,12 @@ void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("rsb%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -3698,11 +4138,16 @@ void ARMv7_instrs::STR_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write32(addr, context.read_gpr(t)); if (wback) @@ -3752,12 +4197,17 @@ void ARMv7_instrs::STR_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write32(addr, context.read_gpr(t)); if (wback) @@ -3819,11 +4269,16 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write8(addr, (u8)context.read_gpr(t)); if (wback) @@ -3873,12 +4328,17 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write8(addr, (u8)context.read_gpr(t)); if (wback) @@ -3916,12 +4376,18 @@ void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strd%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 n_value = context.read_gpr(n); const u32 offset = add ? n_value + imm32 : n_value - imm32; const u32 addr = index ? offset : n_value; - vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | context.read_gpr(t)); + vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | (u64)context.read_gpr(t)); if (wback) { @@ -3991,11 +4457,16 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (imm)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write16(addr, (u16)context.read_gpr(t)); if (wback) @@ -4045,6 +4516,12 @@ void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (reg)", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); @@ -4083,6 +4560,12 @@ void ARMv7_instrs::STREX(ARMv7Context& context, const ARMv7Code code, const ARMv default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strex%s ()", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 addr = context.read_gpr(n) + imm32; @@ -4174,6 +4657,12 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -4225,6 +4714,12 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (reg)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -4291,6 +4786,12 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { bool carry, overflow; @@ -4440,6 +4941,12 @@ void ARMv7_instrs::TST_IMM(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("tst%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u32 result = context.read_gpr(n) & imm32; @@ -4609,6 +5116,12 @@ void ARMv7_instrs::UMULL(ARMv7Context& context, const ARMv7Code code, const ARMv default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("umull%s%s %s,%s,%s,%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d0), fmt_reg(d1), fmt_reg(n), fmt_reg(m)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { const u64 result = (u64)context.read_gpr(n) * (u64)context.read_gpr(m); @@ -4795,6 +5308,12 @@ void ARMv7_instrs::UXTB(ARMv7Context& context, const ARMv7Code code, const ARMv7 default: throw __FUNCTION__; } + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("uxtb%s %s,%s%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m), fmt_shift(SRType_ROR, rot)); + if (process_debug(context)) return; + } + if (ConditionPassed(context, cond)) { context.write_gpr(d, (context.read_gpr(m) >> rot) & 0xff); diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 01521ce9d5..e759f5e40b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -18,12 +18,11 @@ enum ARMv7_encoding enum SRType : u32 { - SRType_None, SRType_LSL, SRType_LSR, SRType_ASR, SRType_ROR, - SRType_RRX + SRType_RRX, }; namespace ARMv7_instrs diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index 29990a3208..21d9c6488e 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -10,7 +10,7 @@ void add_psv_func(psv_func& data) g_psv_func_list.push_back(data); } -psv_func* get_psv_func_by_nid(u32 nid) +const psv_func* get_psv_func_by_nid(u32 nid) { for (auto& f : g_psv_func_list) { @@ -23,7 +23,7 @@ psv_func* get_psv_func_by_nid(u32 nid) return nullptr; } -u32 get_psv_func_index(psv_func* func) +u32 get_psv_func_index(const psv_func* func) { auto res = func - g_psv_func_list.data(); @@ -32,14 +32,21 @@ u32 get_psv_func_index(psv_func* func) return (u32)res; } -void execute_psv_func_by_index(ARMv7Context& context, u32 index) +const psv_func* get_psv_func_by_index(u32 index) { assert(index < g_psv_func_list.size()); + + return &g_psv_func_list[index]; +} + +void execute_psv_func_by_index(ARMv7Context& context, u32 index) +{ + auto func = get_psv_func_by_index(index); auto old_last_syscall = context.thread.m_last_syscall; - context.thread.m_last_syscall = g_psv_func_list[index].nid; + context.thread.m_last_syscall = func->nid; - (*g_psv_func_list[index].func)(context); + (*func->func)(context); context.thread.m_last_syscall = old_last_syscall; } @@ -174,7 +181,7 @@ void initialize_psv_modules() // setup special functions (without NIDs) psv_func unimplemented; unimplemented.nid = 0; - unimplemented.name = "Special function (unimplemented stub)"; + unimplemented.name = "UNIMPLEMENTED"; unimplemented.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) { context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4); @@ -184,7 +191,7 @@ void initialize_psv_modules() psv_func hle_return; hle_return.nid = 1; - hle_return.name = "Special function (return from HLE)"; + hle_return.name = "HLE_RETURN"; hle_return.func.reset(new psv_func_detail::func_binder([](ARMv7Context& context) { context.thread.FastStop(); diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index a1948dcbec..8ddb45ab75 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -492,9 +492,11 @@ template void reg_psv_func(u32 nid, psv_log_base* mo add_psv_func(f); } // Find registered HLE function by its ID -psv_func* get_psv_func_by_nid(u32 nid); +const psv_func* get_psv_func_by_nid(u32 nid); // Get index of registered HLE function -u32 get_psv_func_index(psv_func* func); +u32 get_psv_func_index(const psv_func* func); +// Find registered HLE function by its index +const psv_func* get_psv_func_by_index(u32 index); // Execute registered HLE function by its index void execute_psv_func_by_index(ARMv7Context& context, u32 index); // Register all HLE functions diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 8324e0e54f..db61eac0ea 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -349,6 +349,8 @@ void Emulator::Resume() GetCallbackManager().RunPauseCallbacks(false); } +extern std::map g_armv7_dump; + void Emulator::Stop() { if(IsStopped()) return; @@ -365,6 +367,14 @@ void Emulator::Stop() finalize_psv_modules(); clear_all_psv_objects(); + + for (auto& v : g_armv7_dump) + { + LOG_NOTICE(ARMv7, v.second); + } + + g_armv7_dump.clear(); + m_rsx_callback = 0; // TODO: check finalization order From e93aaf395770eec4ecb09efb932f764dda1700f2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Feb 2015 15:18:10 +0300 Subject: [PATCH 67/94] ARMv7: bugfix, some disasm subroutines --- Utilities/StrFmt.h | 44 ++++++- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 183 +++++++++++++++++++-------- 3 files changed, 176 insertions(+), 53 deletions(-) diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 4015d5077b..bdc99a83af 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -177,6 +177,8 @@ namespace fmt std::string to_udec(u64 value); std::string to_sdec(s64 value); + std::string toupper(std::string source); + namespace detail { size_t get_fmt_start(const char* fmt, size_t len); @@ -198,6 +200,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -218,6 +224,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -238,6 +248,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -258,6 +272,10 @@ namespace fmt { return to_hex(arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u') { return to_udec(arg); @@ -278,6 +296,10 @@ namespace fmt { return to_hex((u8)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u8)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -298,6 +320,10 @@ namespace fmt { return to_hex((u16)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u16)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -318,6 +344,10 @@ namespace fmt { return to_hex((u32)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u32)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -338,6 +368,10 @@ namespace fmt { return to_hex((u64)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'd') { return to_sdec(arg); @@ -358,6 +392,10 @@ namespace fmt { return to_hex((u32&)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u32&)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'f') { return std::to_string(arg); @@ -378,6 +416,10 @@ namespace fmt { return to_hex((u64&)arg, get_fmt_precision(fmt, len)); } + else if (fmt[len - 1] == 'X') + { + return fmt::toupper(to_hex((u64&)arg, get_fmt_precision(fmt, len))); + } else if (fmt[len - 1] == 'f') { return std::to_string(arg); @@ -394,7 +436,7 @@ namespace fmt { static std::string text(const char* fmt, size_t len, bool arg) { - if (fmt[len - 1] == 'x') + if (fmt[len - 1] == 'x' || fmt[len - 1] == 'X') { return to_hex(arg, get_fmt_precision(fmt, len)); } diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 78c0ab0e43..f8ad2c8212 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -130,7 +130,7 @@ struct ARMv7Context u32 debug; // debug flags std::string debug_str; - ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(DF_DISASM | DF_PRINT) {} + ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(/*DF_DISASM | DF_PRINT*/ 0) {} void write_pc(u32 value); u32 read_pc(); diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 1d1add9481..836fd7ef33 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -390,7 +390,7 @@ namespace ARMv7_instrs case 13: return "sp"; case 14: return "lr"; case 15: return "pc"; - default: return "???"; + default: return "r???"; } } @@ -414,17 +414,90 @@ namespace ARMv7_instrs return{}; } + + std::string fmt_reg_list(u32 reg_list) + { + std::vector> lines; + + for (u32 i = 0; i < 13; i++) + { + if (reg_list & (1 << i)) + { + if (lines.size() && lines.rbegin()->second == i - 1) + { + lines.rbegin()->second = i; + } + else + { + lines.push_back({ i, i }); + } + } + } + + if (reg_list & 0x2000) lines.push_back({ 13, 13 }); // sp + if (reg_list & 0x4000) lines.push_back({ 14, 14 }); // lr + if (reg_list & 0x8000) lines.push_back({ 15, 15 }); // pc + + std::string result; + + if (reg_list >> 16) result = "???"; // invalid bits + + for (auto& line : lines) + { + if (!result.empty()) + { + result += ","; + } + + if (line.first == line.second) + { + result += fmt_reg(line.first); + } + else + { + result += fmt_reg(line.first); + result += '-'; + result += fmt_reg(line.second); + } + } + + return result; + } + + std::string fmt_mem_imm(u32 reg, u32 imm, bool index, bool add, bool wback) + { + if (index) + { + return fmt::format("[%s,#%s0x%X]%s", fmt_reg(reg), add ? "" : "-", imm, wback ? "!" : ""); + } + else + { + return fmt::format("[%s],#%s0x%X%s", fmt_reg(reg), add ? "" : "-", imm, wback ? "" : "???"); + } + } + + std::string fmt_mem_reg(u32 n, u32 m, bool index, bool add, bool wback, u32 shift_t = SRType_LSL, u32 shift_n = 0) + { + if (index) + { + return fmt::format("[%s,%s%s%s]%s", fmt_reg(n), add ? "" : "-", fmt_reg(m), fmt_shift(shift_t, shift_n), wback ? "!" : ""); + } + else + { + return fmt::format("[%s],%s%s%s%s", fmt_reg(n), add ? "" : "-", fmt_reg(m), fmt_shift(shift_t, shift_n), wback ? "" : "???"); + } + } } void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) { if (context.ISET == Thumb) { - throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); + throw fmt::format("Unknown/illegal opcode: 0x%04X 0x%04X", code.code1, code.code0); } else { - throw fmt::format("Unknown/illegal opcode: 0x%08x", code.data); + throw fmt::format("Unknown/illegal opcode: 0x%08X", code.data); } } @@ -536,7 +609,7 @@ void ARMv7_instrs::ADC_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adc%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -675,7 +748,7 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -826,7 +899,7 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,sp,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); if (process_debug(context)) return; } @@ -892,7 +965,7 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s (spr)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("add%s%s %s,sp,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(m), fmt_shift(shift_t, shift_n)); if (process_debug(context)) return; } @@ -958,7 +1031,7 @@ void ARMv7_instrs::ADR(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("adr%s r%d, 0x%08x", fmt_cond(cond), d, result); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("adr%s r%d, 0x%08X", fmt_cond(cond), d, result); if (process_debug(context)) return; } @@ -994,7 +1067,7 @@ void ARMv7_instrs::AND_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("and%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -1158,7 +1231,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("b%s 0x%08x", fmt_cond(cond), context.read_pc() + imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("b%s 0x%08X", fmt_cond(cond), context.read_pc() + imm32); if (process_debug(context)) return; } @@ -1212,7 +1285,7 @@ void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bic%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -1337,7 +1410,7 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("bl%s 0x%08x", fmt_cond(cond), pc); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("bl%s 0x%08X", fmt_cond(cond), pc); if (process_debug(context)) return; } @@ -1406,7 +1479,8 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ switch (type) { case T1: context.debug_str += fmt_reg((code.data >> 3) & 0xf); break; - case T2: context.debug_str += fmt::format("0x%08x", target); break; + case T2: context.debug_str += fmt::format("0x%08X", target); break; + case A1: context.debug_str += fmt_reg(code.data & 0xf); break; default: context.debug_str += "???"; } } @@ -1477,7 +1551,7 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("cb%sz 0x%08x", nonzero ? "n" : "", context.read_pc() + imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cb%sz 0x%08X", nonzero ? "n" : "", context.read_pc() + imm32); if (process_debug(context)) return; } @@ -1577,7 +1651,7 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("cmp%s %s,#0x%X", fmt_cond(cond), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -1901,7 +1975,7 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -1947,16 +2021,17 @@ void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const AR default: throw __FUNCTION__; } + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (lit)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s %s,0x%08X", fmt_cond(cond), fmt_reg(t), addr); if (process_debug(context)) return; } if (ConditionPassed(context, cond)) { - const u32 base = context.read_pc() & ~3; - const u32 addr = add ? base + imm32 : base - imm32; const u32 data = vm::psv::read32(addr); context.write_gpr(t, data); } @@ -2005,7 +2080,7 @@ void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldr%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -2080,7 +2155,7 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2149,7 +2224,7 @@ void ARMv7_instrs::LDRB_REG(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -2198,7 +2273,7 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s %s,%s,%s", fmt_cond(cond), fmt_reg(t), fmt_reg(t2), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2240,16 +2315,17 @@ void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const A default: throw __FUNCTION__; } + const u32 base = context.read_pc() & ~3; + const u32 addr = add ? base + imm32 : base - imm32; + if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s (lit)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrd%s %s,%s,0x%08X", fmt_cond(cond), fmt_reg(t), fmt_reg(t2), addr); if (process_debug(context)) return; } if (ConditionPassed(context, cond)) { - const u32 base = context.read_pc() & ~3; - const u32 addr = add ? base + imm32 : base - imm32; const u64 value = vm::psv::read64(addr); context.write_gpr(t, (u32)(value)); context.write_gpr(t2, (u32)(value >> 32)); @@ -2322,7 +2398,7 @@ void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrh%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrh%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2403,7 +2479,7 @@ void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrsb%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrsb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -2412,7 +2488,6 @@ void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 addr = index ? offset_addr : context.read_gpr(n); const s8 value = vm::psv::read8(addr); - context.write_gpr(t, value); // sign-extend if (wback) @@ -2491,7 +2566,7 @@ void ARMv7_instrs::LDREX(ARMv7Context& context, const ARMv7Code code, const ARMv if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrex%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldrex%s %s,[%s,#0x%X]", fmt_cond(cond), fmt_reg(t), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -2758,7 +2833,14 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("mov%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (context.debug & DF_DISASM) + { + switch (type) + { + case T3: case A2: context.debug_str = fmt::format("movw%s%s %s,#0x%04X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); break; + default: context.debug_str = fmt::format("mov%s%s %s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + } + } if (process_debug(context)) return; } @@ -2848,7 +2930,7 @@ void ARMv7_instrs::MOVT(ARMv7Context& context, const ARMv7Code code, const ARMv7 { cond = context.ITSTATE.advance(); d = (code.data & 0xf00) >> 8; - imm16 = (code.data & 0xf0000) >> 4 | (code.data & 0x4000000) >> 14 | (code.data & 0x7000) >> 4 | (code.data & 0xff); + imm16 = (code.data & 0xf0000) >> 4 | (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff); reject(d == 13 || d == 15, "UNPREDICTABLE"); break; @@ -2859,7 +2941,7 @@ void ARMv7_instrs::MOVT(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("movt%s %s,#0x%x", fmt_cond(cond), fmt_reg(d), imm16); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("movt%s %s,#0x%04X", fmt_cond(cond), fmt_reg(d), imm16); if (process_debug(context)) return; } @@ -2974,7 +3056,7 @@ void ARMv7_instrs::MVN_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("mvn%s%s %s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); if (process_debug(context)) return; } @@ -3135,7 +3217,7 @@ void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("orr%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -3281,7 +3363,7 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("pop%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("pop%s {%s}", fmt_cond(cond), fmt_reg_list(reg_list)); if (process_debug(context)) return; } @@ -3352,7 +3434,7 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("push%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("push%s {%s}", fmt_cond(cond), fmt_reg_list(reg_list)); if (process_debug(context)) return; } @@ -3639,7 +3721,7 @@ void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("rsb%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("rsb%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -4140,7 +4222,7 @@ void ARMv7_instrs::STR_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4199,7 +4281,7 @@ void ARMv7_instrs::STR_REG(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("str%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -4271,7 +4353,7 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4330,7 +4412,7 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strb%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -4378,7 +4460,7 @@ void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strd%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strd%s %s,%s,%s", fmt_cond(cond), fmt_reg(t), fmt_reg(t2), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4459,7 +4541,7 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (imm)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_imm(n, imm32, index, add, wback)); if (process_debug(context)) return; } @@ -4518,7 +4600,7 @@ void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const A if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s (reg)", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strh%s %s,%s", fmt_cond(cond), fmt_reg(t), fmt_mem_reg(n, m, index, add, wback, shift_t, shift_n)); if (process_debug(context)) return; } @@ -4527,7 +4609,6 @@ void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const A const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset; const u32 addr = index ? offset_addr : context.read_gpr(n); - vm::psv::write16(addr, (u16)context.read_gpr(t)); if (wback) @@ -4562,7 +4643,7 @@ void ARMv7_instrs::STREX(ARMv7Context& context, const ARMv7Code code, const ARMv if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("strex%s ()", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("strex%s %s,%s,[%s,#0x%x]", fmt_cond(cond), fmt_reg(d), fmt_reg(t), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -4659,7 +4740,7 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,#0x%x", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); if (process_debug(context)) return; } @@ -4716,7 +4797,7 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (reg)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,%s,%s%s", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), fmt_reg(m), fmt_shift(shift_t, shift_n)); if (process_debug(context)) return; } @@ -4788,7 +4869,7 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s (spi)", set_flags ? "s" : "", fmt_cond(cond)); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("sub%s%s %s,sp,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), imm32); if (process_debug(context)) return; } @@ -4943,7 +5024,7 @@ void ARMv7_instrs::TST_IMM(ARMv7Context& context, const ARMv7Code code, const AR if (context.debug) { - if (context.debug & DF_DISASM) context.debug_str = fmt::format("tst%s %s,#0x%x", fmt_cond(cond), fmt_reg(n), imm32); + if (context.debug & DF_DISASM) context.debug_str = fmt::format("tst%s %s,#0x%X", fmt_cond(cond), fmt_reg(n), imm32); if (process_debug(context)) return; } From 5983813d12d3630344ba24f9170989fcdf1fa051 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 5 Feb 2015 21:13:27 +0300 Subject: [PATCH 68/94] ARMv7: new instructions EOR_IMM, LDM, REV, STM --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 2 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 190 +++++++++++++++++++++++++-- 2 files changed, 177 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index 4ae428e985..70ccd9f240 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1281,7 +1281,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); - const u32 instr = vm::psv::read32(target); + const u32 instr = Memory.IsGoodAddr(target, 4) ? vm::psv::read32(target) : 0; // possibly a call to imported function: if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 836fd7ef33..dbe994c42b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -1574,7 +1574,7 @@ void ARMv7_instrs::CLZ(ARMv7Context& context, const ARMv7Code code, const ARMv7_ d = (code.data & 0xf00) >> 8; m = (code.data & 0xf); - reject((code.data & 0xf0000) >> 16 != m, "UNPREDICTABLE"); + reject(m != (code.data & 0xf0000) >> 16, "UNPREDICTABLE"); reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); break; } @@ -1772,11 +1772,45 @@ void ARMv7_instrs::DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_ void ARMv7_instrs::EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + bool set_flags, carry = context.APSR.C; + u32 cond, d, n, imm32; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + n = (code.data & 0xf0000) >> 16; + set_flags = (code.data & 0x100000); + imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry); + + reject(d == 15 && set_flags, "TEQ (immediate)"); + reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("eor%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + const u32 result = context.read_gpr(n) ^ imm32; + context.write_gpr(d, result); + + if (set_flags) + { + context.APSR.N = result >> 31; + context.APSR.Z = result == 0; + context.APSR.C = carry; + } + } } void ARMv7_instrs::EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -1855,7 +1889,7 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e reject(mask == 0, "Related encodings"); reject(first == 15, "UNPREDICTABLE"); - reject(first == 14 && BitCount(mask) != 1, "UNPREDICTABLE"); + reject(first == 14 && BitCount(mask, 4) != 1, "UNPREDICTABLE"); reject(context.ITSTATE, "UNPREDICTABLE"); context.ITSTATE.IT = code.data & 0xff; @@ -1874,11 +1908,61 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e void ARMv7_instrs::LDM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, n, reg_list; + bool wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0x700) >> 8; + reg_list = (code.data & 0xff); + wback = !(reg_list & (1 << n)); + + reject(reg_list == 0, "UNPREDICTABLE"); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0xf0000) >> 16; + reg_list = (code.data & 0xdfff); + wback = (code.data & 0x200000); + + reject(wback && n == 13, "POP"); + reject(n == 15 || BitCount(reg_list, 16) < 2 || reg_list >= 0xc000, "UNPREDICTABLE"); + reject(reg_list & 0x8000 && context.ITSTATE, "UNPREDICTABLE"); + reject(wback && reg_list & (1 << n), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldm%s %s%s,{%s}", fmt_cond(cond), fmt_reg(n), wback ? "!" : "", fmt_reg_list(reg_list)); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + auto memory = vm::psv::ptr::make(context.read_gpr(n)); + + for (u32 i = 0; i < 16; i++) + { + if (reg_list & (1 << i)) + { + context.write_gpr(i, *memory++); + } + } + + if (wback) + { + context.write_gpr(n, memory.addr()); + } + } } void ARMv7_instrs::LDMDA(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -3369,17 +3453,17 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (ConditionPassed(context, cond)) { - u32 written = 0; - for (u16 mask = 1, i = 0; mask; mask <<= 1, i++) + auto stack = vm::psv::ptr::make(context.SP); + + for (u32 i = 0; i < 16; i++) { - if (reg_list & mask) + if (reg_list & (1 << i)) { - context.write_gpr(i, vm::psv::read32(context.SP + written)); - written += 4; + context.write_gpr(i, *stack++); } } - context.SP += written; + context.SP = stack.addr(); } } @@ -3440,17 +3524,17 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (ConditionPassed(context, cond)) { - u32 read = 0; - for (u16 mask = 1 << 15, i = 15; mask; mask >>= 1, i--) + auto memory = vm::psv::ptr::make(context.SP); + + for (u32 i = 15; ~i; i--) { - if (reg_list & mask) + if (reg_list & (1 << i)) { - read += 4; - vm::psv::write32(context.SP - read, context.read_gpr(i)); + *--memory = context.read_gpr(i); } } - context.SP -= read; + context.SP = memory.addr(); } } @@ -3557,11 +3641,41 @@ void ARMv7_instrs::RBIT(ARMv7Context& context, const ARMv7Code code, const ARMv7 void ARMv7_instrs::REV(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, d, m; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0x7); + m = (code.data & 0x38) >> 3; + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + d = (code.data & 0xf00) >> 8; + m = (code.data & 0xf); + + reject(m != (code.data & 0xf0000) >> 16, "UNPREDICTABLE"); + reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("rev%s %s,%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m)); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + context.write_gpr(d, re32(context.read_gpr(m))); + } } void ARMv7_instrs::REV16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -4122,11 +4236,59 @@ void ARMv7_instrs::SSUB8(ARMv7Context& context, const ARMv7Code code, const ARMv void ARMv7_instrs::STM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, n, reg_list; + bool wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0x700) >> 8; + reg_list = (code.data & 0xff); + wback = true; + + reject(reg_list == 0, "UNPREDICTABLE"); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + n = (code.data & 0xf0000) >> 16; + reg_list = (code.data & 0x5fff); + wback = (code.data & 0x200000); + + reject(n == 15 || BitCount(reg_list, 16) < 2, "UNPREDICTABLE"); + reject(wback && reg_list & (1 << n), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (context.debug) + { + if (context.debug & DF_DISASM) context.debug_str = fmt::format("stm%s %s%s,{%s}", fmt_cond(cond), fmt_reg(n), wback ? "!" : "", fmt_reg_list(reg_list)); + if (process_debug(context)) return; + } + + if (ConditionPassed(context, cond)) + { + auto memory = vm::psv::ptr::make(context.read_gpr(n)); + + for (u32 i = 0; i < 16; i++) + { + if (reg_list & (1 << i)) + { + *memory++ = context.read_gpr(i); + } + } + + if (wback) + { + context.write_gpr(n, memory.addr()); + } + } } void ARMv7_instrs::STMDA(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) From c1c586a072a0180430949d6c16a052f80e8a53d5 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 6 Feb 2015 03:23:37 +0300 Subject: [PATCH 69/94] Some drafts --- rpcs3/Emu/ARMv7/Modules/psv_cond.cpp | 13 +++++++++++++ rpcs3/Emu/ARMv7/Modules/psv_cond.h | 24 ++++++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp | 13 +++++++++++++ rpcs3/Emu/ARMv7/Modules/psv_mutex.h | 24 ++++++++++++++++++++++++ rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 18 ++++++++++++++++-- rpcs3/Emu/ARMv7/Modules/scePerf.cpp | 5 +++++ rpcs3/Emu/ARMv7/PSVObjectList.cpp | 6 ++++++ rpcs3/emucore.vcxproj | 4 ++++ rpcs3/emucore.vcxproj.filters | 24 ++++++++++++++++++------ 9 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_cond.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_cond.h create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp create mode 100644 rpcs3/Emu/ARMv7/Modules/psv_mutex.h diff --git a/rpcs3/Emu/ARMv7/Modules/psv_cond.cpp b/rpcs3/Emu/ARMv7/Modules/psv_cond.cpp new file mode 100644 index 0000000000..c89511b19d --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_cond.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_cond.h" + +psv_cond_t::psv_cond_t(const char* name, u32 attr, s32 mutexId) + : attr(attr) + , mutexId(mutexId) +{ + strcpy_trunc(this->name, name); +} diff --git a/rpcs3/Emu/ARMv7/Modules/psv_cond.h b/rpcs3/Emu/ARMv7/Modules/psv_cond.h new file mode 100644 index 0000000000..cd8c518615 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_cond.h @@ -0,0 +1,24 @@ +#pragma once + +struct psv_cond_t +{ + char name[32]; + u32 attr; + s32 mutexId; + +private: + psv_cond_t() = delete; + psv_cond_t(const psv_cond_t&) = delete; + psv_cond_t(psv_cond_t&&) = delete; + + psv_cond_t& operator =(const psv_cond_t&) = delete; + psv_cond_t& operator =(psv_cond_t&&) = delete; + +public: + psv_cond_t(const char* name, u32 attr, s32 mutexId); + void on_init(s32 id) {} + void on_stop() {} + +}; + +extern psv_object_list_t g_psv_cond_list; diff --git a/rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp b/rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp new file mode 100644 index 0000000000..7733ad54ea --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "Emu/Memory/Memory.h" +#include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/ARMv7/PSVObjectList.h" +#include "sceLibKernel.h" +#include "psv_mutex.h" + +psv_mutex_t::psv_mutex_t(const char* name, u32 attr, s32 count) + : attr(attr) + , count(count) +{ + strcpy_trunc(this->name, name); +} diff --git a/rpcs3/Emu/ARMv7/Modules/psv_mutex.h b/rpcs3/Emu/ARMv7/Modules/psv_mutex.h new file mode 100644 index 0000000000..5da6ad4590 --- /dev/null +++ b/rpcs3/Emu/ARMv7/Modules/psv_mutex.h @@ -0,0 +1,24 @@ +#pragma once + +struct psv_mutex_t +{ + char name[32]; + u32 attr; + s32 count; + +private: + psv_mutex_t() = delete; + psv_mutex_t(const psv_mutex_t&) = delete; + psv_mutex_t(psv_mutex_t&&) = delete; + + psv_mutex_t& operator =(const psv_mutex_t&) = delete; + psv_mutex_t& operator =(psv_mutex_t&&) = delete; + +public: + psv_mutex_t(const char* name, u32 attr, s32 count); + void on_init(s32 id) {} + void on_stop() {} + +}; + +extern psv_object_list_t g_psv_mutex_list; diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index d7bd58c79a..016917d6de 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -10,6 +10,8 @@ #include "sceLibKernel.h" #include "psv_sema.h" #include "psv_event_flag.h" +#include "psv_mutex.h" +#include "psv_cond.h" #define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; } @@ -522,7 +524,13 @@ s32 sceKernelGetSemaInfo(s32 semaId, vm::psv::ptr pInfo) s32 sceKernelCreateMutex(vm::psv::ptr pName, u32 attr, s32 initCount, vm::psv::ptr pOptParam) { - throw __FUNCTION__; + sceLibKernel.Error("sceKernelCreateMutex(pName=0x%x, attr=0x%x, initCount=%d, pOptParam=0x%x)", pName, attr, initCount, pOptParam); + + std::shared_ptr mutex(new psv_mutex_t(pName.get_ptr(), attr, initCount)); + + const s32 id = g_psv_mutex_list.add(mutex); + + return id; } s32 sceKernelDeleteMutex(s32 mutexId) @@ -616,7 +624,13 @@ s32 sceKernelGetLwMutexInfoById(s32 lwMutexId, vm::psv::ptr pName, u32 attr, s32 mutexId, vm::psv::ptr pOptParam) { - throw __FUNCTION__; + sceLibKernel.Error("sceKernelCreateCond(pName=0x%x, attr=0x%x, mutexId=0x%x, pOptParam=0x%x)", pName, attr, mutexId, pOptParam); + + std::shared_ptr cond(new psv_cond_t(pName.get_ptr(), attr, mutexId)); + + const s32 id = g_psv_cond_list.add(cond); + + return id; } s32 sceKernelDeleteCond(s32 condId) diff --git a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp index e7939506bc..fabf63691a 100644 --- a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp +++ b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp @@ -134,6 +134,11 @@ s32 scePerfArmPmonSelectEvent(ARMv7Context& context, s32 threadId, u32 counter, case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT: case SCE_PERF_ARM_PMON_DCACHE_MISS: + case SCE_PERF_ARM_PMON_DCACHE_STALL: + case SCE_PERF_ARM_PMON_ICACHE_STALL: + case SCE_PERF_ARM_PMON_DATA_EVICTION: + case SCE_PERF_ARM_PMON_WRITE_STALL: + case SCE_PERF_ARM_PMON_MAINTLB_STALL: case SCE_PERF_ARM_PMON_UNALIGNED: { value = 1; // these events will probably never be implemented diff --git a/rpcs3/Emu/ARMv7/PSVObjectList.cpp b/rpcs3/Emu/ARMv7/PSVObjectList.cpp index cc8e97a1c0..5e89e15c73 100644 --- a/rpcs3/Emu/ARMv7/PSVObjectList.cpp +++ b/rpcs3/Emu/ARMv7/PSVObjectList.cpp @@ -5,12 +5,18 @@ #include "Modules/sceLibKernel.h" #include "Modules/psv_sema.h" #include "Modules/psv_event_flag.h" +#include "Modules/psv_mutex.h" +#include "Modules/psv_cond.h" psv_object_list_t g_psv_sema_list; psv_object_list_t g_psv_ef_list; +psv_object_list_t g_psv_mutex_list; +psv_object_list_t g_psv_cond_list; void clear_all_psv_objects() { g_psv_sema_list.clear(); g_psv_ef_list.clear(); + g_psv_mutex_list.clear(); + g_psv_cond_list.clear(); } diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index daed4a06ea..5327e220e3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -56,7 +56,9 @@ + + @@ -334,7 +336,9 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 0720c265c4..ea11ba34b9 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -583,7 +583,7 @@ Emu\GPU\RSX - + Emu\GPU\RSX @@ -670,7 +670,7 @@ Emu\CPU\ARMv7 - + Emu\CPU\ARMv7 @@ -696,7 +696,7 @@ Emu\CPU\ARMv7\Modules - Emu\CPU\ARMv7\Modules + Emu\CPU\ARMv7\Modules Emu\CPU\ARMv7\Modules @@ -848,6 +848,12 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Objects + @@ -1350,7 +1356,7 @@ Emu\GPU\RSX - + Emu\GPU\RSX @@ -1479,7 +1485,7 @@ Emu\CPU\ARMv7\Modules - + Emu\CPU\ARMv7 @@ -1490,7 +1496,7 @@ Emu\CPU\ARMv7\Objects - Emu\CPU\ARMv7\Modules + Emu\CPU\ARMv7\Modules Emu\CPU\ARMv7\Modules @@ -1510,5 +1516,11 @@ Emu\CPU\ARMv7\Modules + + Emu\CPU\ARMv7\Objects + + + Emu\CPU\ARMv7\Objects + \ No newline at end of file From 1af4848324fa887ba4e58ea56cbaad3eddbfcb7c Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 02:39:51 +0300 Subject: [PATCH 70/94] New reservations (not finished) --- Utilities/Thread.cpp | 32 ++++- rpcs3/Emu/ARMv7/ARMv7Context.h | 3 - rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 14 +- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 2 +- rpcs3/Emu/Cell/PPUInterpreter.h | 66 +++------ rpcs3/Emu/Cell/PPUThread.h | 5 - rpcs3/Emu/Cell/SPUThread.cpp | 103 ++------------ rpcs3/Emu/Cell/SPUThread.h | 3 - rpcs3/Emu/Memory/Memory.cpp | 13 +- rpcs3/Emu/Memory/vm.cpp | 192 +++++++++++++++++++++++++-- rpcs3/Emu/Memory/vm.h | 24 ++++ 11 files changed, 279 insertions(+), 178 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 2539c791cd..b85b96691a 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -215,7 +215,8 @@ static const reg_table_t reg_table[17] = bool handle_access_violation(const u32 addr, x64_context* context) { - if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers + // check if address is RawSPU MMIO register + if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) { // one x64 instruction is manually decoded and interpreted x64_op_t op; @@ -277,6 +278,12 @@ bool handle_access_violation(const u32 addr, x64_context* context) return true; } + // check if fault is caused by reservation + if (vm::reservation_query(addr)) + { + return true; + } + // TODO: allow recovering from a page fault as a feature of PS3 virtual memory return false; } @@ -303,6 +310,24 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) // else some fatal error (should crash) } +extern LPTOP_LEVEL_EXCEPTION_FILTER filter_set; + +LONG __stdcall exception_filter(_EXCEPTION_POINTERS* pExp) +{ + _se_translator(pExp->ExceptionRecord->ExceptionCode, pExp); + + if (filter_set) + { + return filter_set(pExp); + } + else + { + return EXCEPTION_CONTINUE_SEARCH; + } +} + +LPTOP_LEVEL_EXCEPTION_FILTER filter_set = SetUnhandledExceptionFilter(exception_filter); + #else void signal_handler(int sig, siginfo_t* info, void* uct) @@ -352,6 +377,11 @@ void SetCurrentNamedThread(NamedThreadBase* value) return; } + if (old_value) + { + vm::reservation_free(); + } + if (value && value->m_tls_assigned.exchange(true)) { LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName()); diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index f8ad2c8212..9200cd5752 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -114,9 +114,6 @@ struct ARMv7Context u32 TLS; - u32 R_ADDR; - u64 R_DATA; - struct perf_counter { u32 event; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index dbe994c42b..e07bbaa00b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -2657,10 +2657,11 @@ void ARMv7_instrs::LDREX(ARMv7Context& context, const ARMv7Code code, const ARMv if (ConditionPassed(context, cond)) { const u32 addr = context.read_gpr(n) + imm32; - const u32 value = vm::psv::read32(addr); - context.write_gpr(t, value); - context.R_ADDR = addr; - context.R_DATA = value; + + u32 value; + vm::reservation_acquire(&value, addr, sizeof(value)); + + context.write_gpr(t, value); } } @@ -4813,10 +4814,7 @@ void ARMv7_instrs::STREX(ARMv7Context& context, const ARMv7Code code, const ARMv { const u32 addr = context.read_gpr(n) + imm32; const u32 value = context.read_gpr(t); - - auto& sync_obj = vm::get_ref>(addr); - context.write_gpr(d, addr != context.R_ADDR || sync_obj.compare_and_swap((u32)context.R_DATA, value) != context.R_DATA); - context.R_ADDR = 0; + context.write_gpr(d, !vm::reservation_update(addr, &value, sizeof(value))); } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 12b7c7b0b3..0a57e4abcf 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -118,7 +118,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; + context.debug |= DF_DISASM | DF_PRINT; } void ARMv7Thread::InitStack() diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 201385e827..be1611bf78 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2500,39 +2500,16 @@ private: } void MFOCRF(u32 a, u32 rd, u32 crm) { - /* - if(a) - { - u32 n = 0, count = 0; - for(u32 i = 0; i < 8; ++i) - { - if(crm & (1 << i)) - { - n = i; - count++; - } - } - - if(count == 1) - { - //RD[32+4*n : 32+4*n+3] = CR[4*n : 4*n+3]; - u8 offset = n * 4; - CPU.GPR[rd] = (CPU.GPR[rd] & ~(0xf << offset)) | ((u32)CPU.GetCR(7 - n) << offset); - } - else - CPU.GPR[rd] = 0; - } - else - { - */ CPU.GPR[rd] = CPU.CR.CR; - //} } void LWARX(u32 rd, u32 ra, u32 rb) { - CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.R_VALUE = vm::get_ref(vm::cast(CPU.R_ADDR)); - CPU.GPR[rd] = re32((u32)CPU.R_VALUE); + const u32 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + + be_t value; + vm::reservation_acquire(&value, vm::cast(addr), sizeof(value)); + + CPU.GPR[rd] = value; } void LDX(u32 rd, u32 ra, u32 rb) { @@ -2682,9 +2659,12 @@ private: } void LDARX(u32 rd, u32 ra, u32 rb) { - CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.R_VALUE = vm::get_ref(vm::cast(CPU.R_ADDR)); - CPU.GPR[rd] = re64(CPU.R_VALUE); + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + + be_t value; + vm::reservation_acquire(&value, vm::cast(addr), sizeof(value)); + + CPU.GPR[rd] = value; } void DCBF(u32 ra, u32 rb) { @@ -2800,15 +2780,8 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - if (CPU.R_ADDR == addr) - { - CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr(vm::cast(CPU.R_ADDR)), re32((u32)CPU.GPR[rs]), (u32)CPU.R_VALUE) == (u32)CPU.R_VALUE); - } - else - { - CPU.SetCR_EQ(0, false); - } - CPU.R_ADDR = 0; + const be_t value = be_t::make((u32)CPU.GPR[rs]); + CPU.SetCR_EQ(0, vm::reservation_update(vm::cast(addr), &value, sizeof(value))); } void STWX(u32 rs, u32 ra, u32 rb) { @@ -2859,15 +2832,8 @@ private: { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - if (CPU.R_ADDR == addr) - { - CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr(vm::cast(CPU.R_ADDR)), re64(CPU.GPR[rs]), CPU.R_VALUE) == CPU.R_VALUE); - } - else - { - CPU.SetCR_EQ(0, false); - } - CPU.R_ADDR = 0; + const be_t value = be_t::make(CPU.GPR[rs]); + CPU.SetCR_EQ(0, vm::reservation_update(vm::cast(addr), &value, sizeof(value))); } void STBX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 820b244c2b..834200b1ae 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -536,11 +536,6 @@ public: //TBR : Time-Base Registers u64 TB; //TBR 0x10C - 0x10D - u64 cycle; - - u64 R_ADDR; // reservation address - u64 R_VALUE; // reservation value (BE) - u32 owned_mutexes; std::function custom_task; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index f5faf9fff1..71033cbd9d 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -99,8 +99,6 @@ void SPUThread::InitRegs() m_event_mask = 0; m_events = 0; - - R_ADDR = 0; } void SPUThread::InitStack() @@ -437,103 +435,37 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) if (op == MFC_GETLLAR_CMD) // get reservation { - if (R_ADDR) - { - m_events |= SPU_EVENT_LR; - } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack - R_ADDR = ea; - for (u32 i = 0; i < 16; i++) + vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]() { - R_DATA[i] = vm::get_ptr((u32)R_ADDR)[i]; - vm::get_ptr(ls_offset + lsa)[i] = R_DATA[i]; - } + m_events |= SPU_EVENT_LR; // TODO: atomic op + Notify(); + }); + MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); } else if (op == MFC_PUTLLC_CMD) // store conditional { - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); - - if (R_ADDR == ea) + if (vm::reservation_update(ea, vm::get_ptr(ls_offset + lsa), 128)) { - u32 changed = 0, mask = 0; - u64 buf[16]; - for (u32 i = 0; i < 16; i++) - { - buf[i] = vm::get_ptr(ls_offset + lsa)[i]; - if (buf[i] != R_DATA[i]) - { - changed++; - mask |= (0x3 << (i * 2)); - if (vm::get_ptr((u32)R_ADDR)[i] != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - R_ADDR = 0; - return; - } - } - } - - for (u32 i = 0; i < 16; i++) - { - if (buf[i] != R_DATA[i]) - { - if (InterlockedCompareExchange(&vm::get_ptr((u32)R_ADDR)[i], buf[i], R_DATA[i]) != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); - - if (changed > 1) - { - LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - Emu.Pause(); - } - - break; - } - } - } - - if (changed > 1) - { - LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", - changed, mask, op, cmd, lsa, ea, tag, size); - - SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); - for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4) - { - dis_asm.dump_pc = i; - dis_asm.offset = vm::get_ptr(ls_offset); - const u32 opcode = vm::read32(i + ls_offset); - (*SPU_instr::rrr_list)(&dis_asm, opcode); - if (i >= 0 && i < 0x40000) - { - LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str()); - } - } - } + MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS); } else { MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); } - R_ADDR = 0; } - else // store unconditional + else // store unconditional (may be wrong) { - if (R_ADDR) // may be wrong - { - m_events |= SPU_EVENT_LR; - } + vm::reservation_break(ea); ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + if (op == MFC_PUTLLUC_CMD) { MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); } - R_ADDR = 0; } break; } @@ -548,19 +480,6 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) bool SPUThread::CheckEvents() { // checks events: - // SPU_EVENT_LR: - if (R_ADDR) - { - for (u32 i = 0; i < 16; i++) - { - if (vm::get_ptr((u32)R_ADDR)[i] != R_DATA[i]) - { - m_events |= SPU_EVENT_LR; - R_ADDR = 0; - break; - } - } - } return (m_events & m_event_mask) != 0; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index c2e2cc2f03..bab5f1aa2d 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -277,9 +277,6 @@ public: u32 SRR0; SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2) - u64 R_ADDR; // reservation address - u64 R_DATA[16]; // lock line data (BE) - std::shared_ptr SPUPs[64]; // SPU Thread Event Ports EventManager SPUQs; // SPU Queue Mapping std::shared_ptr group; // associated SPU Thread Group (null for raw spu) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 502694ff93..b892bff2b8 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -231,9 +231,11 @@ bool MemoryBase::Unmap(const u64 addr) MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) : MemInfo(_addr, PAGE_4K(_size)) { - void* real_addr = (void*)((u64)Memory.GetBaseAddr() + _addr); + void* real_addr = vm::get_ptr(vm::cast(_addr)); #ifdef _WIN32 - mem = VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE); + void* priv_addr = vm::get_priv_ptr(vm::cast(_addr)); + void* priv_mem = VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE); + mem = priv_mem == priv_addr ? VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE) : priv_mem; #else if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) { @@ -262,7 +264,10 @@ void MemBlockInfo::Free() { Memory.UnregisterPages(addr, size); #ifdef _WIN32 - if (!VirtualFree(mem, size, MEM_DECOMMIT)) + DWORD old; + + if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) + //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else if (::mprotect(mem, size, PROT_NONE)) #endif @@ -715,4 +720,4 @@ bool VirtualMemoryBlock::Unreserve(u32 size) u32 VirtualMemoryBlock::GetReservedAmount() { return m_reserve_size; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 9a5f9eec9e..a32d176b2e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -1,24 +1,194 @@ #include "stdafx.h" +#include "Utilities/Log.h" #include "Memory.h" +#include "Emu/System.h" #include "Emu/CPU/CPUThread.h" #include "Emu/Cell/PPUThread.h" #include "Emu/ARMv7/ARMv7Thread.h" +#include "Emu/SysCalls/lv2/sys_time.h" + +#ifdef _WIN32 +#include +#else +#include + +/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif +#endif + namespace vm { - #ifdef _WIN32 - #include - void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); - #else - #include +#ifdef _WIN32 + HANDLE g_memory_handle; +#endif - /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ - #ifndef MAP_ANONYMOUS - #define MAP_ANONYMOUS MAP_ANON - #endif + void* g_priv_addr; - void* const g_base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - #endif + void* initialize() + { +#ifdef _WIN32 + g_memory_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0x1, 0x0, NULL); + + void* base_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // main memory + g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access + + return base_addr; + //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); +#else + return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +#endif + } + + void finalize() + { +#ifdef _WIN32 + UnmapViewOfFile(g_base_addr); + UnmapViewOfFile(g_priv_addr); + CloseHandle(g_memory_handle); +#else + munmap(g_base_addr, 0x100000000); +#endif + } + + void* const g_base_addr = (atexit(finalize), initialize()); + + void* g_reservation_owner = nullptr; + u32 g_reservation_addr = 0; + + std::function g_reservation_cb = nullptr; + + // break the reservation, return true if it was successfully broken + bool reservation_break(u32 addr) + { + LV2_LOCK(0); + + if (g_reservation_addr >> 12 == addr >> 12) + { + const auto stamp0 = get_time(); + +#ifdef _WIN32 + if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) +#else + +#endif + { + throw fmt::format("vm::reservation_break() failed (addr=0x%x)", addr); + } + + //LOG_NOTICE(MEMORY, "VirtualAlloc: %f us", (get_time() - stamp0) / 80.f); + + if (g_reservation_cb) + { + g_reservation_cb(); + g_reservation_cb = nullptr; + } + + g_reservation_owner = nullptr; + g_reservation_addr = 0; + + return true; + } + + return false; + } + + // read memory and reserve it for further atomic update, return true if the previous reservation was broken + bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback) + { + const auto stamp0 = get_time(); + + bool broken = false; + + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + { + LV2_LOCK(0); + + // break previous reservation + if (g_reservation_addr) + { + broken = reservation_break(g_reservation_addr); + } + + // change memory protection to read-only +#ifdef _WIN32 + DWORD old; + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) +#else + +#endif + { + throw fmt::format("vm::reservation_acquire() failed (addr=0x%x, size=%d)", addr, size); + } + + //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); + + // set the new reservation + g_reservation_addr = addr; + g_reservation_owner = GetCurrentNamedThread(); + g_reservation_cb = callback; + + // copy data + memcpy(data, vm::get_ptr(addr), size); + } + + return broken; + } + + // attempt to atomically update reserved memory + bool reservation_update(u32 addr, const void* data, u32 size) + { + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + LV2_LOCK(0); + + if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) + { + // atomic update failed + return false; + } + + // update memory using privileged access + memcpy(vm::get_priv_ptr(addr), data, size); + + // free the reservation and restore memory protection + reservation_break(addr); + + // atomic update succeeded + return true; + } + + // for internal use + bool reservation_query(u32 addr) + { + LV2_LOCK(0); + + if (!Memory.IsGoodAddr(addr)) + { + return false; + } + + // break the reservation + reservation_break(addr); + + return true; + } + + // for internal use + void reservation_free() + { + LV2_LOCK(0); + + if (g_reservation_owner == GetCurrentNamedThread()) + { + reservation_break(g_reservation_addr); + } + } bool check_addr(u32 addr) { diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 7cc958c3ba..32bcf17859 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -21,7 +21,19 @@ namespace vm static void set_stack_size(u32 size) {} static void initialize_stack() {} +#ifdef _WIN32 + extern HANDLE g_memory_handle; +#endif + + extern void* g_priv_addr; extern void* const g_base_addr; + + bool reservation_break(u32 addr); + bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback = nullptr); + bool reservation_update(u32 addr, const void* data, u32 size); + bool reservation_query(u32 addr); + void reservation_free(); + bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); u32 alloc(u32 size, memory_location location = user_space); @@ -40,6 +52,18 @@ namespace vm return *get_ptr(addr); } + template + T* const get_priv_ptr(u32 addr) + { + return reinterpret_cast(static_cast(g_priv_addr) + addr); + } + + template + T& get_priv_ref(u32 addr) + { + return *get_priv_ptr(addr); + } + u32 get_addr(const void* real_pointer); __noinline void error(const u64 addr, const char* func); From 39db6bb4615d03a704aa283c9077d69da0639a6d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 16:46:42 +0300 Subject: [PATCH 71/94] Reservations improved --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 204 ++++++++++--------- rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp | 15 -- rpcs3/Emu/Cell/SPUThread.cpp | 12 +- rpcs3/Emu/Memory/Memory.cpp | 22 +- rpcs3/Emu/Memory/vm.cpp | 190 +++++++++++++---- rpcs3/Emu/Memory/vm.h | 7 +- rpcs3/Emu/Memory/vm_ptr.h | 15 ++ rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp | 11 +- rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 2 +- 9 files changed, 308 insertions(+), 170 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 5678d5f9d9..99203e1864 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -2463,25 +2463,27 @@ void Compiler::MFOCRF(u32 a, u32 rd, u32 crm) { } void Compiler::LWARX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); - auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false); - auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + //auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false); + //auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); - resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32); - resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); - SetGpr(rd, resv_val_i64); + //resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32); + //resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); + //SetGpr(rd, resv_val_i64); } void Compiler::LDX(u32 rd, u32 ra, u32 rb) { @@ -2739,23 +2741,25 @@ void Compiler::MULHW(u32 rd, u32 ra, u32 rb, bool rc) { } void Compiler::LDARX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); - resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64); - SetGpr(rd, resv_val_i64); + //auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + + //resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64); + //SetGpr(rd, resv_val_i64); } void Compiler::DCBF(u32 ra, u32 rb) { @@ -2919,45 +2923,47 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) { } void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); - auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); - auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); - auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); - m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); + //auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); - m_ir_builder->SetInsertPoint(then_bb); - auto rs_i32 = GetGpr(rs, 32); - rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32); - resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); - auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); - auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8); + //auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); + //auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); + //auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); + //m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); - auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); - auto cr_i32 = GetCr(); - cr_i32 = SetBit(cr_i32, 2, success_i1); - SetCr(cr_i32); - m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); - m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(then_bb); + //auto rs_i32 = GetGpr(rs, 32); + //rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32); + //resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + //auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + //auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8); - m_ir_builder->SetInsertPoint(else_bb); - cr_i32 = GetCr(); - cr_i32 = ClrBit(cr_i32, 2); - SetCr(cr_i32); - m_ir_builder->CreateBr(merge_bb); - m_ir_builder->SetInsertPoint(merge_bb); + //auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); + //auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + //auto cr_i32 = GetCr(); + //cr_i32 = SetBit(cr_i32, 2, success_i1); + //SetCr(cr_i32); + //m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); + //m_ir_builder->CreateBr(merge_bb); + + //m_ir_builder->SetInsertPoint(else_bb); + //cr_i32 = GetCr(); + //cr_i32 = ClrBit(cr_i32, 2); + //SetCr(cr_i32); + //m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(merge_bb); } void Compiler::STWX(u32 rs, u32 ra, u32 rb) { @@ -3060,45 +3066,47 @@ void Compiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { } void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); - auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); - auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); - auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); - m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); + //auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); - m_ir_builder->SetInsertPoint(then_bb); - auto rs_i64 = GetGpr(rs, 64); - rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64); - resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); - auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8); + //auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); + //auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); + //auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); + //m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); - auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); - auto cr_i32 = GetCr(); - cr_i32 = SetBit(cr_i32, 2, success_i1); - SetCr(cr_i32); - m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); - m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(then_bb); + //auto rs_i64 = GetGpr(rs, 64); + //rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64); + //resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + //auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8); - m_ir_builder->SetInsertPoint(else_bb); - cr_i32 = GetCr(); - cr_i32 = ClrBit(cr_i32, 2); - SetCr(cr_i32); - m_ir_builder->CreateBr(merge_bb); - m_ir_builder->SetInsertPoint(merge_bb); + //auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); + //auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + //auto cr_i32 = GetCr(); + //cr_i32 = SetBit(cr_i32, 2, success_i1); + //SetCr(cr_i32); + //m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); + //m_ir_builder->CreateBr(merge_bb); + + //m_ir_builder->SetInsertPoint(else_bb); + //cr_i32 = GetCr(); + //cr_i32 = ClrBit(cr_i32, 2); + //SetCr(cr_i32); + //m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(merge_bb); } void Compiler::STBX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index f30a713c09..e1054ecc89 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -59,10 +59,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp /// Time base register u64 TB; - /// Reservations - u64 R_ADDR; - u64 R_VALUE; - /// Memory block u32 address; u64 mem_block[64]; @@ -86,9 +82,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp CTR = ppu.CTR; TB = ppu.TB; - R_ADDR = ppu.R_ADDR; - R_VALUE = ppu.R_VALUE; - address = addr; for (int i = 0; i < (sizeof(mem_block) / 8); i++) { mem_block[i] = vm::read64(address + (i * 8)); @@ -114,9 +107,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp ppu.CTR = CTR; ppu.TB = TB; - ppu.R_ADDR = R_ADDR; - ppu.R_VALUE = R_VALUE; - for (int i = 0; i < (sizeof(mem_block) / 8); i++) { vm::write64(address + (i * 8), mem_block[i]); } @@ -151,8 +141,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp LR = rng(); CTR = rng(); TB = rng(); - R_ADDR = rng(); - R_VALUE = rng(); address = addr; for (int i = 0; i < (sizeof(mem_block) / 8); i++) { @@ -187,7 +175,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp // fmt::by_value(FPSCR.VXZDZ), fmt::by_value(FPSCR.VXIDI), fmt::by_value(FPSCR.VXISI), fmt::by_value(FPSCR.VXSNAN), // fmt::by_value(FPSCR.XX), fmt::by_value(FPSCR.ZX), fmt::by_value(FPSCR.UX), fmt::by_value(FPSCR.OX), fmt::by_value(FPSCR.VX), fmt::by_value(FPSCR.FEX), fmt::by_value(FPSCR.FX)); //ret += fmt::Format("VSCR = 0x%08x [NJ=%d | SAT=%d]\n", VSCR.VSCR, fmt::by_value(VSCR.NJ), fmt::by_value(VSCR.SAT)); // TODO: Uncomment after implementing VSCR.SAT - ret += fmt::Format("R_ADDR = 0x%016llx R_VALUE = 0x%016llx\n", R_ADDR, R_VALUE); for (int i = 0; i < (sizeof(mem_block) / 8); i += 2) { ret += fmt::Format("mem_block[%d] = 0x%016llx mem_block[%d] = 0x%016llx\n", i, mem_block[i], i + 1, mem_block[i + 1]); @@ -724,8 +711,6 @@ void Compiler::RunAllTests() { input.GPR[14] = 10; input.GPR[21] = 15; input.GPR[23] = 0x10000; - input.R_ADDR = 0x10000; - input.R_VALUE = 0x1122334455667788; input.mem_block[0] = 0x8877665544332211; VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 71033cbd9d..2bd0e0f629 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -435,10 +435,20 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) if (op == MFC_GETLLAR_CMD) // get reservation { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]() { + //std::shared_ptr t = Emu.GetCPU().GetThread(tid); + + //if (t && (t->GetType() == CPU_THREAD_SPU || t->GetType() == CPU_THREAD_RAW_SPU)) + //{ + // SPUThread& spu = static_cast(*t); + + // spu.m_events |= SPU_EVENT_LR; // TODO: atomic op + // spu.Notify(); + //} + m_events |= SPU_EVENT_LR; // TODO: atomic op Notify(); }); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index b892bff2b8..ecd4961d82 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -232,21 +232,13 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) : MemInfo(_addr, PAGE_4K(_size)) { void* real_addr = vm::get_ptr(vm::cast(_addr)); -#ifdef _WIN32 void* priv_addr = vm::get_priv_ptr(vm::cast(_addr)); - void* priv_mem = VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE); - mem = priv_mem == priv_addr ? VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE) : priv_mem; + +#ifdef _WIN32 + if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE)) #else - if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) - { - mem = nullptr; - } - else - { - mem = real_addr; - } + if (!::mprotect(real_addr, size, PROT_READ | PROT_WRITE) || !::mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) #endif - if (mem != real_addr) { LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size); Emu.Pause(); @@ -254,7 +246,9 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) else { Memory.RegisterPages(_addr, PAGE_4K(_size)); - memset(mem, 0, size); + + mem = real_addr; + memset(mem, 0, size); // ??? } } @@ -269,7 +263,7 @@ void MemBlockInfo::Free() if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else - if (::mprotect(mem, size, PROT_NONE)) + if (::mprotect(mem, size, PROT_NONE) || !::mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) #endif { LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index a32d176b2e..55564a371f 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -23,6 +23,8 @@ namespace vm { #ifdef _WIN32 HANDLE g_memory_handle; +#else + int g_memory_handle; #endif void* g_priv_addr; @@ -36,9 +38,17 @@ namespace vm g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access return base_addr; + //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR, 0); + + void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + + return base_addr; + + //return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); #endif } @@ -50,32 +60,112 @@ namespace vm CloseHandle(g_memory_handle); #else munmap(g_base_addr, 0x100000000); + munmap(g_priv_addr, 0x100000000); + + shm_unlink("/rpcs3_vm"); #endif } void* const g_base_addr = (atexit(finalize), initialize()); - void* g_reservation_owner = nullptr; - u32 g_reservation_addr = 0; + class reservation_mutex_t + { + std::atomic m_owner; + std::condition_variable m_cv; + std::atomic test; + std::mutex m_cv_mutex; + + public: + reservation_mutex_t() + : m_owner(nullptr) + , test(0) + { + } + + bool do_notify; + + __noinline void lock() + { + NamedThreadBase* owner = GetCurrentNamedThread(); + NamedThreadBase* old = nullptr; + + while (!m_owner.compare_exchange_strong(old, owner)) + { + std::unique_lock cv_lock(m_cv_mutex); + + m_cv.wait_for(cv_lock, std::chrono::milliseconds(1)); + + if (old == owner) + { + throw __FUNCTION__; + } + + old = nullptr; + } + + do_notify = true; + + test++; + assert(test == 1); + } + + __noinline void unlock() + { + assert(test == 1); + test--; + + NamedThreadBase* owner = GetCurrentNamedThread(); + + if (!m_owner.compare_exchange_strong(owner, nullptr)) + { + throw __FUNCTION__; + } + + if (do_notify) + { + m_cv.notify_one(); + } + } + + }; std::function g_reservation_cb = nullptr; + NamedThreadBase* g_reservation_owner = nullptr; - // break the reservation, return true if it was successfully broken - bool reservation_break(u32 addr) + u32 g_reservation_addr = 0; + + reservation_mutex_t g_reservation_mutex; + + void _reservation_set(u32 addr) { - LV2_LOCK(0); + //const auto stamp0 = get_time(); +#ifdef _WIN32 + DWORD old; + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) +#else + if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) +#endif + { + throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr); + } + + //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); + } + + bool _reservation_break(u32 addr) + { if (g_reservation_addr >> 12 == addr >> 12) { - const auto stamp0 = get_time(); + //const auto stamp0 = get_time(); #ifdef _WIN32 if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) #else - + if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) #endif { - throw fmt::format("vm::reservation_break() failed (addr=0x%x)", addr); + throw fmt::format("vm::_reservation_break() failed (addr=0x%x)", addr); } //LOG_NOTICE(MEMORY, "VirtualAlloc: %f us", (get_time() - stamp0) / 80.f); @@ -95,8 +185,14 @@ namespace vm return false; } - // read memory and reserve it for further atomic update, return true if the previous reservation was broken - bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback) + bool reservation_break(u32 addr) + { + std::lock_guard lock(g_reservation_mutex); + + return _reservation_break(addr); + } + + bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback) { const auto stamp0 = get_time(); @@ -106,28 +202,21 @@ namespace vm assert((addr + size & ~0xfff) == (addr & ~0xfff)); { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); + + // silent unlocking to prevent priority boost for threads going to break reservation + g_reservation_mutex.do_notify = false; // break previous reservation if (g_reservation_addr) { - broken = reservation_break(g_reservation_addr); + broken = _reservation_break(g_reservation_addr); } // change memory protection to read-only -#ifdef _WIN32 - DWORD old; - if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) -#else + _reservation_set(addr); -#endif - { - throw fmt::format("vm::reservation_acquire() failed (addr=0x%x, size=%d)", addr, size); - } - - //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); - - // set the new reservation + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = callback; @@ -139,13 +228,12 @@ namespace vm return broken; } - // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); assert((addr + size & ~0xfff) == (addr & ~0xfff)); - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) { @@ -157,39 +245,69 @@ namespace vm memcpy(vm::get_priv_ptr(addr), data, size); // free the reservation and restore memory protection - reservation_break(addr); + _reservation_break(addr); // atomic update succeeded return true; } - // for internal use bool reservation_query(u32 addr) { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); - if (!Memory.IsGoodAddr(addr)) { - return false; + LV2_LOCK(0); + + if (!Memory.IsGoodAddr(addr)) + { + return false; + } } // break the reservation - reservation_break(addr); + _reservation_break(addr); return true; } - // for internal use void reservation_free() { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); if (g_reservation_owner == GetCurrentNamedThread()) { - reservation_break(g_reservation_addr); + _reservation_break(g_reservation_addr); } } + void reservation_op(u32 addr, u32 size, std::function proc) + { + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + std::lock_guard lock(g_reservation_mutex); + + // break previous reservation + if (g_reservation_addr) + { + _reservation_break(g_reservation_addr); + } + + // change memory protection to read-only + _reservation_set(addr); + + // set additional information + g_reservation_addr = addr; + g_reservation_owner = GetCurrentNamedThread(); + g_reservation_cb = nullptr; + + // do the operation + proc(); + + // remove the reservation + _reservation_break(addr); + } + bool check_addr(u32 addr) { // Checking address before using it is unsafe. diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 32bcf17859..559ccb15e6 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -28,11 +28,16 @@ namespace vm extern void* g_priv_addr; extern void* const g_base_addr; + // break the reservation, return true if it was successfully broken bool reservation_break(u32 addr); - bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback = nullptr); + // read memory and reserve it for further atomic update, return true if the previous reservation was broken + bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback = nullptr); + // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size); bool reservation_query(u32 addr); void reservation_free(); + // perform complete operation + void reservation_op(u32 addr, u32 size, std::function proc); bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 0c588cd7ee..68d940ea6b 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -213,6 +213,11 @@ namespace vm { return vm::get_ptr(vm::cast(m_addr)); } + + T* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } static const _ptr_base make(const AT& addr) { @@ -243,6 +248,11 @@ namespace vm return vm::get_ptr(vm::cast(m_addr)); } + void* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } + explicit operator void*() const { return get_ptr(); @@ -301,6 +311,11 @@ namespace vm return vm::get_ptr(vm::cast(m_addr)); } + const void* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } + explicit operator const void*() const { return get_ptr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp index 69445ccb17..28828c9d38 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp @@ -136,7 +136,7 @@ const char *getModuleName(int id) { } } - return 0; + return "UNKNOWN MODULE"; } int cellSysmoduleInitialize() @@ -159,11 +159,12 @@ int cellSysmoduleSetMemcontainer(u32 ct_id) int cellSysmoduleLoadModule(u16 id) { + cellSysmodule->Warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, getModuleName(id)); + if (id == 0xf054) { cellSysmodule->Todo("cellSysmoduleLoadModule: CELL_SYSMODULE_LIBATRAC3MULTI"); } - cellSysmodule->Warning("cellSysmoduleLoadModule(%s)", getModuleName(id)); if (Module* m = Emu.GetModuleManager().GetModuleById(id)) { @@ -180,7 +181,8 @@ int cellSysmoduleLoadModule(u16 id) int cellSysmoduleUnloadModule(u16 id) { - cellSysmodule->Warning("cellSysmoduleUnloadModule(%s)", getModuleName(id)); + cellSysmodule->Warning("cellSysmoduleUnloadModule(id=0x%04x: %s)", id, getModuleName(id)); + Module* m = Emu.GetModuleManager().GetModuleById(id); if(!m) @@ -199,7 +201,8 @@ int cellSysmoduleUnloadModule(u16 id) int cellSysmoduleIsLoaded(u16 id) { - cellSysmodule->Warning("cellSysmoduleIsLoaded(%s)", getModuleName(id)); + cellSysmodule->Warning("cellSysmoduleIsLoaded(id=0x%04x: %s)", id, getModuleName(id)); + Module* m = Emu.GetModuleManager().GetModuleById(id); if(!m) diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 38ea4fc729..ca72b045ac 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -395,7 +395,7 @@ s32 cellFsFsync(u32 fd) s32 cellFsRmdir(vm::ptr path) { - sys_fs->Warning("cellFsRmdir(path=0x%x)", path.get_ptr()); + sys_fs->Warning("cellFsRmdir(path=0x%x)", path); std::string _path = path.get_ptr(); From c71c5eb422d3ae4ac24e49e39da6e080bc615086 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 16:59:10 +0300 Subject: [PATCH 72/94] Compilation fix --- rpcs3/Emu/Memory/vm.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 55564a371f..1f03c77434 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -12,6 +12,8 @@ #include #else #include +#include +#include /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ #ifndef MAP_ANONYMOUS From c9f994d92d9ba4253231dbaed0f8411b6bde4884 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 17:12:39 +0300 Subject: [PATCH 73/94] Fix 1 --- rpcs3/Emu/Memory/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 1f03c77434..98761f8dd4 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -43,7 +43,7 @@ namespace vm //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - g_memory_handle = shm_open("/rpcs3_vm", O_RDWR, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREATE | O_EXCL, 0); void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); From 6aef58318c18ce660ff6429584d04b2b0518f39f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 17:13:32 +0300 Subject: [PATCH 74/94] Fix 2 --- rpcs3/Emu/Memory/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 98761f8dd4..691d992b1e 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -43,7 +43,7 @@ namespace vm //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREATE | O_EXCL, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0); void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); From e70875ad5cc1b9ffa69a44ce23f562c981447284 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 18:35:54 +0300 Subject: [PATCH 75/94] Linux fix --- rpcs3/Emu/Memory/Memory.cpp | 20 ++++++++------------ rpcs3/Emu/Memory/vm.cpp | 36 +++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index ecd4961d82..7f87615796 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -102,20 +102,17 @@ void MemoryBase::Init(MemoryType type) memset(m_pages, 0, sizeof(m_pages)); memset(RawSPUMem, 0, sizeof(RawSPUMem)); + LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx, priv_addr = 0x%llx", (u64)vm::g_base_addr, (u64)vm::g_priv_addr); + #ifdef _WIN32 - if (!vm::g_base_addr) + if (!vm::g_base_addr || !vm::g_priv_addr) #else - if ((s64)vm::g_base_addr == (s64)-1) + if ((s64)vm::g_base_addr == (s64)-1 || (s64)vm::g_priv_addr == (s64)-1) #endif { LOG_ERROR(MEMORY, "Initializing memory failed"); - assert(0); return; } - else - { - LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr); - } switch (type) { @@ -207,7 +204,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size) } MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size)); - + LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size); return true; } @@ -237,7 +234,7 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) #ifdef _WIN32 if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE)) #else - if (!::mprotect(real_addr, size, PROT_READ | PROT_WRITE) || !::mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) + if (mprotect(real_addr, size, PROT_READ | PROT_WRITE) || mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) #endif { LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size); @@ -261,9 +258,8 @@ void MemBlockInfo::Free() DWORD old; if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) - //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else - if (::mprotect(mem, size, PROT_NONE) || !::mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) + if (mprotect(mem, size, PROT_NONE) || mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) #endif { LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size); @@ -436,7 +432,7 @@ u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align) LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align); return 0; } - + size = PAGE_4K(size); u32 exsize; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 691d992b1e..894e3aff70 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ #ifndef MAP_ANONYMOUS @@ -25,8 +27,6 @@ namespace vm { #ifdef _WIN32 HANDLE g_memory_handle; -#else - int g_memory_handle; #endif void* g_priv_addr; @@ -43,10 +43,22 @@ namespace vm //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - g_memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0); + //shm_unlink("/rpcs3_vm"); - void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); - g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + int memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0); + + if (memory_handle == -1) + { + printf("shm_open() failed\n"); + return (void*)-1; + } + + ftruncate(memory_handle, 0x100000000); + + void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_SHARED, memory_handle, 0); + g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_SHARED, memory_handle, 0); + + shm_unlink("/rpcs3_vm"); return base_addr; @@ -63,8 +75,6 @@ namespace vm #else munmap(g_base_addr, 0x100000000); munmap(g_priv_addr, 0x100000000); - - shm_unlink("/rpcs3_vm"); #endif } @@ -94,7 +104,7 @@ namespace vm while (!m_owner.compare_exchange_strong(old, owner)) { std::unique_lock cv_lock(m_cv_mutex); - + m_cv.wait_for(cv_lock, std::chrono::milliseconds(1)); if (old == owner) @@ -146,7 +156,7 @@ namespace vm DWORD old; if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) #else - if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) + if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) #endif { throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr); @@ -164,7 +174,7 @@ namespace vm #ifdef _WIN32 if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) #else - if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) + if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) #endif { throw fmt::format("vm::_reservation_break() failed (addr=0x%x)", addr); @@ -297,7 +307,7 @@ namespace vm // change memory protection to read-only _reservation_set(addr); - + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); @@ -352,7 +362,7 @@ namespace vm { return res; } - + if (real_pointer) { throw fmt::format("vm::get_addr(0x%016llx) failed: not a part of virtual memory", (u64)real_pointer); @@ -557,4 +567,4 @@ namespace vm } } } -} \ No newline at end of file +} From 90c021fc310ecd4d6290eaacd20e6ebc27cabcef Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 7 Feb 2015 23:06:35 +0300 Subject: [PATCH 76/94] Small fix --- rpcs3/Emu/Memory/vm.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 894e3aff70..2e3aaae4ae 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -84,13 +84,11 @@ namespace vm { std::atomic m_owner; std::condition_variable m_cv; - std::atomic test; std::mutex m_cv_mutex; public: reservation_mutex_t() : m_owner(nullptr) - , test(0) { } @@ -116,16 +114,10 @@ namespace vm } do_notify = true; - - test++; - assert(test == 1); } __noinline void unlock() { - assert(test == 1); - test--; - NamedThreadBase* owner = GetCurrentNamedThread(); if (!m_owner.compare_exchange_strong(owner, nullptr)) @@ -206,7 +198,7 @@ namespace vm bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback) { - const auto stamp0 = get_time(); + //const auto stamp0 = get_time(); bool broken = false; @@ -217,7 +209,7 @@ namespace vm std::lock_guard lock(g_reservation_mutex); // silent unlocking to prevent priority boost for threads going to break reservation - g_reservation_mutex.do_notify = false; + //g_reservation_mutex.do_notify = false; // break previous reservation if (g_reservation_addr) @@ -228,6 +220,9 @@ namespace vm // change memory protection to read-only _reservation_set(addr); + // may not be necessary, just for sure: + _mm_mfence(); + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); @@ -313,6 +308,9 @@ namespace vm g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = nullptr; + // may not be necessary, just for sure: + _mm_mfence(); + // do the operation proc(); From fcbbdc87fc91aa4c471cf4ebfa813972f96059c6 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 8 Feb 2015 01:09:23 +0300 Subject: [PATCH 77/94] Bugfix --- rpcs3/Emu/Memory/vm.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 2e3aaae4ae..5cf8962be4 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -36,8 +36,8 @@ namespace vm #ifdef _WIN32 g_memory_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0x1, 0x0, NULL); - void* base_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // main memory - g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access + void* base_addr = MapViewOfFile(g_memory_handle, FILE_MAP_WRITE, 0, 0, 0x100000000); // main memory + g_priv_addr = MapViewOfFile(g_memory_handle, FILE_MAP_WRITE, 0, 0, 0x100000000); // memory mirror for privileged access return base_addr; @@ -164,7 +164,8 @@ namespace vm //const auto stamp0 = get_time(); #ifdef _WIN32 - if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) + DWORD old; + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READWRITE, &old)) #else if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) #endif From bddff3b70aebcbe0d18845be30da403464422a07 Mon Sep 17 00:00:00 2001 From: darkf Date: Sun, 8 Feb 2015 03:37:10 -0800 Subject: [PATCH 78/94] Improve sceNpTrophy --- rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp | 41 +++++++++++++++------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp index 26a1246041..f72c74a1ea 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp @@ -69,6 +69,13 @@ struct sceNpTrophyInternal sceNpTrophyInternal sceNpTrophyInstance; +static sceNpTrophyInternalContext& getContext(u32 context) { + // The invalid context is 0, so remap contexts 1... to indices 0... + if (context == 0) + throw "getContext: context == 0"; + return sceNpTrophyInstance.contexts[context - 1]; +} + // Functions int sceNpTrophyInit(u32 pool_addr, u32 poolSize, u32 containerId, u64 options) { @@ -114,6 +121,7 @@ int sceNpTrophyCreateContext(vm::ptr context, vm::ptr ctxt.trp_stream.reset(stream); ctxt.trp_name = entry->name; stream = nullptr; + *context = sceNpTrophyInstance.contexts.size(); // contexts start from 1 return CELL_OK; } } @@ -124,7 +132,7 @@ int sceNpTrophyCreateContext(vm::ptr context, vm::ptr int sceNpTrophyCreateHandle(vm::ptr handle) { - sceNpTrophy->Warning("sceNpTrophyCreateHandle(handle_addr=0x%x)", handle.addr()); + sceNpTrophy->Todo("sceNpTrophyCreateHandle(handle_addr=0x%x)", handle.addr()); if (!sceNpTrophyInstance.m_bInitialized) return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; @@ -144,11 +152,13 @@ int sceNpTrophyRegisterContext(u32 context, u32 handle, vm::ptr= sceNpTrophyInstance.contexts.size()) + if (context == 0 || context > sceNpTrophyInstance.contexts.size()) { + sceNpTrophy->Warning("sceNpTrophyRegisterContext: invalid context (%d)", context); return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT; + } // TODO: There are other possible errors - sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context]; + sceNpTrophyInternalContext& ctxt = getContext(context); if (!ctxt.trp_stream) return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST; @@ -219,11 +229,13 @@ int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr reqspa if (!sceNpTrophyInstance.m_bInitialized) return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; - if (context >= sceNpTrophyInstance.contexts.size()) + if (context == 0 || context > sceNpTrophyInstance.contexts.size()) { + sceNpTrophy->Warning("sceNpTrophyGetRequiredDiskSpace: invalid context (%d)", context); return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT; + } // TODO: There are other possible errors - sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context]; + const sceNpTrophyInternalContext& ctxt = getContext(context); if (!ctxt.trp_stream) return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST; @@ -260,7 +272,7 @@ int sceNpTrophyGetGameInfo(u32 context, u32 handle, vm::ptr return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; // TODO: There are other possible errors - sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context]; + sceNpTrophyInternalContext& ctxt = getContext(context); if (trophyId >= (s32)ctxt.tropusr->GetTrophiesCount()) return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID; if (ctxt.tropusr->GetTrophyUnlockState(trophyId)) @@ -351,15 +363,20 @@ int sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr sceNpTrophyInstance.contexts.size()) { + sceNpTrophy->Warning("sceNpTrophyGetTrophyUnlockState: invalid context (%d)", context); + return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT; + } // TODO: There are other possible errors - sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context]; - *count = ctxt.tropusr->GetTrophiesCount(); - if (*count > 128) + const sceNpTrophyInternalContext& ctxt = getContext(context); + u32 count_ = ctxt.tropusr->GetTrophiesCount(); + *count = count_; + if (count_ > 128) sceNpTrophy->Warning("sceNpTrophyGetTrophyUnlockState: More than 128 trophies detected!"); // Pack up to 128 bools in u32 flag_bits[4] - for (u32 id=0; id<*count; id++) + for (u32 id = 0; id < count_; id++) { if (ctxt.tropusr->GetTrophyUnlockState(id)) flags->flag_bits[id/32] |= 1<<(id%32); @@ -387,7 +404,7 @@ int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr Date: Sun, 8 Feb 2015 16:38:08 +0300 Subject: [PATCH 79/94] Bugfix, ECIWX/ECOWX disabled --- Utilities/Thread.cpp | 49 +++++++++++------------ rpcs3/Emu/Cell/PPUInterpreter.h | 8 +--- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 30 +++++++------- rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp | 24 +++++------ rpcs3/Emu/Memory/Memory.h | 5 --- rpcs3/Emu/Memory/vm.cpp | 16 +++++--- 6 files changed, 64 insertions(+), 68 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index b85b96691a..568d262351 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -292,47 +292,39 @@ bool handle_access_violation(const u32 addr, x64_context* context) void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) { - const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr(); + const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0; + if (u == EXCEPTION_ACCESS_VIOLATION && (u32)addr64 == addr64) { - if (handle_access_violation((u32)addr64, pExp->ContextRecord)) - { - // restore context (further code shouldn't be reached) - RtlRestoreContext(pExp->ContextRecord, nullptr); - - // it's dangerous because destructors won't be executed - } - throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64); } - - // else some fatal error (should crash) } -extern LPTOP_LEVEL_EXCEPTION_FILTER filter_set; - -LONG __stdcall exception_filter(_EXCEPTION_POINTERS* pExp) +const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG { - _se_translator(pExp->ExceptionRecord->ExceptionCode, pExp); + const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; - if (filter_set) + if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && + (u32)addr64 == addr64 && + GetCurrentNamedThread() && + handle_access_violation((u32)addr64, pExp->ContextRecord)) { - return filter_set(pExp); + return EXCEPTION_CONTINUE_EXECUTION; } else { return EXCEPTION_CONTINUE_SEARCH; } -} - -LPTOP_LEVEL_EXCEPTION_FILTER filter_set = SetUnhandledExceptionFilter(exception_filter); +})); #else void signal_handler(int sig, siginfo_t* info, void* uct) { - const u64 addr64 = (u64)info->si_addr - (u64)Memory.GetBaseAddr(); + const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr; + const bool is_writing = ((ucontext_t*)uct)->uc_mcontext.gregs[REG_ERR] & 0x2; + if ((u32)addr64 == addr64 && GetCurrentNamedThread()) { if (handle_access_violation((u32)addr64, (ucontext_t*)uct)) @@ -341,7 +333,7 @@ void signal_handler(int sig, siginfo_t* info, void* uct) } // TODO: this may be wrong - throw fmt::format("Access violation at location 0x%llx", addr64); + throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64); } // else some fatal error @@ -451,8 +443,17 @@ void ThreadBase::Start() #ifdef _WIN32 auto old_se_translator = _set_se_translator(_se_translator); + if (!exception_handler) + { + LOG_ERROR(GENERAL, "exception_handler not set"); + return; + } #else - if (sigaction_result == -1) assert(!"sigaction() failed"); + if (sigaction_result == -1) + { + printf("sigaction() failed"); + exit(EXIT_FAILURE); + } #endif SetCurrentNamedThread(this); @@ -590,8 +591,6 @@ void thread_t::start(std::function func) #ifdef _WIN32 auto old_se_translator = _set_se_translator(_se_translator); -#else - if (sigaction_result == -1) assert(!"sigaction() failed"); #endif NamedThreadBase info(name); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index be1611bf78..83a0101e6d 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2911,9 +2911,7 @@ private: } void ECIWX(u32 rd, u32 ra, u32 rb) { - //HACK! - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.GPR[rd] = vm::read32(vm::cast(addr)); + throw __FUNCTION__; } void LHZUX(u32 rd, u32 ra, u32 rb) { @@ -2986,9 +2984,7 @@ private: } void ECOWX(u32 rs, u32 ra, u32 rb) { - //HACK! - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - vm::write32(vm::cast(addr), (u32)CPU.GPR[rs]); + throw __FUNCTION__; } void STHUX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 99203e1864..dedaf358bf 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -3271,15 +3271,16 @@ void Compiler::EQV(u32 ra, u32 rs, u32 rb, bool rc) { } void Compiler::ECIWX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto mem_i32 = ReadMemory(addr_i64, 32); - auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); - SetGpr(rd, mem_i64); + //auto mem_i32 = ReadMemory(addr_i64, 32); + //auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty()); + //SetGpr(rd, mem_i64); } void Compiler::LHZUX(u32 rd, u32 ra, u32 rb) { @@ -3430,13 +3431,14 @@ void Compiler::ORC(u32 ra, u32 rs, u32 rb, bool rc) { } void Compiler::ECOWX(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - WriteMemory(addr_i64, GetGpr(rs, 32)); + //WriteMemory(addr_i64, GetGpr(rs, 32)); } void Compiler::STHUX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index e1054ecc89..511125e233 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -724,8 +724,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0); @@ -765,10 +765,10 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 0, input, 5, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDUX, 0, input, 5, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 0, input, 5, 23, 0); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 1, input, 5, 23, 2); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 2, input, 5, 23, 7); @@ -804,8 +804,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 0, input, 3, 0, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 1, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBU, 0, input, 3, 14, 0x10000); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBUX, 0, input, 3, 14, 23); @@ -814,8 +814,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000); @@ -833,8 +833,8 @@ void Compiler::RunAllTests() { VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDU, 0, input, 3, 14, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 0, input, 3, 0, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 1, input, 3, 14, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23); - VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23); + //VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDUX, 0, input, 3, 14, 23); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 0, input, 3, 0, 0x10000); VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 1, input, 3, 14, 0x10000); diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 3f9a981041..a6aabf35ee 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -72,11 +72,6 @@ public: Close(); } - static void* const GetBaseAddr() - { - return vm::g_base_addr; - } - void RegisterPages(u64 addr, u32 size); void UnregisterPages(u64 addr, u32 size); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 5cf8962be4..563cceddcf 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -137,6 +137,7 @@ namespace vm NamedThreadBase* g_reservation_owner = nullptr; u32 g_reservation_addr = 0; + u32 g_reservation_size = 0; reservation_mutex_t g_reservation_mutex; @@ -183,6 +184,7 @@ namespace vm g_reservation_owner = nullptr; g_reservation_addr = 0; + g_reservation_size = 0; return true; } @@ -204,7 +206,7 @@ namespace vm bool broken = false; assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); - assert((addr + size & ~0xfff) == (addr & ~0xfff)); + assert((addr + size - 1 & ~0xfff) == (addr & ~0xfff)); { std::lock_guard lock(g_reservation_mutex); @@ -213,7 +215,7 @@ namespace vm //g_reservation_mutex.do_notify = false; // break previous reservation - if (g_reservation_addr) + if (g_reservation_owner) { broken = _reservation_break(g_reservation_addr); } @@ -226,6 +228,7 @@ namespace vm // set additional information g_reservation_addr = addr; + g_reservation_size = size; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = callback; @@ -239,11 +242,11 @@ namespace vm bool reservation_update(u32 addr, const void* data, u32 size) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); - assert((addr + size & ~0xfff) == (addr & ~0xfff)); + assert((addr + size - 1 & ~0xfff) == (addr & ~0xfff)); std::lock_guard lock(g_reservation_mutex); - if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) + if (g_reservation_owner != GetCurrentNamedThread() || g_reservation_addr != addr || g_reservation_size != size) { // atomic update failed return false; @@ -291,12 +294,12 @@ namespace vm void reservation_op(u32 addr, u32 size, std::function proc) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); - assert((addr + size & ~0xfff) == (addr & ~0xfff)); + assert((addr + size - 1 & ~0xfff) == (addr & ~0xfff)); std::lock_guard lock(g_reservation_mutex); // break previous reservation - if (g_reservation_addr) + if (g_reservation_owner) { _reservation_break(g_reservation_addr); } @@ -306,6 +309,7 @@ namespace vm // set additional information g_reservation_addr = addr; + g_reservation_size = size; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = nullptr; From 31bbf56ff1f33ab0e1fa8214cbea9e31ff2db703 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 8 Feb 2015 18:25:50 +0300 Subject: [PATCH 80/94] Reservations improved --- Utilities/Thread.cpp | 9 +++++---- rpcs3/Emu/Cell/SPUThread.cpp | 7 ++++--- rpcs3/Emu/Memory/vm.cpp | 38 ++++++++++++++++++++++++------------ rpcs3/Emu/Memory/vm.h | 2 +- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 568d262351..25d5981e23 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -213,7 +213,7 @@ static const reg_table_t reg_table[17] = #endif -bool handle_access_violation(const u32 addr, x64_context* context) +bool handle_access_violation(const u32 addr, bool is_writing, x64_context* context) { // check if address is RawSPU MMIO register if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) @@ -279,7 +279,7 @@ bool handle_access_violation(const u32 addr, x64_context* context) } // check if fault is caused by reservation - if (vm::reservation_query(addr)) + if (vm::reservation_query(addr, is_writing)) { return true; } @@ -304,11 +304,12 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG { const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr; + const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0; if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && (u32)addr64 == addr64 && GetCurrentNamedThread() && - handle_access_violation((u32)addr64, pExp->ContextRecord)) + handle_access_violation((u32)addr64, is_writing, pExp->ContextRecord)) { return EXCEPTION_CONTINUE_EXECUTION; } @@ -327,7 +328,7 @@ void signal_handler(int sig, siginfo_t* info, void* uct) if ((u32)addr64 == addr64 && GetCurrentNamedThread()) { - if (handle_access_violation((u32)addr64, (ucontext_t*)uct)) + if (handle_access_violation((u32)addr64, is_writing, (ucontext_t*)uct)) { return; // proceed execution } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 2bd0e0f629..e944fcd60d 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -468,9 +468,10 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) } else // store unconditional (may be wrong) { - vm::reservation_break(ea); - - ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + vm::reservation_op(ea, 128, [this, tag, lsa, ea]() + { + ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + }); if (op == MFC_PUTLLUC_CMD) { diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 563cceddcf..1a0b9edd5c 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -141,15 +141,15 @@ namespace vm reservation_mutex_t g_reservation_mutex; - void _reservation_set(u32 addr) + void _reservation_set(u32 addr, bool no_access = false) { //const auto stamp0 = get_time(); #ifdef _WIN32 DWORD old; - if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, no_access ? PAGE_NOACCESS : PAGE_READONLY, &old)) #else - if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) + if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, no_access ? PROT_NONE : PROT_READ)) #endif { throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr); @@ -223,7 +223,7 @@ namespace vm // change memory protection to read-only _reservation_set(addr); - // may not be necessary, just for sure: + // may not be necessary _mm_mfence(); // set additional information @@ -252,9 +252,15 @@ namespace vm return false; } + // change memory protection to no access + _reservation_set(addr, true); + // update memory using privileged access memcpy(vm::get_priv_ptr(addr), data, size); + // remove callback to not call it on successful update + g_reservation_cb = nullptr; + // free the reservation and restore memory protection _reservation_break(addr); @@ -262,7 +268,7 @@ namespace vm return true; } - bool reservation_query(u32 addr) + bool reservation_query(u32 addr, bool is_writing) { std::lock_guard lock(g_reservation_mutex); @@ -275,9 +281,12 @@ namespace vm } } - // break the reservation - _reservation_break(addr); - + if (is_writing) + { + // break the reservation + _reservation_break(addr); + } + return true; } @@ -299,13 +308,16 @@ namespace vm std::lock_guard lock(g_reservation_mutex); // break previous reservation - if (g_reservation_owner) + if (g_reservation_owner != GetCurrentNamedThread() || g_reservation_addr != addr || g_reservation_size != size) { - _reservation_break(g_reservation_addr); + if (g_reservation_owner) + { + _reservation_break(g_reservation_addr); + } } - // change memory protection to read-only - _reservation_set(addr); + // change memory protection to no access + _reservation_set(addr, true); // set additional information g_reservation_addr = addr; @@ -313,7 +325,7 @@ namespace vm g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = nullptr; - // may not be necessary, just for sure: + // may not be necessary _mm_mfence(); // do the operation diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 559ccb15e6..a49c21eaab 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -34,7 +34,7 @@ namespace vm bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback = nullptr); // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size); - bool reservation_query(u32 addr); + bool reservation_query(u32 addr, bool is_writing); void reservation_free(); // perform complete operation void reservation_op(u32 addr, u32 size, std::function proc); From 4e28a007c8266a9858d01491c240dc255cc1a2bc Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 9 Feb 2015 01:44:55 +0300 Subject: [PATCH 81/94] NV3089_IMAGE_IN_SIZE --- rpcs3/Emu/RSX/RSXThread.cpp | 196 ++++++++++++++++++++++++++++-------- rpcs3/Emu/RSX/RSXThread.h | 23 +++-- 2 files changed, 170 insertions(+), 49 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 961c1eb641..757f7079a4 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -11,6 +11,11 @@ #include "Emu/SysCalls/CB_FUNC.h" #include "Emu/SysCalls/lv2/sys_time.h" +extern "C" +{ +#include "libswscale/swscale.h" +} + #define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args.addr()) : args[x].value()) #define CMD_DEBUG 0 @@ -2003,42 +2008,85 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const // NV3062 case NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN: { - m_context_dma_img_dst = ARGS(0); + if (count == 1) + { + m_context_dma_img_dst = ARGS(0); + } + else + { + LOG_ERROR(RSX, "NV3062_SET_CONTEXT_DMA_IMAGE__DESTIN: unknown arg count (%d)", count); + } break; } case NV3062_SET_OFFSET_DESTIN: { - m_dst_offset = ARGS(0); + if (count == 1) + { + m_dst_offset = ARGS(0); + } + else + { + LOG_ERROR(RSX, "NV3062_SET_OFFSET_DESTIN: unknown arg count (%d)", count); + } break; } case NV3062_SET_COLOR_FORMAT: { - m_color_format = ARGS(0); - m_color_format_src_pitch = ARGS(1); - m_color_format_dst_pitch = ARGS(1) >> 16; + if (count == 2 || count == 4) + { + m_color_format = ARGS(0); + m_color_format_src_pitch = ARGS(1); + m_color_format_dst_pitch = ARGS(1) >> 16; + + if (count == 4) + { + if (ARGS(2)) + { + LOG_ERROR(RSX, "NV3062_SET_COLOR_FORMAT: unknown arg2 value (0x%x)", ARGS(2)); + } + + m_dst_offset = ARGS(3); + } + + LOG_WARNING(RSX, "NV3062_SET_COLOR_FORMAT: format=%d, src_pitch=%d, dst_pitch=%d", m_color_format, m_color_format_src_pitch, m_color_format_dst_pitch); + } + else + { + LOG_ERROR(RSX, "NV3062_SET_COLOR_FORMAT: unknown arg count (%d)", count); + } break; } // NV309E case NV309E_SET_CONTEXT_DMA_IMAGE: { - if (u32 value = ARGS(0)) + if (count == 1) { - LOG_WARNING(RSX, "TODO: NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", value); + LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: m_context_dma_img_src -> 0x%x", ARGS(0)); + m_context_dma_img_src = ARGS(0); + } + else + { + LOG_ERROR(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: unknown arg count (%d)", count); } break; } case NV309E_SET_FORMAT: { - const u8 height = ARGS(0) >> 24; - const u8 width = ARGS(0) >> 16; - const u8 format = ARGS(0); - const u32 offset = ARGS(1); - - LOG_WARNING(RSX, "TODO: NV309E_SET_FORMAT: Format:0x%x, Width:%d, Height:%d, Offset:0x%x", format, width, height, offset); + if (count == 2) + { + m_swizzle_format = ARGS(0); + m_swizzle_width = ARGS(0) >> 16; + m_swizzle_height = ARGS(0) >> 24; + m_swizzle_offset = ARGS(1); + } + else + { + LOG_ERROR(RSX, "NV309E_SET_FORMAT: unknown arg count (%d)", count); + } break; } @@ -2098,69 +2146,135 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const // NV3089 case NV3089_SET_CONTEXT_DMA_IMAGE: { - m_context_dma_img_src = ARGS(0); + if (count == 1) + { + m_context_dma_img_src = ARGS(0); + } + else + { + LOG_ERROR(RSX, "NV3089_SET_CONTEXT_DMA_IMAGE: unknown arg count (%d)", count); + } break; } case NV3089_SET_CONTEXT_SURFACE: { - if (ARGS(0) != CELL_GCM_CONTEXT_SURFACE2D) + if (count == 1) { - LOG_ERROR(RSX, "NV3089_SET_CONTEXT_SURFACE: Unsupported surface (0x%x)", ARGS(0)); + m_context_surface = ARGS(0); + + if (m_context_surface != CELL_GCM_CONTEXT_SURFACE2D && m_context_surface != CELL_GCM_CONTEXT_SWIZZLE2D) + { + LOG_ERROR(RSX, "NV3089_SET_CONTEXT_SURFACE: unknown surface (0x%x)", ARGS(0)); + } + } + else + { + LOG_ERROR(RSX, "NV3089_SET_CONTEXT_SURFACE: unknown arg count (%d)", count); } break; } case NV3089_IMAGE_IN_SIZE: { - u16 width = ARGS(0); - u16 height = ARGS(0) >> 16; + const u16 width = ARGS(0); + const u16 height = ARGS(0) >> 16; + const u16 pitch = ARGS(1); - u16 pitch = ARGS(1); - u8 origin = ARGS(1) >> 16; - u8 inter = ARGS(1) >> 24; + const u8 origin = ARGS(1) >> 16; + if (origin != 2 /* CELL_GCM_TRANSFER_ORIGIN_CORNER */) + { + LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown origin (%d)", origin); + } - u32 offset = ARGS(2); + const u8 inter = ARGS(1) >> 24; + if (inter != 0 /* CELL_GCM_TRANSFER_INTERPOLATOR_ZOH */ && inter != 1 /* CELL_GCM_TRANSFER_INTERPOLATOR_FOH */) + { + LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown inter (%d)", inter); + } - u16 u = ARGS(3); - u16 v = ARGS(3) >> 16; + const u32 offset = ARGS(2); + + const u16 u = ARGS(3); // inX + const u16 v = ARGS(3) >> 16; // inY u8* pixels_src = vm::get_ptr(GetAddress(offset, m_context_dma_img_src - 0xfeed0000)); u8* pixels_dst = vm::get_ptr(GetAddress(m_dst_offset, m_context_dma_img_dst - 0xfeed0000)); - LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: width=%d, height=%d, pitch=%d, origin=%d, inter=%d, offset=0x%x, u=%d, v=%d", width, height, pitch, origin, inter, offset, u, v); - LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x", - m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y); - - for (u16 y=0; y temp(new u8[m_color_format_dst_pitch * m_color_conv_out_h]); + + SwsContext* sws = sws_getContext(width, height, in_format, m_color_conv_out_w, m_color_conv_out_h, out_format, inter ? SWS_FAST_BILINEAR : SWS_POINT, NULL, NULL, NULL); + int in_line = pitch; + u8* out_ptr = temp.get(); + int out_line = m_color_format_dst_pitch; + sws_scale(sws, &pixels_src, &in_line, 0, height, &out_ptr, &out_line); + sws_freeContext(sws); break; } case NV3089_SET_COLOR_CONVERSION: { m_color_conv = ARGS(0); + if (m_color_conv != 1 /* CELL_GCM_TRANSFER_CONVERSION_TRUNCATE */) + { + LOG_ERROR(RSX, "NV3089_SET_COLOR_CONVERSION: unknown color conv (%d)", m_color_conv); + } + m_color_conv_fmt = ARGS(1); + if (m_color_conv_fmt != 3 /* CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8 */ && m_color_conv_fmt != 7 /* CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 */) + { + LOG_ERROR(RSX, "NV3089_SET_COLOR_CONVERSION: unknown format (%d)", m_color_conv_fmt); + } + m_color_conv_op = ARGS(2); - m_color_conv_in_x = ARGS(3); - m_color_conv_in_y = ARGS(3) >> 16; - m_color_conv_in_w = ARGS(4); - m_color_conv_in_h = ARGS(4) >> 16; + if (m_color_conv_op != 3 /* CELL_GCM_TRANSFER_OPERATION_SRCCOPY */) + { + LOG_ERROR(RSX, "NV3089_SET_COLOR_CONVERSION: unknown color conv op (%d)", m_color_conv_op); + } + + m_color_conv_clip_x = ARGS(3); + m_color_conv_clip_y = ARGS(3) >> 16; + m_color_conv_clip_w = ARGS(4); + m_color_conv_clip_h = ARGS(4) >> 16; m_color_conv_out_x = ARGS(5); m_color_conv_out_y = ARGS(5) >> 16; m_color_conv_out_w = ARGS(6); m_color_conv_out_h = ARGS(6) >> 16; + + LOG_WARNING(RSX, "NV3089_SET_COLOR_CONVERSION: clip=[x=%d,y=%d,w=%d,h=%d], out=[x=%d,y=%d,w=%d,h=%d]", + m_color_conv_clip_x, m_color_conv_clip_y, m_color_conv_clip_w, m_color_conv_clip_h, m_color_conv_out_x, m_color_conv_out_y, m_color_conv_out_w, m_color_conv_out_h); + m_color_conv_dsdx = ARGS(7); m_color_conv_dtdy = ARGS(8); - - LOG_WARNING(RSX, "TODO: NV3089_SET_COLOR_CONVERSION"); break; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index bb6a177ab0..af13521527 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -330,16 +330,16 @@ public: u32 m_color_conv; u32 m_color_conv_fmt; u32 m_color_conv_op; - u16 m_color_conv_in_x; - u16 m_color_conv_in_y; - u16 m_color_conv_in_w; - u16 m_color_conv_in_h; - u16 m_color_conv_out_x; - u16 m_color_conv_out_y; + s16 m_color_conv_clip_x; + s16 m_color_conv_clip_y; + u16 m_color_conv_clip_w; + u16 m_color_conv_clip_h; + s16 m_color_conv_out_x; + s16 m_color_conv_out_y; u16 m_color_conv_out_w; u16 m_color_conv_out_h; - u32 m_color_conv_dsdx; - u32 m_color_conv_dtdy; + s32 m_color_conv_dsdx; + s32 m_color_conv_dtdy; // Semaphore bool m_set_semaphore_offset; @@ -398,12 +398,19 @@ public: u32 m_context_dma_color_d; bool m_set_context_dma_z; u32 m_context_dma_z; + u32 m_context_surface; u32 m_context_dma_img_src; u32 m_context_dma_img_dst; u32 m_context_dma_buffer_in_src; u32 m_context_dma_buffer_in_dst; u32 m_dst_offset; + // Swizzle2D? + u16 m_swizzle_format; + u8 m_swizzle_width; + u8 m_swizzle_height; + u32 m_swizzle_offset; + // Cull face bool m_set_cull_face; u32 m_cull_face; From cd8bcd4c02e17bba3d42e1e46d27f207260f0c76 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Mon, 9 Feb 2015 15:06:46 +0200 Subject: [PATCH 82/94] Various improvements --- rpcs3/Emu/RSX/RSXThread.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/cellFs.cpp | 42 +++++++++++++++-------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index bb6a177ab0..8d4621e60a 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -103,7 +103,6 @@ protected: std::stack m_call_stack; CellGcmControl* m_ctrl; Timer m_timer_sync; - double m_fps_limit = 59.94; public: GcmTileInfo m_tiles[m_tiles_count]; @@ -151,6 +150,7 @@ public: float m_height_scale; u32 m_draw_array_count; u32 m_draw_array_first; + double m_fps_limit = 59.94; public: std::mutex m_cs_main; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 292ca71c30..23659a60e5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -538,7 +538,7 @@ int cellGcmSetSecondVFrequency(u32 freq) switch (freq) { case CELL_GCM_DISPLAY_FREQUENCY_59_94HZ: - Emu.GetGSManager().GetRender().m_frequency_mode = freq; cellGcmSys->Todo("Unimplemented display frequency: 59.94Hz"); break; + Emu.GetGSManager().GetRender().m_frequency_mode = freq; Emu.GetGSManager().GetRender().m_fps_limit = 59.94; break; case CELL_GCM_DISPLAY_FREQUENCY_SCANOUT: Emu.GetGSManager().GetRender().m_frequency_mode = freq; cellGcmSys->Todo("Unimplemented display frequency: Scanout"); break; case CELL_GCM_DISPLAY_FREQUENCY_DISABLE: diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 38ea4fc729..9a77ad0c51 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -41,7 +41,8 @@ struct FsRingBufferConfig s32 cellFsOpen(vm::ptr path, s32 flags, vm::ptr> fd, vm::ptr arg, u64 size) { - sys_fs->Log("cellFsOpen(path=0x%x, flags=0x%x, fd=0x%x, arg=0x%x, size=0x%llx)", path, flags, fd, arg, size); + sys_fs->Log("cellFsOpen(path_addr=0x%x, flags=0x%x, fd=0x%x, arg=0x%x, size=0x%llx)", path.addr(), flags, fd, arg, size); + sys_fs->Log("cellFsOpen(path='%s')", path.get_ptr()); const std::string _path = path.get_ptr(); @@ -171,7 +172,8 @@ s32 cellFsClose(u32 fd) s32 cellFsOpendir(vm::ptr path, vm::ptr fd) { - sys_fs->Warning("cellFsOpendir(path=0x%x, fd=0x%x)", path, fd); + sys_fs->Warning("cellFsOpendir(path_addr=0x%x, fd=0x%x)", path.addr(), fd); + sys_fs->Warning("cellFsOpendir(path='%s')", path.get_ptr()); std::shared_ptr dir(Emu.GetVFS().OpenDir(path.get_ptr())); if (!dir || !dir->IsOpened()) @@ -219,7 +221,8 @@ s32 cellFsClosedir(u32 fd) s32 cellFsStat(vm::ptr path, vm::ptr sb) { - sys_fs->Warning("cellFsStat(path=0x%x, sb=0x%x)", path, sb); + sys_fs->Warning("cellFsStat(path_addr=0x%x, sb=0x%x)", path.addr(), sb); + sys_fs->Warning("cellFsStat(path='%s')", path.get_ptr()); const std::string _path = path.get_ptr(); @@ -327,7 +330,8 @@ s32 cellFsFstat(u32 fd, vm::ptr sb) s32 cellFsMkdir(vm::ptr path, u32 mode) { - sys_fs->Warning("cellFsMkdir(path=0x%x, mode=0x%x)", path, mode); + sys_fs->Warning("cellFsMkdir(path_addr=0x%x, mode=0x%x)", path.addr(), mode); + sys_fs->Warning("cellFsMkdir(path='%s')", path.get_ptr()); const std::string _path = path.get_ptr(); @@ -343,7 +347,8 @@ s32 cellFsMkdir(vm::ptr path, u32 mode) s32 cellFsRename(vm::ptr from, vm::ptr to) { - sys_fs->Warning("cellFsRename(from=0x%x, to=0x%x)", from, to); + sys_fs->Warning("cellFsRename(from_addr=0x%x, to_addr=0x%x)", from.addr(), to.addr()); + sys_fs->Warning("cellFsRename(from='%s', to='%s')", from.get_ptr(), to.get_ptr()); std::string _from = from.get_ptr(); std::string _to = to.get_ptr(); @@ -377,7 +382,8 @@ s32 cellFsRename(vm::ptr from, vm::ptr to) } s32 cellFsChmod(vm::ptr path, u32 mode) { - sys_fs->Todo("cellFsChmod(path=0x%x, mode=0x%x)", path, mode); + sys_fs->Todo("cellFsChmod(path_addr=0x%x, mode=0x%x)", path.addr(), mode); + sys_fs->Todo("cellFsChmod(path='%s')", path.get_ptr()); // TODO: @@ -395,7 +401,8 @@ s32 cellFsFsync(u32 fd) s32 cellFsRmdir(vm::ptr path) { - sys_fs->Warning("cellFsRmdir(path=0x%x)", path.get_ptr()); + sys_fs->Warning("cellFsRmdir(path_addr=0x%x)", path.addr()); + sys_fs->Warning("cellFsRmdir(path='%s')", path.get_ptr()); std::string _path = path.get_ptr(); @@ -412,7 +419,8 @@ s32 cellFsRmdir(vm::ptr path) s32 cellFsUnlink(vm::ptr path) { - sys_fs->Warning("cellFsUnlink(path=0x%x)", path); + sys_fs->Warning("cellFsUnlink(path_addr=0x%x)", path.addr()); + sys_fs->Warning("cellFsUnlink(path='%s')", path.get_ptr()); std::string _path = path.get_ptr(); @@ -484,7 +492,8 @@ s32 cellFsFtruncate(u32 fd, u64 size) s32 cellFsTruncate(vm::ptr path, u64 size) { - sys_fs->Warning("cellFsTruncate(path=0x%x, size=0x%llx)", path, size); + sys_fs->Warning("cellFsTruncate(path_addr=0x%x, size=0x%llx)", path.addr(), size); + sys_fs->Warning("cellFsTruncate(path='%s')", path.get_ptr()); vfsFile f(path.get_ptr(), vfsReadWrite); if (!f.IsOpened()) @@ -530,7 +539,8 @@ s32 cellFsFGetBlockSize(u32 fd, vm::ptr sector_size, vm::ptr block_siz s32 cellFsGetBlockSize(vm::ptr path, vm::ptr sector_size, vm::ptr block_size) { - sys_fs->Warning("cellFsGetBlockSize(path=0x%x, sector_size=0x%x, block_size=0x%x)", path, sector_size, block_size); + sys_fs->Warning("cellFsGetBlockSize(path_addr=0x%x, sector_size=0x%x, block_size=0x%x)", path.addr(), sector_size, block_size); + sys_fs->Warning("cellFsGetBlockSize(path='%s')", path.get_ptr()); *sector_size = 4096; // ? *block_size = 4096; // ? @@ -540,7 +550,8 @@ s32 cellFsGetBlockSize(vm::ptr path, vm::ptr sector_size, vm::p s32 cellFsGetFreeSize(vm::ptr path, vm::ptr block_size, vm::ptr block_count) { - sys_fs->Warning("cellFsGetFreeSize(path=0x%x, block_size=0x%x, block_count=0x%x)", path, block_size, block_count); + sys_fs->Warning("cellFsGetFreeSize(path_addr=0x%x, block_size=0x%x, block_count=0x%x)", path.addr(), block_size, block_count); + sys_fs->Warning("cellFsGetFreeSize(path='%s')", path.get_ptr()); // TODO: Get real values. Currently, it always returns 40 GB of free space divided in 4 KB blocks *block_size = 4096; // ? @@ -857,7 +868,8 @@ int sdata_unpack(const std::string& packed_file, const std::string& unpacked_fil s32 cellFsSdataOpen(vm::ptr path, s32 flags, vm::ptr> fd, vm::ptr arg, u64 size) { - sys_fs->Warning("cellFsSdataOpen(path=0x%x, flags=0x%x, fd=0x%x, arg=0x%x, size=0x%llx) -> cellFsOpen()", path, flags, fd, arg, size); + sys_fs->Warning("cellFsSdataOpen(path_addr=0x%x, flags=0x%x, fd=0x%x, arg=0x%x, size=0x%llx) -> cellFsOpen()", path.addr(), flags, fd, arg, size); + sys_fs->Warning("cellFsSdataOpen(path='%s')", path.get_ptr()); /*if (flags != CELL_O_RDONLY) return CELL_EINVAL; @@ -983,7 +995,8 @@ s32 cellFsAioWrite(vm::ptr aio, vm::ptr id, vm::ptr mount_point) { - sys_fs->Warning("cellFsAioInit(mount_point=0x%x)", mount_point); + sys_fs->Warning("cellFsAioInit(mount_point_addr=0x%x)", mount_point.addr()); + sys_fs->Warning("cellFsAioInit(mount_point='%s')", mount_point.get_ptr()); aio_init = true; return CELL_OK; @@ -991,7 +1004,8 @@ s32 cellFsAioInit(vm::ptr mount_point) s32 cellFsAioFinish(vm::ptr mount_point) { - sys_fs->Warning("cellFsAioFinish(mount_point=0x%x)", mount_point); + sys_fs->Warning("cellFsAioFinish(mount_point_addr=0x%x)", mount_point.addr()); + sys_fs->Warning("cellFsAioFinish(mount_point='%s')", mount_point.get_ptr()); //aio_init = false; return CELL_OK; From e642e393246c4202ab06ab9bd785cff8773fb951 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 10 Feb 2015 15:51:45 +0300 Subject: [PATCH 83/94] NV3089_IMAGE_IN_SIZE --- rpcs3/Emu/CPU/CPUThreadManager.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 104 ++++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellVpost.cpp | 8 +- 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThreadManager.h b/rpcs3/Emu/CPU/CPUThreadManager.h index 9724b4ab34..308ab32832 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.h +++ b/rpcs3/Emu/CPU/CPUThreadManager.h @@ -18,7 +18,7 @@ public: CPUThread& AddThread(CPUThreadType type); void RemoveThread(const u32 id); - std::vector> GetThreads() { return m_threads; } + std::vector> GetThreads() { std::lock_guard lock(m_mtx_thread); return m_threads; } s32 GetThreadNumById(CPUThreadType type, u32 id); std::shared_ptr GetThread(u32 id); std::shared_ptr GetThread(u32 id, CPUThreadType type); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 757f7079a4..925a6de398 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2049,8 +2049,6 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_dst_offset = ARGS(3); } - - LOG_WARNING(RSX, "NV3062_SET_COLOR_FORMAT: format=%d, src_pitch=%d, dst_pitch=%d", m_color_format, m_color_format_src_pitch, m_color_format_dst_pitch); } else { @@ -2064,7 +2062,6 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const { if (count == 1) { - LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: m_context_dma_img_src -> 0x%x", ARGS(0)); m_context_dma_img_src = ARGS(0); } else @@ -2134,7 +2131,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if (count >= 5) { - LOG_WARNING(RSX, "NV308A_COLOR: count = %d", count); + LOG_ERROR(RSX, "NV308A_COLOR: unknown arg count (%d)", count); } m_fragment_constants.push_back(c); @@ -2195,13 +2192,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const const u32 offset = ARGS(2); - const u16 u = ARGS(3); // inX - const u16 v = ARGS(3) >> 16; // inY + const u16 u = ARGS(3); // inX (currently ignored) + const u16 v = ARGS(3) >> 16; // inY (currently ignored) u8* pixels_src = vm::get_ptr(GetAddress(offset, m_context_dma_img_src - 0xfeed0000)); u8* pixels_dst = vm::get_ptr(GetAddress(m_dst_offset, m_context_dma_img_dst - 0xfeed0000)); - if (m_context_surface != CELL_GCM_CONTEXT_SURFACE2D) + if (m_context_surface == CELL_GCM_CONTEXT_SWIZZLE2D) + { + LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: Swizzle2D not implemented"); + } + else if (m_context_surface != CELL_GCM_CONTEXT_SURFACE2D) { LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown m_context_surface (0x%x)", m_context_surface); } @@ -2214,30 +2215,75 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: w=%d, h=%d, pitch=%d, offset=0x%x (src=0x%x), inX=%f, inY=%f", width, height, pitch, offset, vm::get_addr(pixels_src), double(u) / 16, double(v) / 16); - //LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: m_dst_offset=0x%x, format_dst_pitch=0x%x, m_color_conv_in_w=%d, m_color_conv_in_h=%d", - // m_dst_offset, m_color_format_dst_pitch, m_color_conv_in_w, m_color_conv_in_h); + const u32 in_bpp = m_color_format == 4 ? 2 : 4; // bytes per pixel + const u32 out_bpp = m_color_conv_fmt == 7 ? 2 : 4; - //for (u16 y=0; y temp; + + if (in_bpp != out_bpp && width != out_w && height != out_h) + { + // resize/convert if necessary - std::unique_ptr temp(new u8[m_color_format_dst_pitch * m_color_conv_out_h]); + temp.reset(new u8[out_bpp * out_w * out_h]); + + AVPixelFormat in_format = m_color_format == 4 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_BGRA; // ??? + AVPixelFormat out_format = m_color_conv_fmt == 7 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_BGRA; // ??? + + std::unique_ptr sws(sws_getContext(width, height, in_format, out_w, out_h, out_format, inter ? SWS_FAST_BILINEAR : SWS_POINT, NULL, NULL, NULL), sws_freeContext); + + int in_line = in_bpp * width; + u8* out_ptr = temp.get(); + int out_line = out_bpp * out_w; + + sws_scale(sws.get(), &pixels_src, &in_line, 0, height, &out_ptr, &out_line); + + pixels_src = temp.get(); // use resized image as a source + } + + if (m_color_conv_out_w != m_color_conv_clip_w || m_color_conv_out_w != out_w || + m_color_conv_out_h != m_color_conv_clip_h || m_color_conv_out_h != out_h || + m_color_conv_out_x || m_color_conv_out_y || m_color_conv_clip_x || m_color_conv_clip_y) + { + // clip if necessary + + for (s32 y = m_color_conv_clip_y, dst_y = m_color_conv_out_y; y < out_h; y++, dst_y++) + { + if (dst_y >= 0 && dst_y < m_color_conv_out_h) + { + // destination line + u8* dst_line = pixels_dst + dst_y * out_bpp * m_color_conv_out_w + std::min(std::max(m_color_conv_out_x, 0), m_color_conv_out_w); + size_t dst_max = std::min(std::max((s32)m_color_conv_out_w - m_color_conv_out_x, 0), m_color_conv_out_w) * out_bpp; + + if (y >= 0 && y < std::min(m_color_conv_clip_h, out_h)) + { + // source line + u8* src_line = pixels_src + y * out_bpp * out_w + std::min(std::max(m_color_conv_clip_x, 0), m_color_conv_clip_w); + size_t src_max = std::min(std::max((s32)m_color_conv_clip_w - m_color_conv_clip_x, 0), m_color_conv_clip_w) * out_bpp; + + std::pair + z0 = { src_line + 0, std::min(dst_max, std::max(0, m_color_conv_clip_x)) }, + d0 = { src_line + z0.second, std::min(dst_max - z0.second, src_max) }, + z1 = { src_line + d0.second, dst_max - z0.second - d0.second }; + + memset(z0.first, 0, z0.second); + memcpy(d0.first, src_line, d0.second); + memset(z1.first, 0, z1.second); + } + else + { + memset(dst_line, 0, dst_max); + } + } + } + } + else + { + memcpy(pixels_dst, pixels_src, out_w * out_h * out_bpp); + } - SwsContext* sws = sws_getContext(width, height, in_format, m_color_conv_out_w, m_color_conv_out_h, out_format, inter ? SWS_FAST_BILINEAR : SWS_POINT, NULL, NULL, NULL); - int in_line = pitch; - u8* out_ptr = temp.get(); - int out_line = m_color_format_dst_pitch; - sws_scale(sws, &pixels_src, &in_line, 0, height, &out_ptr, &out_line); - sws_freeContext(sws); break; } @@ -2269,10 +2315,6 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const m_color_conv_out_y = ARGS(5) >> 16; m_color_conv_out_w = ARGS(6); m_color_conv_out_h = ARGS(6) >> 16; - - LOG_WARNING(RSX, "NV3089_SET_COLOR_CONVERSION: clip=[x=%d,y=%d,w=%d,h=%d], out=[x=%d,y=%d,w=%d,h=%d]", - m_color_conv_clip_x, m_color_conv_clip_y, m_color_conv_clip_w, m_color_conv_clip_h, m_color_conv_out_x, m_color_conv_out_y, m_color_conv_out_w, m_color_conv_out_h); - m_color_conv_dsdx = ARGS(7); m_color_conv_dtdy = ARGS(8); break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index e393ba8d13..55b82a138b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -132,7 +132,7 @@ int cellVpostExec(u32 handle, vm::ptr inPicBuff, vm::ptr sws(sws_getContext(w, h, AV_PIX_FMT_YUVA420P, ow, oh, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL), sws_freeContext); //u64 stamp2 = get_system_time(); @@ -141,11 +141,7 @@ int cellVpostExec(u32 handle, vm::ptr inPicBuff, vm::ptr(ow*4), 0, 0, 0 }; - sws_scale(sws, in_data, in_line, 0, h, out_data, out_line); - - //u64 stamp3 = get_system_time(); - - sws_freeContext(sws); + sws_scale(sws.get(), in_data, in_line, 0, h, out_data, out_line); //ConLog.Write("cellVpostExec() perf (access=%d, getContext=%d, scale=%d, finalize=%d)", //stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3); From c0a1dab09d3279f768fb4c217076f4cb3ac8e4ea Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 10 Feb 2015 16:20:07 +0300 Subject: [PATCH 84/94] Small fix --- rpcs3/Emu/RSX/RSXThread.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 925a6de398..8f64343edc 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2212,14 +2212,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown m_color_format (%d)", m_color_format); } - LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: w=%d, h=%d, pitch=%d, offset=0x%x (src=0x%x), inX=%f, inY=%f", - width, height, pitch, offset, vm::get_addr(pixels_src), double(u) / 16, double(v) / 16); - const u32 in_bpp = m_color_format == 4 ? 2 : 4; // bytes per pixel const u32 out_bpp = m_color_conv_fmt == 7 ? 2 : 4; - const s32 out_w = (s32)((u64)m_color_conv_dsdx * width / (1 << 20)); - const s32 out_h = (s32)((u64)m_color_conv_dtdy * height / (1 << 20)); + const s32 out_w = (s32)(u64(width) * (1 << 20) / m_color_conv_dsdx); + const s32 out_h = (s32)(u64(height) * (1 << 20) / m_color_conv_dtdy); + + LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: w=%d, h=%d, pitch=%d, offset=0x%x, inX=%f, inY=%f, scaleX=%f, scaleY=%f", + width, height, pitch, offset, double(u) / 16, double(v) / 16, double(1 << 20) / (m_color_conv_dsdx), double(1 << 20) / (m_color_conv_dtdy)); std::unique_ptr temp; From 068883a441129e9465204798cb3459f138f076b0 Mon Sep 17 00:00:00 2001 From: Peter Tissen Date: Wed, 11 Feb 2015 00:44:22 +0100 Subject: [PATCH 85/94] Add librt to the list of linked libraries This is needed by `shm_unlink` and similar functions. Fixes #997 --- rpcs3/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index c5e6ebe4a0..cb6f1030f1 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -120,7 +120,7 @@ set_source_files_properties(${RPCS3_SRC_DIR}/Emu/Cell/PPULLVMRecompiler.cpp PROP add_executable(rpcs3 ${RPCS3_SRC}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_BINARY_DIR}/../asmjit/") #hack because the asmjit cmake file force fno exceptions -target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES} ${LLVM_LIBS}) +target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES} ${LLVM_LIBS} rt) set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h") cotire(rpcs3) From d675c67f798acf696818782aa181b2b8abb1ad20 Mon Sep 17 00:00:00 2001 From: S Gopal Rajagopal Date: Wed, 11 Feb 2015 15:45:43 +0530 Subject: [PATCH 86/94] SPURS: Disable the SPURS kernel --- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 9070a8ce8e..d1dc487eeb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -524,6 +524,13 @@ bool spursKernelWorkloadExit(SPUThread & spu) { /// SPURS kernel entry point bool spursKernelEntry(SPUThread & spu) { + while (true) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (Emu.IsStopped()) { + return false; + } + } + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); memset(ctxt, 0, sizeof(SpursKernelContext)); From fdc5fa34beb6f13a2c8ffec413a4674842484c9f Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Feb 2015 14:39:51 +0300 Subject: [PATCH 87/94] Bugfix --- rpcs3/Emu/Cell/SPUThread.cpp | 10 ++++++--- rpcs3/Emu/RSX/RSXThread.cpp | 4 ++-- rpcs3/Emu/SysCalls/LogBase.cpp | 1 + rpcs3/Emu/SysCalls/LogBase.h | 7 +++++++ rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 11 +++++----- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 26 +++++++++++------------- rpcs3/Emu/SysCalls/Modules/cellVpost.cpp | 2 +- 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index c4cababc01..4c38ac24fd 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -280,13 +280,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) { case MFC_PUT_CMD: { - memcpy(vm::get_ptr((u32)ea), vm::get_ptr(ls_offset + lsa), size); + memcpy(vm::get_ptr(vm::cast(ea)), vm::get_ptr(ls_offset + lsa), size); return; } case MFC_GET_CMD: { - memcpy(vm::get_ptr(ls_offset + lsa), vm::get_ptr((u32)ea), size); + memcpy(vm::get_ptr(ls_offset + lsa), vm::get_ptr(vm::cast(ea)), size); return; } @@ -470,13 +470,17 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) { vm::reservation_op(ea, 128, [this, tag, lsa, ea]() { - ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128); + memcpy(vm::get_priv_ptr(vm::cast(ea)), vm::get_ptr(ls_offset + lsa), 128); }); if (op == MFC_PUTLLUC_CMD) { MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS); } + else + { + // tag may be used here + } } break; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 8f64343edc..45ab4e068d 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2229,8 +2229,8 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const temp.reset(new u8[out_bpp * out_w * out_h]); - AVPixelFormat in_format = m_color_format == 4 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_BGRA; // ??? - AVPixelFormat out_format = m_color_conv_fmt == 7 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_BGRA; // ??? + AVPixelFormat in_format = m_color_format == 4 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB; // ??? + AVPixelFormat out_format = m_color_conv_fmt == 7 ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB; // ??? std::unique_ptr sws(sws_getContext(width, height, in_format, out_w, out_h, out_format, inter ? SWS_FAST_BILINEAR : SWS_POINT, NULL, NULL, NULL), sws_freeContext); diff --git a/rpcs3/Emu/SysCalls/LogBase.cpp b/rpcs3/Emu/SysCalls/LogBase.cpp index f0ff6628fb..651e131eea 100644 --- a/rpcs3/Emu/SysCalls/LogBase.cpp +++ b/rpcs3/Emu/SysCalls/LogBase.cpp @@ -18,6 +18,7 @@ void LogBase::LogOutput(LogType type, const std::string& text) const case LogWarning: LOG_WARNING(HLE, GetName() + ": " + text); break; case LogError: LOG_ERROR(HLE, GetName() + " error: " + text); break; case LogTodo: LOG_ERROR(HLE, GetName() + " TODO: " + text); break; + case LogFatal: throw GetName() + " error: " + text; } } diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index 82e569e808..880f5333c4 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -11,6 +11,7 @@ class LogBase LogSuccess, LogWarning, LogError, + LogFatal, LogTodo, }; @@ -68,6 +69,12 @@ public: LogPrepare(LogError, fmt, fmt::do_unveil(args)...); } + template + __forceinline void Fatal(const char* fmt, Targs... args) const + { + LogPrepare(LogFatal, fmt, fmt::do_unveil(args)...); + } + template __forceinline void Todo(const char* fmt, Targs... args) const { diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 75a8763003..08cdef858c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -679,7 +679,11 @@ int cellAdecGetPcm(u32 handle, vm::ptr outBuffer) return CELL_ADEC_ERROR_EMPTY; } - AVFrame* frame = af.data; + std::unique_ptr frame(af.data, [](AVFrame* frame) + { + av_frame_unref(frame); + av_frame_free(&frame); + }); if (outBuffer) { @@ -766,13 +770,10 @@ int cellAdecGetPcm(u32 handle, vm::ptr outBuffer) } else { - cellAdec->Error("cellAdecGetPcm(): unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format); - Emu.Pause(); + cellAdec->Fatal("cellAdecGetPcm(): unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format); } } - av_frame_unref(af.data); - av_frame_free(&af.data); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 518e4589bb..f2a0d62c40 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -693,36 +693,35 @@ int cellVdecGetPicture(u32 handle, vm::ptr format, vm:: return CELL_OK; } + std::unique_ptr frame(vf.data, [](AVFrame* frame) + { + av_frame_unref(frame); + av_frame_free(&frame); + }); + if (outBuff) { - const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128); - if (format->formatType != CELL_VDEC_PICFMT_YUV420_PLANAR) { - cellVdec->Todo("cellVdecGetPicture: unknown formatType(%d)", (u32)format->formatType); - return CELL_OK; + cellVdec->Fatal("cellVdecGetPicture: unknown formatType(%d)", format->formatType); } if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709) { - cellVdec->Todo("cellVdecGetPicture: unknown colorMatrixType(%d)", (u32)format->colorMatrixType); - return CELL_OK; + cellVdec->Fatal("cellVdecGetPicture: unknown colorMatrixType(%d)", format->colorMatrixType); } - AVFrame& frame = *vf.data; + const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128); // TODO: zero padding bytes - int err = av_image_copy_to_buffer(outBuff.get_ptr(), buf_size, frame.data, frame.linesize, vdec->ctx->pix_fmt, frame.width, frame.height, 1); + int err = av_image_copy_to_buffer(outBuff.get_ptr(), buf_size, frame->data, frame->linesize, vdec->ctx->pix_fmt, frame->width, frame->height, 1); if (err < 0) { - cellVdec->Error("cellVdecGetPicture: av_image_copy_to_buffer failed (err=0x%x)", err); - Emu.Pause(); + cellVdec->Fatal("cellVdecGetPicture: av_image_copy_to_buffer failed (err=0x%x)", err); } } - av_frame_unref(vf.data); - av_frame_free(&vf.data); return CELL_OK; } @@ -863,8 +862,7 @@ int cellVdecGetPicItem(u32 handle, vm::ptr picItem_ptr) { auto mp2 = vm::ptr::make(info.addr() + sizeof(CellVdecPicItem)); - cellVdec->Todo("cellVdecGetPicItem(MPEG2)"); - Emu.Pause(); + cellVdec->Fatal("cellVdecGetPicItem(MPEG2)"); } *picItem_ptr = info.addr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 55b82a138b..fea5149548 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -128,7 +128,7 @@ int cellVpostExec(u32 handle, vm::ptr inPicBuff, vm::ptr pA(new u8[w*h]); - memset(pA.get(), (const u8)ctrlParam->outAlpha, w*h); + memset(pA.get(), ctrlParam->outAlpha, w*h); //u64 stamp1 = get_system_time(); From 43408998334899eb6a664223e39ca5d45c5a9c10 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Feb 2015 15:03:15 +0300 Subject: [PATCH 88/94] Compilation fix --- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 348c795653..59cb901d7e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -593,7 +593,7 @@ struct CellSpursEventFlag u8 _u8[size]; // Real data - struct _CellSpursEventFlag + struct { be_t events; // 0x00 Event bits be_t spuTaskPendingRecv; // 0x02 A bit is set to 1 when the condition of the SPU task using the slot are met and back to 0 when the SPU task unblocks @@ -615,7 +615,7 @@ struct CellSpursEventFlag be_t eventQueueId; // 0x7C } m; - static_assert(sizeof(_CellSpursEventFlag) == size, "Wrong _CellSpursEventFlag size"); + static_assert(sizeof(decltype(m)) == size, "Wrong _CellSpursEventFlag size"); SPURSManagerEventFlag *eventFlag; }; @@ -652,7 +652,7 @@ struct CellSpursTaskset u8 _u8[size]; // Real data - struct _CellSpursTaskset + struct { be_t running; // 0x00 be_t ready; // 0x10 @@ -678,7 +678,7 @@ struct CellSpursTaskset u8 unk3[0x60]; // 0x18A0 } m; - static_assert(sizeof(_CellSpursTaskset) == size, "Wrong _CellSpursTaskset size"); + static_assert(sizeof(decltype(m)) == size, "Wrong _CellSpursTaskset size"); SPURSManagerTaskset *taskset; }; @@ -761,7 +761,7 @@ struct CellSpursTaskset2 u8 _u8[size]; // Real data - struct _CellSpursTaskset2 + struct { be_t running_set[4]; // 0x00 be_t ready_set[4]; // 0x10 @@ -789,7 +789,7 @@ struct CellSpursTaskset2 u8 unk4[0x2900 - 0x2180]; // 0x2180 } m; - static_assert(sizeof(_CellSpursTaskset2) == size, "Wrong _CellSpursTaskset2 size"); + static_assert(sizeof(decltype(m)) == size, "Wrong _CellSpursTaskset2 size"); }; }; From 3e26971044a1920917e6d0bd98962ee8dc9fb1f3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Feb 2015 15:22:53 +0300 Subject: [PATCH 89/94] Compilation fix 2 --- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index d1dc487eeb..6b8c3ed01e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -465,10 +465,10 @@ void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { auto wid = (u32)(widAndPollStatus >> 32); // DMA in the workload info for the selected workload - auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? offsetof(CellSpurs, m.wklInfo1[wid]) : - wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? offsetof(CellSpurs, m.wklInfo2[wid & 0xf]) : - offsetof(CellSpurs, m.wklInfoSysSrv); - spursDma(spu, MFC_GET_CMD, ctxt->spurs.addr() + wklInfoOffset, 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? &ctxt->spurs->m.wklInfo1[wid] : + wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->m.wklInfo2[wid & 0xf] : + &ctxt->spurs->m.wklInfoSysSrv; + spursDma(spu, MFC_GET_CMD, vm::get_addr(wklInfoOffset), 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); spursDmaWaitForCompletion(spu, 0x80000000); // Load the workload to LS @@ -1423,7 +1423,7 @@ void spursTasksetDispatch(SPUThread & spu) { ctxt->taskId = taskId; // DMA in the task info for the selected task - spursDma(spu, MFC_GET_CMD, ctxt->taskset.addr() + offsetof(CellSpursTaskset, m.task_info[taskId]), 0x2780/*LSA*/, sizeof(CellSpursTaskset::TaskInfo), ctxt->dmaTagId); + spursDma(spu, MFC_GET_CMD, vm::get_addr(&ctxt->taskset->m.task_info[taskId]), 0x2780/*LSA*/, sizeof(CellSpursTaskset::TaskInfo), ctxt->dmaTagId); spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); auto elfAddr = taskInfo->elf_addr.addr().value(); @@ -1459,7 +1459,7 @@ void spursTasksetDispatch(SPUThread & spu) { ctxt->x2FD4 = elfAddr & 5; // TODO: Figure this out if ((elfAddr & 5) == 1) { - spursDma(spu, MFC_GET_CMD, ctxt->taskset.addr() + offsetof(CellSpursTaskset2, m.task_exit_code[taskId]), 0x2FC0/*LSA*/, 0x10/*size*/, ctxt->dmaTagId); + spursDma(spu, MFC_GET_CMD, vm::get_addr(&((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->m.task_exit_code[taskId]), 0x2FC0/*LSA*/, 0x10/*size*/, ctxt->dmaTagId); } // Trace - GUID From 250fb15592fa3bd0e7559b98286c3426db015efe Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Feb 2015 15:25:20 +0300 Subject: [PATCH 90/94] Compilation fix 3 --- rpcs3/Emu/Cell/SPUThread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 9c0baa5335..fa0dfd22d9 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -250,7 +250,7 @@ public: } // Write the FPSCR - void Write(u128 & r) + void Write(const u128 & r) { _u32[3] = r._u32[3] & 0x00000F07; _u32[2] = r._u32[2] & 0x00003F07; From 5c08bd6a7359fca404f28ef5a09d7cc6759265e5 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Feb 2015 16:05:50 +0300 Subject: [PATCH 91/94] Compilation fix --- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 59cb901d7e..f6e96733c3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -615,12 +615,12 @@ struct CellSpursEventFlag be_t eventQueueId; // 0x7C } m; - static_assert(sizeof(decltype(m)) == size, "Wrong _CellSpursEventFlag size"); - SPURSManagerEventFlag *eventFlag; }; }; +static_assert(sizeof(CellSpursEventFlag) == CellSpursEventFlag::size, "Wrong CellSpursEventFlag size"); + union CellSpursTaskArgument { be_t _u128; @@ -678,12 +678,12 @@ struct CellSpursTaskset u8 unk3[0x60]; // 0x18A0 } m; - static_assert(sizeof(decltype(m)) == size, "Wrong _CellSpursTaskset size"); - SPURSManagerTaskset *taskset; }; }; +static_assert(sizeof(CellSpursTaskset) == CellSpursTaskset::size, "Wrong CellSpursTaskset size"); + struct CellSpursInfo { be_t nSpus; @@ -788,11 +788,11 @@ struct CellSpursTaskset2 be_t task_exit_code[128]; // 0x1980 u8 unk4[0x2900 - 0x2180]; // 0x2180 } m; - - static_assert(sizeof(decltype(m)) == size, "Wrong _CellSpursTaskset2 size"); }; }; +static_assert(sizeof(CellSpursTaskset2) == CellSpursTaskset2::size, "Wrong CellSpursTaskset2 size"); + struct CellSpursTasksetAttribute { static const u32 align = 8; From 42f961816c3cbcae8ea9db34e90dfa639e4f877a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Feb 2015 23:11:49 +0300 Subject: [PATCH 92/94] SPURS fix, PPU threads are deleted at exit/join --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 6 +- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 233 +++++++++++--------- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 12 +- 3 files changed, 140 insertions(+), 111 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 18eaca3722..5f8dc1c7a1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -180,7 +180,7 @@ s64 spursInit( name += "CellSpursKernel0"; for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) { - auto spu = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, num, spurs.addr(), 0, 0); + auto spu = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, (u64)num << 32, spurs.addr(), 0, 0); #ifndef PRX_DEBUG_XXX spu->RegisterHleFunction(spurs->m.spuImg.entry_point, spursKernelEntry); #endif @@ -389,10 +389,10 @@ s64 spursInit( spurs->m.sub3.unk2 = 3; // unknown const spurs->m.sub3.port = (u64)spurs->m.port; - if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload + if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload (disabled) { s32 res = CELL_OK; -#ifdef PRX_DEBUG +#ifdef PRX_DEBUG_XXX res = cb_call, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x10428, libsre_rtoc, spurs, vm::get_addr(swlPriority), swlMaxSpu, swlIsPreem); #endif diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 6b8c3ed01e..794a17af82 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -156,20 +156,19 @@ void spursHalt(SPUThread & spu) { /// Select a workload to run bool spursKernel1SelectWorkload(SPUThread & spu) { - auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); + auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); // The first and only argument to this function is a boolean that is set to false if the function // is called by the SPURS kernel and set to true if called by cellSpursModulePollStatus. // If the first argument is true then the shared data is not updated with the result. - const auto isPoll = spu.GPR[3]._u32[3]; + const auto isPoll = spu.GPR[3]._u32[3]; - u32 wklSelectedId; - u32 pollStatus; + u32 wklSelectedId; + u32 pollStatus; - do { - // DMA and lock the first 0x80 bytes of spurs - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x100); + vm::reservation_op(vm::cast(ctxt->spurs.addr()), 128, [&]() { + // lock the first 0x80 bytes of spurs + auto spurs = ctxt->spurs.get_priv_ptr(); // Calculate the contention (number of SPUs used) for each workload u8 contention[CELL_SPURS_MAX_WORKLOAD]; @@ -302,7 +301,9 @@ bool spursKernel1SelectWorkload(SPUThread & spu) { ctxt->wklLocPendingContention[i] = 0; } } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x100), spurs, 128); + }); u64 result = (u64)wklSelectedId << 32; result |= pollStatus; @@ -322,10 +323,9 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { u32 wklSelectedId; u32 pollStatus; - do { - // DMA and lock the first 0x80 bytes of spurs - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x100); + vm::reservation_op(vm::cast(ctxt->spurs.addr()), 128, [&]() { + // lock the first 0x80 bytes of spurs + auto spurs = ctxt->spurs.get_priv_ptr(); // Calculate the contention (number of SPUs used) for each workload u8 contention[CELL_SPURS_MAX_WORKLOAD2]; @@ -448,7 +448,9 @@ bool spursKernel2SelectWorkload(SPUThread & spu) { ctxt->wklLocPendingContention[i] = 0; } } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x100), spurs, 128); + }); u64 result = (u64)wklSelectedId << 32; result |= pollStatus; @@ -468,13 +470,13 @@ void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { auto wklInfoOffset = wid < CELL_SPURS_MAX_WORKLOAD ? &ctxt->spurs->m.wklInfo1[wid] : wid < CELL_SPURS_MAX_WORKLOAD2 && isKernel2 ? &ctxt->spurs->m.wklInfo2[wid & 0xf] : &ctxt->spurs->m.wklInfoSysSrv; - spursDma(spu, MFC_GET_CMD, vm::get_addr(wklInfoOffset), 0x3FFE0/*LSA*/, 0x20/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); - spursDmaWaitForCompletion(spu, 0x80000000); + + memcpy(vm::get_ptr(spu.ls_offset + 0x3FFE0), wklInfoOffset, 0x20); // Load the workload to LS auto wklInfo = vm::get_ptr(spu.ls_offset + 0x3FFE0); if (ctxt->wklCurrentAddr != wklInfo->addr) { - switch (wklInfo->addr.addr()) { + switch (wklInfo->addr.addr().value()) { case SPURS_IMG_ADDR_SYS_SRV_WORKLOAD: spu.RegisterHleFunction(0xA00, spursSysServiceEntry); break; @@ -482,8 +484,7 @@ void spursKernelDispatchWorkload(SPUThread & spu, u64 widAndPollStatus) { spu.RegisterHleFunction(0xA00, spursTasksetEntry); break; default: - spursDma(spu, MFC_GET_CMD, wklInfo-> addr.addr(), 0xA00/*LSA*/, wklInfo->size, CELL_SPURS_KERNEL_DMA_TAG_ID); - spursDmaWaitForCompletion(spu, 0x80000000); + memcpy(vm::get_ptr(spu.ls_offset + 0xA00), wklInfo->addr.get_ptr(), wklInfo->size); break; } @@ -524,12 +525,12 @@ bool spursKernelWorkloadExit(SPUThread & spu) { /// SPURS kernel entry point bool spursKernelEntry(SPUThread & spu) { - while (true) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - if (Emu.IsStopped()) { - return false; - } - } + //while (true) { + // std::this_thread::sleep_for(std::chrono::milliseconds(100)); + // if (Emu.IsStopped()) { + // return false; + // } + //} auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); memset(ctxt, 0, sizeof(SpursKernelContext)); @@ -594,12 +595,10 @@ bool spursSysServiceEntry(SPUThread & spu) { /// Wait for an external event or exit the SPURS thread group if no workloads can be scheduled void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { - // Monitor only lock line reservation lost events - spu.WriteChannel(SPU_WrEventMask, u128::from32r(SPU_EVENT_LR)); - bool shouldExit; + while (true) { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + vm::reservation_acquire(vm::get_ptr(spu.ls_offset + 0x100), vm::cast(ctxt->spurs.addr()), 128/*, [&spu](){ spu.Notify(); }*/); auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Find the number of SPUs that are idling in this SPURS instance @@ -666,13 +665,11 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { // If all SPUs are idling and the exit_if_no_work flag is set then the SPU thread group must exit. Otherwise wait for external events. if (spuIdling && shouldExit == false && foundReadyWorkload == false) { // The system service blocks by making a reservation and waiting on the lock line reservation lost event. - u128 r; - spu.ReadChannel(r, SPU_RdEventStat); - spu.WriteChannel(SPU_WrEventAck, u128::from32r(SPU_EVENT_LR)); + spu.WaitForAnySignal(1); + if (Emu.IsStopped()) return; } - auto dmaSuccess = spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - if (dmaSuccess && (shouldExit || foundReadyWorkload)) { + if (vm::reservation_update(vm::cast(ctxt->spurs.addr()), vm::get_ptr(spu.ls_offset + 0x100), 128) && (shouldExit || foundReadyWorkload)) { break; } } @@ -687,28 +684,31 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) { auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); if (ctxt->spurs.addr() % CellSpurs::align) { - spursHalt(spu); - return; + assert(!"spursSysServiceMain(): invalid spurs alignment"); + //spursHalt(spu); + //return; } // Initialise the system service if this is the first time its being started on this SPU if (ctxt->sysSrvInitialised == 0) { ctxt->sysSrvInitialised = 1; - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); + vm::reservation_acquire(vm::get_ptr(spu.ls_offset + 0x100), vm::cast(ctxt->spurs.addr()), 128); - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); // Halt if already initialised if (spurs->m.sysSrvOnSpu & (1 << ctxt->spuNum)) { - spursHalt(spu); - return; + assert(!"spursSysServiceMain(): already initialized"); + //spursHalt(spu); + //return; } spurs->m.sysSrvOnSpu |= 1 << ctxt->spuNum; - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2D80), spurs->m.wklState1, 128); + }); ctxt->traceBuffer = 0; ctxt->traceMsgCount = -1; @@ -751,7 +751,7 @@ poll: pkt.data.stop = SPURS_GUID_SYS_WKL; cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); - spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); break; } @@ -773,6 +773,8 @@ poll: cellSpursModulePutTrace(&pkt, ctxt->dmaTagId); spursSysServiceIdleHandler(spu, ctxt); + if (Emu.IsStopped()) return; + goto poll; } } @@ -783,9 +785,8 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt) bool updateWorkload = false; bool terminate = false; - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); // Terminate request if (spurs->m.sysSrvMsgTerminate & (1 << ctxt->spuNum)) { @@ -803,7 +804,9 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt) if (spurs->m.sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) { updateTrace = true; } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2D80), spurs->m.wklState1, 128); + }); // Process update workload message if (updateWorkload) { @@ -824,9 +827,9 @@ void spursSysServiceProcessRequests(SPUThread & spu, SpursKernelContext * ctxt) /// Activate a workload void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt) { auto spurs = vm::get_ptr(spu.ls_offset + 0x100); - spursDma(spu, MFC_GET_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo1), 0x30000/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + memcpy(vm::get_ptr(spu.ls_offset + 0x30000), vm::get_ptr(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo1))), 0x200); if (spurs->m.flags1 & SF1_32_WORKLOADS) { - spursDma(spu, MFC_GET_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo2), 0x30200/*LSA*/, 0x200/*size*/, CELL_SPURS_KERNEL_DMA_TAG_ID); + memcpy(vm::get_ptr(spu.ls_offset + 0x30200), vm::get_ptr(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklInfo2))), 0x200); } u32 wklShutdownBitSet = 0; @@ -849,9 +852,8 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt) } } - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); for (u32 i = 0; i < CELL_SPURS_MAX_WORKLOAD; i++) { // Update workload status and runnable flag based on the workload state @@ -892,7 +894,9 @@ void spursSysServiceActivateWorkload(SPUThread & spu, SpursKernelContext * ctxt) } } } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2D80), spurs->m.wklState1, 128); + }); if (wklShutdownBitSet) { spursSysServiceUpdateShutdownCompletionEvents(spu, ctxt, wklShutdownBitSet); @@ -905,9 +909,8 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC // workloads that have a shutdown completion hook registered u32 wklNotifyBitSet; u8 spuPort; - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); wklNotifyBitSet = 0; spuPort = spurs->m.spuPort;; @@ -926,7 +929,9 @@ void spursSysServiceUpdateShutdownCompletionEvents(SPUThread & spu, SpursKernelC } } } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2D80), spurs->m.wklState1, 128); + }); if (wklNotifyBitSet) { // TODO: sys_spu_thread_send_event(spuPort, 0, wklNotifyMask); @@ -946,9 +951,8 @@ void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 bool notify; u8 sysSrvMsgUpdateTrace; - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); sysSrvMsgUpdateTrace = spurs->m.sysSrvMsgUpdateTrace; spurs->m.sysSrvMsgUpdateTrace &= ~(1 << ctxt->spuNum); @@ -965,17 +969,19 @@ void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 spurs->m.xCD = 0; notify = true; } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2D80), spurs->m.wklState1, 128); + }); // Get trace parameters from CellSpurs and store them in the LS if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0)) { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.traceBuffer), 0x80/*LSA*/, 0x80/*size*/, 0/*tag*/); + vm::reservation_acquire(vm::get_ptr(spu.ls_offset + 0x80), vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.traceBuffer)), 128); auto spurs = vm::get_ptr(spu.ls_offset + 0x80 - offsetof(CellSpurs, m.traceBuffer)); if (ctxt->traceMsgCount != 0xFF || spurs->m.traceBuffer.addr() == 0) { spursSysServiceTraceSaveCount(spu, ctxt); } else { - spursDma(spu, MFC_GET_CMD, spurs->m.traceBuffer.addr() & 0xFFFFFFFC, 0x2C00/*LSA*/, 0x80/*size*/, ctxt->dmaTagId); + memcpy(vm::get_ptr(spu.ls_offset + 0x2C00), vm::get_ptr(spurs->m.traceBuffer.addr() & -0x4), 0x80); auto traceBuffer = vm::get_ptr(spu.ls_offset + 0x2C00); ctxt->traceMsgCount = traceBuffer->count[ctxt->spuNum]; } @@ -997,23 +1003,28 @@ void spursSysServiceTraceUpdate(SPUThread & spu, SpursKernelContext * ctxt, u32 void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelContext * ctxt) { u8 wklId; - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + bool do_return = false; + + vm::reservation_op(vm::cast(ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1)), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); if (spurs->m.sysSrvWorkload[ctxt->spuNum] == 0xFF) { + do_return = true; return; } wklId = spurs->m.sysSrvWorkload[ctxt->spuNum]; spurs->m.sysSrvWorkload[ctxt->spuNum] = 0xFF; - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr() + offsetof(CellSpurs, m.wklState1), 0x2D80/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2D80), spurs->m.wklState1, 128); + }); + + if (do_return) return; spursSysServiceActivateWorkload(spu, ctxt); - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x100); + vm::reservation_op(vm::cast(ctxt->spurs.addr()), 128, [&]() { + auto spurs = ctxt->spurs.get_priv_ptr(); if (wklId >= CELL_SPURS_MAX_WORKLOAD) { spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x10; @@ -1022,7 +1033,9 @@ void spursSysServiceCleanupAfterSystemWorkload(SPUThread & spu, SpursKernelConte spurs->m.wklCurrentContention[wklId & 0x0F] -= 0x01; spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].write_relaxed(spurs->m.wklIdleSpuCountOrReadyCount2[wklId & 0x0F].read_relaxed() - 1); } - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x100), spurs, 128); + }); // Set the current workload id to the id of the pre-empted workload since cellSpursModulePutTrace // uses the current worload id to determine the workload to which the trace belongs @@ -1144,16 +1157,16 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * s32 rc = CELL_OK; s32 numNewlyReadyTasks; - do { - spursDma(spu, MFC_GETLLAR_CMD, ctxt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto taskset = vm::get_ptr(spu.ls_offset + 0x2700); + vm::reservation_op(vm::cast(ctxt->taskset.addr()), 128, [&]() { + auto taskset = ctxt->taskset.get_priv_ptr(); // Verify taskset state is valid auto _0 = be_t::make(u128::from32(0)); if ((taskset->m.waiting & taskset->m.running) != _0 || (taskset->m.ready & taskset->m.pending_ready) != _0 || ((taskset->m.running | taskset->m.ready | taskset->m.pending_ready | taskset->m.signalled | taskset->m.waiting) & be_t::make(~taskset->m.enabled.value())) != _0) { - spursHalt(spu); - return CELL_OK; + assert(!"Invalid taskset state"); + //spursHalt(spu); + //return CELL_OK; } // Find the number of tasks that have become ready since the last iteration @@ -1269,8 +1282,9 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * } break; default: - spursHalt(spu); - return CELL_OK; + assert(!"Unknown taskset request"); + //spursHalt(spu); + //return CELL_OK; } taskset->m.pending_ready = _0; @@ -1279,12 +1293,13 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * taskset->m.enabled = enabled; taskset->m.signalled = signalled; taskset->m.ready = ready; - } while (spursDma(spu, MFC_PUTLLC_CMD, ctxt->taskset.addr(), 0x2700/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x2700), taskset, 128); + }); // Increment the ready count of the workload by the number of tasks that have become ready - do { - spursDma(spu, MFC_GETLLAR_CMD, kernelCtxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/); - auto spurs = vm::get_ptr(spu.ls_offset + 0x2D80 - offsetof(CellSpurs, m.wklState1)); + vm::reservation_op(vm::cast(kernelCtxt->spurs.addr()), 128, [&]() { + auto spurs = kernelCtxt->spurs.get_priv_ptr(); s32 readyCount = kernelCtxt->wklCurrentId < CELL_SPURS_MAX_WORKLOAD ? spurs->m.wklReadyCount1[kernelCtxt->wklCurrentId].read_relaxed() : spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].read_relaxed(); readyCount += numNewlyReadyTasks; @@ -1295,7 +1310,9 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 * } else { spurs->m.wklIdleSpuCountOrReadyCount2[kernelCtxt->wklCurrentId & 0x0F].write_relaxed(readyCount); } - } while (spursDma(spu, MFC_PUTLLC_CMD, kernelCtxt->spurs.addr(), 0x100/*LSA*/, 0x80/*size*/, 0/*tag*/) == false); + + memcpy(vm::get_ptr(spu.ls_offset + 0x100), spurs, 128); + }); return rc; } @@ -1332,7 +1349,8 @@ void spursTasksetExit(SPUThread & spu) { // Not sure why this check exists. Perhaps to check for memory corruption. if (memcmp(ctxt->moduleId, "SPURSTASK MODULE", 16) != 0) { - spursHalt(spu); + //spursHalt(spu); + assert(!"spursTasksetExit(): memory corruption"); } cellSpursModuleExit(spu); @@ -1342,8 +1360,7 @@ void spursTasksetExit(SPUThread & spu) { void spursTasksetOnTaskExit(SPUThread & spu, u64 addr, u32 taskId, s32 exitCode, u64 args) { auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); - spursDma(spu, MFC_GET_CMD, addr & 0xFFFFFF80, 0x10000/*LSA*/, (addr & 0x7F) << 11/*size*/, 0); - spursDmaWaitForCompletion(spu, 1); + memcpy(vm::get_ptr(spu.ls_offset + 0x10000), vm::get_ptr(addr & -0x80), (addr & 0x7F) << 11); spu.GPR[3]._u64[1] = ctxt->taskset.addr(); spu.GPR[4]._u32[3] = taskId; @@ -1357,7 +1374,7 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { auto ctxt = vm::get_ptr(spu.ls_offset + 0x2700); auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); - spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + //spursDmaWaitForCompletion(spu, 0xFFFFFFFF); if (taskInfo->context_save_storage_and_alloc_ls_blocks == 0) { return CELL_SPURS_TASK_ERROR_STAT; @@ -1392,18 +1409,18 @@ s32 spursTasketSaveTaskContext(SPUThread & spu) { ctxt->savedWriteTagGroupQueryMask = r._u32[3]; // Store the processor context - u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; - spursDma(spu, MFC_PUT_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, ctxt->dmaTagId); + const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80); + memcpy(vm::get_ptr(contextSaveStorage), vm::get_ptr(spu.ls_offset + 0x2C80), 0x380); // Save LS context for (auto i = 6; i < 128; i++) { if (taskInfo->ls_pattern._u128.value()._bit[i]) { // TODO: Combine DMA requests for consecutive blocks into a single request - spursDma(spu, MFC_PUT_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); + memcpy(vm::get_ptr(contextSaveStorage + 0x400 + ((i - 6) << 11)), vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), 0x800); } } - spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); return CELL_OK; } @@ -1423,8 +1440,7 @@ void spursTasksetDispatch(SPUThread & spu) { ctxt->taskId = taskId; // DMA in the task info for the selected task - spursDma(spu, MFC_GET_CMD, vm::get_addr(&ctxt->taskset->m.task_info[taskId]), 0x2780/*LSA*/, sizeof(CellSpursTaskset::TaskInfo), ctxt->dmaTagId); - spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + memcpy(vm::get_ptr(spu.ls_offset + 0x2780), &ctxt->taskset->m.task_info[taskId], sizeof(CellSpursTaskset::TaskInfo)); auto taskInfo = vm::get_ptr(spu.ls_offset + 0x2780); auto elfAddr = taskInfo->elf_addr.addr().value(); taskInfo->elf_addr.set(taskInfo->elf_addr.addr() & 0xFFFFFFFFFFFFFFF8ull); @@ -1445,11 +1461,12 @@ void spursTasksetDispatch(SPUThread & spu) { u32 entryPoint; u32 lowestLoadAddr; if (spursTasksetLoadElf(spu, &entryPoint, &lowestLoadAddr, taskInfo->elf_addr.addr(), false) != CELL_OK) { - spursHalt(spu); - return; + assert(!"spursTaskLoadElf() failed"); + //spursHalt(spu); + //return; } - spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); ctxt->savedContextLr = u128::from32r(entryPoint); ctxt->guidAddr = lowestLoadAddr; @@ -1459,7 +1476,7 @@ void spursTasksetDispatch(SPUThread & spu) { ctxt->x2FD4 = elfAddr & 5; // TODO: Figure this out if ((elfAddr & 5) == 1) { - spursDma(spu, MFC_GET_CMD, vm::get_addr(&((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->m.task_exit_code[taskId]), 0x2FC0/*LSA*/, 0x10/*size*/, ctxt->dmaTagId); + memcpy(vm::get_ptr(spu.ls_offset + 0x2FC0), &((CellSpursTaskset2*)(ctxt->taskset.get_ptr()))->m.task_exit_code[taskId], 0x10); } // Trace - GUID @@ -1485,22 +1502,23 @@ void spursTasksetDispatch(SPUThread & spu) { // Load the ELF u32 entryPoint; if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf_addr.addr(), true) != CELL_OK) { - spursHalt(spu); - return; + assert(!"spursTasksetLoadElf() failed"); + //spursHalt(spu); + //return; } } // Load saved context from main memory to LS - u64 contextSaveStorage = taskInfo->context_save_storage_and_alloc_ls_blocks & 0xFFFFFFFFFFFFFF80ull; - spursDma(spu, MFC_GET_CMD, contextSaveStorage, 0x2C80/*LSA*/, 0x380/*size*/, ctxt->dmaTagId); + const u32 contextSaveStorage = vm::cast(taskInfo->context_save_storage_and_alloc_ls_blocks & -0x80); + memcpy(vm::get_ptr(spu.ls_offset + 0x2C80), vm::get_ptr(contextSaveStorage), 0x380); for (auto i = 6; i < 128; i++) { if (taskInfo->ls_pattern._u128.value()._bit[i]) { // TODO: Combine DMA requests for consecutive blocks into a single request - spursDma(spu, MFC_GET_CMD, contextSaveStorage + 0x400 + ((i - 6) << 11), CELL_SPURS_TASK_TOP + ((i - 6) << 11), 0x800/*size*/, ctxt->dmaTagId); + memcpy(vm::get_ptr(spu.ls_offset + CELL_SPURS_TASK_TOP + ((i - 6) << 11)), vm::get_ptr(contextSaveStorage + 0x400 + ((i - 6) << 11)), 0x800); } } - spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); + //spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId); // Restore saved registers spu.FPSCR.Write(ctxt->savedContextFpscr.value()); @@ -1533,7 +1551,7 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { // syscall (e.g. cellSpursYield2 instead of cellSpursYield) and so don't wait // for DMA completion if ((syscallNum & 0x10) == 0) { - spursDmaWaitForCompletion(spu, 0xFFFFFFFF); + //spursDmaWaitForCompletion(spu, 0xFFFFFFFF); } s32 rc = 0; @@ -1579,7 +1597,8 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args) { break; case CELL_SPURS_TASK_SYSCALL_RECV_WKL_FLAG: if (args == 0) { // TODO: Figure this out - spursHalt(spu); + assert(!"args == 0"); + //spursHalt(spu); } if (spursTasksetPollStatus(spu) || spursTasksetProcessRequest(spu, SPURS_TASKSET_REQUEST_WAIT_WKL_FLAG, nullptr, nullptr) != 1) { @@ -1642,7 +1661,7 @@ s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, return CELL_SPURS_TASK_ERROR_INVAL; } - vfsStreamMemory stream(elfAddr); + vfsStreamMemory stream(vm::cast(elfAddr)); loader::handlers::elf32 loader; auto rc = loader.init(stream); if (rc != loader::handler::ok) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index b182ecd4b5..3a3f32ae6f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -23,6 +23,15 @@ void ppu_thread_exit(PPUThread& CPU, u64 errorcode) CPU.SetExitStatus(errorcode); CPU.Stop(); + + if (!CPU.IsJoinable()) + { + const u32 id = CPU.GetId(); + CallAfter([id]() + { + Emu.GetCPU().RemoveThread(id); + }); + } } void sys_ppu_thread_exit(PPUThread& CPU, u64 errorcode) @@ -65,6 +74,7 @@ s32 sys_ppu_thread_join(u64 thread_id, vm::ptr vptr) } *vptr = thr->GetExitStatus(); + Emu.GetCPU().RemoveThread(thread_id); return CELL_OK; } @@ -156,7 +166,7 @@ PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool i new_thread.SetEntry(entry); new_thread.SetPrio(prio); new_thread.SetStackSize(stacksize); - //new_thread.flags = flags; + new_thread.SetJoinable(is_joinable); new_thread.m_has_interrupt = false; new_thread.m_is_interrupt = is_interrupt; new_thread.SetName(name); From cc6ba726eb69be8fc73aad7dbc539c8bd13e34fb Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Wed, 11 Feb 2015 23:09:48 +0200 Subject: [PATCH 93/94] Big improvements to cellCamera and cellGem --- rpcs3/Emu/SysCalls/Modules/cellCamera.cpp | 268 ++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellCamera.h | 298 +++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellGem.cpp | 12 +- rpcs3/Gui/MainFrame.cpp | 1 + rpcs3/Ini.h | 2 +- 5 files changed, 572 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp b/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp index 467e18e214..d363ca072e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellCamera.cpp @@ -6,10 +6,16 @@ #include "cellCamera.h" Module *cellCamera = nullptr; +const char* attributes[] = {"GAIN", "REDBLUEGAIN", "SATURATION", "EXPOSURE", "BRIGHTNESS", "AEC", "AGC", "AWB", "ABC", "LED", "AUDIOGAIN", "QS", "NONZEROCOEFFS", "YUVFLAG", + "JPEGFLAG", "BACKLIGHTCOMP", "MIRRORFLAG", "MEASUREDQS", "422FLAG", "USBLOAD", "GAMMA", "GREENGAIN", "AGCLIMIT", "DENOISE", "FRAMERATEADJUST", + "PIXELOUTLIERFILTER", "AGCLOW", "AGCHIGH", "DEVICELOCATION", "FORMATCAP", "FORMATINDEX", "NUMFRAME", "FRAMEINDEX", "FRAMESIZE", "INTERVALTYPE", + "INTERVALINDEX", "INTERVALVALUE", "COLORMATCHING", "PLFREQ", "DEVICEID", "DEVICECAP", "DEVICESPEED", "UVCREQCODE", "UVCREQDATA", "DEVICEID2", + "READMODE", "GAMEPID", "PBUFFER", "READFINISH", "ATTRIBUTE_UNKNOWN"}; struct cellCameraInternal { bool m_bInitialized; + CellCamera m_camera; cellCameraInternal() : m_bInitialized(false) @@ -26,7 +32,51 @@ int cellCameraInit() if (cellCameraInstance.m_bInitialized) return CELL_CAMERA_ERROR_ALREADY_INIT; - // TODO: Check if camera is connected, if not return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND + if (Ini.Camera.GetValue() == 0) + return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND; + + if (Ini.CameraType.GetValue() == 1) + { + CellCamera camera; + camera.attributes.SATURATION = 164; + camera.attributes.BRIGHTNESS = 96; + camera.attributes.AEC = 1; + camera.attributes.AGC = 1; + camera.attributes.AWB = 1; + camera.attributes.ABC = 0; + camera.attributes.LED = 1; + camera.attributes.QS = 0; + camera.attributes.NONZEROCOEFFS[0] = 32; + camera.attributes.NONZEROCOEFFS[1] = 32; + camera.attributes.YUVFLAG = 0; + camera.attributes.BACKLIGHTCOMP = 0; + camera.attributes.MIRRORFLAG = 1; + camera.attributes._422FLAG = 1; + camera.attributes.USBLOAD = 4; + cellCameraInstance.m_camera = camera; + } + else if (Ini.CameraType.GetValue() == 2) + { + CellCamera camera; + camera.attributes.SATURATION = 64; + camera.attributes.BRIGHTNESS = 8; + camera.attributes.AEC = 1; + camera.attributes.AGC = 1; + camera.attributes.AWB = 1; + camera.attributes.LED = 1; + camera.attributes.BACKLIGHTCOMP = 0; + camera.attributes.MIRRORFLAG = 1; + camera.attributes.GAMMA = 1; + camera.attributes.AGCLIMIT = 4; + camera.attributes.DENOISE = 0; + camera.attributes.FRAMERATEADJUST = 0; + camera.attributes.PIXELOUTLIERFILTER = 1; + camera.attributes.AGCLOW = 48; + camera.attributes.AGCHIGH = 64; + cellCameraInstance.m_camera = camera; + } + // TODO: Some other default attributes? Need to check the actual behaviour on a real PS3. + cellCameraInstance.m_bInitialized = true; return CELL_OK; @@ -122,23 +172,231 @@ int cellCameraIsStarted() return CELL_OK; } -int cellCameraGetAttribute() +int cellCameraGetAttribute(s32 dev_num, CellCameraAttribute attrib, vm::ptr arg1, vm::ptr arg2) { - UNIMPLEMENTED_FUNC(cellCamera); + cellCamera->Warning("cellCameraGetAttribute(dev_num=%d, attrib=%s(%d), arg1=0x%x, arg2=0x%x)", dev_num, attributes[attrib], arg1.addr(), arg2.addr()); if (!cellCameraInstance.m_bInitialized) return CELL_CAMERA_ERROR_NOT_INIT; + if (attrib == 0) + *arg1 = cellCameraInstance.m_camera.attributes.GAIN; + else if (attrib == 1) + *arg1 = cellCameraInstance.m_camera.attributes.REDBLUEGAIN; + else if (attrib == 2) + *arg1 = cellCameraInstance.m_camera.attributes.SATURATION; + else if (attrib == 3) + *arg1 = cellCameraInstance.m_camera.attributes.EXPOSURE; + else if (attrib == 4) + *arg1 = cellCameraInstance.m_camera.attributes.BRIGHTNESS; + else if (attrib == 5) + *arg1 = cellCameraInstance.m_camera.attributes.AEC; + else if (attrib == 6) + *arg1 = cellCameraInstance.m_camera.attributes.AGC; + else if (attrib == 7) + *arg1 = cellCameraInstance.m_camera.attributes.AWB; + else if (attrib == 8) + *arg1 = cellCameraInstance.m_camera.attributes.ABC; + else if (attrib == 9) + *arg1 = cellCameraInstance.m_camera.attributes.LED; + else if (attrib == 10) + *arg1 = cellCameraInstance.m_camera.attributes.AUDIOGAIN; + else if (attrib == 11) + *arg1 = cellCameraInstance.m_camera.attributes.QS; + else if (attrib == 12) + { + *arg1 = cellCameraInstance.m_camera.attributes.NONZEROCOEFFS[0]; + *arg2 = cellCameraInstance.m_camera.attributes.NONZEROCOEFFS[1]; + } + else if (attrib == 13) + *arg1 = cellCameraInstance.m_camera.attributes.YUVFLAG; + else if (attrib == 14) + *arg1 = cellCameraInstance.m_camera.attributes.JPEGFLAG; + else if (attrib == 15) + *arg1 = cellCameraInstance.m_camera.attributes.BACKLIGHTCOMP; + else if (attrib == 16) + *arg1 = cellCameraInstance.m_camera.attributes.MIRRORFLAG; + else if (attrib == 17) + *arg1 = cellCameraInstance.m_camera.attributes.MEASUREDQS; + else if (attrib == 18) + *arg1 = cellCameraInstance.m_camera.attributes._422FLAG; + else if (attrib == 19) + *arg1 = cellCameraInstance.m_camera.attributes.USBLOAD; + else if (attrib == 20) + *arg1 = cellCameraInstance.m_camera.attributes.GAMMA; + else if (attrib == 21) + *arg1 = cellCameraInstance.m_camera.attributes.GREENGAIN; + else if (attrib == 22) + *arg1 = cellCameraInstance.m_camera.attributes.AGCLIMIT; + else if (attrib == 23) + *arg1 = cellCameraInstance.m_camera.attributes.DENOISE; + else if (attrib == 24) + *arg1 = cellCameraInstance.m_camera.attributes.FRAMERATEADJUST; + else if (attrib == 25) + *arg1 = cellCameraInstance.m_camera.attributes.PIXELOUTLIERFILTER; + else if (attrib == 26) + *arg1 = cellCameraInstance.m_camera.attributes.AGCLOW; + else if (attrib == 27) + *arg1 = cellCameraInstance.m_camera.attributes.AGCHIGH; + else if (attrib == 28) + *arg1 = cellCameraInstance.m_camera.attributes.DEVICELOCATION; + else if (attrib == 29) + *arg1 = cellCameraInstance.m_camera.attributes.FORMATCAP; + else if (attrib == 30) + *arg1 = cellCameraInstance.m_camera.attributes.FORMATINDEX; + else if (attrib == 31) + *arg1 = cellCameraInstance.m_camera.attributes.NUMFRAME; + else if (attrib == 32) + *arg1 = cellCameraInstance.m_camera.attributes.FRAMEINDEX; + else if (attrib == 33) + *arg1 = cellCameraInstance.m_camera.attributes.FRAMESIZE; + else if (attrib == 34) + *arg1 = cellCameraInstance.m_camera.attributes.INTERVALTYPE; + else if (attrib == 35) + *arg1 = cellCameraInstance.m_camera.attributes.INTERVALINDEX; + else if (attrib == 36) + *arg1 = cellCameraInstance.m_camera.attributes.INTERVALVALUE; + else if (attrib == 37) + *arg1 = cellCameraInstance.m_camera.attributes.COLORMATCHING; + else if (attrib == 38) + *arg1 = cellCameraInstance.m_camera.attributes.PLFREQ; + else if (attrib == 39) + *arg1 = cellCameraInstance.m_camera.attributes.DEVICEID; + else if (attrib == 40) + *arg1 = cellCameraInstance.m_camera.attributes.DEVICECAP; + else if (attrib == 41) + *arg1 = cellCameraInstance.m_camera.attributes.DEVICESPEED; + else if (attrib == 42) + *arg1 = cellCameraInstance.m_camera.attributes.UVCREQCODE; + else if (attrib == 43) + *arg1 = cellCameraInstance.m_camera.attributes.UVCREQDATA; + else if (attrib == 44) + *arg1 = cellCameraInstance.m_camera.attributes.DEVICEID2; + else if (attrib == 45) + *arg1 = cellCameraInstance.m_camera.attributes.READMODE; + else if (attrib == 46) + *arg1 = cellCameraInstance.m_camera.attributes.GAMEPID; + else if (attrib == 47) + *arg1 = cellCameraInstance.m_camera.attributes.PBUFFER; + else if (attrib == 48) + *arg1 = cellCameraInstance.m_camera.attributes.READFINISH; + else if (attrib == 49) + *arg1 = cellCameraInstance.m_camera.attributes.ATTRIBUTE_UNKNOWN; + return CELL_OK; } -int cellCameraSetAttribute() +int cellCameraSetAttribute(s32 dev_num, CellCameraAttribute attrib, u32 arg1, u32 arg2) { - UNIMPLEMENTED_FUNC(cellCamera); + cellCamera->Warning("cellCameraSetAttribute(dev_num=%d, attrib=%s(%d), arg1=%d, arg2=%d)", dev_num, attributes[attrib], attrib, arg1, arg2); if (!cellCameraInstance.m_bInitialized) return CELL_CAMERA_ERROR_NOT_INIT; + if (attrib == 0) + cellCameraInstance.m_camera.attributes.GAIN = arg1; + else if (attrib == 1) + cellCameraInstance.m_camera.attributes.REDBLUEGAIN = arg1; + else if (attrib == 2) + cellCameraInstance.m_camera.attributes.SATURATION = arg1; + else if (attrib == 3) + cellCameraInstance.m_camera.attributes.EXPOSURE = arg1; + else if (attrib == 4) + cellCameraInstance.m_camera.attributes.BRIGHTNESS = arg1; + else if (attrib == 5) + cellCameraInstance.m_camera.attributes.AEC = arg1; + else if (attrib == 6) + cellCameraInstance.m_camera.attributes.AGC = arg1; + else if (attrib == 7) + cellCameraInstance.m_camera.attributes.AWB = arg1; + else if (attrib == 8) + cellCameraInstance.m_camera.attributes.ABC = arg1; + else if (attrib == 9) + cellCameraInstance.m_camera.attributes.LED = arg1; + else if (attrib == 10) + cellCameraInstance.m_camera.attributes.AUDIOGAIN = arg1; + else if (attrib == 11) + cellCameraInstance.m_camera.attributes.QS = arg1; + else if (attrib == 12) + { + cellCameraInstance.m_camera.attributes.NONZEROCOEFFS[0] = arg1; + cellCameraInstance.m_camera.attributes.NONZEROCOEFFS[1] = arg2; + } + else if (attrib == 13) + cellCameraInstance.m_camera.attributes.YUVFLAG = arg1; + else if (attrib == 14) + cellCameraInstance.m_camera.attributes.JPEGFLAG = arg1; + else if (attrib == 15) + cellCameraInstance.m_camera.attributes.BACKLIGHTCOMP = arg1; + else if (attrib == 16) + cellCameraInstance.m_camera.attributes.MIRRORFLAG = arg1; + else if (attrib == 17) + return CELL_CAMERA_ERROR_PARAM; + else if (attrib == 18) + cellCameraInstance.m_camera.attributes._422FLAG = arg1; + else if (attrib == 19) + cellCameraInstance.m_camera.attributes.USBLOAD = arg1; + else if (attrib == 20) + cellCameraInstance.m_camera.attributes.GAMMA = arg1; + else if (attrib == 21) + cellCameraInstance.m_camera.attributes.GREENGAIN = arg1; + else if (attrib == 22) + cellCameraInstance.m_camera.attributes.AGCLIMIT = arg1; + else if (attrib == 23) + cellCameraInstance.m_camera.attributes.DENOISE = arg1; + else if (attrib == 24) + cellCameraInstance.m_camera.attributes.FRAMERATEADJUST = arg1; + else if (attrib == 25) + cellCameraInstance.m_camera.attributes.PIXELOUTLIERFILTER = arg1; + else if (attrib == 26) + cellCameraInstance.m_camera.attributes.AGCLOW = arg1; + else if (attrib == 27) + cellCameraInstance.m_camera.attributes.AGCHIGH = arg1; + else if (attrib == 28) + cellCameraInstance.m_camera.attributes.DEVICELOCATION = arg1; + else if (attrib == 29) + cellCamera->Error("Tried to write to read-only (?) value: FORMATCAP"); + else if (attrib == 30) + cellCameraInstance.m_camera.attributes.FORMATINDEX = arg1; + else if (attrib == 31) + cellCameraInstance.m_camera.attributes.NUMFRAME = arg1; + else if (attrib == 32) + cellCameraInstance.m_camera.attributes.FRAMEINDEX = arg1; + else if (attrib == 33) + cellCameraInstance.m_camera.attributes.FRAMESIZE = arg1; + else if (attrib == 34) + cellCameraInstance.m_camera.attributes.INTERVALTYPE = arg1; + else if (attrib == 35) + cellCameraInstance.m_camera.attributes.INTERVALINDEX = arg1; + else if (attrib == 36) + cellCameraInstance.m_camera.attributes.INTERVALVALUE = arg1; + else if (attrib == 37) + cellCameraInstance.m_camera.attributes.COLORMATCHING = arg1; + else if (attrib == 38) + cellCameraInstance.m_camera.attributes.PLFREQ = arg1; + else if (attrib == 39) + return CELL_CAMERA_ERROR_PARAM; + else if (attrib == 40) + cellCameraInstance.m_camera.attributes.DEVICECAP = arg1; + else if (attrib == 41) + cellCameraInstance.m_camera.attributes.DEVICESPEED = arg1; + else if (attrib == 42) + cellCameraInstance.m_camera.attributes.UVCREQCODE = arg1; + else if (attrib == 43) + cellCameraInstance.m_camera.attributes.UVCREQDATA = arg1; + else if (attrib == 44) + return CELL_CAMERA_ERROR_PARAM; + else if (attrib == 45) + cellCamera->Error("Tried to write to read-only (?) value: READMODE"); + else if (attrib == 46) + cellCameraInstance.m_camera.attributes.GAMEPID = arg1; + else if (attrib == 47) + cellCameraInstance.m_camera.attributes.PBUFFER = arg1; + else if (attrib == 48) + cellCameraInstance.m_camera.attributes.READFINISH = arg1; + else if (attrib == 49) + cellCamera->Error("Tried to write to read-only (?) value: ATTRIBUTE_UNKNOWN"); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellCamera.h b/rpcs3/Emu/SysCalls/Modules/cellCamera.h index c56aae37fa..f9242a4660 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellCamera.h +++ b/rpcs3/Emu/SysCalls/Modules/cellCamera.h @@ -18,6 +18,179 @@ enum CELL_CAMERA_ERROR_FATAL = 0x8014080f, }; +// Event types +enum +{ + CELL_CAMERA_EFLAG_FRAME_UPDATE = 0x00000001, + CELL_CAMERA_EFLAG_OPEN = 0x00000002, + CELL_CAMERA_EFLAG_CLOSE = 0x00000004, + CELL_CAMERA_EFLAG_START = 0x00000008, + CELL_CAMERA_EFLAG_STOP = 0x00000010, + CELL_CAMERA_EFLAG_RESET = 0x00000020, +}; + +// Colormatching +enum +{ + CELL_CAMERA_CM_CP_UNSPECIFIED = 0, + CELL_CAMERA_CM_CP_BT709_sRGB = 1, + CELL_CAMERA_CM_CP_BT470_2M = 2, + CELL_CAMERA_CM_CP_BT470_2BG = 3, + CELL_CAMERA_CM_CP_SMPTE170M = 4, + CELL_CAMERA_CM_CP_SMPTE240M = 5, + + CELL_CAMERA_CM_TC_UNSPECIFIED = 0, + CELL_CAMERA_CM_TC_BT709 = 1, + CELL_CAMERA_CM_TC_BT470_2M = 2, + CELL_CAMERA_CM_TC_BT470_2BG = 3, + CELL_CAMERA_CM_TC_SMPTE170M = 4, + CELL_CAMERA_CM_TC_SMPTE240M = 5, + CELL_CAMERA_CM_TC_LINEAR = 6, + CELL_CAMERA_CM_TC_sRGB = 7, + + CELL_CAMERA_CM_MC_UNSPECIFIED = 0, + CELL_CAMERA_CM_MC_BT709 = 1, + CELL_CAMERA_CM_MC_FCC = 2, + CELL_CAMERA_CM_MC_BT470_2BG = 3, + CELL_CAMERA_CM_MC_SMPTE170M = 4, + CELL_CAMERA_CM_MC_SMPTE240M = 5, +}; + +// Power Line Frequency +enum +{ + CELL_CAMERA_PLFREQ_DISABLED = 0, + CELL_CAMERA_PLFREQ_50Hz = 1, + CELL_CAMERA_PLFREQ_60Hz = 2, +}; + +// DEVICECAP +enum +{ + CELL_CAMERA_CTC_SCANNING_MODE = (1 << 0), + CELL_CAMERA_CTC_AUTO_EXPOSURE_MODE = (1 << 1), + CELL_CAMERA_CTC_AUTO_EXPOSURE_PRIORITY = (1 << 2), + CELL_CAMERA_CTC_EXPOSURE_TIME_ABS = (1 << 3), + CELL_CAMERA_CTC_EXPOSURE_TIME_REL = (1 << 4), + CELL_CAMERA_CTC_FOCUS_ABS = (1 << 5), + CELL_CAMERA_CTC_FOCUS_REL = (1 << 6), + CELL_CAMERA_CTC_IRIS_ABS = (1 << 7), + CELL_CAMERA_CTC_IRIS_REL = (1 << 8), + CELL_CAMERA_CTC_ZOOM_ABS = (1 << 9), + CELL_CAMERA_CTC_ZOOM_REL = (1 << 10), + CELL_CAMERA_CTC_PANTILT_ABS = (1 << 11), + CELL_CAMERA_CTC_PANTILT_REL = (1 << 12), + CELL_CAMERA_CTC_ROLL_ABS = (1 << 13), + CELL_CAMERA_CTC_ROLL_REL = (1 << 14), + CELL_CAMERA_CTC_RESERVED_15 = (1 << 15), + CELL_CAMERA_CTC_RESERVED_16 = (1 << 16), + CELL_CAMERA_CTC_FOCUS_AUTO = (1 << 17), + CELL_CAMERA_CTC_PRIVACY = (1 << 18), + + CELL_CAMERA_PUC_BRIGHTNESS = (1 << 0), + CELL_CAMERA_PUC_CONTRAST = (1 << 1), + CELL_CAMERA_PUC_HUE = (1 << 2), + CELL_CAMERA_PUC_SATURATION = (1 << 3), + CELL_CAMERA_PUC_SHARPNESS = (1 << 4), + CELL_CAMERA_PUC_GAMMA = (1 << 5), + CELL_CAMERA_PUC_WHITE_BALANCE_TEMPERATURE = (1 << 6), + CELL_CAMERA_PUC_WHITE_BALANCE_COMPONENT = (1 << 7), + CELL_CAMERA_PUC_BACKLIGHT_COMPENSATION = (1 << 8), + CELL_CAMERA_PUC_GAIN = (1 << 9), + CELL_CAMERA_PUC_POWER_LINE_FREQUENCY = (1 << 10), + CELL_CAMERA_PUC_HUE_AUTO = (1 << 11), + CELL_CAMERA_PUC_WHITE_BALANCE_TEMPERATURE_AUTO = (1 << 12), + CELL_CAMERA_PUC_WHITE_BALANCE_COMPONENT_AUTO = (1 << 13), + CELL_CAMERA_PUC_DIGITAL_MULTIPLIER = (1 << 14), + CELL_CAMERA_PUC_DIGITAL_MULTIPLIER_LIMIT = (1 << 15), + CELL_CAMERA_PUC_ANALOG_VIDEO_STANDARD = (1 << 16), + CELL_CAMERA_PUC_ANALOG_VIDEO_LOCK_STATUS = (1 << 17), +}; + +// UVCREQCODE Control Selector +enum +{ + CELL_CAMERA_CS_SHIFT = 0, + CELL_CAMERA_CS_BITS = 0x000000ff, + CELL_CAMERA_CAP_SHIFT = 8, + CELL_CAMERA_CAP_BITS = 0x0000ff00, + CELL_CAMERA_NUM_SHIFT = 16, + CELL_CAMERA_NUM_BITS = 0x000f0000, + CELL_CAMERA_NUM_1 = 0x00010000, + CELL_CAMERA_NUM_2 = 0x00020000, + CELL_CAMERA_NUM_3 = 0x00030000, + CELL_CAMERA_NUM_4 = 0x00040000, + CELL_CAMERA_LEN_SHIFT = 20, + CELL_CAMERA_LEN_BITS = 0x00f00000, + CELL_CAMERA_LEN_1 = 0x00100000, + CELL_CAMERA_LEN_2 = 0x00200000, + CELL_CAMERA_LEN_4 = 0x00400000, + CELL_CAMERA_ID_SHIFT = 24, + CELL_CAMERA_ID_BITS = 0x0f000000, + CELL_CAMERA_ID_CT = 0x01000000, + CELL_CAMERA_ID_SU = 0x02000000, + CELL_CAMERA_ID_PU = 0x04000000, +}; + +// UVCREQCODE Camera Terminal Control +enum +{ + CELL_CAMERA_UVC_SCANNING_MODE = 0x01110001, + CELL_CAMERA_UVC_AUTO_EXPOSURE_MODE = 0x01110102, + CELL_CAMERA_UVC_AUTO_EXPOSURE_PRIORITY = 0x01110203, + CELL_CAMERA_UVC_EXPOSURE_TIME_ABS = 0x01410304, + CELL_CAMERA_UVC_EXPOSURE_TIME_REL = 0x01110405, + CELL_CAMERA_UVC_FOCUS_ABS = 0x01210506, + CELL_CAMERA_UVC_FOCUS_REL = 0x01120607, + CELL_CAMERA_UVC_FOCUS_AUTO = 0x01111108, + CELL_CAMERA_UVC_IRIS_ABS = 0x01210709, + CELL_CAMERA_UVC_IRIS_REL = 0x0111080a, + CELL_CAMERA_UVC_ZOOM_ABS = 0x0121090b, + CELL_CAMERA_UVC_ZOOM_REL = 0x01130a0c, + CELL_CAMERA_UVC_PANTILT_ABS = 0x01420b0d, + CELL_CAMERA_UVC_PANTILT_REL = 0x01140c0e, + CELL_CAMERA_UVC_ROLL_ABS = 0x01210d0f, + CELL_CAMERA_UVC_ROLL_REL = 0x01120e10, + CELL_CAMERA_UVC_PRIVACY = 0x01111211, +}; + +// UVCREQCODE Selector Unit Control/Processing Unit Control +enum +{ + CELL_CAMERA_UVC_INPUT_SELECT = 0x02110101, + + CELL_CAMERA_UVC_BACKLIGHT_COMPENSATION = 0x04210801, + CELL_CAMERA_UVC_BRIGHTNESS = 0x04210002, + CELL_CAMERA_UVC_CONTRAST = 0x04210103, + CELL_CAMERA_UVC_GAIN = 0x04210904, + CELL_CAMERA_UVC_POWER_LINE_FREQUENCY = 0x04110a05, + CELL_CAMERA_UVC_HUE = 0x04210206, + CELL_CAMERA_UVC_HUE_AUTO = 0x04110b10, + CELL_CAMERA_UVC_SATURATION = 0x04210307, + CELL_CAMERA_UVC_SHARPNESS = 0x04210408, + CELL_CAMERA_UVC_GAMMA = 0x04210509, + CELL_CAMERA_UVC_WHITE_BALANCE_TEMPERATURE = 0x0421060a, + CELL_CAMERA_UVC_WHITE_BALANCE_TEMPERATURE_AUTO = 0x04110c0b, + CELL_CAMERA_UVC_WHITE_BALANCE_COMPONENT = 0x0422070c, + CELL_CAMERA_UVC_WHITE_BALANCE_COMPONENT_AUTO = 0x04110d0d, + CELL_CAMERA_UVC_DIGITAL_MULTIPLIER = 0x04210e0e, + CELL_CAMERA_UVC_DIGITAL_MULTIPLIER_LIMIT = 0x04210f0f, + CELL_CAMERA_UVC_ANALOG_VIDEO_STANDARD = 0x04111011, + CELL_CAMERA_UVC_ANALOG_VIDEO_LOCK_STATUS = 0x04111112, +}; + +// UVCREQCODE Request code bits +enum +{ + CELL_CAMERA_RC_CUR = 0x81, + CELL_CAMERA_RC_MIN = 0x82, + CELL_CAMERA_RC_MAX = 0x83, + CELL_CAMERA_RC_RES = 0x84, + CELL_CAMERA_RC_LEN = 0x85, + CELL_CAMERA_RC_INFO = 0x86, + CELL_CAMERA_RC_DEF = 0x87, +}; + // Camera types enum CellCameraType { @@ -41,7 +214,7 @@ enum CellCameraFormat CELL_CAMERA_Y0_U_Y1_V = CELL_CAMERA_YUV422, }; -// Image resolutiom +// Image resolution enum CellCameraResolution { CELL_CAMERA_RESOLUTION_UNKNOWN, @@ -51,6 +224,64 @@ enum CellCameraResolution CELL_CAMERA_SPECIFIED_WIDTH_HEIGHT, }; +// Camera attributes +enum CellCameraAttribute +{ + CELL_CAMERA_GAIN, + CELL_CAMERA_REDBLUEGAIN, + CELL_CAMERA_SATURATION, + CELL_CAMERA_EXPOSURE, + CELL_CAMERA_BRIGHTNESS, + CELL_CAMERA_AEC, + CELL_CAMERA_AGC, + CELL_CAMERA_AWB, + CELL_CAMERA_ABC, + CELL_CAMERA_LED, + CELL_CAMERA_AUDIOGAIN, + CELL_CAMERA_QS, + CELL_CAMERA_NONZEROCOEFFS, + CELL_CAMERA_YUVFLAG, + CELL_CAMERA_JPEGFLAG, + CELL_CAMERA_BACKLIGHTCOMP, + CELL_CAMERA_MIRRORFLAG, + CELL_CAMERA_MEASUREDQS, + CELL_CAMERA_422FLAG, + CELL_CAMERA_USBLOAD, + CELL_CAMERA_GAMMA, + CELL_CAMERA_GREENGAIN, + CELL_CAMERA_AGCLIMIT, + CELL_CAMERA_DENOISE, + CELL_CAMERA_FRAMERATEADJUST, + CELL_CAMERA_PIXELOUTLIERFILTER, + CELL_CAMERA_AGCLOW, + CELL_CAMERA_AGCHIGH, + CELL_CAMERA_DEVICELOCATION, + + CELL_CAMERA_FORMATCAP = 100, + CELL_CAMERA_FORMATINDEX, + CELL_CAMERA_NUMFRAME, + CELL_CAMERA_FRAMEINDEX, + CELL_CAMERA_FRAMESIZE, + CELL_CAMERA_INTERVALTYPE, + CELL_CAMERA_INTERVALINDEX, + CELL_CAMERA_INTERVALVALUE, + CELL_CAMERA_COLORMATCHING, + CELL_CAMERA_PLFREQ, + CELL_CAMERA_DEVICEID, + CELL_CAMERA_DEVICECAP, + CELL_CAMERA_DEVICESPEED, + CELL_CAMERA_UVCREQCODE, + CELL_CAMERA_UVCREQDATA, + CELL_CAMERA_DEVICEID2, + + CELL_CAMERA_READMODE = 300, + CELL_CAMERA_GAMEPID, + CELL_CAMERA_PBUFFER, + CELL_CAMERA_READFINISH, + + CELL_CAMERA_ATTRIBUTE_UNKNOWN = 500, +}; + struct CellCameraInfoEx { CellCameraFormat format; @@ -68,6 +299,71 @@ struct CellCameraInfoEx be_t pbuf[2]; }; +// Custom struct for keeping track of camera attributes +struct CellCameraAttributes +{ + u32 GAIN; + u32 REDBLUEGAIN; + u32 SATURATION; + u32 EXPOSURE; + u32 BRIGHTNESS; + u32 AEC; + u32 AGC; + u32 AWB; + u32 ABC; + u32 LED; + u32 AUDIOGAIN; + u32 QS; + u32 NONZEROCOEFFS[1]; + u32 YUVFLAG; + u32 JPEGFLAG; + u32 BACKLIGHTCOMP; + u32 MIRRORFLAG; + u32 MEASUREDQS; + u32 _422FLAG; + u32 USBLOAD; + u32 GAMMA; + u32 GREENGAIN; + u32 AGCLIMIT; + u32 DENOISE; + u32 FRAMERATEADJUST; + u32 PIXELOUTLIERFILTER; + u32 AGCLOW; + u32 AGCHIGH; + u32 DEVICELOCATION; + + u32 FORMATCAP = 100; + u32 FORMATINDEX; + u32 NUMFRAME; + u32 FRAMEINDEX; + u32 FRAMESIZE; + u32 INTERVALTYPE; + u32 INTERVALINDEX; + u32 INTERVALVALUE; + u32 COLORMATCHING; + u32 PLFREQ; + u32 DEVICEID; + u32 DEVICECAP; + u32 DEVICESPEED; + u32 UVCREQCODE; + u32 UVCREQDATA; + u32 DEVICEID2; + + u32 READMODE = 300; + u32 GAMEPID; + u32 PBUFFER; + u32 READFINISH; + + u32 ATTRIBUTE_UNKNOWN = 500; +}; + +// Custom struct to keep track of cameras +struct CellCamera +{ + CellCameraAttributes attributes; + CellCameraInfoEx info; +}; + struct CellCameraReadEx { be_t version; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGem.cpp b/rpcs3/Emu/SysCalls/Modules/cellGem.cpp index 118a428a0a..2d629dd16d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGem.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGem.cpp @@ -9,6 +9,7 @@ Module *cellGem = nullptr; struct cellGemInternal { bool m_bInitialized; + CellGemAttribute attribute; cellGemInternal() : m_bInitialized(false) @@ -180,13 +181,19 @@ int cellGemGetInertialState() return CELL_OK; } -int cellGemGetInfo() +int cellGemGetInfo(vm::ptr info) { - UNIMPLEMENTED_FUNC(cellGem); + cellGem->Warning("cellGemGetInfo(info=0x%x)", info.addr()); if (!cellGemInstance.m_bInitialized) return CELL_GEM_ERROR_UNINITIALIZED; + info->max_connect = cellGemInstance.attribute.max_connect; + // TODO: Support many controllers to be connected + info->now_connect = 1; + info->status[0] = CELL_GEM_STATUS_READY; + info->port[0] = 7; + return CELL_OK; } @@ -264,6 +271,7 @@ int cellGemInit(vm::ptr attribute) return CELL_GEM_ERROR_ALREADY_INITIALIZED; cellGemInstance.m_bInitialized = true; + cellGemInstance.attribute = *attribute; return CELL_OK; } diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 975af52f18..72f992a999 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -475,6 +475,7 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) #endif cbox_camera->Append("Null"); + cbox_camera->Append("Connected"); cbox_camera_type->Append("Unknown"); cbox_camera_type->Append("EyeToy"); diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index 6b3b9b1e02..6f2b9a7a11 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -268,7 +268,7 @@ public: AudioConvertToU16.Load(false); // Camera - Camera.Load(0); + Camera.Load(1); CameraType.Load(2); // Input/Ouput From 5986448d67cc0e7cc761ed35123bfeb761e7e1ce Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 12 Feb 2015 11:44:53 +0300 Subject: [PATCH 94/94] Small fix --- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 6 +++--- rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 5f8dc1c7a1..48669968f1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2660,7 +2660,7 @@ s64 cellSpursCreateTaskset(vm::ptr spurs, vm::ptr t return CELL_OK; #endif - return spursCreateTaskset(spurs, taskset, args, priority, maxContention, vm::ptr::make(0), CellSpursTaskset::size, 0); + return spursCreateTaskset(spurs, taskset, args, priority, maxContention, vm::ptr::make(0), 6400/*CellSpursTaskset::size*/, 0); } s64 cellSpursJoinTaskset(vm::ptr taskset) @@ -2990,7 +2990,7 @@ s64 cellSpursTasksetAttributeSetTasksetSize(vm::ptr a return CELL_SPURS_TASK_ERROR_ALIGN; } - if (size != CellSpursTaskset::size && size != CellSpursTaskset2::size) + if (size != 6400/*CellSpursTaskset::size*/ && size != CellSpursTaskset2::size) { return CELL_SPURS_TASK_ERROR_INVAL; } @@ -3425,7 +3425,7 @@ s64 _cellSpursTasksetAttributeInitialize(vm::ptr attr attribute->m.sdk_version = sdk_version; attribute->m.args = args; memcpy(attribute->m.priority, priority.get_ptr(), 8); - attribute->m.taskset_size = CellSpursTaskset::size; + attribute->m.taskset_size = 6400/*CellSpursTaskset::size*/; attribute->m.max_contention = max_contention; return CELL_OK; #endif diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp index 794a17af82..67f07e0bd3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp @@ -525,12 +525,12 @@ bool spursKernelWorkloadExit(SPUThread & spu) { /// SPURS kernel entry point bool spursKernelEntry(SPUThread & spu) { - //while (true) { - // std::this_thread::sleep_for(std::chrono::milliseconds(100)); - // if (Emu.IsStopped()) { - // return false; - // } - //} + while (true) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + if (Emu.IsStopped()) { + return false; + } + } auto ctxt = vm::get_ptr(spu.ls_offset + 0x100); memset(ctxt, 0, sizeof(SpursKernelContext)); @@ -598,7 +598,7 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) { bool shouldExit; while (true) { - vm::reservation_acquire(vm::get_ptr(spu.ls_offset + 0x100), vm::cast(ctxt->spurs.addr()), 128/*, [&spu](){ spu.Notify(); }*/); + vm::reservation_acquire(vm::get_ptr(spu.ls_offset + 0x100), vm::cast(ctxt->spurs.addr()), 128, [&spu](){ spu.Notify(); }); auto spurs = vm::get_ptr(spu.ls_offset + 0x100); // Find the number of SPUs that are idling in this SPURS instance