diff --git a/lcs/generated/generated_unit_0111.cpp b/lcs/generated/generated_unit_0111.cpp index e97e339..95c1147 100644 --- a/lcs/generated/generated_unit_0111.cpp +++ b/lcs/generated/generated_unit_0111.cpp @@ -1,6 +1,7 @@ #include "psprecomp/runtime.hpp" #include "generated_units.hpp" #include "lcs_widescreen.hpp" +#include "lcs_menu.hpp" #include #include #include @@ -7155,11 +7156,13 @@ L_089C2F40: goto L_089C2F60; } L_089C2F60: + lcs::lcs_menu_begin(); ctx.gpr[31] = (0x089C2F68u); ctx.gpr[4] = (ctx.gpr[6] | 0u); if (rt.invoke_chained_direct<&recomp_unit_0182_entry, 182u, 767u, 0x08ADEE88u>(ctx, &aot_mem) && ctx.pc == 0x089C2F68u) goto L_089C2F68; return; L_089C2F68: + lcs::lcs_menu_end(); ctx.gpr[6] = (2230u << 16u); ctx.gpr[6] = (aot_mem.aot_load32(ctx.gpr[6] + static_cast(-25816))); ctx.gpr[4] = (0u | 6u); diff --git a/lcs/host/display_window.cpp b/lcs/host/display_window.cpp index a5587ce..e9db5fb 100644 --- a/lcs/host/display_window.cpp +++ b/lcs/host/display_window.cpp @@ -5,6 +5,7 @@ #include "lcs_mouse.hpp" #include "lcs_controls.hpp" #include "lcs_display_menu.hpp" +#include "lcs_menu.hpp" #include "lcs_render_config.hpp" #if defined(_WIN32) @@ -337,8 +338,7 @@ LRESULT CALLBACK window_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lpar } return DefWindowProcW(hwnd, message, wparam, lparam); } - if (message == WM_SETCURSOR && LOWORD(lparam) == HTCLIENT && lcs_camera_hook_enabled() && - lcs_camera_in_use()) { + if (message == WM_SETCURSOR && LOWORD(lparam) == HTCLIENT && !lcs_menu_active()) { SetCursor(nullptr); return TRUE; } @@ -614,7 +614,7 @@ HostInputState display_window_input() { const std::int32_t mouse_dy = g_mouse_dy.exchange(0, std::memory_order_relaxed); const bool focused = g_window != nullptr && GetForegroundWindow() == g_window; static bool was_captured = false; - const bool in_game = lcs_camera_in_use(); + const bool in_game = lcs_camera_in_use() && !lcs_menu_active(); const bool moving_window = focused && (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0 && GetCapture() != nullptr; const bool capture = focused && in_game && !moving_window && !IsIconic(g_window); diff --git a/lcs/host/display_window_sdl.cpp b/lcs/host/display_window_sdl.cpp index a3616f5..1274ed9 100644 --- a/lcs/host/display_window_sdl.cpp +++ b/lcs/host/display_window_sdl.cpp @@ -4,6 +4,7 @@ #include "ge_gpu_backend.hpp" #include "lcs_controls.hpp" +#include "lcs_menu.hpp" #include "lcs_mouse.hpp" #include "lcs_display_menu.hpp" #include "lcs_render_config.hpp" @@ -523,12 +524,15 @@ HostInputState display_window_input() { const std::int32_t mouse_dx = g_mouse_dx.exchange(0, std::memory_order_relaxed); const std::int32_t mouse_dy = g_mouse_dy.exchange(0, std::memory_order_relaxed); const bool focused = g_window != nullptr && g_focused; - const bool in_game = lcs_camera_in_use(); + const bool menu = lcs_menu_active(); + const bool in_game = lcs_camera_in_use() && !menu; const bool minimized = g_window != nullptr && (SDL_GetWindowFlags(g_window) & SDL_WINDOW_MINIMIZED) != 0; const bool capture = focused && in_game && !minimized && lcs_camera_hook_enabled(); if ((SDL_GetRelativeMouseMode() == SDL_TRUE) != capture) SDL_SetRelativeMouseMode(capture ? SDL_TRUE : SDL_FALSE); + if ((SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE) != menu) + SDL_ShowCursor(menu ? SDL_ENABLE : SDL_DISABLE); const bool driving = lcs_player_in_vehicle(); const ControlsConfiguration &controls = lcs_render_configuration().controls; if (focused) { diff --git a/lcs/host/ge_renderer.cpp b/lcs/host/ge_renderer.cpp index ef44109..895671d 100644 --- a/lcs/host/ge_renderer.cpp +++ b/lcs/host/ge_renderer.cpp @@ -1,7 +1,7 @@ #include "ge_renderer.hpp" #include "ge_gpu_backend.hpp" -#include "lcs_controls.hpp" #include "lcs_fps_overlay.hpp" +#include "lcs_menu.hpp" #include "lcs_render_config.hpp" #include "psprecomp/common.hpp" @@ -4527,8 +4527,7 @@ bool render_ge_primitive(psprecomp::GuestMemory &memory, !(setup.texture_enabled && ge_gpu_backend_is_framebuffer_feedback_texture(gpu_draw)); const float hud_scale = lcs_hud_scale(); - if (hud_candidate && hud_scale < 1.0f && - (lcs_camera_in_use() || !lcs_camera_hook_enabled())) { + if (hud_candidate && hud_scale < 1.0f && !lcs_menu_command()) { std::uint32_t logical_width = 480u; std::uint32_t logical_height = 272u; ge_gpu_backend_display_logical_size(logical_width, logical_height); diff --git a/lcs/host/lcs_ge_exec.cpp b/lcs/host/lcs_ge_exec.cpp index 06411a4..89d1580 100644 --- a/lcs/host/lcs_ge_exec.cpp +++ b/lcs/host/lcs_ge_exec.cpp @@ -1,6 +1,7 @@ #include "lcs_ge_exec.hpp" #include "ge_renderer.hpp" +#include "lcs_menu.hpp" #include "psprecomp/common.hpp" #include @@ -98,6 +99,7 @@ void execute_ge_list_rendered(psprecomp::GuestMemory &memory, std::uint32_t list case 0x04u: { GeRenderStats stats{}; std::string error; + lcs_set_ge_command(op_pc); if (!render_ge_primitive(memory, ge_commands, ge_transform, ge_vertex_address, ge_index_address, data, stats, error, 1u, 0u, 0u, 0u, diag)) { diff --git a/lcs/host/lcs_menu.cpp b/lcs/host/lcs_menu.cpp new file mode 100644 index 0000000..39f1a11 --- /dev/null +++ b/lcs/host/lcs_menu.cpp @@ -0,0 +1,39 @@ +#include "lcs_menu.hpp" + +namespace lcs { +namespace { + +psprecomp::Runtime *g_runtime{}; +std::uint32_t g_pending_begin{}; +std::uint32_t g_pending_end{}; +std::uint32_t g_menu_begin{}; +std::uint32_t g_menu_end{}; +std::uint32_t g_command{}; + +std::uint32_t ge_list_write_pointer() { + return g_runtime->memory().load32(0x08B8EBD0u) & 0x0FFFFFFFu; +} + +} // namespace + +void lcs_menu_init(psprecomp::Runtime &runtime) { g_runtime = &runtime; } + +bool lcs_menu_active() { + return g_runtime != nullptr && g_runtime->memory().load8(0x08B8EE51u) != 0u; +} + +void lcs_menu_begin() { g_pending_begin = ge_list_write_pointer(); } + +void lcs_menu_end() { g_pending_end = ge_list_write_pointer(); } + +void lcs_menu_enqueue() { + g_menu_begin = g_pending_begin; + g_menu_end = g_pending_end; + g_pending_begin = g_pending_end = 0u; +} + +void lcs_set_ge_command(std::uint32_t address) { g_command = address; } + +bool lcs_menu_command() { return g_command >= g_menu_begin && g_command < g_menu_end; } + +} diff --git a/lcs/host/lcs_menu.hpp b/lcs/host/lcs_menu.hpp new file mode 100644 index 0000000..1fe3bfb --- /dev/null +++ b/lcs/host/lcs_menu.hpp @@ -0,0 +1,16 @@ +#pragma once +#include "psprecomp/runtime.hpp" + +#include + +namespace lcs { + +void lcs_menu_init(psprecomp::Runtime &runtime); +[[nodiscard]] bool lcs_menu_active(); +void lcs_menu_begin(); +void lcs_menu_end(); +void lcs_menu_enqueue(); +void lcs_set_ge_command(std::uint32_t address); +[[nodiscard]] bool lcs_menu_command(); + +} diff --git a/lcs/host/lcs_profile.cpp b/lcs/host/lcs_profile.cpp index 080dd12..5140bef 100644 --- a/lcs/host/lcs_profile.cpp +++ b/lcs/host/lcs_profile.cpp @@ -10,6 +10,7 @@ #include "lcs_fps_overlay.hpp" #include "lcs_frame_limit.hpp" #include "lcs_lang.hpp" +#include "lcs_menu.hpp" #include "psprecomp/common.hpp" @@ -2372,6 +2373,7 @@ void dump_pc_profile() { void install_profile(psprecomp::Runtime &runtime, std::uint32_t user_arena_start) { thread_table = ThreadTable{}; + lcs_menu_init(runtime); ThreadRecord module_thread{}; module_thread.name = "module_start"; @@ -3986,6 +3988,7 @@ void install_profile(psprecomp::Runtime &runtime, std::uint32_t user_arena_start list_finished = scan.finished; finish_argument = scan.finish_argument; } else if (ge_worker_wait_idle(); ge_async_enabled()) { + lcs_menu_enqueue(); const GeListPrescan scan = prescan_ge_list(rt.memory(), list_address); list_finished = scan.finished; finish_argument = scan.finish_argument; @@ -3997,6 +4000,7 @@ void install_profile(psprecomp::Runtime &runtime, std::uint32_t user_arena_start std::chrono::steady_clock::now() - list_started).count()); }); } else { + lcs_menu_enqueue(); const auto list_started = std::chrono::steady_clock::now(); execute_ge_list_frame(rt, list_address, display_vblank_index); g_speed_ge_list_ns += static_cast(std::chrono::duration_cast(