saltynx integration

This commit is contained in:
souldbminersmwc
2026-03-12 15:49:58 -04:00
parent e781e67b43
commit be3fc1bb84
10 changed files with 1131 additions and 23 deletions

View File

@@ -43,9 +43,9 @@
#define HOSPPC_HAS_BOOST (hosversionAtLeast(7,0,0))
// governor constants
#define POLL_NS = 5'000'000; // 5 ms governor poll rate
#define DOWN_HOLD_TICKS = 10; // 50 ms how long to in POLL_NS to hold while ramping down
#define STEP_UTIL = 900; // multiplier for step calculations
#define POLL_NS 5'000'000 // 5 ms governor poll rate
#define DOWN_HOLD_TICKS 10 // 50 ms how long to in POLL_NS to hold while ramping down
#define STEP_UTIL 900 // multiplier for step calculations
bool isGpuGovernorEnabled = false;
bool isCpuGovernorEnabled = false;
@@ -100,6 +100,8 @@ ClockManager::ClockManager()
this->lastCsvWriteNs = 0;
this->sysDockIntegration = new SysDockIntegration;
this->saltyNXIntegration = new SaltyNXIntegration;
memset(&initialConfigValues, 0, sizeof(initialConfigValues));
this->GetKipData();
@@ -322,7 +324,7 @@ u32 ClockManager::SchedutilTargetHz(u32 util, u32 tableMaxHz) {
u32 ClockManager::TableIndexForHz(const FreqTable& table, u32 targetHz) { // must pass in a freqTable as tables are different for cpu/gpu
for (u32 i = 0; i < table.count; i++)
if (this->freqTable.list[i] >= targetHz)
if (table.list[i] >= targetHz)
return i;
return table.count - 1;
}
@@ -630,6 +632,7 @@ void ClockManager::HandleFreqReset(SysClkModule module, bool isBoost) {
}
void ClockManager::SetClocks(bool isBoost) {
FileUtils::LogLine("FPS: %d", this->saltyNXIntegration->GetFPS());
std::uint32_t targetHz = 0;
std::uint32_t maxHz = 0;
std::uint32_t nearestHz = 0;

View File

@@ -33,6 +33,7 @@
#include "integrations.h"
class SysDockIntegration;
class SaltyNXIntegration;
class ClockManager
{
public:
@@ -257,4 +258,5 @@ class ClockManager
std::uint64_t lastPowerLogNs;
std::uint64_t lastCsvWriteNs;
SysDockIntegration *sysDockIntegration;
SaltyNXIntegration *saltyNXIntegration;
};

View File

@@ -18,6 +18,8 @@
#include "integrations.h"
#include <sys/stat.h>
#include <SaltyNX.h>
#include "process_management.h"
SysDockIntegration::SysDockIntegration() {
}
@@ -29,4 +31,74 @@ bool SysDockIntegration::getCurrentSysDockState() {
} else {
return false;
}
}
SaltyNXIntegration::SaltyNXIntegration() {
if(!CheckPort()) return;
LoadSharedMemory();
}
//Check if SaltyNX is working
bool SaltyNXIntegration::CheckPort () {
Handle saltysd;
for (int i = 0; i < 67; i++) {
if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) {
svcCloseHandle(saltysd);
break;
}
else {
if (i == 66) return false;
svcSleepThread(1'000'000);
}
}
for (int i = 0; i < 67; i++) {
if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) {
svcCloseHandle(saltysd);
return true;
}
else svcSleepThread(1'000'000);
}
return false;
}
void SaltyNXIntegration::LoadSharedMemory() {
if (SaltySD_Connect())
return;
SaltySD_GetSharedMemoryHandle(&remoteSharedMemory);
SaltySD_Term();
shmemLoadRemote(&_sharedmemory, remoteSharedMemory, 0x1000, Perm_Rw);
if (!shmemMap(&_sharedmemory))
SharedMemoryUsed = true;
}
void SaltyNXIntegration::searchSharedMemoryBlock(uintptr_t base) {
ptrdiff_t search_offset = 0;
while(search_offset < 0x1000) {
NxFps = (NxFpsSharedBlock*)(base + search_offset);
if (NxFps -> MAGIC == 0x465053) {
return;
}
else search_offset += 4;
}
NxFps = 0;
return;
}
u64 prevTid = 0;
u8 SaltyNXIntegration::GetFPS() {
if(ProcessManagement::GetCurrentApplicationId() <= 0x010000000000FFFFULL) return 254; // only try to read fps for games, not system apps
if(prevTid != ProcessManagement::GetCurrentApplicationId()) {
uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory);
searchSharedMemoryBlock(base);
prevTid = ProcessManagement::GetCurrentApplicationId();
}
if (NxFps) {
return NxFps->FPS;
} else {
return 254;
}
}

View File

@@ -34,4 +34,58 @@ public:
SysDockIntegration();
bool getCurrentSysDockState();
};
class SaltyNXIntegration {
public:
struct resolutionCalls {
uint16_t width;
uint16_t height;
uint16_t calls;
};
struct NxFpsSharedBlock {
uint32_t MAGIC;
uint8_t FPS;
float FPSavg;
bool pluginActive;
uint8_t FPSlocked;
uint8_t FPSmode;
uint8_t ZeroSync;
uint8_t patchApplied;
uint8_t API;
uint32_t FPSticks[10];
uint8_t Buffers;
uint8_t SetBuffers;
uint8_t ActiveBuffers;
uint8_t SetActiveBuffers;
union {
struct {
bool handheld: 1;
bool docked: 1;
unsigned int reserved: 6;
} NX_PACKED ds;
uint8_t general;
} displaySync;
resolutionCalls renderCalls[8];
resolutionCalls viewportCalls[8];
bool forceOriginalRefreshRate;
bool dontForce60InDocked;
bool forceSuspend;
uint8_t currentRefreshRate;
float readSpeedPerSecond;
uint8_t FPSlockedDocked;
uint64_t frameNumber;
} NX_PACKED;
NxFpsSharedBlock* NxFps = 0;
SharedMemory _sharedmemory = {};
bool SharedMemoryUsed = false;
Handle remoteSharedMemory = 1;
SaltyNXIntegration();
bool CheckPort();
void LoadSharedMemory();
void searchSharedMemoryBlock(uintptr_t base);
u8 GetFPS();
};

View File

@@ -38,8 +38,11 @@
#include "ipc_service.h"
#define INNER_HEAP_SIZE 0x40000
extern "C"
{
void virtmemSetup(void);
extern std::uint32_t __start__;
std::uint32_t __nx_applet_type = AppletType_None;
@@ -88,6 +91,8 @@ extern "C"
rc = i2cInitialize();
if (R_FAILED(rc))
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
virtmemSetup();
}
void __appExit(void)