Files
SpartanPort/tests/test_menu_hook.cpp
Felipe Prado 138f9e6f8e Feat(Menu): expanded native graphics, display and control settings (#980)
EN-US

Expanded the native options menus with graphics, display, controller and mouse settings, sharing preferences with the launcher and Insert menu.

- Added Graphics Settings with queued frames, asynchronous shaders, RCAS sharpening, anisotropic filtering and restore defaults.
- Added resolution, aspect ratio, frame rate limits, monitor, display mode, VSync and HDR to Display.
- Added button icon choices, vibration strength and mouse settings while preserving the original Controls options.
- Added scrolling indicators and Yes/No confirmations for restoring defaults and applying changes that require a restart.

Validation:
- Passed 260 targeted Python tests and two native tests.
- Built the Windows executable and manually validated the native menus.
- Simulated merging into main at 5abea30 without conflicts.
- Left dedicated HDR and multiple-monitor hardware validation pending.

---

PT-BR

Ampliados os menus nativos de opções com ajustes gráficos, de exibição, controle e mouse, compartilhando preferências com o launcher e o menu Insert.

- Adicionadas Configurações Gráficas com quadros enfileirados, shaders assíncronos, nitidez RCAS, filtragem anisotrópica e restauração dos padrões.
- Adicionados resolução, proporção, limites de FPS, monitor, modo de exibição, VSync e HDR em Exibição.
- Adicionadas opções de ícones, intensidade da vibração e configurações do mouse, preservando as opções originais de Controles.
- Adicionados indicadores de rolagem e confirmações de Sim/Não para restaurar padrões e aplicar alterações que exigem reinício.

Validação:
- Aprovados 260 testes Python focados e dois testes nativos.
- Compilado o executável Windows e validados manualmente os menus nativos.
- Simulado o merge na main em 5abea30 sem conflitos.
- Mantida pendente a validação específica de HDR e múltiplos monitores em hardware.
2026-10-22 23:39:07 -03:00

66 lines
3.0 KiB
C++

// Runs the menu interpreter's builtin-call stub (src/menu_hook.h): any other function replays the
// replaced instructions and resumes; function 0xfff goes to quit.
#include <cassert>
#include <cstdint>
#include "../src/menu_hook.h"
#include <windows.h>
// The stub ends with a jump to its resume address; here that is a `ret` back to the test.
extern "C" void menu_hook_return();
asm(".globl menu_hook_return\nmenu_hook_return:\n ret\n");
static void* back[5];
static int quits;
static void quit() {
++quits;
__builtin_longjmp(back, 1); // no unwinding through the stub
}
// The interpreter frame: [rbp-0x2a0] is the provider table, rax the provider; rdi gets the entry.
alignas(16) static uint64_t frame[96];
static uint64_t providers[2] = {0x1111, 0x2222};
static uint64_t native_provider;
static uint64_t call(unsigned char* stub, uint32_t function, uint64_t provider) {
uint64_t rdi;
asm volatile("push %%rbp\n\tmov %%rbx, %%rbp\n\tcall *%%rcx\n\tpop %%rbp"
: "=D"(rdi), "+c"(stub), "+a"(provider), "+S"(function)
: "b"(frame + 96)
: "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
return rdi;
}
int main() {
assert(spartanport_menu_signature_match(spartanport_menu_original, SPARTAN_MENU_HOOK_LENGTH));
assert(!spartanport_menu_signature_match(spartanport_menu_original, SPARTAN_MENU_HOOK_LENGTH - 1));
auto* stub = static_cast<unsigned char*>(
VirtualAlloc(nullptr, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));
assert(stub);
assert(spartanport_menu_build_stub(stub, reinterpret_cast<uintptr_t>(&quit),
reinterpret_cast<uintptr_t>(&menu_hook_return),
reinterpret_cast<uintptr_t>(&native_provider)) < 256);
frame[96 - 0x2a0 / 8] = reinterpret_cast<uint64_t>(providers);
assert(call(stub, 0x5a, 1) == 0x2222); // a game builtin: the original lookup
assert(call(stub, 0xffc, 0) == 0x1111 && quits == 0);
assert(call(stub, 0xffd, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xffe, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xffe, 1) == 0x2222); // only GBL (provider 0) is extended
assert(call(stub, 0xf00, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xf60, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xf70, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xfb0, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xf90, 1) == 0x2222);
assert(call(stub, 0xfc0, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xff7, 0) == reinterpret_cast<uintptr_t>(&native_provider));
assert(call(stub, 0xff8, 0) == 0x1111);
assert(call(stub, 0xeff, 0) == 0x1111);
if (!__builtin_setjmp(back)) {
call(stub, SPARTAN_MENU_EXIT_FUNCTION, 0);
assert(!"quit returned");
}
assert(quits == 1);
return 0;
}