diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 83 | ||||
-rw-r--r-- | src/core/hle/result.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/cecd/cecd.cpp | 29 | ||||
-rw-r--r-- | src/core/hle/service/cecd/cecd.h | 23 | ||||
-rw-r--r-- | src/core/hle/service/cecd/cecd_u.cpp | 5 | ||||
-rw-r--r-- | src/core/hle/service/dlp_srvr.cpp | 36 | ||||
-rw-r--r-- | src/core/hle/service/dlp_srvr.h | 23 | ||||
-rw-r--r-- | src/core/hle/service/gsp_gpu.cpp | 221 | ||||
-rw-r--r-- | src/core/hle/service/gsp_gpu.h | 2 | ||||
-rw-r--r-- | src/core/hle/service/service.cpp | 2 |
11 files changed, 312 insertions, 115 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 3473e2f5b..a8d891689 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -68,6 +68,7 @@ set(SRCS hle/service/cfg/cfg_s.cpp hle/service/cfg/cfg_u.cpp hle/service/csnd_snd.cpp + hle/service/dlp_srvr.cpp hle/service/dsp_dsp.cpp hle/service/err_f.cpp hle/service/frd/frd.cpp @@ -200,6 +201,7 @@ set(HEADERS hle/service/cfg/cfg_s.h hle/service/cfg/cfg_u.h hle/service/csnd_snd.h + hle/service/dlp_srvr.h hle/service/dsp_dsp.h hle/service/err_f.h hle/service/frd/frd.h diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 5f8826034..9ed61947e 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -36,7 +36,8 @@ enum { CALL = (1 << 4), RET = (1 << 5), END_OF_PAGE = (1 << 6), - THUMB = (1 << 7) + THUMB = (1 << 7), + SINGLE_STEP = (1 << 8) }; #define RM BITS(sht_oper, 0, 3) @@ -3466,7 +3467,35 @@ enum { MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); -static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { +static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { + unsigned int inst_size = 4; + unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); + + // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction + if (cpu->TFlag) { + u32 arm_inst; + ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); + + // We have translated the Thumb branch instruction in the Thumb decoder + if (state == ThumbDecodeStatus::BRANCH) { + return inst_size; + } + inst = arm_inst; + } + + int idx; + if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { + std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); + LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); + LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); + CITRA_IGNORE_EXIT(-1); + } + inst_base = arm_instruction_trans[idx](inst, idx); + + return inst_size; +} + +static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) { Common::Profiling::ScopeTimer timer_decode(profile_decode); MICROPROFILE_SCOPE(DynCom_Decode); @@ -3475,8 +3504,6 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { // Go on next, until terminal instruction // Save start addr of basicblock in CreamCache ARM_INST_PTR inst_base = nullptr; - unsigned int inst, inst_size = 4; - int idx; int ret = NON_BRANCH; int size = 0; // instruction size of basic block bb_start = top; @@ -3485,30 +3512,10 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) { u32 pc_start = cpu->Reg[15]; while (ret == NON_BRANCH) { - inst = Memory::Read32(phys_addr & 0xFFFFFFFC); + unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base); size++; - // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction - if (cpu->TFlag) { - u32 arm_inst; - ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); - - // We have translated the Thumb branch instruction in the Thumb decoder - if (state == ThumbDecodeStatus::BRANCH) { - goto translated; - } - inst = arm_inst; - } - - if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { - std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); - LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); - LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); - CITRA_IGNORE_EXIT(-1); - } - inst_base = arm_instruction_trans[idx](inst, idx); -translated: phys_addr += inst_size; if ((phys_addr & 0xfff) == 0) { @@ -3522,6 +3529,27 @@ translated: return KEEP_GOING; } +static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) { + Common::Profiling::ScopeTimer timer_decode(profile_decode); + MICROPROFILE_SCOPE(DynCom_Decode); + + ARM_INST_PTR inst_base = nullptr; + bb_start = top; + + u32 phys_addr = addr; + u32 pc_start = cpu->Reg[15]; + + InterpreterTranslateInstruction(cpu, phys_addr, inst_base); + + if (inst_base->br == NON_BRANCH) { + inst_base->br = SINGLE_STEP; + } + + cpu->instruction_cache[pc_start] = bb_start; + + return KEEP_GOING; +} + static int clz(unsigned int x) { int n; if (x == 0) return (32); @@ -3871,8 +3899,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { auto itr = cpu->instruction_cache.find(cpu->Reg[15]); if (itr != cpu->instruction_cache.end()) { ptr = itr->second; + } else if (cpu->NumInstrsToExecute != 1) { + if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) + goto END; } else { - if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) + if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) goto END; } diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 0cb76ba1c..2d22652d9 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -24,6 +24,7 @@ enum class ErrorDescription : u32 { FS_InvalidOpenFlags = 230, FS_NotAFile = 250, FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive + OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage FS_InvalidPath = 702, InvalidSection = 1000, TooLarge = 1001, diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp index 6d79ce9b4..e6e36e7ec 100644 --- a/src/core/hle/service/cecd/cecd.cpp +++ b/src/core/hle/service/cecd/cecd.cpp @@ -4,6 +4,7 @@ #include "common/logging/log.h" +#include "core/hle/kernel/event.h" #include "core/hle/service/service.h" #include "core/hle/service/cecd/cecd.h" #include "core/hle/service/cecd/cecd_s.h" @@ -12,14 +13,38 @@ namespace Service { namespace CECD { -void Init() { - using namespace Kernel; +static Kernel::SharedPtr<Kernel::Event> cecinfo_event; +static Kernel::SharedPtr<Kernel::Event> change_state_event; + +void GetCecInfoEventHandle(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle + + LOG_WARNING(Service_CECD, "(STUBBED) called"); +} + +void GetChangeStateEventHandle(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle + + LOG_WARNING(Service_CECD, "(STUBBED) called"); +} + +void Init() { AddService(new CECD_S_Interface); AddService(new CECD_U_Interface); + + cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event"); + change_state_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event"); } void Shutdown() { + cecinfo_event = nullptr; + change_state_event = nullptr; } } // namespace CECD diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h index 9e158521b..89a8d67bb 100644 --- a/src/core/hle/service/cecd/cecd.h +++ b/src/core/hle/service/cecd/cecd.h @@ -5,8 +5,31 @@ #pragma once namespace Service { + +class Interface; + namespace CECD { +/** + * GetCecInfoEventHandle service function + * Inputs: + * 0: 0x000F0000 + * Outputs: + * 1: ResultCode + * 3: Event Handle + */ +void GetCecInfoEventHandle(Service::Interface* self); + +/** + * GetChangeStateEventHandle service function + * Inputs: + * 0: 0x00100000 + * Outputs: + * 1: ResultCode + * 3: Event Handle + */ +void GetChangeStateEventHandle(Service::Interface* self); + /// Initialize CECD service(s) void Init(); diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp index 9b720a738..ace1c73c0 100644 --- a/src/core/hle/service/cecd/cecd_u.cpp +++ b/src/core/hle/service/cecd/cecd_u.cpp @@ -2,13 +2,16 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/hle/service/cecd/cecd.h" #include "core/hle/service/cecd/cecd_u.h" namespace Service { namespace CECD { static const Interface::FunctionInfo FunctionTable[] = { - { 0x00120104, nullptr, "ReadSavedData" }, + {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, + {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, + {0x00120104, nullptr, "ReadSavedData"}, }; CECD_U_Interface::CECD_U_Interface() { diff --git a/src/core/hle/service/dlp_srvr.cpp b/src/core/hle/service/dlp_srvr.cpp new file mode 100644 index 000000000..1f30188da --- /dev/null +++ b/src/core/hle/service/dlp_srvr.cpp @@ -0,0 +1,36 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/hle/hle.h" +#include "core/hle/service/dlp_srvr.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace DLP_SRVR + +namespace DLP_SRVR { + +static void unk_0x000E0040(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = 0; + + LOG_WARNING(Service_DLP, "(STUBBED) called"); +} + +const Interface::FunctionInfo FunctionTable[] = { + {0x00010183, nullptr, "Initialize"}, + {0x00020000, nullptr, "Finalize"}, + {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Interface class + +Interface::Interface() { + Register(FunctionTable); +} + +} // namespace diff --git a/src/core/hle/service/dlp_srvr.h b/src/core/hle/service/dlp_srvr.h new file mode 100644 index 000000000..d65d00814 --- /dev/null +++ b/src/core/hle/service/dlp_srvr.h @@ -0,0 +1,23 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Namespace DLP_SRVR + +namespace DLP_SRVR { + +class Interface : public Service::Interface { +public: + Interface(); + + std::string GetPortName() const override { + return "dlp:SRVR"; + } +}; + +} // namespace diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 2ace2cade..0c655395e 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -31,6 +31,13 @@ const static u32 REGS_BEGIN = 0x1EB00000; namespace GSP_GPU { +const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02A01 +const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2 +const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC + /// Event triggered when GSP interrupt has been signalled Kernel::SharedPtr<Kernel::Event> g_interrupt_event; /// GSP shared memoryings @@ -59,47 +66,87 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { } /** - * Checks if the parameters in a register write call are valid and logs in the case that - * they are not - * @param base_address The first address in the sequence of registers that will be written - * @param size_in_bytes The number of registers that will be written - * @return true if the parameters are valid, false otherwise + * Writes sequential GSP GPU hardware registers using an array of source data + * + * @param base_address The address of the first register in the sequence + * @param size_in_bytes The number of registers to update (size of data) + * @param data A pointer to the source data + * @return RESULT_SUCCESS if the parameters are valid, error code otherwise */ -static bool CheckWriteParameters(u32 base_address, u32 size_in_bytes) { - // TODO: Return proper error codes - if (base_address + size_in_bytes >= 0x420000) { - LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)", +static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { + // This magic number is verified to be done by the gsp module + const u32 max_size_in_bytes = 0x80; + + if (base_address & 3 || base_address >= 0x420000) { + LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", base_address, size_in_bytes); - return false; - } + return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; + } else if (size_in_bytes <= max_size_in_bytes) { + if (size_in_bytes & 3) { + LOG_ERROR(Service_GSP, "Misaligned size 0x%08x", size_in_bytes); + return ERR_GSP_REGS_MISALIGNED; + } else { + while (size_in_bytes > 0) { + HW::Write<u32>(base_address + REGS_BEGIN, *data); + + size_in_bytes -= 4; + ++data; + base_address += 4; + } + return RESULT_SUCCESS; + } - // size should be word-aligned - if ((size_in_bytes % 4) != 0) { - LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes); - return false; + } else { + LOG_ERROR(Service_GSP, "Out of range size 0x%08x", size_in_bytes); + return ERR_GSP_REGS_INVALID_SIZE; } - - return true; } /** - * Writes sequential GSP GPU hardware registers using an array of source data + * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks. + * For each register, the value is updated only where the mask is high * * @param base_address The address of the first register in the sequence * @param size_in_bytes The number of registers to update (size of data) - * @param data A pointer to the source data + * @param data A pointer to the source data to use for updates + * @param masks A pointer to the masks + * @return RESULT_SUCCESS if the parameters are valid, error code otherwise */ -static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { - // TODO: Return proper error codes - if (!CheckWriteParameters(base_address, size_in_bytes)) - return; +static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { + // This magic number is verified to be done by the gsp module + const u32 max_size_in_bytes = 0x80; - while (size_in_bytes > 0) { - HW::Write<u32>(base_address + REGS_BEGIN, *data); + if (base_address & 3 || base_address >= 0x420000) { + LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", + base_address, size_in_bytes); + return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; + } else if (size_in_bytes <= max_size_in_bytes) { + if (size_in_bytes & 3) { + LOG_ERROR(Service_GSP, "Misaligned size 0x%08x", size_in_bytes); + return ERR_GSP_REGS_MISALIGNED; + } else { + while (size_in_bytes > 0) { + const u32 reg_address = base_address + REGS_BEGIN; + + u32 reg_value; + HW::Read<u32>(reg_value, reg_address); + + // Update the current value of the register only for set mask bits + reg_value = (reg_value & ~*masks) | (*data | *masks); + + HW::Write<u32>(reg_address, reg_value); + + size_in_bytes -= 4; + ++data; + ++masks; + base_address += 4; + } + return RESULT_SUCCESS; + } - size_in_bytes -= 4; - ++data; - base_address += 4; + } else { + LOG_ERROR(Service_GSP, "Out of range size 0x%08x", size_in_bytes); + return ERR_GSP_REGS_INVALID_SIZE; } } @@ -120,39 +167,7 @@ static void WriteHWRegs(Service::Interface* self) { u32* src = (u32*)Memory::GetPointer(cmd_buff[4]); - WriteHWRegs(reg_addr, size, src); -} - -/** - * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks. - * For each register, the value is updated only where the mask is high - * - * @param base_address The address of the first register in the sequence - * @param size_in_bytes The number of registers to update (size of data) - * @param data A pointer to the source data to use for updates - * @param masks A pointer to the masks - */ -static void WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { - // TODO: Return proper error codes - if (!CheckWriteParameters(base_address, size_in_bytes)) - return; - - while (size_in_bytes > 0) { - const u32 reg_address = base_address + REGS_BEGIN; - - u32 reg_value; - HW::Read<u32>(reg_value, reg_address); - - // Update the current value of the register only for set mask bits - reg_value = (reg_value & ~*masks) | (*data | *masks); - - HW::Write<u32>(reg_address, reg_value); - - size_in_bytes -= 4; - ++data; - ++masks; - base_address += 4; - } + cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; } /** @@ -174,7 +189,7 @@ static void WriteHWRegsWithMask(Service::Interface* self) { u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); - WriteHWRegsWithMask(reg_addr, size, src_data, mask_data); + cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; } /// Read a GSP GPU hardware register @@ -206,27 +221,27 @@ static void ReadHWRegs(Service::Interface* self) { } } -void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { +ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { u32 base_address = 0x400000; PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); if (info.active_fb == 0) { - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 4, - &phys_address_left); - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 4, - &phys_address_right); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), + 4, &phys_address_left); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), + 4, &phys_address_right); } else { - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 4, - &phys_address_left); - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 4, - &phys_address_right); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), + 4, &phys_address_left); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), + 4, &phys_address_right); } - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 4, - &info.stride); - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 4, - &info.format); - WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4, - &info.shown_fb); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), + 4, &info.stride); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), + 4, &info.format); + WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), + 4, &info.shown_fb); if (Pica::g_debug_context) Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); @@ -234,6 +249,8 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { if (screen_id == 0) { MicroProfileFlip(); } + + return RESULT_SUCCESS; } /** @@ -251,9 +268,8 @@ static void SetBufferSwap(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 screen_id = cmd_buff[1]; FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; - SetBufferSwap(screen_id, *fb_info); - cmd_buff[1] = 0; // No error + cmd_buff[1] = SetBufferSwap(screen_id, *fb_info).raw; } /** @@ -286,6 +302,22 @@ static void FlushDataCache(Service::Interface* self) { } /** + * GSP_GPU::SetAxiConfigQoSMode service function + * Inputs: + * 1 : Mode, unused in emulator + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void SetAxiConfigQoSMode(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 mode = cmd_buff[1]; + + cmd_buff[1] = RESULT_SUCCESS.raw; // No error + + LOG_WARNING(Service_GSP, "(STUBBED) called mode=0x%08X", mode); +} + +/** * GSP_GPU::RegisterInterruptRelayQueue service function * Inputs: * 1 : "Flags" field, purpose is unknown @@ -302,6 +334,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]); ASSERT_MSG((g_interrupt_event != nullptr), "handle is not valid!"); + g_interrupt_event->name = "GSP_GPU::interrupt_event"; + + using Kernel::MemoryPermission; + g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, + MemoryPermission::ReadWrite, "GSPSharedMem"); + Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // This specific code is required for a successful initialization, rather than 0 @@ -314,6 +352,22 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { } /** + * GSP_GPU::UnregisterInterruptRelayQueue service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +static void UnregisterInterruptRelayQueue(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + g_shared_memory = nullptr; + g_interrupt_event = nullptr; + + cmd_buff[1] = RESULT_SUCCESS.raw; + + LOG_WARNING(Service_GSP, "called"); +} + +/** * Signals that the specified interrupt type has occurred to userland code * @param interrupt_id ID of interrupt that is being signalled * @todo This should probably take a thread_id parameter and only signal this thread? @@ -591,11 +645,11 @@ const Interface::FunctionInfo FunctionTable[] = { {0x000D0140, nullptr, "SetDisplayTransfer"}, {0x000E0180, nullptr, "SetTextureCopy"}, {0x000F0200, nullptr, "SetMemoryFill"}, - {0x00100040, nullptr, "SetAxiConfigQoSMode"}, + {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"}, {0x00110040, nullptr, "SetPerfLogMode"}, {0x00120000, nullptr, "GetPerfLog"}, {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, - {0x00140000, nullptr, "UnregisterInterruptRelayQueue"}, + {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, {0x00150002, nullptr, "TryAcquireRight"}, {0x00160042, nullptr, "AcquireRight"}, {0x00170000, nullptr, "ReleaseRight"}, @@ -616,10 +670,7 @@ Interface::Interface() { Register(FunctionTable); g_interrupt_event = nullptr; - - using Kernel::MemoryPermission; - g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, - MemoryPermission::ReadWrite, "GSPSharedMem"); + g_shared_memory = nullptr; g_thread_id = 0; } diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h index 0e2f7a21e..55a993bb8 100644 --- a/src/core/hle/service/gsp_gpu.h +++ b/src/core/hle/service/gsp_gpu.h @@ -194,7 +194,7 @@ public: */ void SignalInterrupt(InterruptId interrupt_id); -void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info); +ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info); /** * Retrieves the framebuffer info stored in the GSP shared memory for the diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 35b648409..7844d2330 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -9,6 +9,7 @@ #include "core/hle/service/ac_u.h" #include "core/hle/service/act_u.h" #include "core/hle/service/csnd_snd.h" +#include "core/hle/service/dlp_srvr.h" #include "core/hle/service/dsp_dsp.h" #include "core/hle/service/err_f.h" #include "core/hle/service/gsp_gpu.h" @@ -121,6 +122,7 @@ void Init() { AddService(new AC_U::Interface); AddService(new ACT_U::Interface); AddService(new CSND_SND::Interface); + AddService(new DLP_SRVR::Interface); AddService(new DSP_DSP::Interface); AddService(new GSP_GPU::Interface); AddService(new GSP_LCD::Interface); |