From 4ee72869cce3625f25fb516a8980460510df6041 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 May 2014 18:50:36 -0400 Subject: - added some function wrappers for HLE - added stub for SVC CreateAddressArbiter - added OutputDebugString SVC --- src/core/hle/function_wrappers.h | 20 ++++++++++++-------- src/core/hle/syscall.cpp | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 10 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 4897d3f28..53bfafa78 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -158,8 +158,8 @@ template void WrapI_UUUUU() { RETURN(retval); } -template void WrapI_V() { - int retval = func(); +template void WrapI_V() { + u32 retval = func(Memory::GetPointer(PARAM(0))); RETURN(retval); } @@ -638,6 +638,10 @@ template void WrapU_CC() { RETURN(retval); } +template void WrapV_C() { + func(Memory::GetCharPointer(PARAM(0))); +} + template void WrapV_CI() { func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); } @@ -716,18 +720,18 @@ template void WrapI_ICI() { } template void WrapI_IVVVVUI(){ - u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); - RETURN(retval); + u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) ); + RETURN(retval); } template void WrapI_ICUVIII(){ - u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); - RETURN(retval); + u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6)); + RETURN(retval); } template void WrapI_VUUUUU(){ - u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); - RETURN(retval); + u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); + RETURN(retval); } template void WrapI_US64() { diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp index df6412743..cc5b561b5 100644 --- a/src/core/hle/syscall.cpp +++ b/src/core/hle/syscall.cpp @@ -82,15 +82,30 @@ Result SendSyncRequest(Handle session) { /// Close a handle Result CloseHandle(Handle handle) { // ImplementMe + NOTICE_LOG(OSHLE, "stubbed function CloseHandle"); return 0; } /// Wait for a handle to synchronize, timeout after the specified nanoseconds Result WaitSynchronization1(Handle handle, s64 nanoseconds) { // ImplementMe + NOTICE_LOG(OSHLE, "stubbed function WaitSynchronization1"); return 0; } +/// Create an address arbiter (to allocate access to shared resources) +Result CreateAddressArbiter(void* arbiter) { + // ImplementMe + NOTICE_LOG(OSHLE, "stubbed function CreateAddressArbiter"); + Core::g_app_core->SetReg(1, 0xDEADBEEF); + return 0; +} + +/// Used to output a message on a debug hardware unit - does nothing on a retail unit +void OutputDebugString(const char* string) { + NOTICE_LOG(OSHLE, "## OSDEBUG: %s", string); +} + const HLE::FunctionDef Syscall_Table[] = { {0x00, NULL, "Unknown"}, {0x01, WrapI_UUUUU, "ControlMemory"}, @@ -125,7 +140,7 @@ const HLE::FunctionDef Syscall_Table[] = { {0x1E, NULL, "CreateMemoryBlock"}, {0x1F, WrapI_UUUU, "MapMemoryBlock"}, {0x20, NULL, "UnmapMemoryBlock"}, - {0x21, NULL, "CreateAddressArbiter"}, + {0x21, WrapI_V, "CreateAddressArbiter"}, {0x22, NULL, "ArbitrateAddress"}, {0x23, WrapI_U, "CloseHandle"}, {0x24, WrapI_US64, "WaitSynchronization1"}, @@ -153,7 +168,7 @@ const HLE::FunctionDef Syscall_Table[] = { {0x3A, NULL, "GetResourceLimitCurrentValues"}, {0x3B, NULL, "GetThreadContext"}, {0x3C, NULL, "Break"}, - {0x3D, NULL, "OutputDebugString"}, + {0x3D, WrapV_C, "OutputDebugString"}, {0x3E, NULL, "ControlPerformanceCounter"}, {0x3F, NULL, "Unknown"}, {0x40, NULL, "Unknown"}, -- cgit v1.2.3 From f0434249150f27d7921a57f70d6af11c12c4e08f Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 May 2014 19:20:44 -0400 Subject: renamed hle "mrc" module to "coprocessor" --- src/core/hle/coprocessor.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/core/hle/coprocessor.h | 20 ++++++++++++++ src/core/hle/mrc.cpp | 64 -------------------------------------------- src/core/hle/mrc.h | 20 -------------- 4 files changed, 84 insertions(+), 84 deletions(-) create mode 100644 src/core/hle/coprocessor.cpp create mode 100644 src/core/hle/coprocessor.h delete mode 100644 src/core/hle/mrc.cpp delete mode 100644 src/core/hle/mrc.h (limited to 'src/core/hle') diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp new file mode 100644 index 000000000..5223be7c9 --- /dev/null +++ b/src/core/hle/coprocessor.cpp @@ -0,0 +1,64 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "core/hle/mrc.h" +#include "core/hle/hle.h" +#include "core/mem_map.h" +#include "core/core.h" + +namespace HLE { + +enum { + CMD_GX_REQUEST_DMA = 0x00000000, +}; + +/// Data synchronization barrier +u32 DataSynchronizationBarrier(u32* command_buffer) { + u32 command = command_buffer[0]; + + switch (command) { + + case CMD_GX_REQUEST_DMA: + { + u32* src = (u32*)Memory::GetPointer(command_buffer[1]); + u32* dst = (u32*)Memory::GetPointer(command_buffer[2]); + u32 size = command_buffer[3]; + memcpy(dst, src, size); + } + break; + + default: + ERROR_LOG(OSHLE, "MRC::DataSynchronizationBarrier unknown command 0x%08X", command); + return -1; + } + + return 0; +} + +/// Returns the coprocessor (in this case, syscore) command buffer pointer +Addr GetThreadCommandBuffer() { + // Called on insruction: mrc p15, 0, r0, c13, c0, 3 + // Returns an address in OSHLE memory for the CPU to read/write to + RETURN(CMD_BUFFER_ADDR); + return CMD_BUFFER_ADDR; +} + +/// Call an MRC operation in HLE +u32 CallMRC(ARM11_MRC_OPERATION operation) { + switch (operation) { + + case DATA_SYNCHRONIZATION_BARRIER: + return DataSynchronizationBarrier((u32*)Memory::GetPointer(PARAM(0))); + + case CALL_GET_THREAD_COMMAND_BUFFER: + return GetThreadCommandBuffer(); + + default: + ERROR_LOG(OSHLE, "unimplemented MRC operation 0x%02X", operation); + break; + } + return -1; +} + +} // namespace diff --git a/src/core/hle/coprocessor.h b/src/core/hle/coprocessor.h new file mode 100644 index 000000000..d6b9f162f --- /dev/null +++ b/src/core/hle/coprocessor.h @@ -0,0 +1,20 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +namespace HLE { + +/// MRC operations (ARM register from coprocessor), decoded as instr[20:27] +enum ARM11_MRC_OPERATION { + DATA_SYNCHRONIZATION_BARRIER = 0xE0, + CALL_GET_THREAD_COMMAND_BUFFER = 0xE1, +}; + +/// Call an MRC operation in HLE +u32 CallMRC(ARM11_MRC_OPERATION operation); + +} // namespace diff --git a/src/core/hle/mrc.cpp b/src/core/hle/mrc.cpp deleted file mode 100644 index 5223be7c9..000000000 --- a/src/core/hle/mrc.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include "core/hle/mrc.h" -#include "core/hle/hle.h" -#include "core/mem_map.h" -#include "core/core.h" - -namespace HLE { - -enum { - CMD_GX_REQUEST_DMA = 0x00000000, -}; - -/// Data synchronization barrier -u32 DataSynchronizationBarrier(u32* command_buffer) { - u32 command = command_buffer[0]; - - switch (command) { - - case CMD_GX_REQUEST_DMA: - { - u32* src = (u32*)Memory::GetPointer(command_buffer[1]); - u32* dst = (u32*)Memory::GetPointer(command_buffer[2]); - u32 size = command_buffer[3]; - memcpy(dst, src, size); - } - break; - - default: - ERROR_LOG(OSHLE, "MRC::DataSynchronizationBarrier unknown command 0x%08X", command); - return -1; - } - - return 0; -} - -/// Returns the coprocessor (in this case, syscore) command buffer pointer -Addr GetThreadCommandBuffer() { - // Called on insruction: mrc p15, 0, r0, c13, c0, 3 - // Returns an address in OSHLE memory for the CPU to read/write to - RETURN(CMD_BUFFER_ADDR); - return CMD_BUFFER_ADDR; -} - -/// Call an MRC operation in HLE -u32 CallMRC(ARM11_MRC_OPERATION operation) { - switch (operation) { - - case DATA_SYNCHRONIZATION_BARRIER: - return DataSynchronizationBarrier((u32*)Memory::GetPointer(PARAM(0))); - - case CALL_GET_THREAD_COMMAND_BUFFER: - return GetThreadCommandBuffer(); - - default: - ERROR_LOG(OSHLE, "unimplemented MRC operation 0x%02X", operation); - break; - } - return -1; -} - -} // namespace diff --git a/src/core/hle/mrc.h b/src/core/hle/mrc.h deleted file mode 100644 index d6b9f162f..000000000 --- a/src/core/hle/mrc.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -namespace HLE { - -/// MRC operations (ARM register from coprocessor), decoded as instr[20:27] -enum ARM11_MRC_OPERATION { - DATA_SYNCHRONIZATION_BARRIER = 0xE0, - CALL_GET_THREAD_COMMAND_BUFFER = 0xE1, -}; - -/// Call an MRC operation in HLE -u32 CallMRC(ARM11_MRC_OPERATION operation); - -} // namespace -- cgit v1.2.3 From c1e71ae1ac6700e2e849c59e55baeacda7a20ae6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 May 2014 19:21:04 -0400 Subject: fixed include in coprocessor.cpp --- src/core/hle/coprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle') diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp index 5223be7c9..5b412c586 100644 --- a/src/core/hle/coprocessor.cpp +++ b/src/core/hle/coprocessor.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include "core/hle/mrc.h" +#include "core/hle/coprocessor.h" #include "core/hle/hle.h" #include "core/mem_map.h" #include "core/core.h" -- cgit v1.2.3 From f7c6302009aa2453c37a6a7a3b1af4843f620078 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 1 May 2014 23:03:50 -0400 Subject: - added CallMCR function to coprocessor HLE module - moved instruction decoding to coprocessor HLE module --- src/core/hle/coprocessor.cpp | 16 +++++++++++++--- src/core/hle/coprocessor.h | 11 +++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp index 5b412c586..df1362176 100644 --- a/src/core/hle/coprocessor.cpp +++ b/src/core/hle/coprocessor.cpp @@ -44,8 +44,18 @@ Addr GetThreadCommandBuffer() { return CMD_BUFFER_ADDR; } -/// Call an MRC operation in HLE -u32 CallMRC(ARM11_MRC_OPERATION operation) { +/// Call an MCR (move to coprocessor from ARM register) instruction in HLE +s32 CallMCR(u32 instruction, u32 value) { + CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF); + ERROR_LOG(OSHLE, "unimplemented MCR instruction=0x%08X, operation=%02X, value=%08X", + instruction, operation, value); + return -1; +} + +/// Call an MRC (move to ARM register from coprocessor) instruction in HLE +s32 CallMRC(u32 instruction) { + CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF); + switch (operation) { case DATA_SYNCHRONIZATION_BARRIER: @@ -55,7 +65,7 @@ u32 CallMRC(ARM11_MRC_OPERATION operation) { return GetThreadCommandBuffer(); default: - ERROR_LOG(OSHLE, "unimplemented MRC operation 0x%02X", operation); + ERROR_LOG(OSHLE, "unimplemented MRC instruction 0x%08X", instruction); break; } return -1; diff --git a/src/core/hle/coprocessor.h b/src/core/hle/coprocessor.h index d6b9f162f..03822af13 100644 --- a/src/core/hle/coprocessor.h +++ b/src/core/hle/coprocessor.h @@ -8,13 +8,16 @@ namespace HLE { -/// MRC operations (ARM register from coprocessor), decoded as instr[20:27] -enum ARM11_MRC_OPERATION { +/// Coprocessor operations +enum CoprocessorOperation { DATA_SYNCHRONIZATION_BARRIER = 0xE0, CALL_GET_THREAD_COMMAND_BUFFER = 0xE1, }; -/// Call an MRC operation in HLE -u32 CallMRC(ARM11_MRC_OPERATION operation); +/// Call an MCR (move to coprocessor from ARM register) instruction in HLE +s32 CallMCR(u32 instruction, u32 value); + +/// Call an MRC (move to ARM register from coprocessor) instruction in HLE +s32 CallMRC(u32 instruction); } // namespace -- cgit v1.2.3 From 34dc0a9b0750321d9556ac2e9c57007526096caf Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 6 May 2014 23:29:39 -0400 Subject: added config_mem module for HLE of firmware configuration memory settings --- src/core/hle/config_mem.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++ src/core/hle/config_mem.h | 21 ++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/core/hle/config_mem.cpp create mode 100644 src/core/hle/config_mem.h (limited to 'src/core/hle') diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp new file mode 100644 index 000000000..48aa878cc --- /dev/null +++ b/src/core/hle/config_mem.cpp @@ -0,0 +1,70 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "common/log.h" + +#include "core/hle/config_mem.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace ConfigMem { + +enum { + KERNEL_VERSIONREVISION = 0x1FF80001, + KERNEL_VERSIONMINOR = 0x1FF80002, + KERNEL_VERSIONMAJOR = 0x1FF80003, + UPDATEFLAG = 0x1FF80004, + NSTID = 0x1FF80008, + SYSCOREVER = 0x1FF80010, + UNITINFO = 0x1FF80014, + KERNEL_CTRSDKVERSION = 0x1FF80018, + APPMEMTYPE = 0x1FF80030, + APPMEMALLOC = 0x1FF80040, + FIRM_VERSIONREVISION = 0x1FF80061, + FIRM_VERSIONMINOR = 0x1FF80062, + FIRM_VERSIONMAJOR = 0x1FF80063, + FIRM_SYSCOREVER = 0x1FF80064, + FIRM_CTRSDKVERSION = 0x1FF80068, +}; + +template +inline void Read(T &var, const u32 addr) { + switch (addr) { + + // Bit 0 set for Retail + case UNITINFO: + var = 0x00000001; + break; + + // Set app memory size to 64MB? + case APPMEMALLOC: + var = 0x04000000; + break; + + // Unknown - normally set to: 0x08000000 - (APPMEMALLOC + *0x1FF80048) + // (Total FCRAM size - APPMEMALLOC - *0x1FF80048) + case 0x1FF80044: + var = 0x08000000 - (0x04000000 + 0x1400000); + break; + + // Unknown - normally set to: 0x1400000 (20MB) + case 0x1FF80048: + var = 0x1400000; + break; + + default: + ERROR_LOG(HLE, "unknown ConfigMem::Read%d @ 0x%08X", sizeof(var) * 8, addr); + } +} + +// Explicitly instantiate template functions because we aren't defining this in the header: + +template void Read(u64 &var, const u32 addr); +template void Read(u32 &var, const u32 addr); +template void Read(u16 &var, const u32 addr); +template void Read(u8 &var, const u32 addr); + + +} // namespace diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h new file mode 100644 index 000000000..da396a3e6 --- /dev/null +++ b/src/core/hle/config_mem.h @@ -0,0 +1,21 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +// Configuration memory stores various hardware/kernel configuration settings. This memory page is +// read-only for ARM11 processes. I'm guessing this would normally be written to by the firmware/ +// bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm +// putting this as a subset of HLE for now. + +#include "common/common_types.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace ConfigMem { + +template +inline void Read(T &var, const u32 addr); + +} // namespace -- cgit v1.2.3 From de36d82ddec86eb0aa3384af935a47fe2879935e Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 6 May 2014 23:34:20 -0400 Subject: - added debug logging to syscall.cpp - added stubbed HLE syscall functions for svc_GetResourceLimit and svc_GetResourceLimitCurrentValues --- src/core/hle/function_wrappers.h | 12 +- src/core/hle/syscall.cpp | 296 +++++++++++++++++++++------------------ 2 files changed, 173 insertions(+), 135 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 53bfafa78..18b01b14b 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -729,7 +729,17 @@ template void WrapI_ICU RETURN(retval); } -template void WrapI_VUUUUU(){ +template void WrapI_VU(){ + u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1)); + RETURN(retval); +} + +template void WrapI_VUVI(){ + u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), PARAM(3)); + RETURN(retval); +} + +template void WrapI_VUUUUU(){ u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); RETURN(retval); } diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp index cc5b561b5..5b4d47485 100644 --- a/src/core/hle/syscall.cpp +++ b/src/core/hle/syscall.cpp @@ -29,6 +29,9 @@ enum MapMemoryPermission { Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { u32 virtual_address = 0x00000000; + DEBUG_LOG(SVC, "ControlMemory called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", + operation, addr0, addr1, size, permissions); + switch (operation) { // Map normal heap memory @@ -43,16 +46,18 @@ Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissi // Unknown ControlMemory operation default: - ERROR_LOG(OSHLE, "Unknown ControlMemory operation %08X", operation); + ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation); } - + DEBUG_LOG(SVC, "...returned virtual_address=0x%08X", virtual_address); Core::g_app_core->SetReg(1, virtual_address); + return 0; } /// Maps a memory block to specified address Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) { - int x = 0; + DEBUG_LOG(SVC, "MapMemoryBlock called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", + memblock, addr, mypermissions, otherpermission); switch (mypermissions) { case MEMORY_PERMISSION_NORMAL: case MEMORY_PERMISSION_NORMAL + 1: @@ -60,20 +65,23 @@ Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherper Memory::MapBlock_Shared(memblock, addr, mypermissions); break; default: - ERROR_LOG(OSHLE, "Unknown MapMemoryBlock permissions %08X", mypermissions); + ERROR_LOG(OSHLE, "MapMemoryBlock unknown permissions=0x%08X", mypermissions); } return 0; } /// Connect to an OS service given the port name, returns the handle to the port to out Result ConnectToPort(void* out, const char* port_name) { + Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); Core::g_app_core->SetReg(1, service->GetUID()); + DEBUG_LOG(SVC, "ConnectToPort called port_name=%s", port_name); return 0; } /// Synchronize to an OS service Result SendSyncRequest(Handle session) { + DEBUG_LOG(SVC, "SendSyncRequest called session=0x%08X"); Service::Interface* service = Service::g_manager->FetchFromUID(session); service->Sync(); return 0; @@ -82,157 +90,177 @@ Result SendSyncRequest(Handle session) { /// Close a handle Result CloseHandle(Handle handle) { // ImplementMe - NOTICE_LOG(OSHLE, "stubbed function CloseHandle"); + DEBUG_LOG(SVC, "(UNIMPLEMENTED) CloseHandle called handle=0x%08X", handle); return 0; } /// Wait for a handle to synchronize, timeout after the specified nanoseconds Result WaitSynchronization1(Handle handle, s64 nanoseconds) { // ImplementMe - NOTICE_LOG(OSHLE, "stubbed function WaitSynchronization1"); + DEBUG_LOG(SVC, "(UNIMPLEMENTED) WaitSynchronization1 called handle=0x%08X, nanoseconds=%d", + handle, nanoseconds); return 0; } /// Create an address arbiter (to allocate access to shared resources) Result CreateAddressArbiter(void* arbiter) { // ImplementMe - NOTICE_LOG(OSHLE, "stubbed function CreateAddressArbiter"); + DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateAddressArbiter called"); Core::g_app_core->SetReg(1, 0xDEADBEEF); return 0; } /// Used to output a message on a debug hardware unit - does nothing on a retail unit void OutputDebugString(const char* string) { - NOTICE_LOG(OSHLE, "## OSDEBUG: %s", string); + NOTICE_LOG(SVC, "## OSDEBUG: %08X %s", Core::g_app_core->GetPC(), string); +} + +/// Get resource limit +Result GetResourceLimit(void* resource_limit, Handle process) { + // With regards to proceess values: + // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for + // the current KThread. + DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimit called process=0x%08X", process); + Core::g_app_core->SetReg(1, 0xDEADBEEF); + return 0; +} + +/// Get resource limit current values +Result GetResourceLimitCurrentValues(void* _values, Handle resource_limit, void* names, s32 name_count) { + //s64* values = (s64*)_values; + DEBUG_LOG(SVC, "(UNIMPLEMENTED) GetResourceLimitCurrentValues called resource_limit=%08X, names=%s, name_count=%d", + resource_limit, names, name_count); + Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now + return 0; } const HLE::FunctionDef Syscall_Table[] = { - {0x00, NULL, "Unknown"}, - {0x01, WrapI_UUUUU, "ControlMemory"}, - {0x02, NULL, "QueryMemory"}, - {0x03, NULL, "ExitProcess"}, - {0x04, NULL, "GetProcessAffinityMask"}, - {0x05, NULL, "SetProcessAffinityMask"}, - {0x06, NULL, "GetProcessIdealProcessor"}, - {0x07, NULL, "SetProcessIdealProcessor"}, - {0x08, NULL, "CreateThread"}, - {0x09, NULL, "ExitThread"}, - {0x0A, NULL, "SleepThread"}, - {0x0B, NULL, "GetThreadPriority"}, - {0x0C, NULL, "SetThreadPriority"}, - {0x0D, NULL, "GetThreadAffinityMask"}, - {0x0E, NULL, "SetThreadAffinityMask"}, - {0x0F, NULL, "GetThreadIdealProcessor"}, - {0x10, NULL, "SetThreadIdealProcessor"}, - {0x11, NULL, "GetCurrentProcessorNumber"}, - {0x12, NULL, "Run"}, - {0x13, NULL, "CreateMutex"}, - {0x14, NULL, "ReleaseMutex"}, - {0x15, NULL, "CreateSemaphore"}, - {0x16, NULL, "ReleaseSemaphore"}, - {0x17, NULL, "CreateEvent"}, - {0x18, NULL, "SignalEvent"}, - {0x19, NULL, "ClearEvent"}, - {0x1A, NULL, "CreateTimer"}, - {0x1B, NULL, "SetTimer"}, - {0x1C, NULL, "CancelTimer"}, - {0x1D, NULL, "ClearTimer"}, - {0x1E, NULL, "CreateMemoryBlock"}, - {0x1F, WrapI_UUUU, "MapMemoryBlock"}, - {0x20, NULL, "UnmapMemoryBlock"}, - {0x21, WrapI_V, "CreateAddressArbiter"}, - {0x22, NULL, "ArbitrateAddress"}, - {0x23, WrapI_U, "CloseHandle"}, - {0x24, WrapI_US64, "WaitSynchronization1"}, - {0x25, NULL, "WaitSynchronizationN"}, - {0x26, NULL, "SignalAndWait"}, - {0x27, NULL, "DuplicateHandle"}, - {0x28, NULL, "GetSystemTick"}, - {0x29, NULL, "GetHandleInfo"}, - {0x2A, NULL, "GetSystemInfo"}, - {0x2B, NULL, "GetProcessInfo"}, - {0x2C, NULL, "GetThreadInfo"}, - {0x2D, WrapI_VC, "ConnectToPort"}, - {0x2E, NULL, "SendSyncRequest1"}, - {0x2F, NULL, "SendSyncRequest2"}, - {0x30, NULL, "SendSyncRequest3"}, - {0x31, NULL, "SendSyncRequest4"}, - {0x32, WrapI_U, "SendSyncRequest"}, - {0x33, NULL, "OpenProcess"}, - {0x34, NULL, "OpenThread"}, - {0x35, NULL, "GetProcessId"}, - {0x36, NULL, "GetProcessIdOfThread"}, - {0x37, NULL, "GetThreadId"}, - {0x38, NULL, "GetResourceLimit"}, - {0x39, NULL, "GetResourceLimitLimitValues"}, - {0x3A, NULL, "GetResourceLimitCurrentValues"}, - {0x3B, NULL, "GetThreadContext"}, - {0x3C, NULL, "Break"}, - {0x3D, WrapV_C, "OutputDebugString"}, - {0x3E, NULL, "ControlPerformanceCounter"}, - {0x3F, NULL, "Unknown"}, - {0x40, NULL, "Unknown"}, - {0x41, NULL, "Unknown"}, - {0x42, NULL, "Unknown"}, - {0x43, NULL, "Unknown"}, - {0x44, NULL, "Unknown"}, - {0x45, NULL, "Unknown"}, - {0x46, NULL, "Unknown"}, - {0x47, NULL, "CreatePort"}, - {0x48, NULL, "CreateSessionToPort"}, - {0x49, NULL, "CreateSession"}, - {0x4A, NULL, "AcceptSession"}, - {0x4B, NULL, "ReplyAndReceive1"}, - {0x4C, NULL, "ReplyAndReceive2"}, - {0x4D, NULL, "ReplyAndReceive3"}, - {0x4E, NULL, "ReplyAndReceive4"}, - {0x4F, NULL, "ReplyAndReceive"}, - {0x50, NULL, "BindInterrupt"}, - {0x51, NULL, "UnbindInterrupt"}, - {0x52, NULL, "InvalidateProcessDataCache"}, - {0x53, NULL, "StoreProcessDataCache"}, - {0x54, NULL, "FlushProcessDataCache"}, - {0x55, NULL, "StartInterProcessDma"}, - {0x56, NULL, "StopDma"}, - {0x57, NULL, "GetDmaState"}, - {0x58, NULL, "RestartDma"}, - {0x59, NULL, "Unknown"}, - {0x5A, NULL, "Unknown"}, - {0x5B, NULL, "Unknown"}, - {0x5C, NULL, "Unknown"}, - {0x5D, NULL, "Unknown"}, - {0x5E, NULL, "Unknown"}, - {0x5F, NULL, "Unknown"}, - {0x60, NULL, "DebugActiveProcess"}, - {0x61, NULL, "BreakDebugProcess"}, - {0x62, NULL, "TerminateDebugProcess"}, - {0x63, NULL, "GetProcessDebugEvent"}, - {0x64, NULL, "ContinueDebugEvent"}, - {0x65, NULL, "GetProcessList"}, - {0x66, NULL, "GetThreadList"}, - {0x67, NULL, "GetDebugThreadContext"}, - {0x68, NULL, "SetDebugThreadContext"}, - {0x69, NULL, "QueryDebugProcessMemory"}, - {0x6A, NULL, "ReadProcessMemory"}, - {0x6B, NULL, "WriteProcessMemory"}, - {0x6C, NULL, "SetHardwareBreakPoint"}, - {0x6D, NULL, "GetDebugThreadParam"}, - {0x6E, NULL, "Unknown"}, - {0x6F, NULL, "Unknown"}, - {0x70, NULL, "ControlProcessMemory"}, - {0x71, NULL, "MapProcessMemory"}, - {0x72, NULL, "UnmapProcessMemory"}, - {0x73, NULL, "Unknown"}, - {0x74, NULL, "Unknown"}, - {0x75, NULL, "Unknown"}, - {0x76, NULL, "TerminateProcess"}, - {0x77, NULL, "Unknown"}, - {0x78, NULL, "CreateResourceLimit"}, - {0x79, NULL, "Unknown"}, - {0x7A, NULL, "Unknown"}, - {0x7B, NULL, "Unknown"}, - {0x7C, NULL, "KernelSetState"}, - {0x7D, NULL, "QueryProcessMemory"}, + {0x00, NULL, "Unknown"}, + {0x01, WrapI_UUUUU, "ControlMemory"}, + {0x02, NULL, "QueryMemory"}, + {0x03, NULL, "ExitProcess"}, + {0x04, NULL, "GetProcessAffinityMask"}, + {0x05, NULL, "SetProcessAffinityMask"}, + {0x06, NULL, "GetProcessIdealProcessor"}, + {0x07, NULL, "SetProcessIdealProcessor"}, + {0x08, NULL, "CreateThread"}, + {0x09, NULL, "ExitThread"}, + {0x0A, NULL, "SleepThread"}, + {0x0B, NULL, "GetThreadPriority"}, + {0x0C, NULL, "SetThreadPriority"}, + {0x0D, NULL, "GetThreadAffinityMask"}, + {0x0E, NULL, "SetThreadAffinityMask"}, + {0x0F, NULL, "GetThreadIdealProcessor"}, + {0x10, NULL, "SetThreadIdealProcessor"}, + {0x11, NULL, "GetCurrentProcessorNumber"}, + {0x12, NULL, "Run"}, + {0x13, NULL, "CreateMutex"}, + {0x14, NULL, "ReleaseMutex"}, + {0x15, NULL, "CreateSemaphore"}, + {0x16, NULL, "ReleaseSemaphore"}, + {0x17, NULL, "CreateEvent"}, + {0x18, NULL, "SignalEvent"}, + {0x19, NULL, "ClearEvent"}, + {0x1A, NULL, "CreateTimer"}, + {0x1B, NULL, "SetTimer"}, + {0x1C, NULL, "CancelTimer"}, + {0x1D, NULL, "ClearTimer"}, + {0x1E, NULL, "CreateMemoryBlock"}, + {0x1F, WrapI_UUUU, "MapMemoryBlock"}, + {0x20, NULL, "UnmapMemoryBlock"}, + {0x21, WrapI_V, "CreateAddressArbiter"}, + {0x22, NULL, "ArbitrateAddress"}, + {0x23, WrapI_U, "CloseHandle"}, + {0x24, WrapI_US64, "WaitSynchronization1"}, + {0x25, NULL, "WaitSynchronizationN"}, + {0x26, NULL, "SignalAndWait"}, + {0x27, NULL, "DuplicateHandle"}, + {0x28, NULL, "GetSystemTick"}, + {0x29, NULL, "GetHandleInfo"}, + {0x2A, NULL, "GetSystemInfo"}, + {0x2B, NULL, "GetProcessInfo"}, + {0x2C, NULL, "GetThreadInfo"}, + {0x2D, WrapI_VC, "ConnectToPort"}, + {0x2E, NULL, "SendSyncRequest1"}, + {0x2F, NULL, "SendSyncRequest2"}, + {0x30, NULL, "SendSyncRequest3"}, + {0x31, NULL, "SendSyncRequest4"}, + {0x32, WrapI_U, "SendSyncRequest"}, + {0x33, NULL, "OpenProcess"}, + {0x34, NULL, "OpenThread"}, + {0x35, NULL, "GetProcessId"}, + {0x36, NULL, "GetProcessIdOfThread"}, + {0x37, NULL, "GetThreadId"}, + {0x38, WrapI_VU, "GetResourceLimit"}, + {0x39, NULL, "GetResourceLimitLimitValues"}, + {0x3A, WrapI_VUVI, "GetResourceLimitCurrentValues"}, + {0x3B, NULL, "GetThreadContext"}, + {0x3C, NULL, "Break"}, + {0x3D, WrapV_C, "OutputDebugString"}, + {0x3E, NULL, "ControlPerformanceCounter"}, + {0x3F, NULL, "Unknown"}, + {0x40, NULL, "Unknown"}, + {0x41, NULL, "Unknown"}, + {0x42, NULL, "Unknown"}, + {0x43, NULL, "Unknown"}, + {0x44, NULL, "Unknown"}, + {0x45, NULL, "Unknown"}, + {0x46, NULL, "Unknown"}, + {0x47, NULL, "CreatePort"}, + {0x48, NULL, "CreateSessionToPort"}, + {0x49, NULL, "CreateSession"}, + {0x4A, NULL, "AcceptSession"}, + {0x4B, NULL, "ReplyAndReceive1"}, + {0x4C, NULL, "ReplyAndReceive2"}, + {0x4D, NULL, "ReplyAndReceive3"}, + {0x4E, NULL, "ReplyAndReceive4"}, + {0x4F, NULL, "ReplyAndReceive"}, + {0x50, NULL, "BindInterrupt"}, + {0x51, NULL, "UnbindInterrupt"}, + {0x52, NULL, "InvalidateProcessDataCache"}, + {0x53, NULL, "StoreProcessDataCache"}, + {0x54, NULL, "FlushProcessDataCache"}, + {0x55, NULL, "StartInterProcessDma"}, + {0x56, NULL, "StopDma"}, + {0x57, NULL, "GetDmaState"}, + {0x58, NULL, "RestartDma"}, + {0x59, NULL, "Unknown"}, + {0x5A, NULL, "Unknown"}, + {0x5B, NULL, "Unknown"}, + {0x5C, NULL, "Unknown"}, + {0x5D, NULL, "Unknown"}, + {0x5E, NULL, "Unknown"}, + {0x5F, NULL, "Unknown"}, + {0x60, NULL, "DebugActiveProcess"}, + {0x61, NULL, "BreakDebugProcess"}, + {0x62, NULL, "TerminateDebugProcess"}, + {0x63, NULL, "GetProcessDebugEvent"}, + {0x64, NULL, "ContinueDebugEvent"}, + {0x65, NULL, "GetProcessList"}, + {0x66, NULL, "GetThreadList"}, + {0x67, NULL, "GetDebugThreadContext"}, + {0x68, NULL, "SetDebugThreadContext"}, + {0x69, NULL, "QueryDebugProcessMemory"}, + {0x6A, NULL, "ReadProcessMemory"}, + {0x6B, NULL, "WriteProcessMemory"}, + {0x6C, NULL, "SetHardwareBreakPoint"}, + {0x6D, NULL, "GetDebugThreadParam"}, + {0x6E, NULL, "Unknown"}, + {0x6F, NULL, "Unknown"}, + {0x70, NULL, "ControlProcessMemory"}, + {0x71, NULL, "MapProcessMemory"}, + {0x72, NULL, "UnmapProcessMemory"}, + {0x73, NULL, "Unknown"}, + {0x74, NULL, "Unknown"}, + {0x75, NULL, "Unknown"}, + {0x76, NULL, "TerminateProcess"}, + {0x77, NULL, "Unknown"}, + {0x78, NULL, "CreateResourceLimit"}, + {0x79, NULL, "Unknown"}, + {0x7A, NULL, "Unknown"}, + {0x7B, NULL, "Unknown"}, + {0x7C, NULL, "KernelSetState"}, + {0x7D, NULL, "QueryProcessMemory"}, }; void Register() { -- cgit v1.2.3 From 72622a1b5a13083e1b4eda3d4584bfa2f04dc55c Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 7 May 2014 21:04:55 -0400 Subject: - removed HLE mem "hack" and replaced with kernel mem region - added a helper function for getting command buffer for services - fixed bug where GSP DMA was incorrectly being done in DataSynchronizationBarrier (instead of gsp_TriggerCmdReqQueue) --- src/core/hle/coprocessor.cpp | 34 +++---------------- src/core/hle/hle.cpp | 47 -------------------------- src/core/hle/hle.h | 21 ------------ src/core/hle/service/apt.cpp | 2 +- src/core/hle/service/gsp.cpp | 76 +++++++++++++++++++++++++++++++++++++++--- src/core/hle/service/service.h | 12 ++++++- src/core/hle/service/srv.cpp | 2 +- 7 files changed, 89 insertions(+), 105 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp index df1362176..74305331c 100644 --- a/src/core/hle/coprocessor.cpp +++ b/src/core/hle/coprocessor.cpp @@ -9,39 +9,15 @@ namespace HLE { -enum { - CMD_GX_REQUEST_DMA = 0x00000000, -}; - /// Data synchronization barrier -u32 DataSynchronizationBarrier(u32* command_buffer) { - u32 command = command_buffer[0]; - - switch (command) { - - case CMD_GX_REQUEST_DMA: - { - u32* src = (u32*)Memory::GetPointer(command_buffer[1]); - u32* dst = (u32*)Memory::GetPointer(command_buffer[2]); - u32 size = command_buffer[3]; - memcpy(dst, src, size); - } - break; - - default: - ERROR_LOG(OSHLE, "MRC::DataSynchronizationBarrier unknown command 0x%08X", command); - return -1; - } - +u32 DataSynchronizationBarrier() { return 0; } /// Returns the coprocessor (in this case, syscore) command buffer pointer Addr GetThreadCommandBuffer() { // Called on insruction: mrc p15, 0, r0, c13, c0, 3 - // Returns an address in OSHLE memory for the CPU to read/write to - RETURN(CMD_BUFFER_ADDR); - return CMD_BUFFER_ADDR; + return Memory::KERNEL_MEMORY_VADDR; } /// Call an MCR (move to coprocessor from ARM register) instruction in HLE @@ -49,7 +25,7 @@ s32 CallMCR(u32 instruction, u32 value) { CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF); ERROR_LOG(OSHLE, "unimplemented MCR instruction=0x%08X, operation=%02X, value=%08X", instruction, operation, value); - return -1; + return 0; } /// Call an MRC (move to ARM register from coprocessor) instruction in HLE @@ -59,7 +35,7 @@ s32 CallMRC(u32 instruction) { switch (operation) { case DATA_SYNCHRONIZATION_BARRIER: - return DataSynchronizationBarrier((u32*)Memory::GetPointer(PARAM(0))); + return DataSynchronizationBarrier(); case CALL_GET_THREAD_COMMAND_BUFFER: return GetThreadCommandBuffer(); @@ -68,7 +44,7 @@ s32 CallMRC(u32 instruction) { ERROR_LOG(OSHLE, "unimplemented MRC instruction 0x%08X", instruction); break; } - return -1; + return 0; } } // namespace diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index aae9a3943..be151665b 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -15,49 +15,6 @@ namespace HLE { static std::vector g_module_db; -u8* g_command_buffer = NULL; ///< Command buffer used for sharing between appcore and syscore - -// Read from memory used by CTROS HLE functions -template -inline void Read(T &var, const u32 addr) { - if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { - var = *((const T*)&g_command_buffer[addr & CMD_BUFFER_MASK]); - } else { - ERROR_LOG(HLE, "unknown read from address %08X", addr); - } -} - -// Write to memory used by CTROS HLE functions -template -inline void Write(u32 addr, const T data) { - if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { - *(T*)&g_command_buffer[addr & CMD_BUFFER_MASK] = data; - } else { - ERROR_LOG(HLE, "unknown write to address %08X", addr); - } -} - -u8 *GetPointer(const u32 addr) { - if (addr >= HLE::CMD_BUFFER_ADDR && addr < HLE::CMD_BUFFER_ADDR_END) { - return g_command_buffer + (addr & CMD_BUFFER_MASK); - } else { - ERROR_LOG(HLE, "unknown pointer from address %08X", addr); - return 0; - } -} - -// Explicitly instantiate template functions because we aren't defining this in the header: - -template void Read(u64 &var, const u32 addr); -template void Read(u32 &var, const u32 addr); -template void Read(u16 &var, const u32 addr); -template void Read(u8 &var, const u32 addr); - -template void Write(u32 addr, const u64 data); -template void Write(u32 addr, const u32 data); -template void Write(u32 addr, const u16 data); -template void Write(u32 addr, const u8 data); - const FunctionDef* GetSyscallInfo(u32 opcode) { u32 func_num = opcode & 0xFFFFFF; // 8 bits if (func_num > 0xFF) { @@ -91,8 +48,6 @@ void RegisterAllModules() { void Init() { Service::Init(); - - g_command_buffer = new u8[CMD_BUFFER_SIZE]; RegisterAllModules(); @@ -102,8 +57,6 @@ void Init() { void Shutdown() { Service::Shutdown(); - delete g_command_buffer; - g_module_db.clear(); NOTICE_LOG(HLE, "shutdown OK"); diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 907e2d741..42f37e29c 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -17,13 +17,6 @@ namespace HLE { -enum { - CMD_BUFFER_ADDR = 0xA0010000, ///< Totally arbitrary unused address space - CMD_BUFFER_SIZE = 0x10000, - CMD_BUFFER_MASK = (CMD_BUFFER_SIZE - 1), - CMD_BUFFER_ADDR_END = (CMD_BUFFER_ADDR + CMD_BUFFER_SIZE), -}; - typedef u32 Addr; typedef void (*Func)(); @@ -39,20 +32,6 @@ struct ModuleDef { const FunctionDef* func_table; }; -// Read from memory used by CTROS HLE functions -template -inline void Read(T &var, const u32 addr); - -// Write to memory used by CTROS HLE functions -template -inline void Write(u32 addr, const T data); - -u8* GetPointer(const u32 Address); - -inline const char* GetCharPointer(const u32 address) { - return (const char *)GetPointer(address); -} - void RegisterModule(std::string name, int num_functions, const FunctionDef *func_table); void CallSyscall(u32 opcode); diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp index 4a1e8c992..709ac5493 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -18,7 +18,7 @@ void Initialize(Service::Interface* self) { } void GetLockHandle(Service::Interface* self) { - u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); + u32* cmd_buff = Service::GetCommandBuffer(); cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle } diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 88c1f1a0f..58df970c4 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -4,6 +4,7 @@ #include "common/log.h" +#include "common/bit_field.h" #include "core/mem_map.h" #include "core/hle/hle.h" @@ -11,11 +12,57 @@ #include "core/hw/lcd.h" +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/// GSP shared memory GX command buffer header +union GX_CmdBufferHeader { + u32 hex; + + // Current command index. This index is updated by GSP module after loading the command data, + // right before the command is processed. When this index is updated by GSP module, the total + // commands field is decreased by one as well. + BitField<0,8,u32> index; + + // Total commands to process, must not be value 0 when GSP module handles commands. This must be + // <=15 when writing a command to shared memory. This is incremented by the application when + // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only + // used if this field is value 1. + BitField<8,8,u32> number_commands; + + // Must not be value 1. When the error-code u32 is set, this u8 is set to value 0x80. + BitField<16,8,u32> unk_0; + + // Bit 0 must not be set + BitField<24,8,u32> unk_1; +}; + +/// Gets the address of the start (header) of a command buffer in GSP shared memory +static inline u32 GX_GetCmdBufferAddress(u32 thread_id) { + return (0x10002000 + 0x800 + (thread_id * 0x200)); +} + +/// Gets a pointer to the start (header) of a command buffer in GSP shared memory +static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) { + return Memory::GetPointer(GX_GetCmdBufferAddress(thread_id) + offset); +} + +/// Finishes execution of a GSP command +void GX_FinishCommand(u32 thread_id) { + GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(thread_id); + header->number_commands = header->number_commands - 1; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace GSP_GPU namespace GSP_GPU { +u32 g_thread_id = 0; + +enum { + CMD_GX_REQUEST_DMA = 0x00000000, +}; + enum { REG_FRAMEBUFFER_1 = 0x00400468, REG_FRAMEBUFFER_2 = 0x00400494, @@ -26,7 +73,7 @@ void ReadHWRegs(Service::Interface* self) { static const u32 framebuffer_1[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME1, LCD::PADDR_VRAM_TOP_RIGHT_FRAME1}; static const u32 framebuffer_2[] = {LCD::PADDR_VRAM_TOP_LEFT_FRAME2, LCD::PADDR_VRAM_TOP_RIGHT_FRAME2}; - u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); + u32* cmd_buff = Service::GetCommandBuffer(); u32 reg_addr = cmd_buff[1]; u32 size = cmd_buff[2]; u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); @@ -50,18 +97,37 @@ void ReadHWRegs(Service::Interface* self) { break; default: - ERROR_LOG(OSHLE, "GSP_GPU::ReadHWRegs unknown register read at address %08X", reg_addr); + ERROR_LOG(GSP, "ReadHWRegs unknown register read at address %08X", reg_addr); } } void RegisterInterruptRelayQueue(Service::Interface* self) { - u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); + u32* cmd_buff = Service::GetCommandBuffer(); u32 flags = cmd_buff[1]; u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling + + cmd_buff[2] = g_thread_id; // ThreadID cmd_buff[4] = self->NewHandle(); +} + +/// This triggers handling of the GX command written to the command buffer in shared memory. +void TriggerCmdReqQueue(Service::Interface* self) { + GX_CmdBufferHeader* header = (GX_CmdBufferHeader*)GX_GetCmdBufferPointer(g_thread_id); + u32* cmd_buff = (u32*)GX_GetCmdBufferPointer(g_thread_id, 0x20 + (header->index * 0x20)); - return; + switch (cmd_buff[0]) { + + // GX request DMA - typically used for copying memory from GSP heap to VRAM + case CMD_GX_REQUEST_DMA: + memcpy(Memory::GetPointer(cmd_buff[2]), Memory::GetPointer(cmd_buff[1]), cmd_buff[3]); + break; + + default: + ERROR_LOG(GSP, "TriggerCmdReqQueue unknown command 0x%08X", cmd_buff[0]); + } + + GX_FinishCommand(g_thread_id); } const Interface::FunctionInfo FunctionTable[] = { @@ -76,7 +142,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00090082, NULL, "InvalidateDataCache"}, {0x000A0044, NULL, "RegisterInterruptEvents"}, {0x000B0040, NULL, "SetLcdForceBlack"}, - {0x000C0000, NULL, "TriggerCmdReqQueue"}, + {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, {0x000D0140, NULL, "SetDisplayTransfer"}, {0x000E0180, NULL, "SetTextureCopy"}, {0x000F0200, NULL, "SetMemoryFill"}, diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index b79dc9458..b260a290a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -10,6 +10,7 @@ #include "common/common.h" #include "common/common_types.h" +#include "core/mem_map.h" #include "core/hle/syscall.h" //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -22,6 +23,15 @@ typedef s32 NativeUID; ///< Native handle for a service static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header +/** + * Returns a pointer to the command buffer in kernel memory + * @param offset Optional offset into command buffer + * @return Pointer to command buffer + */ +inline static u32* GetCommandBuffer(const int offset=0) { + return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset); +} + class Manager; /// Interface to a CTROS service @@ -81,7 +91,7 @@ public: * @return Return result of svcSendSyncRequest passed back to user app */ Syscall::Result Sync() { - u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + kCommandHeaderOffset); + u32* cmd_buff = GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); if (itr == m_functions.end()) { diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 9437868c5..071741444 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -18,7 +18,7 @@ void Initialize(Service::Interface* self) { void GetServiceHandle(Service::Interface* self) { Syscall::Result res = 0; - u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); + u32* cmd_buff = Service::GetCommandBuffer(); std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); -- cgit v1.2.3 From 4de763f462abb986a58052a69127d50789ffeb06 Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 7 May 2014 21:19:03 -0400 Subject: removed unnecessary log message --- src/core/hle/syscall.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle') diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp index 5b4d47485..d47df6038 100644 --- a/src/core/hle/syscall.cpp +++ b/src/core/hle/syscall.cpp @@ -48,7 +48,7 @@ Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissi default: ERROR_LOG(SVC, "ControlMemory unknown operation=0x%08X", operation); } - DEBUG_LOG(SVC, "...returned virtual_address=0x%08X", virtual_address); + Core::g_app_core->SetReg(1, virtual_address); return 0; -- cgit v1.2.3 From b39cd3a64c69792ffd720ffa6e0f5fe35740a087 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 8 May 2014 17:12:07 -0400 Subject: removed unknown fields from GX_CmdBufferHeader --- src/core/hle/service/gsp.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/core/hle') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 58df970c4..12c7dabcd 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -28,12 +28,7 @@ union GX_CmdBufferHeader { // writing a command to shared memory, after increasing this value TriggerCmdReqQueue is only // used if this field is value 1. BitField<8,8,u32> number_commands; - - // Must not be value 1. When the error-code u32 is set, this u8 is set to value 0x80. - BitField<16,8,u32> unk_0; - // Bit 0 must not be set - BitField<24,8,u32> unk_1; }; /// Gets the address of the start (header) of a command buffer in GSP shared memory -- cgit v1.2.3