diff options
| author | bunnei <ericbunnie@gmail.com> | 2014-04-27 21:25:16 -0400 | 
|---|---|---|
| committer | bunnei <ericbunnie@gmail.com> | 2014-04-27 21:25:16 -0400 | 
| commit | 438dba40c1def91e9de252ef05f8650464e5c0c2 (patch) | |
| tree | 8f323d6095dfefe9d00f34cc4d7229be58a9f409 /src/core/hle | |
| parent | 2d1c8078c925a8456f456fb94e593a5e44829954 (diff) | |
| parent | a48c6b947d5314ab804f375cca22af159cc3b77b (diff) | |
Merge branch 'hle-interface-updates'
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"}, | 
