diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/hle.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/hle.h | 2 | ||||
-rw-r--r-- | src/core/hle/mrc.cpp | 64 | ||||
-rw-r--r-- | src/core/hle/mrc.h | 20 | ||||
-rw-r--r-- | src/core/hle/service/apt.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/service/apt.h | 4 | ||||
-rw-r--r-- | src/core/hle/service/gsp.cpp | 113 | ||||
-rw-r--r-- | src/core/hle/service/gsp.h | 3 | ||||
-rw-r--r-- | src/core/hle/service/hid.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/hid.h | 3 | ||||
-rw-r--r-- | src/core/hle/service/service.h | 40 | ||||
-rw-r--r-- | src/core/hle/service/srv.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/service/srv.h | 3 | ||||
-rw-r--r-- | src/core/hle/syscall.cpp | 42 |
14 files changed, 241 insertions, 75 deletions
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 5672a659f..aae9a3943 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -80,14 +80,6 @@ void CallSyscall(u32 opcode) { } } -/// Returns the coprocessor (in this case, syscore) command buffer pointer -Addr CallGetThreadCommandBuffer() { - // 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; -} - void RegisterModule(std::string name, int num_functions, const FunctionDef* func_table) { ModuleDef module = {name, num_functions, func_table}; g_module_db.push_back(module); diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 628a1da89..907e2d741 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -57,8 +57,6 @@ void RegisterModule(std::string name, int num_functions, const FunctionDef *func void CallSyscall(u32 opcode); -Addr CallGetThreadCommandBuffer(); - void Init(); void Shutdown(); diff --git a/src/core/hle/mrc.cpp b/src/core/hle/mrc.cpp new file mode 100644 index 000000000..5223be7c9 --- /dev/null +++ b/src/core/hle/mrc.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/mrc.h b/src/core/hle/mrc.h new file mode 100644 index 000000000..d6b9f162f --- /dev/null +++ b/src/core/hle/mrc.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/service/apt.cpp b/src/core/hle/service/apt.cpp index 4f8d7248d..4a1e8c992 100644 --- a/src/core/hle/service/apt.cpp +++ b/src/core/hle/service/apt.cpp @@ -13,16 +13,16 @@ namespace APT_U { -void Initialize() { +void Initialize(Service::Interface* self) { NOTICE_LOG(OSHLE, "APT_U::Sync - Initialize"); } -void GetLockHandle() { +void GetLockHandle(Service::Interface* self) { u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); cmd_buff[5] = 0x00000000; // TODO: This should be an actual mutex handle } -const HLE::FunctionDef FunctionTable[] = { +const Interface::FunctionInfo FunctionTable[] = { {0x00010040, GetLockHandle, "GetLockHandle"}, {0x00020080, Initialize, "Initialize"}, {0x00030040, NULL, "Enable"}, diff --git a/src/core/hle/service/apt.h b/src/core/hle/service/apt.h index e74baac0c..4c7dd07e7 100644 --- a/src/core/hle/service/apt.h +++ b/src/core/hle/service/apt.h @@ -32,10 +32,6 @@ public: std::string GetPortName() const { return "APT:U"; } - -private: - - DISALLOW_COPY_AND_ASSIGN(Interface); }; } // namespace diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 7c80ab8b5..88c1f1a0f 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -5,45 +5,96 @@ #include "common/log.h" +#include "core/mem_map.h" #include "core/hle/hle.h" #include "core/hle/service/gsp.h" +#include "core/hw/lcd.h" + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace GSP_GPU namespace GSP_GPU { -const HLE::FunctionDef FunctionTable[] = { - {0x00010082, NULL, "WriteHWRegs"}, - {0x00020084, NULL, "WriteHWRegsWithMask"}, - {0x00030082, NULL, "WriteHWRegRepeat"}, - {0x00040080, NULL, "ReadHWRegs"}, - {0x00050200, NULL, "SetBufferSwap"}, - {0x00060082, NULL, "SetCommandList"}, - {0x000700C2, NULL, "RequestDma"}, - {0x00080082, NULL, "FlushDataCache"}, - {0x00090082, NULL, "InvalidateDataCache"}, - {0x000A0044, NULL, "RegisterInterruptEvents"}, - {0x000B0040, NULL, "SetLcdForceBlack"}, - {0x000C0000, NULL, "TriggerCmdReqQueue"}, - {0x000D0140, NULL, "SetDisplayTransfer"}, - {0x000E0180, NULL, "SetTextureCopy"}, - {0x000F0200, NULL, "SetMemoryFill"}, - {0x00100040, NULL, "SetAxiConfigQoSMode"}, - {0x00110040, NULL, "SetPerfLogMode"}, - {0x00120000, NULL, "GetPerfLog"}, - {0x00130042, NULL, "RegisterInterruptRelayQueue"}, - {0x00140000, NULL, "UnregisterInterruptRelayQueue"}, - {0x00150002, NULL, "TryAcquireRight"}, - {0x00160042, NULL, "AcquireRight"}, - {0x00170000, NULL, "ReleaseRight"}, - {0x00180000, NULL, "ImportDisplayCaptureInfo"}, - {0x00190000, NULL, "SaveVramSysArea"}, - {0x001A0000, NULL, "RestoreVramSysArea"}, - {0x001B0000, NULL, "ResetGpuCore"}, - {0x001C0040, NULL, "SetLedForceOff"}, - {0x001D0040, NULL, "SetTestCommand"}, - {0x001E0080, NULL, "SetInternalPriorities"}, +enum { + REG_FRAMEBUFFER_1 = 0x00400468, + REG_FRAMEBUFFER_2 = 0x00400494, +}; + +/// Read a GSP GPU hardware register +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 reg_addr = cmd_buff[1]; + u32 size = cmd_buff[2]; + u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); + + switch (reg_addr) { + + // NOTE: Calling SetFramebufferLocation here is a hack... Not sure the correct way yet to set + // whether the framebuffers should be in VRAM or GSP heap, but from what I understand, if the + // user application is reading from either of these registers, then its going to be in VRAM. + + // Top framebuffer 1 addresses + case REG_FRAMEBUFFER_1: + LCD::SetFramebufferLocation(LCD::FRAMEBUFFER_LOCATION_VRAM); + memcpy(dst, framebuffer_1, size); + break; + + // Top framebuffer 2 addresses + case REG_FRAMEBUFFER_2: + LCD::SetFramebufferLocation(LCD::FRAMEBUFFER_LOCATION_VRAM); + memcpy(dst, framebuffer_2, size); + break; + + default: + ERROR_LOG(OSHLE, "GSP_GPU::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 flags = cmd_buff[1]; + u32 event_handle = cmd_buff[3]; // TODO(bunnei): Implement event handling + cmd_buff[4] = self->NewHandle(); + + return; +} + +const Interface::FunctionInfo FunctionTable[] = { + {0x00010082, NULL, "WriteHWRegs"}, + {0x00020084, NULL, "WriteHWRegsWithMask"}, + {0x00030082, NULL, "WriteHWRegRepeat"}, + {0x00040080, ReadHWRegs, "ReadHWRegs"}, + {0x00050200, NULL, "SetBufferSwap"}, + {0x00060082, NULL, "SetCommandList"}, + {0x000700C2, NULL, "RequestDma"}, + {0x00080082, NULL, "FlushDataCache"}, + {0x00090082, NULL, "InvalidateDataCache"}, + {0x000A0044, NULL, "RegisterInterruptEvents"}, + {0x000B0040, NULL, "SetLcdForceBlack"}, + {0x000C0000, NULL, "TriggerCmdReqQueue"}, + {0x000D0140, NULL, "SetDisplayTransfer"}, + {0x000E0180, NULL, "SetTextureCopy"}, + {0x000F0200, NULL, "SetMemoryFill"}, + {0x00100040, NULL, "SetAxiConfigQoSMode"}, + {0x00110040, NULL, "SetPerfLogMode"}, + {0x00120000, NULL, "GetPerfLog"}, + {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, + {0x00140000, NULL, "UnregisterInterruptRelayQueue"}, + {0x00150002, NULL, "TryAcquireRight"}, + {0x00160042, NULL, "AcquireRight"}, + {0x00170000, NULL, "ReleaseRight"}, + {0x00180000, NULL, "ImportDisplayCaptureInfo"}, + {0x00190000, NULL, "SaveVramSysArea"}, + {0x001A0000, NULL, "RestoreVramSysArea"}, + {0x001B0000, NULL, "ResetGpuCore"}, + {0x001C0040, NULL, "SetLedForceOff"}, + {0x001D0040, NULL, "SetTestCommand"}, + {0x001E0080, NULL, "SetInternalPriorities"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h index 3b1846082..5ba09ab70 100644 --- a/src/core/hle/service/gsp.h +++ b/src/core/hle/service/gsp.h @@ -27,9 +27,6 @@ public: return "gsp::Gpu"; } -private: - - DISALLOW_COPY_AND_ASSIGN(Interface); }; } // namespace diff --git a/src/core/hle/service/hid.cpp b/src/core/hle/service/hid.cpp index 2d823dd16..5542e5bf2 100644 --- a/src/core/hle/service/hid.cpp +++ b/src/core/hle/service/hid.cpp @@ -12,7 +12,7 @@ namespace HID_User { -const HLE::FunctionDef FunctionTable[] = { +const Interface::FunctionInfo FunctionTable[] = { {0x000A0000, NULL, "GetIPCHandles"}, {0x00110000, NULL, "EnableAccelerometer"}, {0x00130000, NULL, "EnableGyroscopeLow"}, diff --git a/src/core/hle/service/hid.h b/src/core/hle/service/hid.h index 746c1b1fc..b17fcfa86 100644 --- a/src/core/hle/service/hid.h +++ b/src/core/hle/service/hid.h @@ -29,9 +29,6 @@ public: return "hid:USER"; } -private: - - DISALLOW_COPY_AND_ASSIGN(Interface); }; } // namespace diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 9cbf8b6fa..b79dc9458 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -25,7 +25,7 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer class Manager; /// Interface to a CTROS service -class Interface { +class Interface : NonCopyable { friend class Manager; public: @@ -35,6 +35,14 @@ public: virtual ~Interface() { } + typedef void (*Function)(Interface*); + + struct FunctionInfo { + u32 id; + Function func; + std::string name; + }; + /** * Gets the UID for the serice * @return UID of service in native format @@ -51,6 +59,23 @@ public: return "[UNKNOWN SERVICE PORT]"; } + /// Allocates a new handle for the service + Syscall::Handle NewHandle() { + Syscall::Handle handle = (m_handles.size() << 16) | m_uid; + m_handles.push_back(handle); + return handle; + } + + /// Frees a handle from the service + void DeleteHandle(Syscall::Handle handle) { + for(auto iter = m_handles.begin(); iter != m_handles.end(); ++iter) { + if(*iter == handle) { + m_handles.erase(iter); + break; + } + } + } + /** * Called when svcSendSyncRequest is called, loads command buffer and executes comand * @return Return result of svcSendSyncRequest passed back to user app @@ -70,16 +95,17 @@ public: return -1; } - itr->second.func(); + itr->second.func(this); return 0; // TODO: Implement return from actual function } protected: + /** * Registers the functions in the service */ - void Register(const HLE::FunctionDef* functions, int len) { + void Register(const FunctionInfo* functions, int len) { for (int i = 0; i < len; i++) { m_functions[functions[i].id] = functions[i]; } @@ -87,9 +113,9 @@ protected: private: u32 m_uid; - std::map<u32, HLE::FunctionDef> m_functions; - - DISALLOW_COPY_AND_ASSIGN(Interface); + + std::vector<Syscall::Handle> m_handles; + std::map<u32, FunctionInfo> m_functions; }; /// Simple class to manage accessing services from ports and UID handles @@ -126,8 +152,6 @@ private: std::vector<Interface*> m_services; std::map<std::string, u32> m_port_map; - - DISALLOW_COPY_AND_ASSIGN(Manager); }; /// Initialize ServiceManager diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 579ea4a34..9437868c5 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -12,11 +12,11 @@ namespace SRV { -void Initialize() { +void Initialize(Service::Interface* self) { NOTICE_LOG(OSHLE, "SRV::Sync - Initialize"); } -void GetServiceHandle() { +void GetServiceHandle(Service::Interface* self) { Syscall::Result res = 0; u32* cmd_buff = (u32*)HLE::GetPointer(HLE::CMD_BUFFER_ADDR + Service::kCommandHeaderOffset); @@ -37,7 +37,7 @@ void GetServiceHandle() { //return res; } -const HLE::FunctionDef FunctionTable[] = { +const Interface::FunctionInfo FunctionTable[] = { {0x00010002, Initialize, "Initialize"}, {0x00020000, NULL, "GetProcSemaphore"}, {0x00030100, NULL, "RegisterService"}, diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h index d9ac8fc88..760c976b4 100644 --- a/src/core/hle/service/srv.h +++ b/src/core/hle/service/srv.h @@ -32,9 +32,6 @@ public: */ Syscall::Result Sync(); -private: - - DISALLOW_COPY_AND_ASSIGN(Interface); }; } // namespace diff --git a/src/core/hle/syscall.cpp b/src/core/hle/syscall.cpp index e5533a741..df6412743 100644 --- a/src/core/hle/syscall.cpp +++ b/src/core/hle/syscall.cpp @@ -15,14 +15,29 @@ namespace Syscall { +enum ControlMemoryOperation { + MEMORY_OPERATION_HEAP = 0x00000003, + MEMORY_OPERATION_GSP_HEAP = 0x00010003, +}; + +enum MapMemoryPermission { + MEMORY_PERMISSION_UNMAP = 0x00000000, + MEMORY_PERMISSION_NORMAL = 0x00000001, +}; + /// Map application or GSP heap memory -Result ControlMemory(void* outaddr, u32 addr0, u32 addr1, u32 size, u32 operation, u32 permissions) { +Result ControlMemory(u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { u32 virtual_address = 0x00000000; switch (operation) { - // Map GSP heap memory? - case 0x00010003: + // Map normal heap memory + case MEMORY_OPERATION_HEAP: + virtual_address = Memory::MapBlock_Heap(size, operation, permissions); + break; + + // Map GSP heap memory + case MEMORY_OPERATION_GSP_HEAP: virtual_address = Memory::MapBlock_HeapGSP(size, operation, permissions); break; @@ -31,7 +46,22 @@ Result ControlMemory(void* outaddr, u32 addr0, u32 addr1, u32 size, u32 operatio ERROR_LOG(OSHLE, "Unknown ControlMemory operation %08X", operation); } - Core::g_app_core->SetReg(1, Memory::MapBlock_HeapGSP(size, operation, permissions)); + 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; + switch (mypermissions) { + case MEMORY_PERMISSION_NORMAL: + case MEMORY_PERMISSION_NORMAL + 1: + case MEMORY_PERMISSION_NORMAL + 2: + Memory::MapBlock_Shared(memblock, addr, mypermissions); + break; + default: + ERROR_LOG(OSHLE, "Unknown MapMemoryBlock permissions %08X", mypermissions); + } return 0; } @@ -63,7 +93,7 @@ Result WaitSynchronization1(Handle handle, s64 nanoseconds) { const HLE::FunctionDef Syscall_Table[] = { {0x00, NULL, "Unknown"}, - {0x01, WrapI_VUUUUU<ControlMemory>, "ControlMemory"}, + {0x01, WrapI_UUUUU<ControlMemory>, "ControlMemory"}, {0x02, NULL, "QueryMemory"}, {0x03, NULL, "ExitProcess"}, {0x04, NULL, "GetProcessAffinityMask"}, @@ -93,7 +123,7 @@ const HLE::FunctionDef Syscall_Table[] = { {0x1C, NULL, "CancelTimer"}, {0x1D, NULL, "ClearTimer"}, {0x1E, NULL, "CreateMemoryBlock"}, - {0x1F, NULL, "MapMemoryBlock"}, + {0x1F, WrapI_UUUU<MapMemoryBlock>, "MapMemoryBlock"}, {0x20, NULL, "UnmapMemoryBlock"}, {0x21, NULL, "CreateAddressArbiter"}, {0x22, NULL, "ArbitrateAddress"}, |