Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 36 additions & 92 deletions Sources/main.cpp
Original file line number Diff line number Diff line change
@@ -1,105 +1,49 @@
#include <3ds.h>
#include "csvc.h"
#include <CTRPluginFramework.hpp>

#include <vector>
using namespace CTRPluginFramework;

namespace CTRPluginFramework
{
// This patch the NFC disabling the touchscreen when scanning an amiibo, which prevents ctrpf to be used
static void ToggleTouchscreenForceOn(void)
{
static u32 original = 0;
static u32 *patchAddress = nullptr;
static int fps = 0;
static int frameCounter = 0;
static u64 lastTime = 0;
static bool showOverlay = true;

if (patchAddress && original)
{
*patchAddress = original;
return;
}

static const std::vector<u32> pattern =
{
0xE59F10C0, 0xE5840004, 0xE5841000, 0xE5DD0000,
0xE5C40008, 0xE28DD03C, 0xE8BD80F0, 0xE5D51001,
0xE1D400D4, 0xE3510003, 0x159F0034, 0x1A000003
};

Result res;
Handle processHandle;
s64 textTotalSize = 0;
s64 startAddress = 0;
u32 * found;

if (R_FAILED(svcOpenProcess(&processHandle, 16)))
return;

svcGetProcessInfo(&textTotalSize, processHandle, 0x10002);
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
if(R_FAILED(svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x14000000, processHandle, (u32)startAddress, textTotalSize)))
goto exit;

found = (u32 *)Utils::Search<u32>(0x14000000, (u32)textTotalSize, pattern);

if (found != nullptr)
{
original = found[13];
patchAddress = (u32 *)PA_FROM_VA((found + 13));
found[13] = 0xE1A00000;
}

svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x14000000, textTotalSize);
exit:
svcCloseHandle(processHandle);
}

// This function is called before main and before the game starts
// Useful to do code edits safely
void PatchProcess(FwkSettings &settings)
{
ToggleTouchscreenForceOn();
}

// This function is called when the process exits
// Useful to save settings, undo patchs or clean up things
void OnProcessExit(void)
{
ToggleTouchscreenForceOn();
}

void InitMenu(PluginMenu &menu)
{
// Create your entries here, or elsewhere
// You can create your entries whenever/wherever you feel like it

// Example entry
/*menu += new MenuEntry("Test", nullptr, [](MenuEntry *entry)
{
std::string body("What's the answer ?\n");

body += std::to_string(42);
u64 GetTimeSeconds() {
return svcGetSystemTick() * 1000ULL / SYSCLOCK_ARM11 / 1000;
}

MessageBox("UA", body)();
});*/
void UpdateFPS() {
frameCounter++;
u64 now = GetTimeSeconds();
if (now != lastTime) {
lastTime = now;
fps = frameCounter;
frameCounter = 0;
}
}

int main(void)
{
PluginMenu *menu = new PluginMenu("Action Replay", 0, 8, 0,
"A blank template plugin.\nGives you access to the ActionReplay and others tools.");
void DrawOverlay() {
Color color = Color::Green;
if (fps < 20) color = Color::Red;
else if (fps < 40) color = Color::Orange;

// Synnchronize the menu with frame event
menu->SynchronizeWithFrame(true);
OSD::Draw("FPS: " + std::to_string(fps), 10, 10, color);
OSD::Draw("SELECT = ON/OFF overlay", 10, 25, Color::White);
}

// Init our menu entries & folders
InitMenu(*menu);
int main() {
PluginMenu menu("FPS Overlay");

// Launch menu and mainloop
menu->Run();
menu.OnFrame([]() {
UpdateFPS();
if (Controller::IsKeyPressed(Key::Select))
showOverlay = !showOverlay;
});

delete menu;
menu.OnDraw([]() {
if (showOverlay)
DrawOverlay();
});

// Exit plugin
return (0);
}
menu.Run();
return 0;
}