diff --git a/libultraship/libultraship/GameSettings.cpp b/libultraship/libultraship/GameSettings.cpp index c2d876ab0..d9353a58a 100644 --- a/libultraship/libultraship/GameSettings.cpp +++ b/libultraship/libultraship/GameSettings.cpp @@ -10,13 +10,12 @@ #include "Cvar.h" #include "GlobalCtx2.h" #include "SohImGuiImpl.h" -#include "stox.h" #include "../../soh/include/z64audio.h" -#include #include "SohHooks.h" #include "../../soh/soh/Enhancements/debugconsole.h" #include "Window.h" +#include "Lib/Fast3D/gfx_rendering_api.h" #define ABS(var) var < 0 ? -(var) : var @@ -25,14 +24,6 @@ using namespace Ship; namespace Game { bool DeSyncAudio = false; - SoHConfigType Settings; - const std::string ConfSection = DEBUG_SECTION; - const std::string AudioSection = AUDIO_SECTION; - const std::string ControllerSection = CONTROLLER_SECTION; - const std::string EnhancementSection = ENHANCEMENTS_SECTION; - const std::string CosmeticsSection = COSMETICS_SECTION; - const std::string CheatSection = CHEATS_SECTION; - const std::string LanguagesSection = LANGUAGES_SECTION; void UpdateAudio() { Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1)); @@ -41,18 +32,6 @@ namespace Game { Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); } - void LoadSettings() { - const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf; - - // Debug - SohImGui::console->opened = stob(Conf[ConfSection]["console"]); - Settings.debug.menu_bar = stob(Conf[ConfSection]["menu_bar"]); - Settings.debug.soh = stob(Conf[ConfSection]["soh_debug"]); - - UpdateAudio(); - } - void LoadPadSettings() { const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); ConfigFile& Conf = *pConf; @@ -65,16 +44,11 @@ namespace Game { } } + void LoadSettings() { + DebugConsole_LoadCVars(); + } + void SaveSettings() { - const std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig(); - ConfigFile& Conf = *pConf; - - // Debug - Conf[ConfSection]["console"] = std::to_string(SohImGui::console->opened); - Conf[ConfSection]["menu_bar"] = std::to_string(Settings.debug.menu_bar); - Conf[ConfSection]["soh_debug"] = std::to_string(Settings.debug.soh); - - Conf.Save(); DebugConsole_SaveCVars(); } @@ -82,6 +56,11 @@ namespace Game { ModInternal::registerHookListener({ AUDIO_INIT, [](HookEvent ev) { UpdateAudio(); }}); + ModInternal::registerHookListener({ GFX_INIT, [](HookEvent ev) { + gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", THREE_POINT)); + SohImGui::console->opened = CVar_GetS32("gConsoleEnabled", 0); + UpdateAudio(); + }}); } void SetSeqPlayerVolume(SeqPlayers playerId, float volume) { diff --git a/libultraship/libultraship/GameSettings.h b/libultraship/libultraship/GameSettings.h index 9d4e3e776..0a9aa0ee6 100644 --- a/libultraship/libultraship/GameSettings.h +++ b/libultraship/libultraship/GameSettings.h @@ -1,19 +1,5 @@ #pragma once -struct SoHConfigType { - // Debug - struct { - bool soh = false; - bool menu_bar = false; - bool soh_sink = true; - } debug; - - // Graphics - struct { - bool show = false; - } graphics; -}; - enum SeqPlayers { /* 0 */ SEQ_BGM_MAIN, /* 1 */ SEQ_FANFARE, @@ -22,16 +8,7 @@ enum SeqPlayers { /* 4 */ SEQ_MAX }; -#define DEBUG_SECTION "DEBUG SETTINGS" -#define AUDIO_SECTION "AUDIO SETTINGS" -#define CONTROLLER_SECTION "CONTROLLER SECTION" -#define ENHANCEMENTS_SECTION "ENHANCEMENT SETTINGS" -#define COSMETICS_SECTION "COSMETIC SETTINGS" -#define CHEATS_SECTION "CHEATS SETTINGS" -#define LANGUAGES_SECTION "LANGUAGES SETTINGS" - namespace Game { - extern SoHConfigType Settings; void InitSettings(); void LoadSettings(); void LoadPadSettings(); diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp index cea82e09e..8671c3df4 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_direct3d11.cpp @@ -15,11 +15,9 @@ #ifndef _LANGUAGE_C #define _LANGUAGE_C #endif -#include +#include "PR/ultra64/gbi.h" -#include "gfx_cc.h" #include "gfx_window_manager_api.h" -#include "gfx_rendering_api.h" #include "gfx_direct3d_common.h" #define DECLARE_GFX_DXGI_FUNCTIONS @@ -28,7 +26,9 @@ #include "gfx_screen_config.h" #include "../../SohImGuiImpl.h" -#define THREE_POINT_FILTERING 0 +#include "gfx_cc.h" +#include "gfx_rendering_api.h" +#include "gfx_pc.h" #define DEBUG_D3D 0 using namespace Microsoft::WRL; // For ComPtr @@ -135,6 +135,7 @@ static struct { //uint32_t current_width, current_height; uint32_t render_target_height; int current_framebuffer; + FilteringMode current_filter_mode = NONE; int8_t depth_test; int8_t depth_mask; @@ -397,7 +398,7 @@ static struct ShaderProgram *gfx_d3d11_create_and_load_new_shader(uint64_t shade char buf[4096]; size_t len, num_floats; - gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, THREE_POINT_FILTERING); + gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, d3d.current_filter_mode == THREE_POINT); ComPtr vs, ps; ComPtr error_blob; @@ -564,11 +565,8 @@ static void gfx_d3d11_set_sampler_parameters(int tile, bool linear_filter, uint3 D3D11_SAMPLER_DESC sampler_desc; ZeroMemory(&sampler_desc, sizeof(D3D11_SAMPLER_DESC)); -#if THREE_POINT_FILTERING - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; -#else - sampler_desc.Filter = linear_filter ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT; -#endif + sampler_desc.Filter = linear_filter && d3d.current_filter_mode == LINEAR ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT; + sampler_desc.AddressU = gfx_cm_to_d3d11(cms); sampler_desc.AddressV = gfx_cm_to_d3d11(cmt); sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; @@ -672,12 +670,12 @@ static void gfx_d3d11_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t d3d.last_resource_views[i] = d3d.textures[d3d.current_texture_ids[i]].resource_view.Get(); d3d.context->PSSetShaderResources(i, 1, d3d.textures[d3d.current_texture_ids[i]].resource_view.GetAddressOf()); -#if THREE_POINT_FILTERING - d3d.per_draw_cb_data.textures[i].width = d3d.textures[d3d.current_texture_ids[i]].width; - d3d.per_draw_cb_data.textures[i].height = d3d.textures[d3d.current_texture_ids[i]].height; - d3d.per_draw_cb_data.textures[i].linear_filtering = d3d.textures[d3d.current_texture_ids[i]].linear_filtering; - textures_changed = true; -#endif + if (d3d.current_filter_mode == THREE_POINT) { + d3d.per_draw_cb_data.textures[i].width = d3d.textures[d3d.current_texture_ids[i]].width; + d3d.per_draw_cb_data.textures[i].height = d3d.textures[d3d.current_texture_ids[i]].height; + d3d.per_draw_cb_data.textures[i].linear_filtering = d3d.textures[d3d.current_texture_ids[i]].linear_filtering; + textures_changed = true; + } if (d3d.last_sampler_states[i].Get() != d3d.textures[d3d.current_texture_ids[i]].sampler_state.Get()) { d3d.last_sampler_states[i] = d3d.textures[d3d.current_texture_ids[i]].sampler_state.Get(); @@ -880,6 +878,15 @@ void gfx_d3d11_select_texture_fb(int fbID) { gfx_d3d11_select_texture(tile, d3d.framebuffers[fbID].texture_id); } +void gfx_d3d11_set_texture_filter(FilteringMode mode) { + d3d.current_filter_mode = mode; + gfx_texture_cache_clear(); +} + +FilteringMode gfx_d3d11_get_texture_filter(void) { + return d3d.current_filter_mode; +} + std::map, uint16_t> gfx_d3d11_get_pixel_depth(int fb_id, const std::set>& coordinates) { Framebuffer& fb = d3d.framebuffers[fb_id]; TextureData& td = d3d.textures[fb.texture_id]; @@ -1019,7 +1026,9 @@ struct GfxRenderingAPI gfx_direct3d11_api = { gfx_d3d11_get_pixel_depth, gfx_d3d11_get_framebuffer_texture_id, gfx_d3d11_select_texture_fb, - gfx_d3d11_delete_texture + gfx_d3d11_delete_texture, + gfx_d3d11_set_texture_filter, + gfx_d3d11_get_texture_filter }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp index 6c5f47577..0c649d562 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp @@ -73,6 +73,7 @@ static uint32_t frame_count; static vector framebuffers; static size_t current_framebuffer; static float current_noise_scale; +static FilteringMode current_filter_mode = THREE_POINT; GLuint pixel_depth_rb, pixel_depth_fb; size_t pixel_depth_rb_size; @@ -211,7 +212,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad gfx_cc_get_features(shader_id0, shader_id1, &cc_features); char vs_buf[1024]; - char fs_buf[1024]; + char fs_buf[3000]; size_t vs_len = 0; size_t fs_len = 0; size_t num_floats = 4; @@ -312,21 +313,42 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad append_line(fs_buf, &fs_len, "}"); } + if (current_filter_mode == THREE_POINT) { + append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)"); + append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));"); + append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);"); + append_line(fs_buf, &fs_len, " vec4 c0 = TEX_OFFSET(offset);"); + append_line(fs_buf, &fs_len, " vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y));"); + append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)));"); + append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);"); + append_line(fs_buf, &fs_len, "}"); + append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, " return filter3point(tex, uv, texSize);"); + append_line(fs_buf, &fs_len, "}"); + } else { + append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {"); + append_line(fs_buf, &fs_len, " return texture2D(tex, uv);"); + append_line(fs_buf, &fs_len, "}"); + } + append_line(fs_buf, &fs_len, "void main() {"); for (int i = 0; i < 2; i++) { if (cc_features.used_textures[i]) { bool s = cc_features.clamp[i][0], t = cc_features.clamp[i][1]; + + fs_len += sprintf(fs_buf + fs_len, "vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i); + if (!s && !t) { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, vTexCoord%d);\n", i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vTexCoord%d, texSize%d);\n", i, i, i, i); } else { - fs_len += sprintf(fs_buf + fs_len, "vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i); if (s && t) { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, clamp(vTexCoord%d, 0.5 / texSize%d, vec2(vTexClampS%d, vTexClampT%d)));\n", i, i, i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, clamp(vTexCoord%d, 0.5 / texSize%d, vec2(vTexClampS%d, vTexClampT%d)), texSize%d);\n", i, i, i, i, i, i, i); } else if (s) { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, vec2(clamp(vTexCoord%d.s, 0.5 / texSize%d.s, vTexClampS%d), vTexCoord%d.t));\n", i, i, i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vec2(clamp(vTexCoord%d.s, 0.5 / texSize%d.s, vTexClampS%d), vTexCoord%d.t), texSize%d);\n", i, i, i, i, i, i, i); } else { - fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = texture2D(uTex%d, vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, 0.5 / texSize%d.t, vTexClampT%d)));\n", i, i, i, i, i, i); + fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, 0.5 / texSize%d.t, vTexClampT%d)), texSize%d);\n", i, i, i, i, i, i, i); } } } @@ -422,9 +444,9 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad GLint max_length = 0; glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &max_length); char error_log[1024]; - //fprintf(stderr, "Fragment shader compilation failed\n"); + fprintf(stderr, "Fragment shader compilation failed\n"); glGetShaderInfoLog(fragment_shader, max_length, &max_length, &error_log[0]); - //fprintf(stderr, "%s\n", &error_log[0]); + fprintf(stderr, "%s\n", &error_log[0]); abort(); } @@ -552,9 +574,10 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) { } static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { + const GLint filter = linear_filter && current_filter_mode == LINEAR ? GL_LINEAR : GL_NEAREST; glActiveTexture(GL_TEXTURE0 + tile); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gfx_cm_to_opengl(cms)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt)); } @@ -823,6 +846,15 @@ static std::map, uint16_t> gfx_opengl_get_pixel_depth(in return res; } +void gfx_opengl_set_texture_filter(FilteringMode mode) { + current_filter_mode = mode; + gfx_texture_cache_clear(); +} + +FilteringMode gfx_opengl_get_texture_filter(void) { + return current_filter_mode; +} + struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_get_clip_parameters, gfx_opengl_unload_shader, @@ -853,7 +885,9 @@ struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_get_pixel_depth, gfx_opengl_get_framebuffer_texture_id, gfx_opengl_select_texture_fb, - gfx_opengl_delete_texture + gfx_opengl_delete_texture, + gfx_opengl_set_texture_filter, + gfx_opengl_get_texture_filter }; #endif diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h b/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h index 84247fe60..6318be492 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h +++ b/libultraship/libultraship/Lib/Fast3D/gfx_rendering_api.h @@ -15,6 +15,12 @@ struct GfxClipParameters { bool invert_y; }; +enum FilteringMode { + THREE_POINT, + LINEAR, + NONE +}; + struct GfxRenderingAPI { struct GfxClipParameters (*get_clip_parameters)(void); void (*unload_shader)(struct ShaderProgram *old_prg); @@ -46,6 +52,8 @@ struct GfxRenderingAPI { void *(*get_framebuffer_texture_id)(int fb_id); void (*select_texture_fb)(int fb_id); void (*delete_texture)(uint32_t texID); + void (*set_texture_filter)(FilteringMode mode); + FilteringMode(*get_texture_filter)(void); }; #endif diff --git a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h index 08729f4dc..c674495a6 100644 --- a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h +++ b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h @@ -10,6 +10,7 @@ #include #include "SohImGuiImpl.h" #include "GameSettings.h" +#include "Cvar.h" #include #include #include @@ -45,7 +46,7 @@ protected: } formatted.push_back('\0'); const char *msg_output = formatted.data(); - if (Game::Settings.debug.soh_sink && SohImGui::console->opened) + if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->opened) SohImGui::console->Append("SoH Logging", priority, msg_output); } diff --git a/libultraship/libultraship/SohConsole.cpp b/libultraship/libultraship/SohConsole.cpp index 618cd1e1d..c360ea968 100644 --- a/libultraship/libultraship/SohConsole.cpp +++ b/libultraship/libultraship/SohConsole.cpp @@ -106,7 +106,7 @@ void Console::Draw() { if (!this->opened) return; ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - ImGui::Begin("Console", &this->opened); + ImGui::Begin("Console", nullptr); const ImVec2 pos = ImGui::GetWindowPos(); const ImVec2 size = ImGui::GetWindowSize(); diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index af5066159..ccb3b4a75 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -43,6 +43,11 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPAR using namespace Ship; bool oldCursorState = true; +#define EXPERIMENTAL() \ + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ + ImGui::Text("Experimental"); \ + ImGui::PopStyleColor(); \ + ImGui::Separator(); #define TOGGLE_BTN ImGuiKey_F1 #define HOOK(b) if(b) needs_save = true; OSContPad* pads; @@ -73,6 +78,12 @@ namespace SohImGui { float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f }; float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f }; + const char* filters[3] = { + "Three-Point", + "Linear", + "None" + }; + std::map> windowCategories; std::map customWindows; @@ -85,7 +96,7 @@ namespace SohImGui { ImGui_ImplWin32_Init(impl.dx11.window); break; } - + // OTRTODO: This gameplay specific stuff should not be in libultraship. This needs to be moved to soh and use sTunicColors kokiri_col[0] = 30 / 255.0f; kokiri_col[1] = 105 / 255.0f; @@ -94,7 +105,7 @@ namespace SohImGui { goron_col[0] = 100 / 255.0f; goron_col[1] = 20 / 255.0f; goron_col[2] = 0; - + zora_col[0] = 0; zora_col[1] = 60 / 255.0f; zora_col[2] = 100 / 255.0f; @@ -201,7 +212,7 @@ namespace SohImGui { return; } - if (d == Dialogues::dConsole && Game::Settings.debug.menu_bar) { + if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { return; } if (!GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) { @@ -280,8 +291,8 @@ namespace SohImGui { } void Init(WindowImpl window_impl) { - impl = window_impl; Game::LoadSettings(); + impl = window_impl; ImGuiContext* ctx = ImGui::CreateContext(); ImGui::SetCurrentContext(ctx); io = &ImGui::GetIO(); @@ -296,7 +307,7 @@ namespace SohImGui { ModInternal::registerHookListener({ GFX_INIT, [](const HookEvent ev) { if (GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen()) - ShowCursor(Game::Settings.debug.menu_bar, Dialogues::dLoadSettings); + ShowCursor(CVar_GetS32("gOpenMenuBar", 0), Dialogues::dLoadSettings); LoadTexture("Game_Icon", "assets/ship_of_harkinian/icons/gSohIcon.png"); LoadTexture("A-Btn", "assets/ship_of_harkinian/buttons/ABtn.png"); @@ -320,7 +331,7 @@ namespace SohImGui { ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) { pads = static_cast(ev->baseArgs["cont_pad"]); - } }); + }}); Game::InitSettings(); } @@ -334,7 +345,7 @@ namespace SohImGui { #define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0)); - void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) + void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) { float value = CVar_GetFloat(key, defaultValue); @@ -380,7 +391,7 @@ namespace SohImGui { ImGui::Text(text.c_str(), val); - if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str())) + if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str())) { CVar_SetS32(cvarName.c_str(), val); needs_save = true; @@ -443,7 +454,7 @@ namespace SohImGui { colors[2] = b / 255.0f; { - if (ImGui::ColorEdit3(text.c_str(), colors)) + if (ImGui::ColorEdit3(text.c_str(), colors)) { CVar_SetS32((cvarName + "_Red").c_str(), (int)(colors[0] * 255)); CVar_SetS32((cvarName + "_Green").c_str(), (int)(colors[1] * 255)); @@ -463,7 +474,7 @@ namespace SohImGui { ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoResize; - if (Game::Settings.debug.menu_bar) window_flags |= ImGuiWindowFlags_MenuBar; + if (CVar_GetS32("gOpenMenuBar", 0)) window_flags |= ImGuiWindowFlags_MenuBar; const ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->WorkPos); @@ -491,10 +502,11 @@ namespace SohImGui { ImGui::DockSpace(dockId, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None); if (ImGui::IsKeyPressed(TOGGLE_BTN)) { - Game::Settings.debug.menu_bar = !Game::Settings.debug.menu_bar; + bool menu_bar = CVar_GetS32("gOpenMenuBar", 0); + CVar_SetS32("gOpenMenuBar", !menu_bar); needs_save = true; - GlobalCtx2::GetInstance()->GetWindow()->dwMenubar = Game::Settings.debug.menu_bar; - ShowCursor(Game::Settings.debug.menu_bar, Dialogues::dMenubar); + GlobalCtx2::GetInstance()->GetWindow()->dwMenubar = menu_bar; + ShowCursor(menu_bar, Dialogues::dMenubar); } if (ImGui::BeginMenuBar()) { @@ -563,9 +575,41 @@ namespace SohImGui { ImGui::EndMenu(); } + if (ImGui::BeginMenu("Graphics")) + { + EnhancementSliderInt("Internal Resolution: %dx", "##IMul", "gInternalResolution", 1, 8, ""); + gfx_current_dimensions.internal_mul = CVar_GetS32("gInternalResolution", 1); + EnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, ""); + gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); + + EXPERIMENTAL(); + ImGui::Text("Texture Filter (Needs reload)"); + GfxRenderingAPI* gapi = gfx_get_current_rendering_api(); + if (ImGui::BeginCombo("##filters", filters[gapi->get_texture_filter()])) { + for (int fId = 0; fId <= FilteringMode::NONE; fId++) { + if (ImGui::Selectable(filters[fId], fId == gapi->get_texture_filter())) { + INFO("New Filter: %s", filters[fId]); + gapi->set_texture_filter((FilteringMode)fId); + + CVar_SetS32("gTextureFilter", (int) fId); + needs_save = true; + } + + } + ImGui::EndCombo(); + } + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Languages")) { + EnhancementRadioButton("English", "gLanguages", 0); + EnhancementRadioButton("German", "gLanguages", 1); + EnhancementRadioButton("French", "gLanguages", 2); + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Enhancements")) { - ImGui::Text("Gameplay"); ImGui::Separator(); @@ -583,62 +627,22 @@ namespace SohImGui { EnhancementCheckbox("N64 Mode", "gN64Mode"); EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink"); - EnhancementCheckbox("Disable LOD", "gDisableLOD"); EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops"); EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon"); EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon"); - - if (ImGui::BeginMenu("Fixes")) { - EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); - EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Developer Tools")) - { - HOOK(ImGui::MenuItem("Stats", nullptr, &Game::Settings.debug.soh)); - HOOK(ImGui::MenuItem("Console", nullptr, &console->opened)); - - ImGui::Text("Debug"); + ImGui::Text("Fixes"); ImGui::Separator(); + EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); + EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon"); - EnhancementCheckbox("Debug Mode", "gDebugEnabled"); + EXPERIMENTAL(); + + EnhancementCheckbox("Disable LOD", "gDisableLOD"); ImGui::EndMenu(); } - if (ImGui::BeginMenu("Graphics")) - { - HOOK(ImGui::MenuItem("Anti-aliasing", nullptr, &Game::Settings.graphics.show)); - ImGui::EndMenu(); - } - - if (ImGui::BeginMenu("Cheats")) - { - if (ImGui::BeginMenu("Infinite...")) { - EnhancementCheckbox("Money", "gInfiniteMoney"); - EnhancementCheckbox("Health", "gInfiniteHealth"); - EnhancementCheckbox("Ammo", "gInfiniteAmmo"); - EnhancementCheckbox("Magic", "gInfiniteMagic"); - EnhancementCheckbox("Nayru's Love", "gInfiniteNayru"); - - ImGui::EndMenu(); - } - - EnhancementCheckbox("No Clip", "gNoClip"); - EnhancementCheckbox("Climb Everything", "gClimbEverything"); - EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL"); - EnhancementCheckbox("Super Tunic", "gSuperTunic"); - EnhancementCheckbox("Easy ISG", "gEzISG"); - EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems"); - EnhancementCheckbox("Freeze Time", "gFreezeTime"); - - ImGui::EndMenu(); - - } - if (ImGui::BeginMenu("Cosmetics")) { ImGui::Text("Tunics"); @@ -663,24 +667,48 @@ namespace SohImGui { ImGui::EndMenu(); } - if (CVar_GetS32("gLanguages", 0) == 0) { - SelectedLanguage = 0; - } else if (CVar_GetS32("gLanguages", 0) == 1) { - SelectedLanguage = 1; - } else if (CVar_GetS32("gLanguages", 0) == 2) { - SelectedLanguage = 2; + if (ImGui::BeginMenu("Cheats")) + { + if (ImGui::BeginMenu("Infinite...")) { + EnhancementCheckbox("Money", "gInfiniteMoney"); + EnhancementCheckbox("Health", "gInfiniteHealth"); + EnhancementCheckbox("Ammo", "gInfiniteAmmo"); + EnhancementCheckbox("Magic", "gInfiniteMagic"); + EnhancementCheckbox("Nayru's Love", "gInfiniteNayru"); + + ImGui::EndMenu(); + } + + EnhancementCheckbox("No Clip", "gNoClip"); + EnhancementCheckbox("Climb Everything", "gClimbEverything"); + EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL"); + EnhancementCheckbox("Super Tunic", "gSuperTunic"); + EnhancementCheckbox("Easy ISG", "gEzISG"); + EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems"); + EnhancementCheckbox("Freeze Time", "gFreezeTime"); + + ImGui::EndMenu(); } - if (ImGui::BeginMenu("Languages")) { - EnhancementRadioButton("English", "gLanguages", 0); - EnhancementRadioButton("German", "gLanguages", 1); - EnhancementRadioButton("French", "gLanguages", 2); + + if (ImGui::BeginMenu("Developer Tools")) + { + EnhancementCheckbox("Stats", "gStatsEnabled"); + EnhancementCheckbox("Console", "gConsoleEnabled"); + console->opened = CVar_GetS32("gConsoleEnabled", 0); + EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); + ImGui::EndMenu(); } for (const auto& category : windowCategories) { if (ImGui::BeginMenu(category.first.c_str())) { for (const std::string& name : category.second) { - HOOK(ImGui::MenuItem(name.c_str(), nullptr, &customWindows[name].enabled)); + std::string varName(name); + varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end()); + std::string toggleName = "g" + varName + "Enabled"; + + EnhancementCheckbox(name, toggleName); + customWindows[name].enabled = CVar_GetS32(toggleName.c_str(), 0); } ImGui::EndMenu(); } @@ -691,7 +719,7 @@ namespace SohImGui { ImGui::End(); - if (Game::Settings.debug.soh) { + if (CVar_GetS32("gStatsEnabled", 0)) { const float framerate = ImGui::GetIO().Framerate; ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); ImGui::Begin("Debug Stats", nullptr, ImGuiWindowFlags_None); @@ -702,17 +730,6 @@ namespace SohImGui { ImGui::PopStyleColor(); } - if (Game::Settings.graphics.show) { - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); - ImGui::Begin("Anti-aliasing settings", nullptr, ImGuiWindowFlags_None); - ImGui::Text("Internal Resolution:"); - ImGui::SliderInt("Mul", reinterpret_cast(&gfx_current_dimensions.internal_mul), 1, 8); - ImGui::Text("MSAA:"); - ImGui::SliderInt("MSAA", reinterpret_cast(&gfx_msaa_level), 1, 8); - ImGui::End(); - ImGui::PopStyleColor(); - } - console->Draw(); for (auto& windowIter : customWindows) { diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index ff69830e7..87252ee92 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -122,7 +122,7 @@ static bool RuppeHandler(const std::vector& args) { try { rupeeAmount = std::stoi(args[1]); } - catch (std::invalid_argument const& ex) { + catch (std::invalid_argument const& ex) { ERROR("[SOH] Rupee count must be an integer."); return CMD_FAILED; } @@ -168,13 +168,13 @@ static bool ResetHandler(std::vector args) { ERROR("GlobalCtx == nullptr"); return CMD_FAILED; } - + SET_NEXT_GAMESTATE(&gGlobalCtx->state, TitleSetup_Init, GameState); gGlobalCtx->state.running = false; return CMD_SUCCESS; } -const static std::map ammoItems{ +const static std::map ammoItems{ { "sticks", ITEM_STICK }, { "deku_sticks", ITEM_STICK }, { "nuts", ITEM_NUT }, { "deku_nuts", ITEM_NUT }, { "bombs", ITEM_BOMB }, { "arrows", ITEM_BOW }, @@ -194,7 +194,7 @@ static bool AmmoHandler(const std::vector& args) { try { count = std::stoi(args[2]); - } catch (std::invalid_argument const& ex) { + } catch (std::invalid_argument const& ex) { ERROR("Ammo count must be an integer"); return CMD_FAILED; } @@ -203,7 +203,7 @@ static bool AmmoHandler(const std::vector& args) { ERROR("Ammo count must be positive"); return CMD_FAILED; } - + const auto& it = ammoItems.find(args[1]); if (it == ammoItems.end()) { @@ -213,7 +213,7 @@ static bool AmmoHandler(const std::vector& args) { // I dont think you can do OOB with just this AMMO(it->second) = count; - + //To use a change by uncomment this //Inventory_ChangeAmmo(it->second, count); } @@ -236,7 +236,7 @@ static bool BottleHandler(const std::vector& args) { unsigned int slot; try { slot = std::stoi(args[2]); - } catch (std::invalid_argument const& ex) { + } catch (std::invalid_argument const& ex) { ERROR("[SOH] Bottle slot must be an integer."); return CMD_FAILED; } @@ -275,7 +275,7 @@ static bool ItemHandler(const std::vector& args) { return CMD_FAILED; } - gSaveContext.inventory.items[std::stoi(args[1])] = std::stoi(args[2]); + gSaveContext.inventory.items[std::stoi(args[1])] = std::stoi(args[2]); return CMD_SUCCESS; } @@ -414,8 +414,11 @@ void DebugConsole_Init(void) { { { "slot", ArgumentType::NUMBER }, { "item id", ArgumentType::NUMBER } } }); CMD_REGISTER("entrance", { EntranceHandler, "Sends player to the entered entrance (hex)", { { "entrance", ArgumentType::NUMBER } } }); +} - DebugConsole_LoadCVars(); +template bool is_number(const std::string& s) { + Numeric n; + return ((std::istringstream(s) >> n >> std::ws).eof()); } void DebugConsole_LoadCVars() @@ -424,7 +427,18 @@ void DebugConsole_LoadCVars() const auto lines = File::ReadAllLines("cvars.cfg"); for (const std::string& line : lines) { - SohImGui::console->Dispatch(line); + std::vector cfg = StringHelper::Split(line, " = "); + if (line.empty()) continue; + if (cfg.size() < 2) continue; + if (cfg[1].find("\"") != std::string::npos) { + CVar_SetString(cfg[0].c_str(), const_cast(cfg[1].c_str())); + } + if (is_number(cfg[1])) { + CVar_SetFloat(cfg[0].c_str(), std::stof(cfg[1])); + } + if (is_number(cfg[1])) { + CVar_SetS32(cfg[0].c_str(), std::stoi(cfg[1])); + } } } } @@ -435,11 +449,11 @@ void DebugConsole_SaveCVars() for (const auto &cvar : cvars) { if (cvar.second->type == CVAR_TYPE_STRING) - output += StringHelper::Sprintf("set %s %s\n", cvar.first.c_str(), cvar.second->value.valueStr); + output += StringHelper::Sprintf("%s = \"%s\"\n", cvar.first.c_str(), cvar.second->value.valueStr); else if (cvar.second->type == CVAR_TYPE_S32) - output += StringHelper::Sprintf("set %s %i\n", cvar.first.c_str(), cvar.second->value.valueS32); + output += StringHelper::Sprintf("%s = %i\n", cvar.first.c_str(), cvar.second->value.valueS32); else if (cvar.second->type == CVAR_TYPE_FLOAT) - output += StringHelper::Sprintf("set %s %f\n", cvar.first.c_str(), cvar.second->value.valueFloat); + output += StringHelper::Sprintf("%s = %f\n", cvar.first.c_str(), cvar.second->value.valueFloat); } File::WriteAllText("cvars.cfg", output); diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index ad9d341d4..8cfad1166 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -322,7 +322,7 @@ void CreateSphereData() { } void InitColViewer() { - SohImGui::AddWindow("Debug", "Collision Viewer", DrawColViewerWindow); + SohImGui::AddWindow("Developer Tools", "Collision Viewer", DrawColViewerWindow); CreateCylinderData(); CreateSphereData(); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index e2ed02705..e7bf0a783 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1101,7 +1101,7 @@ void DrawSaveEditor(bool& open) { } void InitSaveEditor() { - SohImGui::AddWindow("Debug", "Save Editor", DrawSaveEditor); + SohImGui::AddWindow("Developer Tools", "Save Editor", DrawSaveEditor); // Load item icons into ImGui for (const auto& entry : itemMapping) {