From 590c206ac8836f0e4544d2cb84191d77d07b9f36 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Fri, 25 Jul 2014 11:23:28 +0200 Subject: GSP: Implement SetBufferSwap. --- src/core/hle/service/gsp.cpp | 36 +++++++++++++++++++++++++++++++++++- src/core/hle/service/gsp.h | 12 ++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'src/core/hle') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index f793b592..417c01b8 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -105,6 +105,40 @@ void ReadHWRegs(Service::Interface* self) { } } +void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { + u32 base_address = 0x400000; + if (info.active_fb == 0) { + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_left1), 4, &info.address_left); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_right1), 4, &info.address_right); + } else { + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_left2), 4, &info.address_left); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_right2), 4, &info.address_right); + } + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].stride), 4, &info.stride); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].color_format), 4, &info.format); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].active_fb), 4, &info.shown_fb); +} + +/** + * GSP_GPU::SetBufferSwap service function + * + * Updates GPU display framebuffer configuration using the specified parameters. + * + * Inputs: + * 1 : Screen ID (0 = top screen, 1 = bottom screen) + * 2-7 : FrameBufferInfo structure + * Outputs: + * 1: Result code + */ +void SetBufferSwap(Service::Interface* self) { + u32* cmd_buff = Service::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 +} + /** * GSP_GPU::RegisterInterruptRelayQueue service function * Inputs: @@ -283,7 +317,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00020084, nullptr, "WriteHWRegsWithMask"}, {0x00030082, nullptr, "WriteHWRegRepeat"}, {0x00040080, ReadHWRegs, "ReadHWRegs"}, - {0x00050200, nullptr, "SetBufferSwap"}, + {0x00050200, SetBufferSwap, "SetBufferSwap"}, {0x00060082, nullptr, "SetCommandList"}, {0x000700C2, nullptr, "RequestDma"}, {0x00080082, nullptr, "FlushDataCache"}, diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h index b25dbb7b..884cfd65 100644 --- a/src/core/hle/service/gsp.h +++ b/src/core/hle/service/gsp.h @@ -64,6 +64,18 @@ struct InterruptRelayQueue { static_assert(sizeof(InterruptRelayQueue) == 0x40, "InterruptRelayQueue struct has incorrect size"); +struct FrameBufferInfo { + BitField<0, 1, u32> active_fb; // 0 = first, 1 = second + + u32 address_left; + u32 address_right; + u32 stride; // maps to 0x1EF00X90 ? + u32 format; // maps to 0x1EF00X70 ? + u32 shown_fb; // maps to 0x1EF00X78 ? + u32 unknown; +}; +static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); + /// GSP command struct Command { BitField<0, 8, CommandId> id; -- cgit v1.2.3