summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/ac_u.cpp20
-rw-r--r--src/core/hle/service/frd/frd.cpp12
-rw-r--r--src/core/hle/service/frd/frd.h9
-rw-r--r--src/core/hle/service/frd/frd_u.cpp2
-rw-r--r--src/core/hle/service/fs/fs_user.cpp24
-rw-r--r--src/core/hle/service/gsp_gpu.cpp2
-rw-r--r--src/core/hle/service/mic_u.cpp20
-rw-r--r--src/core/hle/service/service.h12
-rw-r--r--src/core/hw/gpu.cpp33
-rw-r--r--src/core/settings.cpp1
-rw-r--r--src/core/settings.h1
11 files changed, 122 insertions, 14 deletions
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 18026975f..fe367aca5 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -230,6 +230,24 @@ static void IsConnected(Service::Interface* self) {
LOG_WARNING(Service_AC, "(STUBBED) called");
}
+/**
+ * AC_U::SetClientVersion service function
+ * Inputs:
+ * 1 : Used SDK Version
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetClientVersion(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ const u32 version = cmd_buff[1];
+ self->SetVersion(version);
+
+ LOG_WARNING(Service_AC, "(STUBBED) called, version: 0x%08X", version);
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010000, CreateDefaultConfig, "CreateDefaultConfig"},
{0x00040006, ConnectAsync, "ConnectAsync"},
@@ -250,7 +268,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00300004, RegisterDisconnectEvent, "RegisterDisconnectEvent"},
{0x003C0042, nullptr, "GetAPSSIDList"},
{0x003E0042, IsConnected, "IsConnected"},
- {0x00400042, nullptr, "SetClientVersion"},
+ {0x00400042, SetClientVersion, "SetClientVersion"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index 1d16f8732..34fdf7f53 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -100,6 +100,18 @@ void GetMyScreenName(Service::Interface* self) {
LOG_WARNING(Service_FRD, "(STUBBED) called");
}
+void SetClientSdkVersion(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ const u32 version = cmd_buff[1];
+
+ self->SetVersion(version);
+
+ LOG_WARNING(Service_FRD, "(STUBBED) called, version: 0x%08X", version);
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+}
+
void Init() {
using namespace Kernel;
diff --git a/src/core/hle/service/frd/frd.h b/src/core/hle/service/frd/frd.h
index c8283a7f3..e61940ea0 100644
--- a/src/core/hle/service/frd/frd.h
+++ b/src/core/hle/service/frd/frd.h
@@ -95,6 +95,15 @@ void GetMyFriendKey(Service::Interface* self);
*/
void GetMyScreenName(Service::Interface* self);
+/**
+ * FRD::SetClientSdkVersion service function
+ * Inputs:
+ * 1 : Used SDK Version
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void SetClientSdkVersion(Service::Interface* self);
+
/// Initialize FRD service(s)
void Init();
diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp
index bd1c9c16b..496f29ca9 100644
--- a/src/core/hle/service/frd/frd_u.cpp
+++ b/src/core/hle/service/frd/frd_u.cpp
@@ -58,7 +58,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x002F0040, nullptr, "AllowHalfAwake"},
{0x00300000, nullptr, "GetServerTypes"},
{0x00310082, nullptr, "GetFriendComment"},
- {0x00320042, nullptr, "SetClientSdkVersion"},
+ {0x00320042, SetClientSdkVersion, "SetClientSdkVersion"},
{0x00330000, nullptr, "GetMyApproachContext"},
{0x00340046, nullptr, "AddFriendWithApproach"},
{0x00350082, nullptr, "DecryptApproachContext"},
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 00edc7622..9ec17b395 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -763,23 +763,27 @@ static void CreateLegacySystemSaveData(Service::Interface* self) {
* FS_User::InitializeWithSdkVersion service function.
* Inputs:
* 0 : 0x08610042
- * 1 : Unknown
- * 2 : Unknown
- * 3 : Unknown
+ * 1 : Used SDK Version
+ * 2 : ProcessId Header
+ * 3 : placeholder for ProcessId
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
static void InitializeWithSdkVersion(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 unk1 = cmd_buff[1];
- u32 unk2 = cmd_buff[2];
- u32 unk3 = cmd_buff[3];
+ const u32 version = cmd_buff[1];
+ self->SetVersion(version);
- cmd_buff[1] = RESULT_SUCCESS.raw;
-
- LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", unk1, unk2,
- unk3);
+ if (cmd_buff[2] == IPC::CallingPidDesc()) {
+ LOG_WARNING(Service_FS, "(STUBBED) called, version: 0x%08X", version);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ } else {
+ LOG_ERROR(Service_FS, "ProcessId Header must be 0x20");
+ cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
+ ErrorSummary::WrongArgument, ErrorLevel::Permanent)
+ .raw;
+ }
}
/**
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 710e0e485..78cb761be 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -346,7 +346,7 @@ static void SetAxiConfigQoSMode(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
- LOG_WARNING(Service_GSP, "(STUBBED) called mode=0x%08X", mode);
+ LOG_DEBUG(Service_GSP, "(STUBBED) called mode=0x%08X", mode);
}
/**
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 563341504..1f851d328 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -287,6 +287,24 @@ static void SetAllowShellClosed(Service::Interface* self) {
LOG_WARNING(Service_MIC, "(STUBBED) called, allow_shell_closed=%u", allow_shell_closed);
}
+/**
+ * MIC_U::SetClientVersion service function
+ * Inputs:
+ * 1 : Used SDK Version
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetClientVersion(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ const u32 version = cmd_buff[1];
+ self->SetVersion(version);
+
+ LOG_WARNING(Service_MIC, "(STUBBED) called, version: 0x%08X", version);
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+}
+
const Interface::FunctionInfo FunctionTable[] = {
{0x00010042, MapSharedMem, "MapSharedMem"},
{0x00020000, UnmapSharedMem, "UnmapSharedMem"},
@@ -303,7 +321,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x000D0040, SetClamp, "SetClamp"},
{0x000E0000, GetClamp, "GetClamp"},
{0x000F0040, SetAllowShellClosed, "SetAllowShellClosed"},
- {0x00100040, nullptr, "SetClientSDKVersion"},
+ {0x00100040, SetClientVersion, "SetClientVersion"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 39b5ffaae..29daacfc4 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -29,6 +29,10 @@ public:
return GetPortName();
}
+ virtual void SetVersion(u32 raw_version) {
+ version.raw = raw_version;
+ }
+
typedef void (*Function)(Interface*);
struct FunctionInfo {
@@ -58,6 +62,14 @@ protected:
void Register(const FunctionInfo* functions, size_t n);
+ union {
+ u32 raw;
+ BitField<0, 8, u32> major;
+ BitField<8, 8, u32> minor;
+ BitField<16, 8, u32> build;
+ BitField<24, 8, u32> revision;
+ } version = {};
+
private:
boost::container::flat_map<u32, FunctionInfo> m_functions;
};
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 45dedea68..cfba82e51 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -8,7 +8,10 @@
#include "common/color.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/math_util.h"
#include "common/microprofile.h"
+#include "common/thread.h"
+#include "common/timer.h"
#include "common/vector_math.h"
#include "core/core_timing.h"
#include "core/hle/service/gsp_gpu.h"
@@ -35,6 +38,14 @@ const u64 frame_ticks = 268123480ull / 60;
static int vblank_event;
/// Total number of frames drawn
static u64 frame_count;
+/// Start clock for frame limiter
+static u32 time_point;
+/// Total delay caused by slow frames
+static float time_delay;
+constexpr float FIXED_FRAME_TIME = 1000.0f / 60;
+// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher
+// values increases time needed to limit frame rate after spikes
+constexpr float MAX_LAG_TIME = 18;
template <typename T>
inline void Read(T& var, const u32 raw_addr) {
@@ -512,6 +523,21 @@ template void Write<u32>(u32 addr, const u32 data);
template void Write<u16>(u32 addr, const u16 data);
template void Write<u8>(u32 addr, const u8 data);
+static void FrameLimiter() {
+ time_delay += FIXED_FRAME_TIME;
+ time_delay = MathUtil::Clamp(time_delay, -MAX_LAG_TIME, MAX_LAG_TIME);
+ s32 desired_time = static_cast<s32>(time_delay);
+ s32 elapsed_time = static_cast<s32>(Common::Timer::GetTimeMs() - time_point);
+
+ if (elapsed_time < desired_time) {
+ Common::SleepCurrentThread(desired_time - elapsed_time);
+ }
+
+ u32 frame_time = Common::Timer::GetTimeMs() - time_point;
+
+ time_delay -= frame_time;
+}
+
/// Update hardware
static void VBlankCallback(u64 userdata, int cycles_late) {
frame_count++;
@@ -528,6 +554,12 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
// Check for user input updates
Service::HID::Update();
+ if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) {
+ FrameLimiter();
+ }
+
+ time_point = Common::Timer::GetTimeMs();
+
// Reschedule recurrent event
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
}
@@ -563,6 +595,7 @@ void Init() {
framebuffer_sub.active_fb = 0;
frame_count = 0;
+ time_point = Common::Timer::GetTimeMs();
vblank_event = CoreTiming::RegisterEvent("GPU::VBlankCallback", VBlankCallback);
CoreTiming::ScheduleEvent(frame_ticks, vblank_event);
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 05f41f798..626e06cd9 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -21,6 +21,7 @@ void Apply() {
VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
VideoCore::g_shader_jit_enabled = values.use_shader_jit;
VideoCore::g_scaled_resolution_enabled = values.use_scaled_resolution;
+ VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit;
if (VideoCore::g_emu_window) {
auto layout = VideoCore::g_emu_window->GetFramebufferLayout();
diff --git a/src/core/settings.h b/src/core/settings.h
index 7470fdbeb..db4c8fada 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -90,6 +90,7 @@ struct Values {
bool use_shader_jit;
bool use_scaled_resolution;
bool use_vsync;
+ bool toggle_framelimit;
LayoutOption layout_option;
bool swap_screen;