├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── README.md ├── dependencies ├── dncomlib │ ├── .gitignore │ ├── ALL_BUILD.vcxproj │ ├── ALL_BUILD.vcxproj.filters │ ├── CMakeFiles │ │ ├── generate.stamp │ │ └── generate.stamp.depend │ ├── CMakeLists.txt │ ├── cmake_install.cmake │ ├── dncomlib.sln │ ├── dncomlib.vcxproj │ ├── dncomlib.vcxproj.filters │ ├── includes │ │ └── dncomlib │ │ │ ├── app_domain.hpp │ │ │ ├── dncomlib.hpp │ │ │ ├── meta_host.hpp │ │ │ ├── runtime_host.hpp │ │ │ ├── runtime_info.hpp │ │ │ ├── unique_releasable.hpp │ │ │ └── unknown_enumerator.hpp │ └── src │ │ ├── app_domain.cpp │ │ ├── dncomlib.cpp │ │ ├── meta_host.cpp │ │ ├── runtime_host.cpp │ │ ├── runtime_info.cpp │ │ └── unknown_enumerator.cpp ├── gl3w │ ├── CMakeLists.txt │ ├── README.rst │ ├── SConstruct │ ├── UNLICENSE │ ├── gl3w_gen.py │ ├── public-domain-mark.png │ └── src │ │ ├── glfw_test.c │ │ └── glut_test.c ├── gl3w_out │ ├── .gitignore │ └── CMakeLists.txt └── imgui │ ├── CMakeLists.txt │ ├── LICENSE.txt │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_draw.cpp │ ├── imgui_impl_opengl3.cpp │ ├── imgui_impl_opengl3.h │ ├── imgui_impl_opengl3_loader.h │ ├── imgui_impl_win32.cpp │ ├── imgui_impl_win32.h │ ├── imgui_internal.h │ ├── imgui_tables.cpp │ ├── imgui_widgets.cpp │ ├── imstb_rectpack.h │ ├── imstb_textedit.h │ └── imstb_truetype.h ├── framework ├── CMakeLists.txt └── sed │ ├── console.cpp │ ├── console.hpp │ ├── macro.hpp │ ├── memory.cpp │ ├── memory.hpp │ ├── strings.hpp │ └── windows │ ├── protect_guard.cpp │ ├── protect_guard.hpp │ ├── smart_handle.cpp │ ├── smart_handle.hpp │ ├── suspend_guard.cpp │ └── suspend_guard.hpp ├── osu-cheese-client ├── CMakeLists.txt ├── client_main.cpp ├── features │ ├── aim_assist.cpp │ ├── aim_assist.hpp │ ├── esp.cpp │ ├── esp.hpp │ ├── features.hpp │ ├── relax.cpp │ └── relax.hpp ├── game.cpp ├── game.hpp ├── hooks.cpp ├── hooks.hpp ├── manager │ ├── gamefield_manager.cpp │ └── gamefield_manager.hpp ├── menu.cpp ├── menu.hpp ├── oc_client.cpp ├── oc_client.hpp └── sdk │ ├── hitobject.cpp │ ├── hitobject.hpp │ ├── info_player.hpp │ ├── info_struct.hpp │ ├── osu_vec.cpp │ ├── osu_vec.hpp │ ├── player_keys.hpp │ ├── position_info.hpp │ ├── raw_info.hpp │ └── wnd_info.hpp ├── osu-cheese-loader ├── CMakeLists.txt ├── loader_main.cpp └── loader_main.hpp └── osu-cheese.sln /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | .vscode/ 3 | .idea/ 4 | 5 | .out/ 6 | out/ 7 | 8 | .build/ 9 | build/ 10 | 11 | .test/ 12 | test/ 13 | 14 | .bin/ 15 | bin/ 16 | 17 | .obj/ 18 | obj/ 19 | 20 | .packages/ 21 | packages/ 22 | 23 | /.docs/ 24 | /docs/ 25 | 26 | /osu-cheese-loader/client_path.hpp 27 | 28 | cmake-build-debug/ 29 | cmake-build-release/ 30 | cmake-build-relwithdebinfo/ 31 | 32 | CMakeSettings.json 33 | notes.txt 34 | re/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dependencies/gl3w"] 2 | path = dependencies/gl3w 3 | url = https://github.com/skaslev/gl3w.git 4 | shallow = true 5 | [submodule "dependencies/dncomlib"] 6 | path = dependencies/dncomlib 7 | url = https://github.com/u16rogue/dncomlib.git 8 | shallow = true 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | 3 | project(osu-cheese CXX) 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_STANDARD_REQUIRED True) 6 | 7 | # Settings 8 | option(DEFINE_DEBUG_MACRO "Enables the OSU_CHEESE_DEBUG_BUILD macro. Used for logging, testing, and dumping of information. (DOES NOT SET BUILD MODE TO DEBUG!)" OFF) 9 | if (DEFINE_DEBUG_MACRO) 10 | add_compile_definitions(OSU_CHEESE_DEBUG_BUILD) 11 | endif () 12 | 13 | # Libraries 14 | add_subdirectory("dependencies/dncomlib") 15 | add_subdirectory("dependencies/gl3w_out") 16 | add_subdirectory("framework") 17 | add_subdirectory("dependencies/imgui") 18 | 19 | # Projects 20 | option(BUILD_CLIENT "Build's the client library (DLL)." ON) 21 | option(BUILD_LOADER "Build's the loader executable, this depends on the CLIENT project." ON) 22 | 23 | if (BUILD_LOADER) 24 | set(BUILD_CLIENT ON) # Force client if loader build is enabled 25 | add_subdirectory("osu-cheese-client") 26 | endif () 27 | 28 | if (BUILD_LOADER) 29 | add_subdirectory("osu-cheese-loader") 30 | endif () -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # osu-cheat 2 | 3 | old osu cheat source with some decent features, initially meant to be the sapphire.ac cheat. 4 | 5 | patterns are probably outdated by now. the source is mainly for learning! 6 | -------------------------------------------------------------------------------- /dependencies/dncomlib/.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | out/ -------------------------------------------------------------------------------- /dependencies/dncomlib/ALL_BUILD.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | x64 5 | 6 | 7 | false 8 | 9 | 10 | 11 | Debug 12 | x64 13 | 14 | 15 | Release 16 | x64 17 | 18 | 19 | MinSizeRel 20 | x64 21 | 22 | 23 | RelWithDebInfo 24 | x64 25 | 26 | 27 | 28 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567} 29 | Win32Proj 30 | 10.0.22000.0 31 | x64 32 | ALL_BUILD 33 | NoUpgrade 34 | 35 | 36 | 37 | Utility 38 | MultiByte 39 | v142 40 | 41 | 42 | Utility 43 | MultiByte 44 | v142 45 | 46 | 47 | Utility 48 | MultiByte 49 | v142 50 | 51 | 52 | Utility 53 | MultiByte 54 | v142 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | <_ProjectFileVersion>10.0.20506.1 65 | $(Platform)\$(Configuration)\$(ProjectName)\ 66 | $(Platform)\$(Configuration)\$(ProjectName)\ 67 | $(Platform)\$(Configuration)\$(ProjectName)\ 68 | $(Platform)\$(Configuration)\$(ProjectName)\ 69 | 70 | 71 | 72 | %(AdditionalIncludeDirectories) 73 | $(ProjectDir)/$(IntDir) 74 | %(Filename).h 75 | %(Filename).tlb 76 | %(Filename)_i.c 77 | %(Filename)_p.c 78 | 79 | 80 | 81 | 82 | %(AdditionalIncludeDirectories) 83 | $(ProjectDir)/$(IntDir) 84 | %(Filename).h 85 | %(Filename).tlb 86 | %(Filename)_i.c 87 | %(Filename)_p.c 88 | 89 | 90 | 91 | 92 | %(AdditionalIncludeDirectories) 93 | $(ProjectDir)/$(IntDir) 94 | %(Filename).h 95 | %(Filename).tlb 96 | %(Filename)_i.c 97 | %(Filename)_p.c 98 | 99 | 100 | 101 | 102 | %(AdditionalIncludeDirectories) 103 | $(ProjectDir)/$(IntDir) 104 | %(Filename).h 105 | %(Filename).tlb 106 | %(Filename)_i.c 107 | %(Filename)_p.c 108 | 109 | 110 | 111 | 112 | Always 113 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 114 | setlocal 115 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 116 | if %errorlevel% neq 0 goto :cmEnd 117 | :cmEnd 118 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 119 | :cmErrorLevel 120 | exit /b %1 121 | :cmDone 122 | if %errorlevel% neq 0 goto :VCEnd 123 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 124 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 125 | false 126 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 127 | setlocal 128 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 129 | if %errorlevel% neq 0 goto :cmEnd 130 | :cmEnd 131 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 132 | :cmErrorLevel 133 | exit /b %1 134 | :cmDone 135 | if %errorlevel% neq 0 goto :VCEnd 136 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 137 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 138 | false 139 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 140 | setlocal 141 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 142 | if %errorlevel% neq 0 goto :cmEnd 143 | :cmEnd 144 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 145 | :cmErrorLevel 146 | exit /b %1 147 | :cmDone 148 | if %errorlevel% neq 0 goto :VCEnd 149 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 150 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 151 | false 152 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 153 | setlocal 154 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 155 | if %errorlevel% neq 0 goto :cmEnd 156 | :cmEnd 157 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 158 | :cmErrorLevel 159 | exit /b %1 160 | :cmDone 161 | if %errorlevel% neq 0 goto :VCEnd 162 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 163 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 164 | false 165 | 166 | 167 | 168 | 169 | 170 | 171 | {834B196A-8A59-3234-B76A-FF2223ADDF07} 172 | ZERO_CHECK 173 | false 174 | Never 175 | 176 | 177 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} 178 | dncomlib 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /dependencies/dncomlib/ALL_BUILD.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dependencies/dncomlib/CMakeFiles/generate.stamp: -------------------------------------------------------------------------------- 1 | # CMake generation timestamp file for this directory. 2 | -------------------------------------------------------------------------------- /dependencies/dncomlib/CMakeFiles/generate.stamp.depend: -------------------------------------------------------------------------------- 1 | # CMake generation dependency list for this directory. 2 | C:/Program Files/CMake/share/cmake-3.24/Modules/CMakeCInformation.cmake 3 | C:/Program Files/CMake/share/cmake-3.24/Modules/CMakeCommonLanguageInclude.cmake 4 | C:/Program Files/CMake/share/cmake-3.24/Modules/CMakeLanguageInformation.cmake 5 | C:/Program Files/CMake/share/cmake-3.24/Modules/Compiler/CMakeCommonCompilerMacros.cmake 6 | C:/Program Files/CMake/share/cmake-3.24/Modules/Compiler/MSVC-C.cmake 7 | C:/Program Files/CMake/share/cmake-3.24/Modules/Compiler/MSVC.cmake 8 | C:/Program Files/CMake/share/cmake-3.24/Modules/Platform/Windows-MSVC-C.cmake 9 | C:/Program Files/CMake/share/cmake-3.24/Modules/Platform/Windows-MSVC.cmake 10 | C:/Users/admin/Desktop/osu-cheese/CMakeFiles/3.24.0-rc4/CMakeCCompiler.cmake 11 | C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 12 | -------------------------------------------------------------------------------- /dependencies/dncomlib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | 3 | project(dncomlib) 4 | 5 | add_library(${PROJECT_NAME} STATIC 6 | "includes/dncomlib/unique_releasable.hpp" 7 | 8 | "includes/dncomlib/meta_host.hpp" 9 | "src/meta_host.cpp" 10 | 11 | "includes/dncomlib/unknown_enumerator.hpp" 12 | "src/unknown_enumerator.cpp" 13 | 14 | "includes/dncomlib/dncomlib.hpp" 15 | "src/dncomlib.cpp" 16 | 17 | "includes/dncomlib/runtime_info.hpp" 18 | "src/runtime_info.cpp" 19 | 20 | "includes/dncomlib/runtime_host.hpp" 21 | "src/runtime_host.cpp" 22 | 23 | "includes/dncomlib/app_domain.hpp" 24 | "src/app_domain.cpp" 25 | ) 26 | 27 | target_include_directories(${PROJECT_NAME} PUBLIC "includes/") -------------------------------------------------------------------------------- /dependencies/dncomlib/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/osu-cheese") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "Release") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Is this installation the result of a crosscompile? 31 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 32 | set(CMAKE_CROSSCOMPILING "FALSE") 33 | endif() 34 | 35 | -------------------------------------------------------------------------------- /dependencies/dncomlib/dncomlib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} = {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} 7 | EndProjectSection 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dncomlib", "dncomlib.vcxproj", "{43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}" 10 | ProjectSection(ProjectDependencies) = postProject 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Release|x64 = Release|x64 17 | MinSizeRel|x64 = MinSizeRel|x64 18 | RelWithDebInfo|x64 = RelWithDebInfo|x64 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.Debug|x64.ActiveCfg = Debug|x64 22 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.Release|x64.ActiveCfg = Release|x64 23 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 24 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 25 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Debug|x64.ActiveCfg = Debug|x64 26 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Debug|x64.Build.0 = Debug|x64 27 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Release|x64.ActiveCfg = Release|x64 28 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Release|x64.Build.0 = Release|x64 29 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 30 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 31 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 32 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {A607517F-C206-36F6-9E12-82FD330E4D91} 36 | EndGlobalSection 37 | GlobalSection(ExtensibilityAddIns) = postSolution 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /dependencies/dncomlib/dncomlib.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | x64 5 | 6 | 7 | 8 | Debug 9 | x64 10 | 11 | 12 | Release 13 | x64 14 | 15 | 16 | MinSizeRel 17 | x64 18 | 19 | 20 | RelWithDebInfo 21 | x64 22 | 23 | 24 | 25 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} 26 | Win32Proj 27 | 10.0.22000.0 28 | x64 29 | dncomlib 30 | NoUpgrade 31 | 32 | 33 | 34 | StaticLibrary 35 | MultiByte 36 | v142 37 | 38 | 39 | StaticLibrary 40 | MultiByte 41 | v142 42 | 43 | 44 | StaticLibrary 45 | MultiByte 46 | v142 47 | 48 | 49 | StaticLibrary 50 | MultiByte 51 | v142 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | <_ProjectFileVersion>10.0.20506.1 62 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\Debug\ 63 | dncomlib.dir\Debug\ 64 | dncomlib 65 | .lib 66 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\Release\ 67 | dncomlib.dir\Release\ 68 | dncomlib 69 | .lib 70 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\MinSizeRel\ 71 | dncomlib.dir\MinSizeRel\ 72 | dncomlib 73 | .lib 74 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\RelWithDebInfo\ 75 | dncomlib.dir\RelWithDebInfo\ 76 | dncomlib 77 | .lib 78 | 79 | 80 | 81 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 82 | $(IntDir) 83 | EnableFastChecks 84 | ProgramDatabase 85 | Sync 86 | Disabled 87 | stdcpp20 88 | Disabled 89 | NotUsing 90 | MultiThreadedDebugDLL 91 | true 92 | false 93 | %(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug" 94 | $(IntDir) 95 | 96 | 97 | %(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\" 98 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 99 | 100 | 101 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 102 | $(ProjectDir)/$(IntDir) 103 | %(Filename).h 104 | %(Filename).tlb 105 | %(Filename)_i.c 106 | %(Filename)_p.c 107 | 108 | 109 | %(AdditionalOptions) /machine:x64 110 | 111 | 112 | 113 | 114 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 115 | $(IntDir) 116 | Sync 117 | AnySuitable 118 | stdcpp20 119 | MaxSpeed 120 | NotUsing 121 | MultiThreadedDLL 122 | true 123 | false 124 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release" 125 | $(IntDir) 126 | 127 | 128 | 129 | 130 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\" 131 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 132 | 133 | 134 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 135 | $(ProjectDir)/$(IntDir) 136 | %(Filename).h 137 | %(Filename).tlb 138 | %(Filename)_i.c 139 | %(Filename)_p.c 140 | 141 | 142 | %(AdditionalOptions) /machine:x64 143 | 144 | 145 | 146 | 147 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 148 | $(IntDir) 149 | Sync 150 | OnlyExplicitInline 151 | stdcpp20 152 | MinSpace 153 | NotUsing 154 | MultiThreadedDLL 155 | true 156 | false 157 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel" 158 | $(IntDir) 159 | 160 | 161 | 162 | 163 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\" 164 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 165 | 166 | 167 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 168 | $(ProjectDir)/$(IntDir) 169 | %(Filename).h 170 | %(Filename).tlb 171 | %(Filename)_i.c 172 | %(Filename)_p.c 173 | 174 | 175 | %(AdditionalOptions) /machine:x64 176 | 177 | 178 | 179 | 180 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 181 | $(IntDir) 182 | ProgramDatabase 183 | Sync 184 | OnlyExplicitInline 185 | stdcpp20 186 | MaxSpeed 187 | NotUsing 188 | MultiThreadedDLL 189 | true 190 | false 191 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo" 192 | $(IntDir) 193 | 194 | 195 | %(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\" 196 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 197 | 198 | 199 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\includes;%(AdditionalIncludeDirectories) 200 | $(ProjectDir)/$(IntDir) 201 | %(Filename).h 202 | %(Filename).tlb 203 | %(Filename)_i.c 204 | %(Filename)_p.c 205 | 206 | 207 | %(AdditionalOptions) /machine:x64 208 | 209 | 210 | 211 | 212 | Always 213 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 214 | setlocal 215 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 216 | if %errorlevel% neq 0 goto :cmEnd 217 | :cmEnd 218 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 219 | :cmErrorLevel 220 | exit /b %1 221 | :cmDone 222 | if %errorlevel% neq 0 goto :VCEnd 223 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 224 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 225 | false 226 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 227 | setlocal 228 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 229 | if %errorlevel% neq 0 goto :cmEnd 230 | :cmEnd 231 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 232 | :cmErrorLevel 233 | exit /b %1 234 | :cmDone 235 | if %errorlevel% neq 0 goto :VCEnd 236 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 237 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 238 | false 239 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 240 | setlocal 241 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 242 | if %errorlevel% neq 0 goto :cmEnd 243 | :cmEnd 244 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 245 | :cmErrorLevel 246 | exit /b %1 247 | :cmDone 248 | if %errorlevel% neq 0 goto :VCEnd 249 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 250 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 251 | false 252 | Building Custom Rule C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeLists.txt 253 | setlocal 254 | "C:\Program Files\CMake\bin\cmake.exe" -SC:/Users/admin/Desktop/osu-cheese -BC:/Users/admin/Desktop/osu-cheese --check-stamp-file C:/Users/admin/Desktop/osu-cheese/dependencies/dncomlib/CMakeFiles/generate.stamp 255 | if %errorlevel% neq 0 goto :cmEnd 256 | :cmEnd 257 | endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone 258 | :cmErrorLevel 259 | exit /b %1 260 | :cmDone 261 | if %errorlevel% neq 0 goto :VCEnd 262 | C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Compiler\MSVC.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.24\Modules\Platform\Windows-MSVC.cmake;C:\Users\admin\Desktop\osu-cheese\CMakeFiles\3.24.0-rc4\CMakeCCompiler.cmake;%(AdditionalInputs) 263 | C:\Users\admin\Desktop\osu-cheese\dependencies\dncomlib\CMakeFiles\generate.stamp 264 | false 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | {834B196A-8A59-3234-B76A-FF2223ADDF07} 285 | ZERO_CHECK 286 | false 287 | Never 288 | 289 | 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /dependencies/dncomlib/dncomlib.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Source Files 6 | 7 | 8 | Source Files 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | Source Files 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | {BD6EA2C8-7C84-310E-8E1C-540A74AF9239} 52 | 53 | 54 | {C8F9D66D-E847-3727-BEE1-BD2C01819B1A} 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/app_domain.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "unique_releasable.hpp" 4 | #include 5 | #include 6 | 7 | namespace dncomlib 8 | { 9 | class app_domain : public dncomlib::unique_releasable 10 | { 11 | public: 12 | app_domain(app_domain &) = delete; 13 | app_domain(const app_domain &) = delete; 14 | 15 | app_domain() = default; 16 | app_domain(IUnknown * i_); 17 | 18 | auto get_friendly_name() -> std::wstring; 19 | 20 | static auto from_unknown(const dncomlib::unique_releasable & unk) -> app_domain; 21 | }; 22 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/dncomlib.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "meta_host.hpp" 7 | #include "unique_releasable.hpp" 8 | #include "unknown_enumerator.hpp" 9 | #include "runtime_info.hpp" 10 | 11 | namespace dncomlib 12 | { 13 | auto clr_create_instance(const IID & clsid, const IID & riid) -> dncomlib::meta_host; 14 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/meta_host.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "unique_releasable.hpp" 4 | #include "unknown_enumerator.hpp" 5 | #include 6 | #include 7 | 8 | namespace dncomlib 9 | { 10 | class meta_host : public dncomlib::unique_releasable 11 | { 12 | public: 13 | meta_host() = default; 14 | meta_host(ICLRMetaHost * i_); 15 | 16 | auto enumerate_loaded_runtimes(void * process_handle) -> dncomlib::unknown_enumerator; 17 | }; 18 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/runtime_host.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "unique_releasable.hpp" 4 | #include "app_domain.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace dncomlib 10 | { 11 | class runtime_host : public dncomlib::unique_releasable 12 | { 13 | public: 14 | runtime_host(runtime_host &) = delete; 15 | runtime_host(const runtime_host &) = delete; 16 | 17 | runtime_host() = default; 18 | runtime_host(ICorRuntimeHost * i_); 19 | 20 | auto get_default_domain_thunk() -> dncomlib::unique_releasable; 21 | }; 22 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/runtime_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "unique_releasable.hpp" 4 | #include "runtime_host.hpp" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace dncomlib 10 | { 11 | class runtime_info : public dncomlib::unique_releasable 12 | { 13 | public: 14 | runtime_info(runtime_info &) = delete; 15 | runtime_info(const runtime_info &) = delete; 16 | 17 | runtime_info() = default; 18 | runtime_info(ICLRRuntimeInfo *i_); 19 | 20 | auto is_started(DWORD * out_startup_flags = nullptr) -> bool; 21 | auto get_host() -> runtime_host; 22 | 23 | static auto from_unknown(const dncomlib::unique_releasable & unk) -> runtime_info; 24 | }; 25 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/unique_releasable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace dncomlib 4 | { 5 | // TODO: implement sfinae to check if class has a Release method 6 | template 7 | class unique_releasable 8 | { 9 | public: 10 | unique_releasable(unique_releasable &) = delete; 11 | unique_releasable(const unique_releasable &) = delete; 12 | 13 | unique_releasable() = default; 14 | 15 | ~unique_releasable() 16 | { 17 | remove(); 18 | } 19 | 20 | unique_releasable(T * instance_) 21 | : instance(instance_) 22 | { 23 | } 24 | 25 | unique_releasable(unique_releasable && other) 26 | { 27 | remove(); 28 | instance = other.instance; 29 | other.instance = nullptr; 30 | } 31 | 32 | auto remove() -> void 33 | { 34 | if (instance) 35 | instance->Release(); 36 | 37 | instance = nullptr; 38 | } 39 | 40 | auto operator ->() const -> T * 41 | { 42 | return instance; 43 | } 44 | 45 | auto operator =(T * rhs) -> void 46 | { 47 | remove(); 48 | instance = rhs; 49 | } 50 | 51 | auto operator =(unique_releasable && rhs) -> void 52 | { 53 | remove(); 54 | instance = rhs.instance; 55 | rhs.instance = nullptr; 56 | } 57 | 58 | operator bool() const noexcept 59 | { 60 | return instance != nullptr; 61 | } 62 | 63 | auto ppinstance() -> T ** 64 | { 65 | return &instance; 66 | } 67 | 68 | template 69 | auto vcall(vargs_t... args) -> R 70 | { 71 | return reinterpret_cast(instance)[0][index](instance, args...); 72 | } 73 | 74 | protected: 75 | T * instance { nullptr }; 76 | }; 77 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/includes/dncomlib/unknown_enumerator.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "unique_releasable.hpp" 6 | 7 | namespace dncomlib 8 | { 9 | class unknown_enumerator 10 | { 11 | class enumerable 12 | { 13 | public: 14 | enumerable(IEnumUnknown * i_); 15 | 16 | auto operator * () -> dncomlib::unique_releasable; 17 | auto operator ++ () -> void; 18 | auto operator != (const enumerable & rhs) -> bool; 19 | private: 20 | IUnknown * current; 21 | IEnumUnknown * instance; 22 | }; 23 | 24 | public: 25 | unknown_enumerator(unknown_enumerator &) = delete; 26 | unknown_enumerator(const unknown_enumerator &) = delete; 27 | 28 | unknown_enumerator() = default; 29 | unknown_enumerator(IEnumUnknown * i_); 30 | 31 | operator bool () const noexcept; 32 | auto operator -> () -> IEnumUnknown *; 33 | auto operator = (unknown_enumerator && rhs) -> void; 34 | 35 | auto begin() -> unknown_enumerator::enumerable; 36 | auto end() -> unknown_enumerator::enumerable; 37 | 38 | private: 39 | dncomlib::unique_releasable instance; 40 | }; 41 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/src/app_domain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | dncomlib::app_domain::app_domain(IUnknown* i_) 6 | : dncomlib::unique_releasable(i_) 7 | { 8 | } 9 | 10 | auto dncomlib::app_domain::get_friendly_name() -> std::wstring 11 | { 12 | // x86: (_WORD *)(*(int (__stdcall **)(int, _WORD **))(*(_DWORD *)a3 + 212))(a3, &v78) 13 | // x64: (*(__int64 (__fastcall **)(__int64, _WORD **))(*(_QWORD *)v98 + 424i64))(v98, &v89); 14 | BSTR name{}; 15 | 16 | if (vcall<53, HRESULT>(&name) != S_OK) 17 | return std::wstring(); 18 | 19 | auto out = std::wstring(name); 20 | 21 | if (name) 22 | SysFreeString(name); 23 | 24 | return out; 25 | } 26 | 27 | auto dncomlib::app_domain::from_unknown(const dncomlib::unique_releasable& unk) -> app_domain 28 | { 29 | GUID _appdomain_uuid 30 | { 31 | .Data1 = 0x5F696DC, 32 | .Data2 = 0x2B29, 33 | .Data3 = 0x3663, 34 | .Data4 = { 0xAD, 0x8B, 0xC4, 0x38, 0x9C, 0xF2, 0xA7, 0x13 } 35 | }; 36 | 37 | IUnknown* res{}; 38 | 39 | unk->QueryInterface(_appdomain_uuid, reinterpret_cast(&res)); 40 | 41 | return app_domain(res); 42 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/src/dncomlib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | auto dncomlib::clr_create_instance(const IID& clsid, const IID& riid) -> dncomlib::meta_host 6 | { 7 | ICLRMetaHost* res{}; 8 | 9 | HMODULE hmscoree = LoadLibraryW(L"MSCorEE.dll"); 10 | 11 | if (hmscoree) 12 | { 13 | decltype(CLRCreateInstance)* _CLRCreateInstance; 14 | _CLRCreateInstance = reinterpret_cast(GetProcAddress(hmscoree, "CLRCreateInstance")); 15 | 16 | if (_CLRCreateInstance) 17 | _CLRCreateInstance(clsid, riid, reinterpret_cast(&res)); 18 | } 19 | 20 | return dncomlib::meta_host(res); 21 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/src/meta_host.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | dncomlib::meta_host::meta_host(ICLRMetaHost* i_) 6 | : dncomlib::unique_releasable(i_) 7 | { 8 | } 9 | 10 | auto dncomlib::meta_host::enumerate_loaded_runtimes(void* process_handle) -> dncomlib::unknown_enumerator 11 | { 12 | IEnumUnknown* res{}; 13 | 14 | if (instance->EnumerateLoadedRuntimes(reinterpret_cast(process_handle), &res) != S_OK) 15 | return dncomlib::unknown_enumerator(nullptr); 16 | 17 | return dncomlib::unknown_enumerator(res); 18 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/src/runtime_host.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | dncomlib::runtime_host::runtime_host(ICorRuntimeHost* i_) 4 | : dncomlib::unique_releasable(i_) 5 | { 6 | } 7 | 8 | auto dncomlib::runtime_host::get_default_domain_thunk() -> dncomlib::unique_releasable 9 | { 10 | IUnknown* res{}; 11 | instance->GetDefaultDomain(&res); 12 | return dncomlib::unique_releasable(res); 13 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/src/runtime_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | dncomlib::runtime_info::runtime_info(ICLRRuntimeInfo* i_) 4 | : dncomlib::unique_releasable(i_) 5 | { 6 | } 7 | 8 | auto dncomlib::runtime_info::is_started(DWORD* out_startup_flags) -> bool 9 | { 10 | BOOL flag{}; 11 | DWORD dummy_flags{}; 12 | 13 | if (instance->IsStarted(&flag, out_startup_flags ? out_startup_flags : /* hello msvc compiler users :) */ &dummy_flags) != S_OK) 14 | return false; 15 | 16 | return flag; 17 | } 18 | 19 | auto dncomlib::runtime_info::get_host() -> runtime_host 20 | { 21 | ICorRuntimeHost* res{}; 22 | 23 | instance->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast(&res)); 24 | 25 | return runtime_host(res); 26 | } 27 | 28 | auto dncomlib::runtime_info::from_unknown(const dncomlib::unique_releasable& unk) -> runtime_info 29 | { 30 | ICLRRuntimeInfo* res{}; 31 | 32 | unk->QueryInterface(IID_ICLRRuntimeInfo, reinterpret_cast(&res)); 33 | 34 | return runtime_info(res); 35 | } -------------------------------------------------------------------------------- /dependencies/dncomlib/src/unknown_enumerator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | dncomlib::unknown_enumerator::unknown_enumerator(IEnumUnknown * i_) 6 | : instance(i_) 7 | { 8 | } 9 | 10 | dncomlib::unknown_enumerator::operator bool () const noexcept 11 | { 12 | return static_cast(instance); 13 | } 14 | 15 | auto dncomlib::unknown_enumerator::operator -> () -> IEnumUnknown * 16 | { 17 | return *instance.ppinstance(); 18 | } 19 | 20 | auto dncomlib::unknown_enumerator::operator = (unknown_enumerator && rhs) -> void 21 | { 22 | instance = std::move(rhs.instance); 23 | } 24 | 25 | auto dncomlib::unknown_enumerator::begin() -> unknown_enumerator::enumerable 26 | { 27 | return unknown_enumerator::enumerable(*instance.ppinstance()); 28 | } 29 | 30 | auto dncomlib::unknown_enumerator::end() -> unknown_enumerator::enumerable 31 | { 32 | return unknown_enumerator::enumerable(nullptr); 33 | } 34 | 35 | dncomlib::unknown_enumerator::enumerable::enumerable(IEnumUnknown * i_) 36 | : instance(i_), current(nullptr) 37 | { 38 | } 39 | 40 | auto dncomlib::unknown_enumerator::enumerable::operator * () -> dncomlib::unique_releasable 41 | { 42 | return dncomlib::unique_releasable(current); 43 | } 44 | 45 | auto dncomlib::unknown_enumerator::enumerable::operator ++ () -> void 46 | { 47 | ULONG fetched {}; 48 | if (instance->Next(1, ¤t, &fetched) == S_OK && fetched) 49 | return; 50 | 51 | current = nullptr; 52 | instance = nullptr; 53 | } 54 | 55 | auto dncomlib::unknown_enumerator::enumerable::operator != (const enumerable & rhs) -> bool 56 | { 57 | if (instance && !current) 58 | ++*this; 59 | 60 | return instance != rhs.instance && current != rhs.current; 61 | } -------------------------------------------------------------------------------- /dependencies/gl3w/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) 2 | 3 | project(gl3w) 4 | 5 | set(CMAKE_VERBOSE_MAKEFILE false) 6 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) # -fPIC 7 | 8 | set(SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/src) 9 | set(HEADER_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) 10 | 11 | set(HEADER_FILES 12 | "${HEADER_DIR}/GL/gl3w.h" 13 | "${HEADER_DIR}/GL/glcorearb.h" 14 | "${HEADER_DIR}/KHR/khrplatform.h" 15 | ) 16 | 17 | set(SOURCE_FILES 18 | "${SOURCE_DIR}/gl3w.c" 19 | ) 20 | 21 | # add and depend on OpenGL 22 | find_package(OpenGL REQUIRED) 23 | 24 | # find python interpreter 25 | find_package(PythonInterp REQUIRED) 26 | 27 | if(CMAKE_VERSION VERSION_LESS 3.8.0) 28 | set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR}) 29 | set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${OPENGL_LIBRARIES}) 30 | else() 31 | # Since CMake 3.8 the IMPORTED targets available 32 | set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} OpenGL::GL OpenGL::GLU) 33 | endif() 34 | # add command to create the header and source files 35 | add_custom_command( 36 | OUTPUT 37 | "${SOURCE_DIR}/gl3w.c" 38 | "${HEADER_DIR}/GL/gl3w.h" 39 | "${HEADER_DIR}/GL/glcorearb.h" 40 | "${HEADER_DIR}/KHR/khrplatform.h" 41 | COMMAND "${PYTHON_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/gl3w_gen.py 42 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gl3w_gen.py 43 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 44 | ) 45 | 46 | # add pseudo target that depends on the generated files 47 | add_custom_target( 48 | gl3w_gen ALL 49 | DEPENDS 50 | "${SOURCE_DIR}/gl3w.c" 51 | "${HEADER_DIR}/GL/gl3w.h" 52 | "${HEADER_DIR}/GL/glcorearb.h" 53 | "${HEADER_DIR}/KHR/khrplatform.h" 54 | ) 55 | 56 | # create gl3w target 57 | add_library(${PROJECT_NAME} INTERFACE) 58 | 59 | # make gl3w target depend on the generator target 60 | add_dependencies(${PROJECT_NAME} gl3w_gen) 61 | 62 | include(GNUInstallDirs) 63 | 64 | # let remote project know about source and header files 65 | foreach(SOURCE_FILE ${SOURCE_FILES}) 66 | get_filename_component(SOURCE_FILENAME ${SOURCE_FILE} NAME) 67 | target_sources(${PROJECT_NAME} INTERFACE 68 | $ 69 | $) 70 | install(FILES "${SOURCE_FILE}" 71 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 72 | endforeach() 73 | foreach(HEADER_FILE ${HEADER_FILES}) 74 | get_filename_component(HEADER_FILENAME ${HEADER_FILE} NAME) 75 | file(RELATIVE_PATH HEADER_PATH "${HEADER_DIR}" "${HEADER_FILE}") 76 | get_filename_component(HEADER_PATH ${HEADER_PATH} PATH) 77 | install(FILES "${HEADER_FILE}" 78 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${HEADER_PATH}") 79 | endforeach() 80 | 81 | target_include_directories(${PROJECT_NAME} INTERFACE 82 | $ 83 | $ 84 | ) 85 | if(DEFINED EXTERNAL_INCLUDE_DIRS) 86 | target_include_directories(${PROJECT_NAME} INTERFACE ${EXTERNAL_INCLUDE_DIRS}) 87 | endif() 88 | # let remote project know which libraries need to be linked 89 | target_link_libraries(${PROJECT_NAME} INTERFACE ${EXTERNAL_LIBRARIES} ${CMAKE_DL_LIBS}) 90 | 91 | set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 92 | set(BUILD_CMAKE_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake") 93 | 94 | # export targets for remote projects (i.e. make find_package(gl3w) work) 95 | configure_file( 96 | "${MODULE_PATH}/${PROJECT_NAME}-config.cmake" 97 | "${BUILD_CMAKE_DIR}/${PROJECT_NAME}-config.cmake" 98 | COPYONLY 99 | ) 100 | 101 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets) 102 | 103 | install(FILES "${MODULE_PATH}/${PROJECT_NAME}-config.cmake" 104 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 105 | install(EXPORT ${PROJECT_NAME}-targets 106 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 107 | 108 | export( 109 | TARGETS ${PROJECT_NAME} 110 | FILE "${BUILD_CMAKE_DIR}/${PROJECT_NAME}-targets.cmake" 111 | ) 112 | 113 | export(PACKAGE ${PROJECT_NAME}) 114 | -------------------------------------------------------------------------------- /dependencies/gl3w/README.rst: -------------------------------------------------------------------------------- 1 | ======================================== 2 | gl3w: Simple OpenGL core profile loading 3 | ======================================== 4 | 5 | Introduction 6 | ------------ 7 | 8 | gl3w_ is the easiest way to get your hands on the functionality offered by the 9 | OpenGL core profile specification. 10 | 11 | Its main part is a simple gl3w_gen.py_ Python script that downloads the 12 | Khronos_ supported glcorearb.h_ header and generates gl3w.h and gl3w.c from it. 13 | Those files can then be added and linked (statically or dynamically) into your 14 | project. 15 | 16 | Requirements 17 | ------------ 18 | 19 | gl3w_gen.py_ requires Python version 2.7 or newer. 20 | It is also compatible with Python 3.x. 21 | 22 | Example 23 | ------- 24 | 25 | Here is a simple example of using gl3w_ with glut. Note that GL/gl3w.h must be 26 | included before any other OpenGL related headers:: 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | // ... 33 | 34 | int main(int argc, char **argv) 35 | { 36 | glutInit(&argc, argv); 37 | glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 38 | glutInitWindowSize(width, height); 39 | glutCreateWindow("cookie"); 40 | 41 | glutReshapeFunc(reshape); 42 | glutDisplayFunc(display); 43 | glutKeyboardFunc(keyboard); 44 | glutSpecialFunc(special); 45 | glutMouseFunc(mouse); 46 | glutMotionFunc(motion); 47 | 48 | if (gl3wInit()) { 49 | fprintf(stderr, "failed to initialize OpenGL\n"); 50 | return -1; 51 | } 52 | if (!gl3wIsSupported(3, 2)) { 53 | fprintf(stderr, "OpenGL 3.2 not supported\n"); 54 | return -1; 55 | } 56 | printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), 57 | glGetString(GL_SHADING_LANGUAGE_VERSION)); 58 | 59 | // ... 60 | 61 | glutMainLoop(); 62 | return 0; 63 | } 64 | 65 | API Reference 66 | ------------- 67 | 68 | The gl3w_ API consists of just three functions: 69 | 70 | ``int gl3wInit(void)`` 71 | 72 | Initializes the library. Should be called once after an OpenGL context has 73 | been created. Returns ``0`` when gl3w_ was initialized successfully, 74 | ``non-zero`` if there was an error. 75 | 76 | ``int gl3wIsSupported(int major, int minor)`` 77 | 78 | Returns ``1`` when OpenGL core profile version *major.minor* is available 79 | and ``0`` otherwise. 80 | 81 | ``GL3WglProc gl3wGetProcAddress(const char *proc)`` 82 | 83 | Returns the address of an OpenGL extension function. Generally, you won't 84 | need to use it since gl3w_ loads all functions defined in the OpenGL core 85 | profile on initialization. It allows you to load OpenGL extensions outside 86 | of the core profile. 87 | 88 | Options 89 | ------- 90 | 91 | The generator script optionally takes the arguments: 92 | 93 | ``--ext`` to include the GL Extensions in output header. 94 | 95 | ``--root=outputdir`` to set the location for the output to something else than current working directory. 96 | 97 | License 98 | ------- 99 | 100 | .. image:: public-domain-mark.png 101 | 102 | gl3w_ is in the public domain. See the file UNLICENSE for more information. 103 | 104 | Credits 105 | ------- 106 | 107 | Slavomir Kaslev 108 | Initial implementation 109 | 110 | Kelvin McDowell 111 | Mac OS X support 112 | 113 | Sjors Gielen 114 | Mac OS X support 115 | 116 | Travis Gesslein 117 | Patches regarding glcorearb.h 118 | 119 | Arthur Tombs 120 | Port to Python 3 121 | 122 | Daniel Cousens [https://github.com/dcousens] 123 | Code contributions 124 | 125 | Copyright 126 | --------- 127 | 128 | OpenGL_ is a registered trademark of SGI_. 129 | 130 | .. _gl3w: https://github.com/skaslev/gl3w 131 | .. _gl3w_gen.py: https://github.com/skaslev/gl3w/blob/master/gl3w_gen.py 132 | .. _glcorearb.h: https://www.opengl.org/registry/api/GL/glcorearb.h 133 | .. _OpenGL: http://www.opengl.org/ 134 | .. _Khronos: http://www.khronos.org/ 135 | .. _SGI: http://www.sgi.com/ 136 | -------------------------------------------------------------------------------- /dependencies/gl3w/SConstruct: -------------------------------------------------------------------------------- 1 | import os 2 | import platform 3 | import shutil 4 | 5 | env = Environment() 6 | if env.GetOption('clean'): 7 | for d in ['bin', 'include', 'lib']: 8 | shutil.rmtree(d, True) 9 | try: 10 | os.unlink('src/gl3w.c') 11 | except: 12 | pass 13 | else: 14 | print('Generating gl3w...') 15 | os.system('./gl3w_gen.py') 16 | 17 | libs = [] 18 | if platform.system() == 'Darwin': 19 | env.Append(CFLAGS=['-Wno-deprecated-declarations'], 20 | FRAMEWORKS=['GLUT']) 21 | else: 22 | libs = ['glut', 'dl'] 23 | 24 | env.Append(CFLAGS=['-Wall', '-Wextra', '-pedantic', '-O2']) 25 | env.Append(CPPPATH='include') 26 | env.SharedLibrary('lib/gl3w', 'src/gl3w.c') 27 | o = env.Object('src/glut_test', 'src/glut_test.c') 28 | env.Program('bin/glut_test_static', [o, 'src/gl3w.c'], LIBS=libs) 29 | env.Program('bin/glut_test_shared', o, LIBS=libs + ['gl3w'], 30 | LIBPATH='lib', RPATH=os.path.abspath('lib')) 31 | -------------------------------------------------------------------------------- /dependencies/gl3w/UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /dependencies/gl3w/gl3w_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This file is part of gl3w, hosted at https://github.com/skaslev/gl3w 4 | # 5 | # This is free and unencumbered software released into the public domain. 6 | # 7 | # Anyone is free to copy, modify, publish, use, compile, sell, or 8 | # distribute this software, either in source code form or as a compiled 9 | # binary, for any purpose, commercial or non-commercial, and by any 10 | # means. 11 | # 12 | # In jurisdictions that recognize copyright laws, the author or authors 13 | # of this software dedicate any and all copyright interest in the 14 | # software to the public domain. We make this dedication for the benefit 15 | # of the public at large and to the detriment of our heirs and 16 | # successors. We intend this dedication to be an overt act of 17 | # relinquishment in perpetuity of all present and future rights to this 18 | # software under copyright law. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | # OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | # Allow Python 2.6+ to use the print() function 29 | from __future__ import print_function 30 | 31 | import argparse 32 | import os 33 | import re 34 | 35 | # Try to import Python 3 library urllib.request 36 | # and if it fails, fall back to Python 2 urllib2 37 | try: 38 | import urllib.request as urllib2 39 | except ImportError: 40 | import urllib2 41 | 42 | # UNLICENSE copyright header 43 | UNLICENSE = r'''/* 44 | * This file was generated with gl3w_gen.py, part of gl3w 45 | * (hosted at https://github.com/skaslev/gl3w) 46 | * 47 | * This is free and unencumbered software released into the public domain. 48 | * 49 | * Anyone is free to copy, modify, publish, use, compile, sell, or 50 | * distribute this software, either in source code form or as a compiled 51 | * binary, for any purpose, commercial or non-commercial, and by any 52 | * means. 53 | * 54 | * In jurisdictions that recognize copyright laws, the author or authors 55 | * of this software dedicate any and all copyright interest in the 56 | * software to the public domain. We make this dedication for the benefit 57 | * of the public at large and to the detriment of our heirs and 58 | * successors. We intend this dedication to be an overt act of 59 | * relinquishment in perpetuity of all present and future rights to this 60 | * software under copyright law. 61 | * 62 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 63 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 64 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 65 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 66 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 67 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 68 | * OTHER DEALINGS IN THE SOFTWARE. 69 | */ 70 | 71 | ''' 72 | 73 | EXT_SUFFIX = ['ARB', 'EXT', 'KHR', 'OVR', 'NV', 'AMD', 'INTEL'] 74 | 75 | def is_ext(proc): 76 | return any(proc.endswith(suffix) for suffix in EXT_SUFFIX) 77 | 78 | def write(f, s): 79 | f.write(s.encode('utf-8')) 80 | 81 | def touch_dir(path): 82 | if not os.path.exists(path): 83 | os.makedirs(path) 84 | 85 | def download(url, dst): 86 | if os.path.exists(dst): 87 | print('Reusing {0}...'.format(dst)) 88 | return 89 | 90 | print('Downloading {0}...'.format(dst)) 91 | headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36'} 92 | req = urllib2.Request(url=url, headers=headers) 93 | web = urllib2.urlopen(req) 94 | with open(dst, 'wb') as f: 95 | f.writelines(web.readlines()) 96 | 97 | parser = argparse.ArgumentParser(description='gl3w generator script') 98 | parser.add_argument('--ext', action='store_true', help='Load extensions') 99 | parser.add_argument('--root', type=str, default='', help='Root directory') 100 | args = parser.parse_args() 101 | 102 | # Create directories 103 | touch_dir(os.path.join(args.root, 'include/GL')) 104 | touch_dir(os.path.join(args.root, 'include/KHR')) 105 | touch_dir(os.path.join(args.root, 'src')) 106 | 107 | # Download glcorearb.h and khrplatform.h 108 | download('https://www.khronos.org/registry/OpenGL/api/GL/glcorearb.h', 109 | os.path.join(args.root, 'include/GL/glcorearb.h')) 110 | download('https://www.khronos.org/registry/EGL/api/KHR/khrplatform.h', 111 | os.path.join(args.root, 'include/KHR/khrplatform.h')) 112 | 113 | # Parse function names from glcorearb.h 114 | print('Parsing glcorearb.h header...') 115 | procs = [] 116 | p = re.compile(r'GLAPI.*APIENTRY\s+(\w+)') 117 | with open(os.path.join(args.root, 'include/GL/glcorearb.h'), 'r') as f: 118 | for line in f: 119 | m = p.match(line) 120 | if not m: 121 | continue 122 | proc = m.group(1) 123 | if args.ext or not is_ext(proc): 124 | procs.append(proc) 125 | procs.sort() 126 | 127 | # Generate gl3w.h 128 | print('Generating {0}...'.format(os.path.join(args.root, 'include/GL/gl3w.h'))) 129 | with open(os.path.join(args.root, 'include/GL/gl3w.h'), 'wb') as f: 130 | write(f, UNLICENSE) 131 | write(f, r'''#ifndef __gl3w_h_ 132 | #define __gl3w_h_ 133 | 134 | #include 135 | 136 | #ifndef GL3W_API 137 | #define GL3W_API 138 | #endif 139 | 140 | #ifndef __gl_h_ 141 | #define __gl_h_ 142 | #endif 143 | 144 | #ifdef __cplusplus 145 | extern "C" { 146 | #endif 147 | 148 | #define GL3W_OK 0 149 | #define GL3W_ERROR_INIT -1 150 | #define GL3W_ERROR_LIBRARY_OPEN -2 151 | #define GL3W_ERROR_OPENGL_VERSION -3 152 | 153 | typedef void (*GL3WglProc)(void); 154 | typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc); 155 | 156 | /* gl3w api */ 157 | GL3W_API int gl3wInit(void); 158 | GL3W_API int gl3wInit2(GL3WGetProcAddressProc proc); 159 | GL3W_API int gl3wIsSupported(int major, int minor); 160 | GL3W_API GL3WglProc gl3wGetProcAddress(const char *proc); 161 | 162 | /* gl3w internal state */ 163 | ''') 164 | write(f, 'union GL3WProcs {\n') 165 | write(f, '\tGL3WglProc ptr[{0}];\n'.format(len(procs))) 166 | write(f, '\tstruct {\n') 167 | for proc in procs: 168 | write(f, '\t\t{0: <55} {1};\n'.format('PFN{0}PROC'.format(proc.upper()), proc[2:])) 169 | write(f, r''' } gl; 170 | }; 171 | 172 | GL3W_API extern union GL3WProcs gl3wProcs; 173 | 174 | /* OpenGL functions */ 175 | ''') 176 | for proc in procs: 177 | write(f, '#define {0: <48} gl3wProcs.gl.{1}\n'.format(proc, proc[2:])) 178 | write(f, r''' 179 | #ifdef __cplusplus 180 | } 181 | #endif 182 | 183 | #endif 184 | ''') 185 | 186 | # Generate gl3w.c 187 | print('Generating {0}...'.format(os.path.join(args.root, 'src/gl3w.c'))) 188 | with open(os.path.join(args.root, 'src/gl3w.c'), 'wb') as f: 189 | write(f, UNLICENSE) 190 | write(f, r'''#include 191 | #include 192 | 193 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 194 | 195 | #if defined(_WIN32) 196 | #ifndef WIN32_LEAN_AND_MEAN 197 | #define WIN32_LEAN_AND_MEAN 1 198 | #endif 199 | #include 200 | 201 | static HMODULE libgl; 202 | typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR); 203 | static GL3WglGetProcAddr wgl_get_proc_address; 204 | 205 | static int open_libgl(void) 206 | { 207 | libgl = LoadLibraryA("opengl32.dll"); 208 | if (!libgl) 209 | return GL3W_ERROR_LIBRARY_OPEN; 210 | 211 | wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress"); 212 | return GL3W_OK; 213 | } 214 | 215 | static void close_libgl(void) 216 | { 217 | FreeLibrary(libgl); 218 | } 219 | 220 | static GL3WglProc get_proc(const char *proc) 221 | { 222 | GL3WglProc res; 223 | 224 | res = (GL3WglProc)wgl_get_proc_address(proc); 225 | if (!res) 226 | res = (GL3WglProc)GetProcAddress(libgl, proc); 227 | return res; 228 | } 229 | #elif defined(__APPLE__) 230 | #include 231 | 232 | static void *libgl; 233 | 234 | static int open_libgl(void) 235 | { 236 | libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL); 237 | if (!libgl) 238 | return GL3W_ERROR_LIBRARY_OPEN; 239 | 240 | return GL3W_OK; 241 | } 242 | 243 | static void close_libgl(void) 244 | { 245 | dlclose(libgl); 246 | } 247 | 248 | static GL3WglProc get_proc(const char *proc) 249 | { 250 | GL3WglProc res; 251 | 252 | *(void **)(&res) = dlsym(libgl, proc); 253 | return res; 254 | } 255 | #else 256 | #include 257 | 258 | static void *libgl; 259 | static GL3WglProc (*glx_get_proc_address)(const GLubyte *); 260 | 261 | static int open_libgl(void) 262 | { 263 | libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); 264 | if (!libgl) 265 | return GL3W_ERROR_LIBRARY_OPEN; 266 | 267 | *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); 268 | return GL3W_OK; 269 | } 270 | 271 | static void close_libgl(void) 272 | { 273 | dlclose(libgl); 274 | } 275 | 276 | static GL3WglProc get_proc(const char *proc) 277 | { 278 | GL3WglProc res; 279 | 280 | res = glx_get_proc_address((const GLubyte *)proc); 281 | if (!res) 282 | *(void **)(&res) = dlsym(libgl, proc); 283 | return res; 284 | } 285 | #endif 286 | 287 | static struct { 288 | int major, minor; 289 | } version; 290 | 291 | static int parse_version(void) 292 | { 293 | if (!glGetIntegerv) 294 | return GL3W_ERROR_INIT; 295 | 296 | glGetIntegerv(GL_MAJOR_VERSION, &version.major); 297 | glGetIntegerv(GL_MINOR_VERSION, &version.minor); 298 | 299 | if (version.major < 3) 300 | return GL3W_ERROR_OPENGL_VERSION; 301 | return GL3W_OK; 302 | } 303 | 304 | static void load_procs(GL3WGetProcAddressProc proc); 305 | 306 | int gl3wInit(void) 307 | { 308 | int res; 309 | 310 | res = open_libgl(); 311 | if (res) 312 | return res; 313 | 314 | atexit(close_libgl); 315 | return gl3wInit2(get_proc); 316 | } 317 | 318 | int gl3wInit2(GL3WGetProcAddressProc proc) 319 | { 320 | load_procs(proc); 321 | return parse_version(); 322 | } 323 | 324 | int gl3wIsSupported(int major, int minor) 325 | { 326 | if (major < 3) 327 | return 0; 328 | if (version.major == major) 329 | return version.minor >= minor; 330 | return version.major >= major; 331 | } 332 | 333 | GL3WglProc gl3wGetProcAddress(const char *proc) 334 | { 335 | return get_proc(proc); 336 | } 337 | 338 | static const char *proc_names[] = { 339 | ''') 340 | for proc in procs: 341 | write(f, '\t"{0}",\n'.format(proc)) 342 | write(f, r'''}; 343 | 344 | GL3W_API union GL3WProcs gl3wProcs; 345 | 346 | static void load_procs(GL3WGetProcAddressProc proc) 347 | { 348 | size_t i; 349 | 350 | for (i = 0; i < ARRAY_SIZE(proc_names); i++) 351 | gl3wProcs.ptr[i] = proc(proc_names[i]); 352 | } 353 | ''') 354 | -------------------------------------------------------------------------------- /dependencies/gl3w/public-domain-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-eternal/osu-cheat/71fed5bb230aa2307b7d493a209a71f3890244c5/dependencies/gl3w/public-domain-mark.png -------------------------------------------------------------------------------- /dependencies/gl3w/src/glfw_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of gl3w, hosted at https://github.com/skaslev/gl3w 4 | 5 | This is free and unencumbered software released into the public domain. 6 | 7 | Anyone is free to copy, modify, publish, use, compile, sell, or 8 | distribute this software, either in source code form or as a compiled 9 | binary, for any purpose, commercial or non-commercial, and by any 10 | means. 11 | 12 | In jurisdictions that recognize copyright laws, the author or authors 13 | of this software dedicate any and all copyright interest in the 14 | software to the public domain. We make this dedication for the benefit 15 | of the public at large and to the detriment of our heirs and 16 | successors. We intend this dedication to be an overt act of 17 | relinquishment in perpetuity of all present and future rights to this 18 | software under copyright law. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | static int width = 600, height = 600; 36 | 37 | static float randf() 38 | { 39 | return (float) rand() / ((float) RAND_MAX + 1); 40 | } 41 | 42 | static void display(GLFWwindow *window) 43 | { 44 | glClearColor(randf(), randf(), randf(), 1.0f); 45 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 46 | glfwSwapBuffers(window); 47 | } 48 | 49 | static void reshape(GLFWwindow *window, int w, int h) 50 | { 51 | width = w > 1 ? w : 1; 52 | height = h > 1 ? h : 1; 53 | glViewport(0, 0, width, height); 54 | glClearDepth(1.0); 55 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 56 | glEnable(GL_DEPTH_TEST); 57 | } 58 | 59 | int main(int argc, char **argv) 60 | { 61 | GLFWwindow *window; 62 | 63 | glfwInit(); 64 | 65 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 66 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 67 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); 68 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 69 | window = glfwCreateWindow(width, height, "cookie", NULL, NULL); 70 | 71 | glfwSetFramebufferSizeCallback(window, reshape); 72 | glfwSetWindowRefreshCallback(window, display); 73 | 74 | glfwMakeContextCurrent(window); 75 | 76 | if (gl3wInit()) { 77 | fprintf(stderr, "failed to initialize OpenGL\n"); 78 | return -1; 79 | } 80 | if (!gl3wIsSupported(3, 2)) { 81 | fprintf(stderr, "OpenGL 3.2 not supported\n"); 82 | return -1; 83 | } 84 | printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), 85 | glGetString(GL_SHADING_LANGUAGE_VERSION)); 86 | 87 | while (!glfwWindowShouldClose(window)) { 88 | display(window); 89 | glfwPollEvents(); 90 | } 91 | 92 | glfwTerminate(); 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /dependencies/gl3w/src/glut_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of gl3w, hosted at https://github.com/skaslev/gl3w 4 | 5 | This is free and unencumbered software released into the public domain. 6 | 7 | Anyone is free to copy, modify, publish, use, compile, sell, or 8 | distribute this software, either in source code form or as a compiled 9 | binary, for any purpose, commercial or non-commercial, and by any 10 | means. 11 | 12 | In jurisdictions that recognize copyright laws, the author or authors 13 | of this software dedicate any and all copyright interest in the 14 | software to the public domain. We make this dedication for the benefit 15 | of the public at large and to the detriment of our heirs and 16 | successors. We intend this dedication to be an overt act of 17 | relinquishment in perpetuity of all present and future rights to this 18 | software under copyright law. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | static int width = 600, height = 600; 36 | 37 | static float randf() 38 | { 39 | return (float) rand() / ((float) RAND_MAX + 1); 40 | } 41 | 42 | static void display(void) 43 | { 44 | glClearColor(randf(), randf(), randf(), 1.0f); 45 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 46 | glutSwapBuffers(); 47 | glutPostRedisplay(); 48 | } 49 | 50 | static void reshape(int w, int h) 51 | { 52 | width = w > 1 ? w : 1; 53 | height = h > 1 ? h : 1; 54 | glViewport(0, 0, width, height); 55 | glClearDepth(1.0); 56 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 57 | glEnable(GL_DEPTH_TEST); 58 | } 59 | 60 | int main(int argc, char **argv) 61 | { 62 | unsigned mode = GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE; 63 | 64 | glutInit(&argc, argv); 65 | glutInitContextVersion(3, 2); 66 | glutInitContextProfile(GLUT_CORE_PROFILE); 67 | glutInitDisplayMode(mode); 68 | glutInitWindowSize(width, height); 69 | glutCreateWindow("cookie"); 70 | 71 | glutReshapeFunc(reshape); 72 | glutDisplayFunc(display); 73 | 74 | if (gl3wInit()) { 75 | fprintf(stderr, "failed to initialize OpenGL\n"); 76 | return -1; 77 | } 78 | if (!gl3wIsSupported(3, 2)) { 79 | fprintf(stderr, "OpenGL 3.2 not supported\n"); 80 | return -1; 81 | } 82 | printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), 83 | glGetString(GL_SHADING_LANGUAGE_VERSION)); 84 | 85 | glutMainLoop(); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /dependencies/gl3w_out/.gitignore: -------------------------------------------------------------------------------- 1 | /src/ 2 | /include/ -------------------------------------------------------------------------------- /dependencies/gl3w_out/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # no idea how to use gl3w's cmake file... TODO: figure it out 2 | # Generate this dep by running: py gl3w_gen.py --root ../gl3w_out/ 3 | 4 | cmake_minimum_required(VERSION 3.18) 5 | project(gl3w) 6 | add_library(gl3w STATIC "src/gl3w.c") 7 | 8 | set(gl3w-includes "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE) 9 | set_target_properties(gl3w PROPERTIES LINKER_LANGUAGE C) 10 | target_include_directories(gl3w PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") 11 | -------------------------------------------------------------------------------- /dependencies/imgui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | 3 | add_library(imgui 4 | "imgui.cpp" 5 | "imgui_impl_opengl3.cpp" 6 | "imgui_impl_win32.cpp" 7 | "imgui_tables.cpp" 8 | "imgui_widgets.cpp" 9 | "imgui_draw.cpp" 10 | ) 11 | 12 | set(imgui-includes "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE) 13 | set_target_properties(imgui PROPERTIES LINKER_LANGUAGE CXX) -------------------------------------------------------------------------------- /dependencies/imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2021 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dependencies/imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec( dllexport ) 27 | //#define IMGUI_API __declspec( dllimport ) 28 | 29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 31 | 32 | //---- Disable all of Dear ImGui or don't implement standard windows. 33 | // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. 34 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 35 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. 36 | //#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty. 37 | 38 | //---- Don't implement some functions to reduce linkage requirements. 39 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 40 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) 41 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) 42 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 43 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 44 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 45 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 46 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 47 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 48 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 49 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available 50 | 51 | //---- Include imgui_user.h at the end of imgui.h as a convenience 52 | //#define IMGUI_INCLUDE_IMGUI_USER_H 53 | 54 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 55 | //#define IMGUI_USE_BGRA_PACKED_COLOR 56 | 57 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 58 | //#define IMGUI_USE_WCHAR32 59 | 60 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 61 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 62 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 63 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 64 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 65 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 66 | 67 | //---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 68 | // Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. 69 | // #define IMGUI_USE_STB_SPRINTF 70 | 71 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 72 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 73 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. 74 | //#define IMGUI_ENABLE_FREETYPE 75 | 76 | //---- Use stb_truetype to build and rasterize the font atlas (default) 77 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 78 | //#define IMGUI_ENABLE_STB_TRUETYPE 79 | 80 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 81 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 82 | /* 83 | #define IM_VEC2_CLASS_EXTRA \ 84 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 85 | operator MyVec2() const { return MyVec2(x,y); } 86 | 87 | #define IM_VEC4_CLASS_EXTRA \ 88 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 89 | operator MyVec4() const { return MyVec4(x,y,z,w); } 90 | */ 91 | 92 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 93 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 94 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 95 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 96 | //#define ImDrawIdx unsigned int 97 | 98 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 99 | //struct ImDrawList; 100 | //struct ImDrawCmd; 101 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 102 | //#define ImDrawCallback MyImDrawCallback 103 | 104 | //---- Debug Tools: Macro to break in Debugger 105 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 106 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 107 | //#define IM_DEBUG_BREAK __debugbreak() 108 | 109 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), 110 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) 111 | // This adds a small runtime cost which is why it is not enabled by default. 112 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 113 | 114 | //---- Debug Tools: Enable slower asserts 115 | //#define IMGUI_DEBUG_PARANOID 116 | 117 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 118 | /* 119 | namespace ImGui 120 | { 121 | void MyFunction(const char* name, const MyMatrix44& v); 122 | } 123 | */ 124 | -------------------------------------------------------------------------------- /dependencies/imgui/imgui_impl_opengl3.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline 2 | // - Desktop GL: 2.x 3.x 4.x 3 | // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) 4 | // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) 5 | 6 | // Implemented features: 7 | // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! 8 | // [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | // About GLSL version: 16 | // The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string. 17 | // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" 18 | // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. 19 | 20 | #pragma once 21 | #include "imgui.h" // IMGUI_IMPL_API 22 | 23 | // Backend API 24 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL); 25 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); 26 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); 27 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); 28 | 29 | // (Optional) Called by Init/NewFrame/Shutdown 30 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); 31 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); 32 | IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); 33 | IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); 34 | 35 | // Specific OpenGL ES versions 36 | //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten 37 | //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android 38 | 39 | // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. 40 | #if !defined(IMGUI_IMPL_OPENGL_ES2) \ 41 | && !defined(IMGUI_IMPL_OPENGL_ES3) 42 | 43 | // Try to detect GLES on matching platforms 44 | #if defined(__APPLE__) 45 | #include 46 | #endif 47 | #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) 48 | #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" 49 | #elif defined(__EMSCRIPTEN__) 50 | #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" 51 | #else 52 | // Otherwise imgui_impl_opengl3_loader.h will be used. 53 | #endif 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /dependencies/imgui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | 10 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 12 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 13 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 14 | 15 | #pragma once 16 | #include "imgui.h" // IMGUI_IMPL_API 17 | 18 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 19 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 20 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 21 | 22 | // Win32 message handler your application need to call. 23 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 24 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 25 | #if 0 26 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 27 | #endif 28 | 29 | // DPI-related helpers (optional) 30 | // - Use to enable DPI awareness without having to create an application manifest. 31 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 32 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 33 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 34 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 35 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 36 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 37 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 38 | 39 | // Transparency related helpers (optional) [experimental] 40 | // - Use to enable alpha compositing transparency with the desktop. 41 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 42 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 43 | -------------------------------------------------------------------------------- /dependencies/imgui/imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_rect_pack.h 1.00. 3 | // Those changes would need to be pushed into nothings/stb: 4 | // - Added STBRP__CDECL 5 | // Grep for [DEAR IMGUI] to find the changes. 6 | 7 | // stb_rect_pack.h - v1.00 - public domain - rectangle packing 8 | // Sean Barrett 2014 9 | // 10 | // Useful for e.g. packing rectangular textures into an atlas. 11 | // Does not do rotation. 12 | // 13 | // Not necessarily the awesomest packing method, but better than 14 | // the totally naive one in stb_truetype (which is primarily what 15 | // this is meant to replace). 16 | // 17 | // Has only had a few tests run, may have issues. 18 | // 19 | // More docs to come. 20 | // 21 | // No memory allocations; uses qsort() and assert() from stdlib. 22 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 23 | // 24 | // This library currently uses the Skyline Bottom-Left algorithm. 25 | // 26 | // Please note: better rectangle packers are welcome! Please 27 | // implement them to the same API, but with a different init 28 | // function. 29 | // 30 | // Credits 31 | // 32 | // Library 33 | // Sean Barrett 34 | // Minor features 35 | // Martins Mozeiko 36 | // github:IntellectualKitty 37 | // 38 | // Bugfixes / warning fixes 39 | // Jeremy Jaussaud 40 | // Fabian Giesen 41 | // 42 | // Version history: 43 | // 44 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles 45 | // 0.99 (2019-02-07) warning fixes 46 | // 0.11 (2017-03-03) return packing success/fail result 47 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 48 | // 0.09 (2016-08-27) fix compiler warnings 49 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 50 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 51 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 52 | // 0.05: added STBRP_ASSERT to allow replacing assert 53 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 54 | // 0.01: initial release 55 | // 56 | // LICENSE 57 | // 58 | // See end of file for license information. 59 | 60 | ////////////////////////////////////////////////////////////////////////////// 61 | // 62 | // INCLUDE SECTION 63 | // 64 | 65 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 66 | #define STB_INCLUDE_STB_RECT_PACK_H 67 | 68 | #define STB_RECT_PACK_VERSION 1 69 | 70 | #ifdef STBRP_STATIC 71 | #define STBRP_DEF static 72 | #else 73 | #define STBRP_DEF extern 74 | #endif 75 | 76 | #ifdef __cplusplus 77 | extern "C" { 78 | #endif 79 | 80 | typedef struct stbrp_context stbrp_context; 81 | typedef struct stbrp_node stbrp_node; 82 | typedef struct stbrp_rect stbrp_rect; 83 | 84 | #ifdef STBRP_LARGE_RECTS 85 | typedef int stbrp_coord; 86 | #else 87 | typedef unsigned short stbrp_coord; 88 | #endif 89 | 90 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 91 | // Assign packed locations to rectangles. The rectangles are of type 92 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 93 | // are 'num_rects' many of them. 94 | // 95 | // Rectangles which are successfully packed have the 'was_packed' flag 96 | // set to a non-zero value and 'x' and 'y' store the minimum location 97 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 98 | // if you imagine y increasing downwards). Rectangles which do not fit 99 | // have the 'was_packed' flag set to 0. 100 | // 101 | // You should not try to access the 'rects' array from another thread 102 | // while this function is running, as the function temporarily reorders 103 | // the array while it executes. 104 | // 105 | // To pack into another rectangle, you need to call stbrp_init_target 106 | // again. To continue packing into the same rectangle, you can call 107 | // this function again. Calling this multiple times with multiple rect 108 | // arrays will probably produce worse packing results than calling it 109 | // a single time with the full rectangle array, but the option is 110 | // available. 111 | // 112 | // The function returns 1 if all of the rectangles were successfully 113 | // packed and 0 otherwise. 114 | 115 | struct stbrp_rect 116 | { 117 | // reserved for your use: 118 | int id; 119 | 120 | // input: 121 | stbrp_coord w, h; 122 | 123 | // output: 124 | stbrp_coord x, y; 125 | int was_packed; // non-zero if valid packing 126 | 127 | }; // 16 bytes, nominally 128 | 129 | 130 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 131 | // Initialize a rectangle packer to: 132 | // pack a rectangle that is 'width' by 'height' in dimensions 133 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 134 | // 135 | // You must call this function every time you start packing into a new target. 136 | // 137 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 138 | // the following stbrp_pack_rects() call (or calls), but can be freed after 139 | // the call (or calls) finish. 140 | // 141 | // Note: to guarantee best results, either: 142 | // 1. make sure 'num_nodes' >= 'width' 143 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 144 | // 145 | // If you don't do either of the above things, widths will be quantized to multiples 146 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 147 | // 148 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 149 | // may run out of temporary storage and be unable to pack some rectangles. 150 | 151 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 152 | // Optionally call this function after init but before doing any packing to 153 | // change the handling of the out-of-temp-memory scenario, described above. 154 | // If you call init again, this will be reset to the default (false). 155 | 156 | 157 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 158 | // Optionally select which packing heuristic the library should use. Different 159 | // heuristics will produce better/worse results for different data sets. 160 | // If you call init again, this will be reset to the default. 161 | 162 | enum 163 | { 164 | STBRP_HEURISTIC_Skyline_default=0, 165 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 166 | STBRP_HEURISTIC_Skyline_BF_sortHeight 167 | }; 168 | 169 | 170 | ////////////////////////////////////////////////////////////////////////////// 171 | // 172 | // the details of the following structures don't matter to you, but they must 173 | // be visible so you can handle the memory allocations for them 174 | 175 | struct stbrp_node 176 | { 177 | stbrp_coord x,y; 178 | stbrp_node *next; 179 | }; 180 | 181 | struct stbrp_context 182 | { 183 | int width; 184 | int height; 185 | int align; 186 | int init_mode; 187 | int heuristic; 188 | int num_nodes; 189 | stbrp_node *active_head; 190 | stbrp_node *free_head; 191 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 192 | }; 193 | 194 | #ifdef __cplusplus 195 | } 196 | #endif 197 | 198 | #endif 199 | 200 | ////////////////////////////////////////////////////////////////////////////// 201 | // 202 | // IMPLEMENTATION SECTION 203 | // 204 | 205 | #ifdef STB_RECT_PACK_IMPLEMENTATION 206 | #ifndef STBRP_SORT 207 | #include 208 | #define STBRP_SORT qsort 209 | #endif 210 | 211 | #ifndef STBRP_ASSERT 212 | #include 213 | #define STBRP_ASSERT assert 214 | #endif 215 | 216 | // [DEAR IMGUI] Added STBRP__CDECL 217 | #ifdef _MSC_VER 218 | #define STBRP__NOTUSED(v) (void)(v) 219 | #define STBRP__CDECL __cdecl 220 | #else 221 | #define STBRP__NOTUSED(v) (void)sizeof(v) 222 | #define STBRP__CDECL 223 | #endif 224 | 225 | enum 226 | { 227 | STBRP__INIT_skyline = 1 228 | }; 229 | 230 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 231 | { 232 | switch (context->init_mode) { 233 | case STBRP__INIT_skyline: 234 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 235 | context->heuristic = heuristic; 236 | break; 237 | default: 238 | STBRP_ASSERT(0); 239 | } 240 | } 241 | 242 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 243 | { 244 | if (allow_out_of_mem) 245 | // if it's ok to run out of memory, then don't bother aligning them; 246 | // this gives better packing, but may fail due to OOM (even though 247 | // the rectangles easily fit). @TODO a smarter approach would be to only 248 | // quantize once we've hit OOM, then we could get rid of this parameter. 249 | context->align = 1; 250 | else { 251 | // if it's not ok to run out of memory, then quantize the widths 252 | // so that num_nodes is always enough nodes. 253 | // 254 | // I.e. num_nodes * align >= width 255 | // align >= width / num_nodes 256 | // align = ceil(width/num_nodes) 257 | 258 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 259 | } 260 | } 261 | 262 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 263 | { 264 | int i; 265 | #ifndef STBRP_LARGE_RECTS 266 | STBRP_ASSERT(width <= 0xffff && height <= 0xffff); 267 | #endif 268 | 269 | for (i=0; i < num_nodes-1; ++i) 270 | nodes[i].next = &nodes[i+1]; 271 | nodes[i].next = NULL; 272 | context->init_mode = STBRP__INIT_skyline; 273 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 274 | context->free_head = &nodes[0]; 275 | context->active_head = &context->extra[0]; 276 | context->width = width; 277 | context->height = height; 278 | context->num_nodes = num_nodes; 279 | stbrp_setup_allow_out_of_mem(context, 0); 280 | 281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 282 | context->extra[0].x = 0; 283 | context->extra[0].y = 0; 284 | context->extra[0].next = &context->extra[1]; 285 | context->extra[1].x = (stbrp_coord) width; 286 | #ifdef STBRP_LARGE_RECTS 287 | context->extra[1].y = (1<<30); 288 | #else 289 | context->extra[1].y = 65535; 290 | #endif 291 | context->extra[1].next = NULL; 292 | } 293 | 294 | // find minimum y position if it starts at x1 295 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 296 | { 297 | stbrp_node *node = first; 298 | int x1 = x0 + width; 299 | int min_y, visited_width, waste_area; 300 | 301 | STBRP__NOTUSED(c); 302 | 303 | STBRP_ASSERT(first->x <= x0); 304 | 305 | #if 0 306 | // skip in case we're past the node 307 | while (node->next->x <= x0) 308 | ++node; 309 | #else 310 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 311 | #endif 312 | 313 | STBRP_ASSERT(node->x <= x0); 314 | 315 | min_y = 0; 316 | waste_area = 0; 317 | visited_width = 0; 318 | while (node->x < x1) { 319 | if (node->y > min_y) { 320 | // raise min_y higher. 321 | // we've accounted for all waste up to min_y, 322 | // but we'll now add more waste for everything we've visted 323 | waste_area += visited_width * (node->y - min_y); 324 | min_y = node->y; 325 | // the first time through, visited_width might be reduced 326 | if (node->x < x0) 327 | visited_width += node->next->x - x0; 328 | else 329 | visited_width += node->next->x - node->x; 330 | } else { 331 | // add waste area 332 | int under_width = node->next->x - node->x; 333 | if (under_width + visited_width > width) 334 | under_width = width - visited_width; 335 | waste_area += under_width * (min_y - node->y); 336 | visited_width += under_width; 337 | } 338 | node = node->next; 339 | } 340 | 341 | *pwaste = waste_area; 342 | return min_y; 343 | } 344 | 345 | typedef struct 346 | { 347 | int x,y; 348 | stbrp_node **prev_link; 349 | } stbrp__findresult; 350 | 351 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 352 | { 353 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 354 | stbrp__findresult fr; 355 | stbrp_node **prev, *node, *tail, **best = NULL; 356 | 357 | // align to multiple of c->align 358 | width = (width + c->align - 1); 359 | width -= width % c->align; 360 | STBRP_ASSERT(width % c->align == 0); 361 | 362 | // if it can't possibly fit, bail immediately 363 | if (width > c->width || height > c->height) { 364 | fr.prev_link = NULL; 365 | fr.x = fr.y = 0; 366 | return fr; 367 | } 368 | 369 | node = c->active_head; 370 | prev = &c->active_head; 371 | while (node->x + width <= c->width) { 372 | int y,waste; 373 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 374 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 375 | // bottom left 376 | if (y < best_y) { 377 | best_y = y; 378 | best = prev; 379 | } 380 | } else { 381 | // best-fit 382 | if (y + height <= c->height) { 383 | // can only use it if it first vertically 384 | if (y < best_y || (y == best_y && waste < best_waste)) { 385 | best_y = y; 386 | best_waste = waste; 387 | best = prev; 388 | } 389 | } 390 | } 391 | prev = &node->next; 392 | node = node->next; 393 | } 394 | 395 | best_x = (best == NULL) ? 0 : (*best)->x; 396 | 397 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 398 | // 399 | // e.g, if fitting 400 | // 401 | // ____________________ 402 | // |____________________| 403 | // 404 | // into 405 | // 406 | // | | 407 | // | ____________| 408 | // |____________| 409 | // 410 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 411 | // 412 | // This makes BF take about 2x the time 413 | 414 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 415 | tail = c->active_head; 416 | node = c->active_head; 417 | prev = &c->active_head; 418 | // find first node that's admissible 419 | while (tail->x < width) 420 | tail = tail->next; 421 | while (tail) { 422 | int xpos = tail->x - width; 423 | int y,waste; 424 | STBRP_ASSERT(xpos >= 0); 425 | // find the left position that matches this 426 | while (node->next->x <= xpos) { 427 | prev = &node->next; 428 | node = node->next; 429 | } 430 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 431 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 432 | if (y + height <= c->height) { 433 | if (y <= best_y) { 434 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 435 | best_x = xpos; 436 | STBRP_ASSERT(y <= best_y); 437 | best_y = y; 438 | best_waste = waste; 439 | best = prev; 440 | } 441 | } 442 | } 443 | tail = tail->next; 444 | } 445 | } 446 | 447 | fr.prev_link = best; 448 | fr.x = best_x; 449 | fr.y = best_y; 450 | return fr; 451 | } 452 | 453 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 454 | { 455 | // find best position according to heuristic 456 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 457 | stbrp_node *node, *cur; 458 | 459 | // bail if: 460 | // 1. it failed 461 | // 2. the best node doesn't fit (we don't always check this) 462 | // 3. we're out of memory 463 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 464 | res.prev_link = NULL; 465 | return res; 466 | } 467 | 468 | // on success, create new node 469 | node = context->free_head; 470 | node->x = (stbrp_coord) res.x; 471 | node->y = (stbrp_coord) (res.y + height); 472 | 473 | context->free_head = node->next; 474 | 475 | // insert the new node into the right starting point, and 476 | // let 'cur' point to the remaining nodes needing to be 477 | // stiched back in 478 | 479 | cur = *res.prev_link; 480 | if (cur->x < res.x) { 481 | // preserve the existing one, so start testing with the next one 482 | stbrp_node *next = cur->next; 483 | cur->next = node; 484 | cur = next; 485 | } else { 486 | *res.prev_link = node; 487 | } 488 | 489 | // from here, traverse cur and free the nodes, until we get to one 490 | // that shouldn't be freed 491 | while (cur->next && cur->next->x <= res.x + width) { 492 | stbrp_node *next = cur->next; 493 | // move the current node to the free list 494 | cur->next = context->free_head; 495 | context->free_head = cur; 496 | cur = next; 497 | } 498 | 499 | // stitch the list back in 500 | node->next = cur; 501 | 502 | if (cur->x < res.x + width) 503 | cur->x = (stbrp_coord) (res.x + width); 504 | 505 | #ifdef _DEBUG 506 | cur = context->active_head; 507 | while (cur->x < context->width) { 508 | STBRP_ASSERT(cur->x < cur->next->x); 509 | cur = cur->next; 510 | } 511 | STBRP_ASSERT(cur->next == NULL); 512 | 513 | { 514 | int count=0; 515 | cur = context->active_head; 516 | while (cur) { 517 | cur = cur->next; 518 | ++count; 519 | } 520 | cur = context->free_head; 521 | while (cur) { 522 | cur = cur->next; 523 | ++count; 524 | } 525 | STBRP_ASSERT(count == context->num_nodes+2); 526 | } 527 | #endif 528 | 529 | return res; 530 | } 531 | 532 | // [DEAR IMGUI] Added STBRP__CDECL 533 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 534 | { 535 | const stbrp_rect *p = (const stbrp_rect *) a; 536 | const stbrp_rect *q = (const stbrp_rect *) b; 537 | if (p->h > q->h) 538 | return -1; 539 | if (p->h < q->h) 540 | return 1; 541 | return (p->w > q->w) ? -1 : (p->w < q->w); 542 | } 543 | 544 | // [DEAR IMGUI] Added STBRP__CDECL 545 | static int STBRP__CDECL rect_original_order(const void *a, const void *b) 546 | { 547 | const stbrp_rect *p = (const stbrp_rect *) a; 548 | const stbrp_rect *q = (const stbrp_rect *) b; 549 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 550 | } 551 | 552 | #ifdef STBRP_LARGE_RECTS 553 | #define STBRP__MAXVAL 0xffffffff 554 | #else 555 | #define STBRP__MAXVAL 0xffff 556 | #endif 557 | 558 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 559 | { 560 | int i, all_rects_packed = 1; 561 | 562 | // we use the 'was_packed' field internally to allow sorting/unsorting 563 | for (i=0; i < num_rects; ++i) { 564 | rects[i].was_packed = i; 565 | } 566 | 567 | // sort according to heuristic 568 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 569 | 570 | for (i=0; i < num_rects; ++i) { 571 | if (rects[i].w == 0 || rects[i].h == 0) { 572 | rects[i].x = rects[i].y = 0; // empty rect needs no space 573 | } else { 574 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 575 | if (fr.prev_link) { 576 | rects[i].x = (stbrp_coord) fr.x; 577 | rects[i].y = (stbrp_coord) fr.y; 578 | } else { 579 | rects[i].x = rects[i].y = STBRP__MAXVAL; 580 | } 581 | } 582 | } 583 | 584 | // unsort 585 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 586 | 587 | // set was_packed flags and all_rects_packed status 588 | for (i=0; i < num_rects; ++i) { 589 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 590 | if (!rects[i].was_packed) 591 | all_rects_packed = 0; 592 | } 593 | 594 | // return the all_rects_packed status 595 | return all_rects_packed; 596 | } 597 | #endif 598 | 599 | /* 600 | ------------------------------------------------------------------------------ 601 | This software is available under 2 licenses -- choose whichever you prefer. 602 | ------------------------------------------------------------------------------ 603 | ALTERNATIVE A - MIT License 604 | Copyright (c) 2017 Sean Barrett 605 | Permission is hereby granted, free of charge, to any person obtaining a copy of 606 | this software and associated documentation files (the "Software"), to deal in 607 | the Software without restriction, including without limitation the rights to 608 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 609 | of the Software, and to permit persons to whom the Software is furnished to do 610 | so, subject to the following conditions: 611 | The above copyright notice and this permission notice shall be included in all 612 | copies or substantial portions of the Software. 613 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 614 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 615 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 616 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 617 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 618 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 619 | SOFTWARE. 620 | ------------------------------------------------------------------------------ 621 | ALTERNATIVE B - Public Domain (www.unlicense.org) 622 | This is free and unencumbered software released into the public domain. 623 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 624 | software, either in source code form or as a compiled binary, for any purpose, 625 | commercial or non-commercial, and by any means. 626 | In jurisdictions that recognize copyright laws, the author or authors of this 627 | software dedicate any and all copyright interest in the software to the public 628 | domain. We make this dedication for the benefit of the public at large and to 629 | the detriment of our heirs and successors. We intend this dedication to be an 630 | overt act of relinquishment in perpetuity of all present and future rights to 631 | this software under copyright law. 632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 635 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 636 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 637 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 638 | ------------------------------------------------------------------------------ 639 | */ 640 | -------------------------------------------------------------------------------- /framework/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | 3 | set(CMAKE_CXX_STANDARD 20) 4 | set(CMAKE_CXX_STANDARD_REQUIRED True) 5 | 6 | project(osu-cheese-framework) 7 | 8 | add_library(${PROJECT_NAME} STATIC 9 | "sed/windows/smart_handle.hpp" 10 | "sed/windows/smart_handle.cpp" 11 | "sed/windows/suspend_guard.hpp" 12 | "sed/windows/suspend_guard.cpp" 13 | "sed/windows/protect_guard.hpp" 14 | "sed/windows/protect_guard.cpp" 15 | 16 | "sed/console.hpp" 17 | "sed/console.cpp" 18 | "sed/memory.hpp" 19 | "sed/memory.cpp" 20 | "sed/macro.hpp" 21 | "sed/strings.hpp" 22 | ) 23 | 24 | set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) 25 | set(osu-cheese-framework-includes "${CMAKE_CURRENT_SOURCE_DIR}" PARENT_SCOPE) -------------------------------------------------------------------------------- /framework/sed/console.cpp: -------------------------------------------------------------------------------- 1 | #include "console.hpp" 2 | #include 3 | 4 | static HWND _conwindow_handle { nullptr }; 5 | static HANDLE _stdout_handle { nullptr }; 6 | 7 | auto sed::console::init() -> bool 8 | { 9 | if (AllocConsole()) 10 | { 11 | FILE * fp { nullptr }; 12 | _wfreopen_s(&fp, L"CONOUT$", L"w", stdout); 13 | _wfreopen_s(&fp, L"CONOUT$", L"w", stderr); 14 | _wfreopen_s(&fp, L"CONIN$", L"r", stdin); 15 | } 16 | 17 | _conwindow_handle = GetConsoleWindow(); 18 | _stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); 19 | 20 | if (!_conwindow_handle || !_stdout_handle) 21 | return false; 22 | 23 | return true; 24 | } 25 | -------------------------------------------------------------------------------- /framework/sed/console.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace sed::console 8 | { 9 | auto init() -> bool; 10 | } -------------------------------------------------------------------------------- /framework/sed/macro.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define OC_GLUE(x, y) x ## y 4 | #define OC_MGLUE(x, y) OC_GLUE(x, y) 5 | 6 | #define OC_PAD(n) char OC_MGLUE(_pad_, __LINE__) [n] 7 | 8 | #define OC_UNS_PAD(n, type, name) \ 9 | struct \ 10 | { \ 11 | OC_PAD(n); \ 12 | type name; \ 13 | }; 14 | 15 | #if defined(OSU_CHEESE_DEBUG_BUILD) 16 | #include 17 | #include 18 | #define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) 19 | #define DEBUG_WPRINTF(fmt, ...) wprintf(fmt, __VA_ARGS__) 20 | #define DEBUG_OPT_NULL(x) x 21 | #else 22 | #define DEBUG_PRINTF(fmt, ...) 23 | #define DEBUG_WPRINTF(fmt, ...) 24 | #define DEBUG_OPT_NULL(x) nullptr 25 | #endif 26 | 27 | #define OC_IMGUI_HOVER_TXT(fmt, ...) \ 28 | if (ImGui::IsItemHovered()) \ 29 | ImGui::SetTooltip(fmt, __VA_ARGS__) -------------------------------------------------------------------------------- /framework/sed/memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.hpp" 2 | 3 | #include 4 | 5 | auto sed::abs2rel32(void * from, std::size_t size, void * to) -> std::int32_t 6 | { 7 | return static_cast(reinterpret_cast(to) - (reinterpret_cast(from) + size)); 8 | } 9 | 10 | auto sed::rel2abs32(void * instruction, std::size_t size) -> std::uintptr_t 11 | { 12 | std::uintptr_t next = reinterpret_cast(instruction) + size; 13 | return next + *reinterpret_cast(next - sizeof(std::int32_t)); 14 | } 15 | 16 | auto sed::abs32(void * instruction, std::size_t size) -> std::uintptr_t 17 | { 18 | return *reinterpret_cast(reinterpret_cast(instruction) + size - sizeof(std::uintptr_t)); 19 | } 20 | 21 | auto sed::op1rel32_apply(std::uint8_t opcode, void * from, void * to) -> bool 22 | { 23 | std::uint8_t shell[] = { opcode, 0x00, 0x00, 0x00, 0x00 }; 24 | *reinterpret_cast(shell + 1) = sed::abs2rel32(from, sizeof(shell), to); 25 | 26 | DWORD oprot { 0 }; 27 | if (!VirtualProtect(from, sizeof(shell), PAGE_EXECUTE_READWRITE, &oprot)) 28 | return false; 29 | 30 | for (int i = 0; i < sizeof(shell); ++i) 31 | reinterpret_cast(from)[i] = shell[i]; 32 | 33 | if (!VirtualProtect(from, sizeof(shell), oprot, &oprot)) 34 | return false; 35 | 36 | return true; 37 | } 38 | 39 | auto sed::jmprel32_apply(void * from, void * to) -> bool 40 | { 41 | return sed::op1rel32_apply(0xE9, from, to); 42 | } 43 | 44 | auto sed::callrel32_apply(void * from, void * to) -> bool 45 | { 46 | return sed::op1rel32_apply(0xE8, from, to); 47 | } 48 | 49 | auto sed::pattern_scan(void * start_, std::size_t size, const char * pattern, const char * mask) -> std::uintptr_t 50 | { 51 | std::uint8_t * start = reinterpret_cast(start_); 52 | const auto len = strlen(mask); 53 | 54 | for (std::size_t rva = 0; rva < size - len; ++rva) 55 | { 56 | for (int pat_i = 0; pat_i < len; ++pat_i) 57 | { 58 | if (mask[pat_i] == '?') 59 | continue; 60 | 61 | if (mask[pat_i] != 'x' || pattern[pat_i] != reinterpret_cast(start)[rva + pat_i]) 62 | break; 63 | 64 | if (pat_i == len - 1) 65 | return reinterpret_cast(start_) + rva; 66 | } 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | auto sed::pattern_scan_exec_region(void * start_, std::size_t size, const char * pattern, const char * mask) -> std::uintptr_t 73 | { 74 | std::uint8_t * current = reinterpret_cast(start_); 75 | std::uint8_t * end = size == -1 ? reinterpret_cast(-1) : current + size; 76 | 77 | MEMORY_BASIC_INFORMATION mbi { 0 }; 78 | while (VirtualQuery(current, &mbi, sizeof(mbi)) && current < end) 79 | { 80 | constexpr DWORD any_execute = PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; 81 | if (mbi.State != MEM_COMMIT || !(mbi.Protect & any_execute)) 82 | { 83 | current += mbi.RegionSize; 84 | continue; 85 | } 86 | 87 | if (auto match = sed::pattern_scan(current, mbi.RegionSize, pattern, mask); match) 88 | return match; 89 | 90 | current += mbi.RegionSize; 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | auto sed::_impl_pattern_scan(const pattern_fragment * fragments, int count) -> void * 97 | { 98 | std::uint8_t * current = nullptr; 99 | 100 | MEMORY_BASIC_INFORMATION mbi { 0 }; 101 | while (VirtualQuery(current, &mbi, sizeof(mbi))) 102 | { 103 | constexpr DWORD any_execute = PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; 104 | if (mbi.State != MEM_COMMIT || !(mbi.Protect & any_execute)) 105 | { 106 | current += mbi.RegionSize; 107 | continue; 108 | } 109 | 110 | for (auto pscan = current, end = current + mbi.RegionSize - count; pscan < end; ++pscan) 111 | { 112 | for (int i = 0; i < count; ++i) 113 | { 114 | const auto & frag = fragments[i]; 115 | 116 | if (!frag.masked) 117 | continue; 118 | 119 | if (frag.byte != pscan[i]) 120 | break; 121 | 122 | if (i == count - 1) 123 | return pscan; 124 | } 125 | } 126 | 127 | current += mbi.RegionSize; 128 | } 129 | 130 | return nullptr; 131 | } -------------------------------------------------------------------------------- /framework/sed/memory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "windows/protect_guard.hpp" 11 | 12 | namespace sed 13 | { 14 | auto abs2rel32(void * from, std::size_t size, void * to) -> std::int32_t; 15 | auto rel2abs32(void * instruction, std::size_t size) -> std::uintptr_t; 16 | auto abs32(void * instruction, std::size_t size) -> std::uintptr_t; 17 | 18 | auto op1rel32_apply(std::uint8_t opcode, void * from, void * to) -> bool; 19 | auto jmprel32_apply(void * from, void * to) -> bool; 20 | auto callrel32_apply(void * from, void * to) -> bool; 21 | 22 | class mempatch_interface 23 | { 24 | public: 25 | virtual bool patch() = 0; 26 | virtual bool restore() = 0; 27 | virtual operator bool() const noexcept = 0; 28 | }; 29 | 30 | template 31 | class basic_mempatch_op1r32 : public mempatch_interface 32 | { 33 | public: 34 | basic_mempatch_op1r32(void * from, void * to) 35 | : from(from), to(to) {} 36 | 37 | bool patch() override 38 | { 39 | auto prot = sed::protect_guard(this->from, 0x5); 40 | if (!prot) 41 | return false; 42 | 43 | // backup 44 | std::memcpy(this->restore_buffer, this->from, 0x5); 45 | 46 | // patch 47 | std::uint8_t shell[] = { opcode, 0x00, 0x00, 0x00, 0x00 }; 48 | *reinterpret_cast(shell + 1) = sed::abs2rel32(this->from, sizeof(shell), this->to); 49 | std::memcpy(this->from, shell, sizeof(shell)); 50 | 51 | this->patched = true; 52 | return true; 53 | } 54 | 55 | bool restore() override 56 | { 57 | if (!this->patched) 58 | return true; 59 | 60 | auto prot = sed::protect_guard(this->from, 0x5); 61 | if (!prot) 62 | return false; 63 | 64 | std::memcpy(this->from, this->restore_buffer, 0x5); 65 | this->patched = false; 66 | return true; 67 | } 68 | 69 | operator bool() const noexcept override 70 | { 71 | return this->patched; 72 | } 73 | 74 | private: 75 | bool patched { false }; 76 | void * from { nullptr }, 77 | * to { nullptr }; 78 | 79 | std::uint8_t restore_buffer[5] { 0x00 }; 80 | }; 81 | 82 | using mempatch_jmpr32 = basic_mempatch_op1r32<0xE9>; 83 | using mempatch_callr32 = basic_mempatch_op1r32<0xE8>; 84 | 85 | [[deprecated("Use compile time IDA pattern scanner")]] auto pattern_scan(void * start_, std::size_t size, const char * pattern, const char * mask) -> std::uintptr_t; 86 | [[deprecated("Use compile time IDA pattern scanner")]] auto pattern_scan_exec_region(void * start_, std::size_t size, const char * pattern, const char * mask) -> std::uintptr_t; 87 | 88 | struct pattern_fragment 89 | { 90 | unsigned char byte; 91 | bool masked; 92 | }; 93 | 94 | template requires (len % 3 == 0) 95 | struct ida_pattern 96 | { 97 | consteval ida_pattern(const char (& pattern)[len]) 98 | { 99 | for (int i = 0; i < len / 3; ++i) 100 | { 101 | auto chunk = &pattern[i * 3]; 102 | 103 | auto char_to_nibble = [](const char c) -> unsigned char 104 | { 105 | if (c == '?') 106 | return 0; 107 | 108 | if (c >= '0' && c <= '9') 109 | return c - '0'; 110 | else if (c >= 'A' && c <= 'F') 111 | return c - 'A' + 0xA; 112 | else if (c >= 'a' && c <= 'f') 113 | return c - 'a' + 0xa; 114 | 115 | return 0; 116 | }; 117 | 118 | unsigned char byte = char_to_nibble(chunk[0]) << 4 | char_to_nibble(chunk[1]); 119 | 120 | fragments[i] = { 121 | .byte = byte, 122 | .masked = chunk[0] != '?' 123 | }; 124 | } 125 | } 126 | 127 | std::array fragments {}; 128 | }; 129 | 130 | // Implementation, do not use. 131 | auto _impl_pattern_scan(const pattern_fragment * fragments, int count) -> void *; 132 | 133 | template 134 | auto pattern_scan(/*vargs_t... offsets*/) -> T * 135 | { 136 | return reinterpret_cast(_impl_pattern_scan(pattern.fragments.data(), pattern.fragments.size())); 137 | } 138 | 139 | template 140 | class basic_ptrptr 141 | { 142 | public: 143 | auto operator*() -> data * 144 | { 145 | if (this->ptr && *this->ptr) 146 | return *this->ptr; 147 | 148 | return nullptr; 149 | } 150 | 151 | auto operator->() -> data * 152 | { 153 | if (this->ptr && *this->ptr) 154 | return *this->ptr; 155 | 156 | return &this->dummy; 157 | } 158 | 159 | operator bool() const noexcept 160 | { 161 | return this->ptr && *this->ptr != nullptr; 162 | } 163 | 164 | public: 165 | data ** ptr { nullptr }; 166 | data dummy { }; 167 | }; 168 | 169 | } -------------------------------------------------------------------------------- /framework/sed/strings.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace sed 6 | { 7 | template 8 | constexpr auto str_starts_with(const str1 * str, const str2 * with) -> const str1 * 9 | { 10 | if (!str || !*str || !with || !*with) 11 | return nullptr; 12 | 13 | while (*str == *with) 14 | { 15 | if (++str; !*++with) 16 | return str; 17 | } 18 | 19 | return nullptr; 20 | } 21 | 22 | template 23 | constexpr auto str_len(const T * str) -> std::size_t 24 | { 25 | std::size_t len = 0; 26 | while (str[len++]); 27 | return len - 1; 28 | } 29 | } -------------------------------------------------------------------------------- /framework/sed/windows/protect_guard.cpp: -------------------------------------------------------------------------------- 1 | #include "protect_guard.hpp" 2 | 3 | sed::protect_guard::protect_guard(void * address, std::size_t size, DWORD prot_flags) 4 | // : address(address), size(size) 5 | { 6 | if (!VirtualProtect(address, size, prot_flags, &this->oprot)) 7 | return; 8 | 9 | this->address = address; 10 | this->size = size; 11 | } 12 | 13 | sed::protect_guard::~protect_guard() 14 | { 15 | if (!*this || !VirtualProtect(this->address, this->size, this->oprot, &this->oprot)) 16 | return; 17 | 18 | this->address = nullptr; 19 | this->size = 0; 20 | } 21 | 22 | sed::protect_guard::operator bool() const noexcept 23 | { 24 | return this->address && this->size; 25 | } 26 | -------------------------------------------------------------------------------- /framework/sed/windows/protect_guard.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace sed 6 | { 7 | class protect_guard 8 | { 9 | protect_guard(protect_guard &&) = delete; 10 | protect_guard(const protect_guard &&) = delete; 11 | protect_guard(protect_guard &) = delete; 12 | protect_guard(const protect_guard &) = delete; 13 | 14 | public: 15 | protect_guard(void * address, std::size_t size, DWORD prot_flags = PAGE_EXECUTE_READWRITE); 16 | ~protect_guard(); 17 | 18 | operator bool() const noexcept; 19 | 20 | private: 21 | void * address; 22 | std::size_t size; 23 | DWORD oprot; 24 | }; 25 | } -------------------------------------------------------------------------------- /framework/sed/windows/smart_handle.cpp: -------------------------------------------------------------------------------- 1 | #include "smart_handle.hpp" 2 | 3 | #include 4 | 5 | sed::smart_handle::smart_handle(HANDLE hnd_) 6 | : hnd(hnd_) {} 7 | 8 | sed::smart_handle::~smart_handle() 9 | { 10 | if (this->hnd) 11 | CloseHandle(this->hnd); 12 | 13 | this->hnd = nullptr; 14 | } 15 | 16 | sed::smart_handle::smart_handle(smart_handle && other) 17 | { 18 | *this = std::move(other); 19 | } 20 | 21 | sed::smart_handle & sed::smart_handle::operator =(sed::smart_handle && rhs) 22 | { 23 | if (this->hnd) 24 | CloseHandle(this->hnd); 25 | 26 | this->hnd = rhs.hnd; 27 | rhs.hnd = nullptr; 28 | 29 | return *this; 30 | } 31 | 32 | sed::smart_handle::operator HANDLE() const noexcept 33 | { 34 | return this->hnd; 35 | } 36 | 37 | sed::smart_handle::operator bool() const noexcept 38 | { 39 | return this->hnd != nullptr; 40 | } 41 | -------------------------------------------------------------------------------- /framework/sed/windows/smart_handle.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace sed 6 | { 7 | class smart_handle 8 | { 9 | public: 10 | // Disable copying 11 | smart_handle(smart_handle &) = delete; 12 | smart_handle(const smart_handle &) = delete; 13 | 14 | smart_handle() = default; 15 | smart_handle(HANDLE hnd_); 16 | ~smart_handle(); 17 | 18 | smart_handle(smart_handle && other); 19 | smart_handle & operator =(smart_handle && rhs); 20 | 21 | operator HANDLE() const noexcept; 22 | operator bool() const noexcept; 23 | private: 24 | HANDLE hnd = nullptr; 25 | }; 26 | } -------------------------------------------------------------------------------- /framework/sed/windows/suspend_guard.cpp: -------------------------------------------------------------------------------- 1 | #include "suspend_guard.hpp" 2 | 3 | #include 4 | 5 | sed::suspend_guard::suspend_guard(DWORD id_) 6 | { 7 | if (!id_) 8 | return; 9 | 10 | this->thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, id_); 11 | if (!this->thread_handle) 12 | return; 13 | 14 | if (SuspendThread(this->thread_handle) == static_cast(-1)) 15 | { 16 | this->thread_handle = nullptr; 17 | return; 18 | } 19 | 20 | this->id = id_; 21 | } 22 | 23 | sed::suspend_guard::~suspend_guard() 24 | { 25 | if (this->thread_handle) 26 | ResumeThread(this->thread_handle); 27 | 28 | this->id = 0; 29 | this->thread_handle = nullptr; 30 | } 31 | 32 | sed::suspend_guard::suspend_guard(suspend_guard && other) 33 | { 34 | *this = std::move(other); 35 | } 36 | 37 | sed::suspend_guard & sed::suspend_guard::operator=(suspend_guard && rhs) 38 | { 39 | if (this->thread_handle) 40 | ResumeThread(this->thread_handle); 41 | 42 | this->id = rhs.id; 43 | this->thread_handle = std::move(rhs.thread_handle); 44 | 45 | rhs.id = 0; 46 | rhs.thread_handle = nullptr; 47 | 48 | return *this; 49 | } 50 | 51 | sed::suspend_guard::operator bool() const noexcept 52 | { 53 | return this->id && this->thread_handle; 54 | } 55 | 56 | sed::suspend_guard::operator HANDLE() const noexcept 57 | { 58 | return this->thread_handle; 59 | } 60 | 61 | bool sed::suspend_guard::suspend() 62 | { 63 | return this->thread_handle && SuspendThread(this->thread_handle) != static_cast(-1); 64 | } 65 | 66 | bool sed::suspend_guard::resume() 67 | { 68 | return this->thread_handle && ResumeThread(this->thread_handle) != static_cast(-1); 69 | } 70 | 71 | DWORD sed::suspend_guard::get_id() 72 | { 73 | return this->id; 74 | } -------------------------------------------------------------------------------- /framework/sed/windows/suspend_guard.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "smart_handle.hpp" 5 | 6 | namespace sed 7 | { 8 | class suspend_guard 9 | { 10 | public: 11 | suspend_guard(suspend_guard &) = delete; 12 | suspend_guard(const suspend_guard &) = delete; 13 | 14 | suspend_guard() = default; 15 | suspend_guard(DWORD id_); 16 | ~suspend_guard(); 17 | 18 | suspend_guard(suspend_guard && other); 19 | suspend_guard & operator=(suspend_guard && rhs); 20 | operator bool() const noexcept; 21 | operator HANDLE() const noexcept; 22 | 23 | bool suspend(); 24 | bool resume(); 25 | 26 | DWORD get_id(); 27 | 28 | private: 29 | sed::smart_handle thread_handle { nullptr }; 30 | DWORD id { 0 }; 31 | }; 32 | } -------------------------------------------------------------------------------- /osu-cheese-client/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | 3 | project(osu-cheese-client) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | add_library(${PROJECT_NAME} SHARED 9 | "client_main.cpp" 10 | "hooks.hpp" 11 | "hooks.cpp" 12 | "game.hpp" 13 | "game.cpp" 14 | "sdk/info_struct.hpp" 15 | "sdk/info_player.hpp" 16 | "sdk/osu_vec.hpp" 17 | "sdk/osu_vec.cpp" 18 | "manager/gamefield_manager.hpp" 19 | "manager/gamefield_manager.cpp" 20 | "menu.hpp" 21 | "menu.cpp" 22 | "features/aim_assist.hpp" 23 | "features/aim_assist.cpp" 24 | "features/relax.hpp" 25 | "features/relax.cpp" 26 | "features/esp.hpp" 27 | "features/esp.cpp" 28 | "features/features.hpp" 29 | "sdk/position_info.hpp" 30 | "sdk/raw_info.hpp" 31 | "sdk/wnd_info.hpp" 32 | "oc_client.hpp" 33 | "oc_client.cpp" 34 | "sdk/player_keys.hpp" 35 | "sdk/hitobject.hpp" 36 | "sdk/hitobject.cpp" 37 | ) 38 | 39 | set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) 40 | 41 | target_link_libraries(${PROJECT_NAME} PRIVATE 42 | osu-cheese-framework 43 | imgui 44 | gl3w 45 | dncomlib 46 | ) 47 | 48 | target_include_directories(${PROJECT_NAME} PRIVATE 49 | ${osu-cheese-framework-includes} 50 | ${imgui-includes} 51 | ${gl3w-includes} 52 | ) 53 | -------------------------------------------------------------------------------- /osu-cheese-client/client_main.cpp: -------------------------------------------------------------------------------- 1 | // Main entry point of the client 2 | 3 | #include 4 | #include 5 | #include "oc_client.hpp" 6 | 7 | auto WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID res0) -> BOOL 8 | { 9 | if (reason == DLL_PROCESS_ATTACH) sed::smart_handle(CreateThread(nullptr, NULL, [](LPVOID inst) -> DWORD 10 | { 11 | if (!oc::load()) 12 | FreeLibraryAndExitThread(HMODULE(inst), 0); 13 | 14 | return 0; 15 | 16 | }, inst, NULL, nullptr)); 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /osu-cheese-client/features/aim_assist.cpp: -------------------------------------------------------------------------------- 1 | #include "aim_assist.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "../game.hpp" 7 | #include "../sdk/osu_vec.hpp" 8 | 9 | #include "../manager/gamefield_manager.hpp" 10 | 11 | #include 12 | 13 | auto features::aim_assist::on_tab_render() -> void 14 | { 15 | if (!ImGui::BeginTabItem("Aim assist")) 16 | return; 17 | 18 | ImGui::Checkbox("Aim assist", &enable); 19 | OC_IMGUI_HOVER_TXT("Enable aim assistance - Corrects your aim to the neareast hit object when moving your cursor."); 20 | 21 | ImGui::Checkbox("Silent", &silent); 22 | OC_IMGUI_HOVER_TXT("\"Server\" side only visible aim assist."); 23 | 24 | ImGui::SliderFloat("FOV", &fov, 0.f, 800.f); 25 | OC_IMGUI_HOVER_TXT("Distance between your cursor and the hit object required before aim assistance activates. (0 = Global)"); 26 | 27 | ImGui::SliderFloat("Direction FOV", &dir_fov, 0.f, 180.f); 28 | OC_IMGUI_HOVER_TXT("Directional angle field of view for aim assist to activate. (0 = full 360)"); 29 | 30 | ImGui::SliderFloat("Safezone FOV", &safezone, 0.f, 800.f); 31 | OC_IMGUI_HOVER_TXT("Disables the aim assist when the player cursor is within the safezone. (0 = Never)"); 32 | 33 | ImGui::SliderFloat("Assist Scale", &scaleassist, 0.f, 2.f); 34 | OC_IMGUI_HOVER_TXT("Scales the aim assist amount."); 35 | 36 | ImGui::SliderFloat("Target time offset ratio", &timeoffsetratio, 0.f, 1.f); 37 | OC_IMGUI_HOVER_TXT("Amount of time ahead on recognizing a hit object as active."); 38 | 39 | ImGui::Combo("Assist movement method", reinterpret_cast(&method), "Linear\0Directional Curve\0"); 40 | 41 | switch (method) 42 | { 43 | case features::aim_assist::method_e::DIRECTIONAL_CURVE: 44 | { 45 | ImGui::SliderFloat("Player to Hit object ratio", &mdc_ho_ratio, 0.f, 1.f); 46 | OC_IMGUI_HOVER_TXT("Ratio to take in account from the player to the hit object when calculating the curve used for the aim assist."); 47 | 48 | ImGui::SliderFloat("Player to direction ratio", &mdc_pdir_ratio, 0.f, 1.f); 49 | OC_IMGUI_HOVER_TXT("Ratio to take in account from the player to the forward direction when calculating the curve used for the aim assist."); 50 | 51 | ImGui::SliderFloat("Midpoint ratio", &mdc_midpoint_ratio, 0.f, 1.f); 52 | OC_IMGUI_HOVER_TXT("Ratio to calculate the mid point for the curve of the aim assist."); 53 | 54 | ImGui::Combo("Follow method", reinterpret_cast(&mdc_method), "Hit object to Player direction\0Player direction to Hit object\0Dynamic (Auto)\0"); 55 | OC_IMGUI_HOVER_TXT("Starting point of where to calculate the midpoint ratio from."); 56 | 57 | break; 58 | } 59 | 60 | default: 61 | break; 62 | } 63 | 64 | ImGui::Separator(); 65 | 66 | ImGui::Checkbox("Visualize Aim FOV", &vis_fov); 67 | ImGui::Checkbox("Visualize Safezone FOV", &vis_safezonefov); 68 | 69 | ImGui::EndTabItem(); 70 | } 71 | 72 | auto features::aim_assist::on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void* reserved) -> bool 73 | { 74 | return false; 75 | } 76 | 77 | auto features::aim_assist::on_render() -> void 78 | { 79 | if (!enable || !game::pp_phitobject || !game::pp_info_player->async_complete || game::pp_info_player->is_replay_mode) 80 | return; 81 | 82 | auto draw = ImGui::GetBackgroundDrawList(); 83 | 84 | if (vis_fov) 85 | draw->AddCircle(game::pp_viewpos_info->pos, fov, 0xFFFFFFFF); 86 | 87 | auto [ho, i] = game::pp_phitobject.get_coming_hitobject(game::p_game_info->beat_time); 88 | 89 | if (!ho) 90 | return; 91 | 92 | if (vis_safezonefov) 93 | draw->AddCircle(ho->position.field_to_view(), safezone, 0xFFFFFFFF); 94 | } 95 | 96 | auto features::aim_assist::on_osu_set_raw_coords(sdk::vec2* raw_coords) -> void 97 | { 98 | if (auto _velocity = last_tick_point.distance(*raw_coords); _velocity != 0.f) 99 | { 100 | velocity = _velocity; 101 | player_direction = last_tick_point.normalize_towards(*raw_coords); 102 | last_tick_point = *raw_coords; 103 | } 104 | 105 | if (!enable || !game::pp_phitobject || !game::pp_info_player->async_complete || game::pp_info_player->is_replay_mode || !game::p_game_info->is_playing) 106 | return; 107 | 108 | auto [ho, i] = game::pp_phitobject.get_coming_hitobject(game::p_game_info->beat_time); 109 | 110 | if (!ho) return; 111 | 112 | // Check time offset 113 | if (timeoffsetratio != 0.f && i != 0) 114 | { 115 | auto prev = ho - 1; 116 | 117 | auto time_sub = ho->time.start - ((ho->time.start - prev->time.end) * (1.f - timeoffsetratio)); 118 | 119 | if (game::p_game_info->beat_time < time_sub) 120 | return; 121 | } 122 | 123 | auto player_field_pos = game::pp_viewpos_info->pos.view_to_field(); 124 | auto dist_to_ho = player_field_pos.distance(ho->position); 125 | 126 | // Check fov 127 | if (fov != 0.f && dist_to_ho > fov) 128 | return; 129 | 130 | // Check direction 131 | if (dir_fov != 0.f && player_direction.vec2vec_angle(player_field_pos.normalize_towards(ho->position)) > dir_fov) 132 | return; 133 | 134 | // Check if we're at the same point 135 | if (player_field_pos == ho->position) 136 | return; 137 | 138 | // Safezone override 139 | if (safezone != 0.f && dist_to_ho <= safezone) 140 | return; 141 | 142 | sdk::vec2 new_coords, target /* temporary for optimization, might be irrelevant in the future */; 143 | 144 | switch (method) 145 | { 146 | case method_e::LINEAR: 147 | { 148 | target = ho->position; 149 | break; 150 | } 151 | 152 | case method_e::DIRECTIONAL_CURVE: 153 | { 154 | auto p2ho_p = player_field_pos.forward_towards(ho->position, dist_to_ho * mdc_ho_ratio); 155 | auto p2dir_p = player_field_pos.forward(player_direction, dist_to_ho * mdc_pdir_ratio); 156 | 157 | sdk::vec2 start, end; 158 | 159 | switch (mdc_method) 160 | { 161 | case mdc_mpoint_method_e::HO_TO_PDIR: 162 | { 163 | start = p2ho_p; 164 | end = p2dir_p; 165 | break; 166 | } 167 | 168 | case mdc_mpoint_method_e::DYNAMIC: // TODO: implement this 169 | case mdc_mpoint_method_e::PDIR_TO_HO: 170 | { 171 | start = p2dir_p; 172 | end = p2ho_p; 173 | break; 174 | } 175 | 176 | default: 177 | break; 178 | } 179 | 180 | target = start.forward_towards(end, start.distance(end) * mdc_midpoint_ratio); 181 | break; 182 | } 183 | 184 | default: 185 | return; 186 | } 187 | 188 | new_coords = player_field_pos.forward_towards(target, std::clamp(velocity * scaleassist, 0.f, dist_to_ho)).field_to_view(); 189 | last_tick_point = new_coords; // update last tick point to our new coordinates since the new coords will now be our current point for the tick this also prevents over calculating the velocity 190 | *raw_coords = new_coords; // update the ingame coordinates 191 | 192 | if (!game::pp_raw_mode_info->is_raw) 193 | { 194 | POINT pscr = new_coords; 195 | ClientToScreen(game::hwnd, &pscr); 196 | SetCursorPos(pscr.x, pscr.y); 197 | } 198 | 199 | return; 200 | } 201 | 202 | auto features::aim_assist::osu_set_field_coords_rebuilt(sdk::vec2* out_coords) -> void 203 | { 204 | } 205 | 206 | auto features::aim_assist::run_aim_assist() -> void 207 | { 208 | } 209 | -------------------------------------------------------------------------------- /osu-cheese-client/features/aim_assist.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../sdk/osu_vec.hpp" 5 | 6 | namespace features 7 | { 8 | class aim_assist 9 | { 10 | enum class method_e : int 11 | { 12 | LINEAR, 13 | DIRECTIONAL_CURVE 14 | }; 15 | 16 | enum class mdc_mpoint_method_e : int 17 | { 18 | HO_TO_PDIR, 19 | PDIR_TO_HO, 20 | DYNAMIC 21 | }; 22 | 23 | // Generic settings 24 | inline static method_e method = method_e::LINEAR; 25 | inline static bool enable = false; 26 | inline static bool silent = false; 27 | inline static float fov = 0.f; 28 | inline static float dir_fov = 20.f; 29 | inline static float safezone = 20.f; 30 | inline static float scaleassist = 1.f; 31 | inline static float timeoffsetratio = 0.8f; 32 | 33 | // Visuals settings 34 | inline static bool vis_fov = false; 35 | inline static bool vis_safezonefov = false; 36 | 37 | // Directional curve settings 38 | inline static float mdc_ho_ratio = 0.5f; 39 | inline static float mdc_pdir_ratio = 0.5f; // player direction 40 | inline static float mdc_midpoint_ratio = 0.1f; 41 | inline static mdc_mpoint_method_e mdc_method = mdc_mpoint_method_e::PDIR_TO_HO; 42 | 43 | // Internal calculations and tracking 44 | inline static sdk::vec2 last_tick_point {}; 45 | inline static sdk::vec2 player_direction {}; 46 | inline static float velocity { 0.f }; 47 | 48 | public: 49 | aim_assist() = delete; 50 | static auto on_tab_render() -> void; 51 | static auto on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void * reserved) -> bool; 52 | static auto on_render() -> void; 53 | static auto on_osu_set_raw_coords(sdk::vec2 * raw_coords) -> void; 54 | static auto osu_set_field_coords_rebuilt(sdk::vec2 * out_coords) -> void; 55 | 56 | private: 57 | static auto run_aim_assist() -> void; 58 | }; 59 | } -------------------------------------------------------------------------------- /osu-cheese-client/features/esp.cpp: -------------------------------------------------------------------------------- 1 | #include "esp.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "../game.hpp" 7 | #include 8 | 9 | auto features::esp::on_tab_render() -> void 10 | { 11 | if (!ImGui::BeginTabItem("ESP")) 12 | return; 13 | 14 | ImGui::Checkbox("Hit object timer", &timer); 15 | OC_IMGUI_HOVER_TXT("Shows a countdown timer towards the next hit object."); 16 | ImGui::Checkbox("Hit object distance", &distance); 17 | OC_IMGUI_HOVER_TXT("Shows the distance between the player cursor and the next hit object (also your current FOV value)."); 18 | ImGui::Checkbox("Hit object tracer", &tracer); 19 | OC_IMGUI_HOVER_TXT("Draws a line from the players cursor to the next hit object."); 20 | 21 | ImGui::EndTabItem(); 22 | } 23 | 24 | auto features::esp::on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void * reserved) -> bool 25 | { 26 | return false; 27 | } 28 | 29 | auto features::esp::on_render() -> void 30 | { 31 | if (!game::pp_info_player->async_complete || !game::pp_phitobject || game::pp_info_player->is_replay_mode || !game::p_game_info->is_playing) 32 | return; 33 | 34 | auto [ho, i] = game::pp_phitobject.get_coming_hitobject(game::p_game_info->beat_time); 35 | 36 | if (!ho) 37 | return; 38 | 39 | auto draw = ImGui::GetBackgroundDrawList(); 40 | 41 | std::string esp_text{}; 42 | 43 | if (timer) 44 | esp_text.append("TIME: " + std::to_string(ho->time.start - game::p_game_info->beat_time) + "\n"); 45 | 46 | if (distance) 47 | esp_text.append("DST: " + std::to_string(ho->position.distance(game::pp_viewpos_info->pos.view_to_field())) + "\n"); 48 | 49 | if (tracer) 50 | draw->AddLine(game::pp_viewpos_info->pos, ho->position.field_to_view(), 0xFFFFFFFF); 51 | 52 | if (!esp_text.empty()) 53 | draw->AddText(ho->position.field_to_view(), 0xFFFFFFFF, esp_text.c_str()); 54 | } 55 | 56 | auto features::esp::on_osu_set_raw_coords(sdk::vec2 * raw_coords) -> void 57 | { 58 | } 59 | 60 | auto features::esp::osu_set_field_coords_rebuilt(sdk::vec2 * out_coords) -> void 61 | { 62 | } 63 | -------------------------------------------------------------------------------- /osu-cheese-client/features/esp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../sdk/osu_vec.hpp" 5 | 6 | namespace features 7 | { 8 | class esp 9 | { 10 | inline static bool timer = false; 11 | inline static bool tracer = false; 12 | inline static bool distance = false; 13 | 14 | public: 15 | esp() = delete; 16 | 17 | static auto on_tab_render() -> void; 18 | static auto on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void * reserved) -> bool; 19 | static auto on_render() -> void; 20 | static auto on_osu_set_raw_coords(sdk::vec2 * raw_coords) -> void; 21 | static auto osu_set_field_coords_rebuilt(sdk::vec2 * out_coords) -> void; 22 | }; 23 | } -------------------------------------------------------------------------------- /osu-cheese-client/features/features.hpp: -------------------------------------------------------------------------------- 1 | #include "aim_assist.hpp" 2 | #include "relax.hpp" 3 | #include "esp.hpp" 4 | 5 | namespace features 6 | { 7 | template 8 | struct _features_dispatch_pack 9 | { 10 | static auto on_tab_render() -> void 11 | { 12 | (fts::on_tab_render(), ...); 13 | } 14 | 15 | static auto on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void * reserved) -> bool 16 | { 17 | return (fts::on_wndproc(hWnd, Msg, wParam, lParam, reserved) || ...); 18 | } 19 | 20 | static auto on_render() -> void 21 | { 22 | (fts::on_render(), ...); 23 | } 24 | 25 | static auto on_osu_set_raw_coords(sdk::vec2 * raw_coords) -> void 26 | { 27 | (fts::on_osu_set_raw_coords(raw_coords), ...); 28 | } 29 | 30 | static auto osu_set_field_coords_rebuilt(sdk::vec2 * out_coords) -> void 31 | { 32 | (fts::osu_set_field_coords_rebuilt(out_coords), ...); 33 | } 34 | }; 35 | 36 | using dispatcher = _features_dispatch_pack< 37 | aim_assist, 38 | relax, 39 | esp 40 | >; 41 | } -------------------------------------------------------------------------------- /osu-cheese-client/features/relax.cpp: -------------------------------------------------------------------------------- 1 | #include "relax.hpp" 2 | 3 | #include 4 | 5 | #include 6 | #include "../sdk/osu_vec.hpp" 7 | #include "../game.hpp" 8 | 9 | auto features::relax::on_tab_render() -> void 10 | { 11 | if (!ImGui::BeginTabItem("Relax")) 12 | return; 13 | 14 | ImGui::Checkbox("Relax", &enable); 15 | OC_IMGUI_HOVER_TXT("Auto click hit objects."); 16 | ImGui::SliderFloat("Edge field", &edge, 0.f, 300.f); 17 | OC_IMGUI_HOVER_TXT("Edge field area where relax is enabled. (0 = Global)"); 18 | ImGui::SliderInt("Timing offset", &offset, -10000, 10000); 19 | OC_IMGUI_HOVER_TXT("Hit timing offset from the hit object's time."); 20 | ImGui::Checkbox("Randomize timing offset", &offsetrand); 21 | OC_IMGUI_HOVER_TXT("Randomizes the timing offset and uses the current timing offset as the range."); 22 | 23 | ImGui::EndTabItem(); 24 | } 25 | 26 | auto features::relax::on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void * reserved) -> bool 27 | { 28 | static const void * filter_ho = nullptr; 29 | 30 | if (Msg != WM_MOUSEMOVE || !enable || !game::pp_phitobject || !game::pp_info_player->async_complete || game::pp_info_player->is_replay_mode || !game::p_game_info->is_playing) 31 | return false; 32 | 33 | auto [ho, i] = game::pp_phitobject.get_coming_hitobject(game::p_game_info->beat_time); 34 | 35 | if (!ho) 36 | return false; 37 | 38 | if (offset >= 0) 39 | --ho; 40 | 41 | if (ho->time.start + offset <= game::p_game_info->beat_time || ho == filter_ho) 42 | return false; 43 | 44 | filter_ho = ho; 45 | 46 | INPUT inp[2] { 0 }; 47 | 48 | inp[0].type = INPUT_KEYBOARD; 49 | inp[0].ki.wVk = game::pp_pplayer_keys->ppk->osu.left_click.vkey; 50 | 51 | inp[1].type = INPUT_KEYBOARD; 52 | inp[1].ki.dwFlags = KEYEVENTF_KEYUP; 53 | inp[1].ki.wVk = game::pp_pplayer_keys->ppk->osu.left_click.vkey; 54 | 55 | SendInput(2, inp, sizeof(INPUT)); 56 | 57 | return false; 58 | } 59 | 60 | auto features::relax::on_render() -> void 61 | {} 62 | 63 | auto features::relax::on_osu_set_raw_coords(sdk::vec2 * raw_coords) -> void 64 | {} 65 | 66 | auto features::relax::osu_set_field_coords_rebuilt(sdk::vec2 * out_coords) -> void 67 | {} 68 | -------------------------------------------------------------------------------- /osu-cheese-client/features/relax.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../sdk/osu_vec.hpp" 5 | 6 | namespace features 7 | { 8 | class relax 9 | { 10 | inline static bool enable = false; 11 | inline static float edge = 80.f; 12 | inline static int offset = -50; 13 | inline static bool offsetrand = false; 14 | 15 | public: 16 | relax() = delete; 17 | static auto on_tab_render() -> void; 18 | static auto on_wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, void * reserved) -> bool; 19 | static auto on_render() -> void; 20 | static auto on_osu_set_raw_coords(sdk::vec2 * raw_coords) -> void; 21 | static auto osu_set_field_coords_rebuilt(sdk::vec2 * out_coords) -> void; 22 | }; 23 | } -------------------------------------------------------------------------------- /osu-cheese-client/game.cpp: -------------------------------------------------------------------------------- 1 | #include "game.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | static auto pattern_scan_helper(const char * name, T & out, int sz32 = 0, bool is_abs = true) -> bool 9 | { 10 | DEBUG_PRINTF("\n[+] Searching for %s...", name); 11 | auto res = sed::pattern_scan(); 12 | DEBUG_PRINTF(" 0x%p", res); 13 | 14 | if (!res) 15 | return false; 16 | 17 | out = reinterpret_cast(res); 18 | 19 | if (sz32) 20 | { 21 | out = reinterpret_cast(is_abs ? sed::abs32(out, sz32) : sed::rel2abs32(out, sz32)); 22 | 23 | DEBUG_PRINTF(" -> 0x%p", out); 24 | } 25 | 26 | return true; 27 | } 28 | 29 | auto game::initialize() -> bool 30 | { 31 | DEBUG_PRINTF("\n[+] Loading game information..." 32 | "\n[+] Obtaining handle to window..."); 33 | 34 | while (!game::hwnd) 35 | { 36 | EnumWindows([](HWND hwnd, LPARAM lparam) -> BOOL 37 | { 38 | DWORD pid { 0 }; 39 | GetWindowThreadProcessId(hwnd, &pid); 40 | wchar_t text_buffer[MAX_PATH] { 0 }; 41 | constexpr auto text_buffer_sz = ARRAYSIZE(text_buffer); 42 | 43 | if (pid != GetCurrentProcessId() 44 | || !GetWindowTextW(hwnd, text_buffer, text_buffer_sz) 45 | || !sed::str_starts_with(text_buffer, L"osu!") 46 | || !RealGetWindowClassW(hwnd, text_buffer, text_buffer_sz) 47 | || sed::str_starts_with(text_buffer, L"Console") 48 | ) { 49 | return TRUE; 50 | } 51 | 52 | game::hwnd = hwnd; 53 | return FALSE; 54 | }, NULL); 55 | 56 | Sleep(800); 57 | } 58 | 59 | DEBUG_WPRINTF(L"0x%p", game::hwnd); 60 | 61 | if (!pattern_scan_helper<"DB 05 ?? ?? ?? ?? D9 5D F8"> (DEBUG_OPT_NULL("game::p_game_info"), game::p_game_info, 0x6) 62 | || !pattern_scan_helper<"8b 05 ?? ?? ?? ?? d9 40 ?? 8b 15"> (DEBUG_OPT_NULL("game::pp_viewpos_info"), game::pp_viewpos_info.ptr, 0x6) 63 | || !pattern_scan_helper<"FF 50 0C 8B D8 8B 15"> (DEBUG_OPT_NULL("game::pp_info_player"), game::pp_info_player.ptr, 0xB) 64 | || !pattern_scan_helper<"8b ec 83 ec ?? a1 ?? ?? ?? ?? 85 c0 74"> (DEBUG_OPT_NULL("game::pp_raw_mode_info"), game::pp_raw_mode_info.ptr, 0xA) 65 | || !pattern_scan_helper<"8b 0d ?? ?? ?? ?? 8b 55 ?? 39 09 ff 15 ?? ?? ?? ?? 85 c0 74"> (DEBUG_OPT_NULL("game::pp_pplayer_keys"), game::pp_pplayer_keys.ptr, 0x6) 66 | || !pattern_scan_helper<"8B 0D ?? ?? ?? ?? 85 C9 75 ?? B8 ?? ?? ?? ?? EB ?? 8B 01 8B 40 ?? FF 50"> (DEBUG_OPT_NULL("game::pp_phitobject"), game::pp_phitobject.ptr, 0x6) 67 | ) { 68 | return false; 69 | } 70 | 71 | return true; 72 | } 73 | -------------------------------------------------------------------------------- /osu-cheese-client/game.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Used for interfacing with the game's internals 4 | 5 | #include "sdk/info_player.hpp" 6 | #include "sdk/info_struct.hpp" 7 | #include "sdk/position_info.hpp" 8 | #include "sdk/raw_info.hpp" 9 | #include "sdk/wnd_info.hpp" 10 | #include "sdk/player_keys.hpp" 11 | #include "sdk/hitobject.hpp" 12 | 13 | namespace game 14 | { 15 | inline sdk::pp_info_player_t pp_info_player; 16 | inline sdk::pp_viewpos_info_t pp_viewpos_info; 17 | inline sdk::unk_game_info_a * p_game_info { nullptr }; 18 | inline sdk::pp_raw_mode_info_t pp_raw_mode_info; 19 | inline sdk::pp_pplayer_keys_t pp_pplayer_keys; 20 | inline sdk::pp_phitobject_t pp_phitobject; 21 | inline HWND hwnd; 22 | 23 | auto initialize() -> bool; 24 | } -------------------------------------------------------------------------------- /osu-cheese-client/hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "hooks.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "manager/gamefield_manager.hpp" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "game.hpp" 15 | #include "menu.hpp" 16 | #include "features/features.hpp" 17 | 18 | enum class CallWindowProc_variant : int 19 | { 20 | A = 0, 21 | MOUSE = A, 22 | W = 1, 23 | KEY = W 24 | }; 25 | 26 | static auto CALLBACK CallWindowProc_hook(CallWindowProc_variant variant, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -> bool 27 | { 28 | if (oc::menu::wndproc(hWnd, Msg, wParam, lParam)) 29 | return true; 30 | 31 | if (variant == CallWindowProc_variant::MOUSE) 32 | { 33 | if (features::dispatcher::on_wndproc(hWnd, Msg, wParam, lParam, nullptr)) 34 | return true; 35 | } 36 | 37 | return false; 38 | } 39 | 40 | static decltype(CallWindowProcA)* CallWindowProcA_target = CallWindowProcA; 41 | static decltype(CallWindowProcW)* CallWindowProcW_target = CallWindowProcW; 42 | 43 | static auto [[naked]] CallWindowProc_proxy(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -> LRESULT 44 | { 45 | __asm 46 | { 47 | push ebp 48 | mov ebp, esp 49 | push eax 50 | push[ebp + 24] 51 | push[ebp + 20] 52 | push[ebp + 16] 53 | push[ebp + 12] 54 | push eax 55 | call CallWindowProc_hook; 56 | test al, al 57 | jnz LBL_CWP_SKIP_ORIGINAL 58 | pop eax 59 | test al, al 60 | jnz LBL_CWP_VARIANT_A 61 | 62 | LBL_CWP_VARIANT_W : 63 | mov eax, CallWindowProcA_target 64 | jmp LBL_CWP_CALL_ORIGINAL 65 | 66 | // Call A variant 67 | LBL_CWP_VARIANT_A : 68 | mov eax, CallWindowProcW_target 69 | jmp LBL_CWP_CALL_ORIGINAL 70 | 71 | // Call original 72 | LBL_CWP_SKIP_ORIGINAL : 73 | pop eax 74 | pop ebp 75 | mov eax, 1 76 | ret 0x14 77 | 78 | LBL_CWP_CALL_ORIGINAL : 79 | lea eax, [eax + 5] 80 | jmp eax 81 | } 82 | } 83 | 84 | static auto [[naked]] CallWindowProcW_proxy(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -> LRESULT 85 | { 86 | __asm 87 | { 88 | mov eax, 1 89 | jmp CallWindowProc_proxy 90 | }; 91 | } 92 | 93 | static auto [[naked]] CallWindowProcA_proxy(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -> LRESULT 94 | { 95 | __asm 96 | { 97 | mov eax, 0 // can just be xor eax, eax but this looks more verbose... 98 | jmp CallWindowProc_proxy 99 | }; 100 | } 101 | 102 | static auto WINAPI gdi32full_SwapBuffers_hook(HDC hdc) -> void 103 | { 104 | if (static bool init = true; init) 105 | { 106 | //HGLRC ctx = wglCreateContext(hdc); 107 | gl3wInit(); 108 | ImGui::CreateContext(); 109 | ImGui::StyleColorsDark(); 110 | ImGui::GetIO().IniFilename = nullptr; 111 | ImGui_ImplWin32_Init(WindowFromDC(hdc)); 112 | ImGui_ImplOpenGL3_Init(); 113 | init = false; 114 | } 115 | 116 | ImGui_ImplOpenGL3_NewFrame(); 117 | ImGui_ImplWin32_NewFrame(); 118 | ImGui::NewFrame(); 119 | 120 | features::dispatcher::on_render(); 121 | oc::menu::render(); 122 | 123 | ImGui::Render(); 124 | ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); 125 | } 126 | 127 | static decltype(SwapBuffers)* gdi32full_SwapBuffers_target{ nullptr }; 128 | 129 | static auto [[naked]] gdi32full_SwapBuffers_proxy(HDC hdc) -> BOOL 130 | { 131 | __asm 132 | { 133 | push ebp 134 | mov ebp, esp 135 | 136 | push[ebp + 8] 137 | call gdi32full_SwapBuffers_hook 138 | 139 | mov eax, gdi32full_SwapBuffers_target 140 | lea eax, [eax + 5] 141 | jmp eax 142 | } 143 | } 144 | 145 | // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 146 | 147 | static auto WINAPI SetWindowTextW_hook(HWND hWnd, LPCWSTR lpString) -> void 148 | { 149 | if (!sed::str_starts_with(lpString, L"osu!")) 150 | return; 151 | 152 | // TODO: dynamically load these values, we already have the sig stop being lazy. 153 | RECT wr{}; 154 | GetClientRect(hWnd, &wr); 155 | 156 | manager::game_field::resize(wr.right, wr.bottom); 157 | } 158 | 159 | static decltype(SetWindowTextW)* SetWindowTextW_target = SetWindowTextW; 160 | 161 | static auto [[naked]] SetWindowTextW_proxy(HWND hWnd, LPCWSTR lpString) -> BOOL 162 | { 163 | __asm 164 | { 165 | push ebp 166 | mov ebp, esp 167 | 168 | push[ebp + 12] 169 | push[ebp + 8] 170 | call SetWindowTextW_hook 171 | 172 | mov eax, SetWindowTextW_target // we cant do load effective address because clang (msvc?) does some funny 173 | lea eax, [eax + 5] // things like using the ecx register causing the ctx to get corrupted 174 | jmp eax 175 | } 176 | } 177 | 178 | // Name: #=zP4nKUSUPOssQxNF6$g==::#=z9UGmDcmwjvbl 179 | 180 | static auto __fastcall osu_set_field_coords_rebuilt(void* ecx, sdk::vec2* out_coords) -> void 181 | { 182 | // Can do psilent here by setting the field coordinates 183 | *out_coords = game::pp_viewpos_info->pos.view_to_field(); 184 | features::dispatcher::osu_set_field_coords_rebuilt(out_coords); 185 | } 186 | 187 | static auto [[naked]] osu_set_field_coords_proxy(void* ecx, sdk::vec2* out_coords) -> void 188 | { 189 | __asm 190 | { 191 | push esi 192 | sub esp, 8 193 | call osu_set_field_coords_rebuilt 194 | add esp, 8 195 | pop esi 196 | ret 8 197 | } 198 | } 199 | 200 | static auto __fastcall osu_set_raw_coords_rebuilt(sdk::vec2* raw_coords) -> void 201 | { 202 | if (oc::menu::visible && game::pp_raw_mode_info->is_raw) 203 | { 204 | *raw_coords = oc::menu::freeze_view_point; 205 | return; 206 | } 207 | 208 | // TODO: actually rebuild this function from assembly 209 | // but seems like there are other functions that does our 210 | // job for us so we don't have to worry about it but it's 211 | // a better idea to actually rebuild it and restore functionality 212 | features::dispatcher::on_osu_set_raw_coords(raw_coords); 213 | } 214 | 215 | static auto [[naked]] osu_set_raw_coords_proxy() -> void 216 | { 217 | __asm 218 | { 219 | mov ecx, [ebp - 0x34] 220 | add ecx, 0x24 221 | jmp osu_set_raw_coords_rebuilt 222 | }; 223 | } 224 | 225 | void* osu_ac_flag_original{ nullptr }; 226 | 227 | static auto __stdcall osu_ac_flag() -> void 228 | { 229 | DEBUG_PRINTF("\n[!] Anti-cheat flag triggered!"); 230 | } 231 | 232 | static auto [[naked]] osu_ac_flag_proxy() -> void 233 | { 234 | __asm 235 | { 236 | call osu_ac_flag 237 | jmp osu_ac_flag_original 238 | }; 239 | } 240 | 241 | // TODO: write a small ghetto hooking class so we dont get ugly chunks of code like this 242 | 243 | using mouse_get_position_t = void(__fastcall*)(std::uintptr_t); 244 | 245 | mouse_get_position_t* mouse_get_position_callptr = nullptr; 246 | mouse_get_position_t mouse_get_position_original = nullptr; 247 | 248 | auto __fastcall mouse_get_position_hook(std::uintptr_t ecx) -> void 249 | { 250 | if (!ecx) 251 | return; 252 | 253 | if (oc::menu::visible) 254 | { 255 | POINT p = oc::menu::freeze_view_point; 256 | ClientToScreen(game::hwnd, &p); 257 | *reinterpret_cast(ecx + 0x4) = p; 258 | return; 259 | } 260 | 261 | return mouse_get_position_original(ecx); 262 | } 263 | 264 | using hook_instances_t = std::vector>; 265 | static hook_instances_t hook_instances; 266 | 267 | auto hooks::install() -> bool 268 | { 269 | DEBUG_PRINTF("\n[+] Installing hooks..." 270 | "\n[+] Importing gdi32full.SwapBuffers..."); 271 | 272 | // TODO: port these signatures 273 | 274 | // Swap buffers 275 | gdi32full_SwapBuffers_target = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"gdi32full.dll"), "SwapBuffers")); 276 | 277 | if (!gdi32full_SwapBuffers_target) 278 | { 279 | DEBUG_PRINTF("\n[!] Failed to import gdi32full.SwapBuffers"); 280 | return false; 281 | } 282 | 283 | DEBUG_PRINTF(" 0x%p", gdi32full_SwapBuffers_target); 284 | 285 | // Set field coordinates 286 | 287 | DEBUG_PRINTF("\n[+] Searching for osu_set_field_coords... "); 288 | 289 | auto osu_set_field_coords_target = sed::pattern_scan<"56 83 EC ?? 8B F2 8D 41 ?? D9 00 D9 40 ?? d9 44", void>(); 290 | 291 | if (!osu_set_field_coords_target) 292 | { 293 | DEBUG_PRINTF("\n[!] Failed to look for osu_set_field_coords!"); 294 | return false; 295 | } 296 | 297 | DEBUG_PRINTF(" 0x%p", osu_set_field_coords_target); 298 | 299 | // Set raw input coordinates 300 | DEBUG_PRINTF("\n[+] Searching for osu_set_raw_coords..."); 301 | 302 | auto cond_raw_coords = sed::pattern_scan<"74 ?? 8b 75 ?? 83 c6 ?? 8b 45", std::uint8_t>(); 303 | 304 | if (!cond_raw_coords) 305 | { 306 | DEBUG_PRINTF("\n[!] Failed to look for osu_set_raw_coords!"); 307 | return false; 308 | } 309 | 310 | DEBUG_PRINTF(" 0x%p", cond_raw_coords); 311 | auto cond_raw_rel8 = *(cond_raw_coords + 1); 312 | DEBUG_PRINTF("\n[+] raw coords rel8 and abs -> 0x%x", cond_raw_rel8); 313 | auto cond_raw_abs = cond_raw_coords + 2 + cond_raw_rel8; 314 | DEBUG_PRINTF(" -> 0x%p", cond_raw_abs); 315 | 316 | // Mouse get position 317 | DEBUG_PRINTF("\n[+] Searching for mouse.get_Position's call to GetCursorPos..."); 318 | auto mouse_get_position_target = sed::pattern_scan<"FF 15 ?? ?? ?? ?? 8B 56 04 8B 46 08 89 17 89 47 04 5E 5F 5D", std::uint8_t>(); 319 | 320 | if (!mouse_get_position_target) 321 | { 322 | DEBUG_PRINTF("\n[!] Failed to locate call to GetCursorPos!"); 323 | return false; 324 | } 325 | 326 | DEBUG_PRINTF(" 0x%p", mouse_get_position_target); 327 | mouse_get_position_callptr = *reinterpret_cast(mouse_get_position_target + 2); 328 | DEBUG_PRINTF(" -> 0x%p (callptr)", mouse_get_position_callptr); 329 | 330 | // Anticheat flag sig 331 | DEBUG_PRINTF("\n[+] Searching for ac_flag_call..."); 332 | auto ac_flag_call = sed::pattern_scan<"E8 ?? ?? ?? ?? 83 C4 ?? 89 45 ?? 8B 4D ?? 8B 11 8B 42 ?? 89 45 ?? 0F B6 4D", void>(); // TODO: this doesn't necessarily need to be scanned through regions 333 | 334 | if (!ac_flag_call) 335 | { 336 | DEBUG_PRINTF("\n[!] Failed to look for ac_flag_call"); 337 | return false; 338 | } 339 | 340 | DEBUG_PRINTF(" 0x%p", ac_flag_call); 341 | osu_ac_flag_original = reinterpret_cast(sed::rel2abs32(reinterpret_cast(ac_flag_call), 0x5)); 342 | DEBUG_PRINTF(" -> 0x%p", osu_ac_flag_original); 343 | 344 | #if 0 345 | // WindowProc 346 | DEBUG_PRINTF("\n[+] Loading WindowProcedure..."); 347 | auto wp = GetWindowLongPtrA(game::hwnd, GWLP_WNDPROC); 348 | DEBUG_PRINTF(" 0x%p", wp); 349 | auto wp_jmp = wp + 5; 350 | DEBUG_PRINTF(" -> rel(0x%p)", *reinterpret_cast(wp_jmp + 1)); 351 | WindowProc_original = reinterpret_cast(sed::rel2abs32(reinterpret_cast(wp_jmp), 0x5)); 352 | DEBUG_PRINTF(" -> abs(0x%p)", WindowProc_original); 353 | #endif 354 | 355 | #define _OC_ADD_HOOK_INSTANCE(patchtype, from, to) \ 356 | _instances.push_back(std::make_unique(reinterpret_cast(from), reinterpret_cast(to))) 357 | 358 | hook_instances_t _instances {}; 359 | 360 | _OC_ADD_HOOK_INSTANCE(jmp, CallWindowProcA_target, CallWindowProcA_proxy); 361 | _OC_ADD_HOOK_INSTANCE(jmp, CallWindowProcW_target, CallWindowProcW_proxy); 362 | _OC_ADD_HOOK_INSTANCE(jmp, SetWindowTextW, SetWindowTextW_proxy); 363 | _OC_ADD_HOOK_INSTANCE(jmp, gdi32full_SwapBuffers_target, gdi32full_SwapBuffers_proxy); 364 | _OC_ADD_HOOK_INSTANCE(jmp, osu_set_field_coords_target, osu_set_field_coords_proxy); 365 | _OC_ADD_HOOK_INSTANCE(call, cond_raw_coords, osu_set_raw_coords_proxy); 366 | _OC_ADD_HOOK_INSTANCE(jmp, cond_raw_coords + 5, cond_raw_abs); 367 | _OC_ADD_HOOK_INSTANCE(call, ac_flag_call, osu_ac_flag_proxy); 368 | 369 | #undef _OC_ADD_HOOK_INSTANCE 370 | 371 | for (auto& h : _instances) 372 | { 373 | if (!h->patch()) 374 | { 375 | DEBUG_PRINTF("\n[!] Failed to install hooks!"); 376 | return false; 377 | } 378 | } 379 | 380 | hook_instances = std::move(_instances); 381 | 382 | mouse_get_position_original = *mouse_get_position_callptr; 383 | *mouse_get_position_callptr = mouse_get_position_hook; 384 | 385 | return true; 386 | } 387 | 388 | auto hooks::uninstall() -> bool 389 | { 390 | if (hook_instances.empty()) 391 | return false; 392 | 393 | for (auto& h : hook_instances) 394 | { 395 | if (!h->restore()) 396 | { 397 | DEBUG_PRINTF("\n[!] Failed to uninstall hook!"); 398 | } 399 | } 400 | 401 | *mouse_get_position_callptr = mouse_get_position_original; 402 | 403 | hook_instances.clear(); 404 | 405 | return true; 406 | } 407 | -------------------------------------------------------------------------------- /osu-cheese-client/hooks.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // For hooks 4 | 5 | namespace hooks 6 | { 7 | auto install() -> bool; 8 | auto uninstall() -> bool; 9 | } -------------------------------------------------------------------------------- /osu-cheese-client/manager/gamefield_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "gamefield_manager.hpp" 2 | 3 | #include 4 | #include 5 | 6 | auto manager::game_field::resize(int vw, int vh, float size) -> void 7 | { 8 | DEBUG_PRINTF("\n[D] view resize: %d, %d", vw, vh); 9 | 10 | float window_ratio = static_cast(vh) / osu_native_h; 11 | 12 | float w = osu_field_w * window_ratio * size; 13 | float h = osu_field_h * window_ratio * size; 14 | 15 | float offset = -16.f * window_ratio; 16 | 17 | game_field::offset_x = (static_cast(vw) - w) / 2.f; 18 | game_field::offset_y = (static_cast(vh) - h) / 4.f * 3.f + offset; 19 | 20 | game_field::field_ratio = h / osu_field_h; 21 | } 22 | 23 | auto manager::game_field::v2f(int x, int y) -> std::pair 24 | { 25 | return std::make_pair( 26 | (static_cast(x) - game_field::offset_x) / field_ratio, 27 | (static_cast(y) - game_field::offset_y) / field_ratio 28 | ); 29 | } 30 | 31 | auto manager::game_field::f2v(float x, float y) -> std::pair 32 | { 33 | return std::make_pair( 34 | static_cast(x * field_ratio + game_field::offset_x), 35 | static_cast(y * field_ratio + game_field::offset_y) 36 | ); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /osu-cheese-client/manager/gamefield_manager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../sdk/osu_vec.hpp" 5 | 6 | namespace manager 7 | { 8 | class game_field 9 | { 10 | static constexpr float osu_native_w = 640.f; 11 | static constexpr float osu_native_h = 480.f; 12 | static constexpr float osu_field_w = osu_native_w * 0.8f; 13 | static constexpr float osu_field_h = osu_native_h * 0.8f; 14 | static constexpr float osu_margin_ratio = 0.1f; 15 | static constexpr float osu_scale_ratio = 0.28f; 16 | 17 | public: 18 | inline static float field_ratio = 0.f; 19 | inline static float offset_x = 0.f; 20 | inline static float offset_y = 0.f; 21 | 22 | game_field() = delete; 23 | 24 | static auto resize(int vw, int vh, float size = 1.f) -> void; 25 | 26 | // view to field (/world) | For abstraction purposes: LEGACY! DO NOT USE!!! 27 | [[deprecated("Use vec2")]] static auto v2f(int x, int y) -> std::pair; 28 | 29 | // Field to view | For abstraction purposes: LEGACY! DO NOT USE!!! 30 | [[deprecated("Use vec2")]] static auto f2v(float x, float y) -> std::pair; 31 | }; 32 | } -------------------------------------------------------------------------------- /osu-cheese-client/menu.cpp: -------------------------------------------------------------------------------- 1 | #include "menu.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "game.hpp" 9 | #include "features/features.hpp" 10 | #include "oc_client.hpp" 11 | 12 | extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 13 | 14 | auto oc::menu::render() -> void 15 | { 16 | if (!menu::visible) 17 | return; 18 | 19 | ImGui::SetNextWindowSize(ImVec2(660.f, 460.f), ImGuiCond_FirstUseEver); 20 | 21 | ImGui::Begin("osu!"); 22 | 23 | if (ImGui::Button("Unload")) 24 | sed::smart_handle(CreateThread(nullptr, NULL, [](LPVOID arg) -> DWORD { oc::unload(); return 0; }, nullptr, NULL, nullptr)); 25 | 26 | ImGui::SameLine(); 27 | ImGui::Text("[PAUSE] Key to toggle menu."); 28 | 29 | if (ImGui::BeginTabBar("##oc_tabs")) 30 | { 31 | features::dispatcher::on_tab_render(); 32 | ImGui::EndTabBar(); 33 | } 34 | ImGui::End(); 35 | } 36 | 37 | auto oc::menu::wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -> bool 38 | { 39 | if (Msg == WM_KEYDOWN && wParam == VK_PAUSE) 40 | { 41 | menu::visible = !menu::visible; 42 | ShowCursor(menu::visible); 43 | 44 | if (menu::visible) 45 | menu::freeze_view_point = game::pp_viewpos_info->pos; 46 | 47 | if (menu::visible && game::pp_raw_mode_info->is_raw || !menu::visible) 48 | { 49 | POINT p = menu::freeze_view_point; 50 | ClientToScreen(game::hwnd, &p); 51 | SetCursorPos(p.x, p.y); 52 | } 53 | 54 | return true; 55 | } 56 | 57 | if (!menu::visible) 58 | return false; 59 | 60 | ImGui_ImplWin32_WndProcHandler(hWnd, Msg, wParam, lParam); 61 | 62 | switch (Msg) 63 | { 64 | case WM_KEYDOWN: 65 | case WM_KEYUP: 66 | case WM_LBUTTONDBLCLK: 67 | case WM_LBUTTONDOWN: 68 | case WM_LBUTTONUP: 69 | case WM_RBUTTONDBLCLK: 70 | case WM_RBUTTONDOWN: 71 | case WM_RBUTTONUP: 72 | case WM_XBUTTONDBLCLK: 73 | case WM_XBUTTONDOWN: 74 | case WM_XBUTTONUP: 75 | return true; 76 | } 77 | 78 | return false; 79 | } -------------------------------------------------------------------------------- /osu-cheese-client/menu.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "sdk/osu_vec.hpp" 5 | 6 | namespace oc 7 | { 8 | class menu 9 | { 10 | public: 11 | menu() = delete; 12 | 13 | inline static bool visible = false; 14 | inline static sdk::vec2 freeze_view_point; // Used for locking the player position when the menu is open 15 | 16 | static auto render() -> void; 17 | static auto wndproc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) -> bool; 18 | }; 19 | } -------------------------------------------------------------------------------- /osu-cheese-client/oc_client.cpp: -------------------------------------------------------------------------------- 1 | #include "oc_client.hpp" 2 | 3 | #include 4 | #include 5 | #include "game.hpp" 6 | #include "hooks.hpp" 7 | #include "menu.hpp" 8 | 9 | auto oc::load() -> bool 10 | { 11 | #ifdef OSU_CHEESE_DEBUG_BUILD 12 | sed::console::init(); 13 | #endif 14 | 15 | DEBUG_PRINTF("\n[+] Initializing...."); 16 | 17 | if (!game::initialize() || !hooks::install()) 18 | { 19 | DEBUG_PRINTF("\n[!] Initialization failed"); 20 | return false; 21 | } 22 | 23 | DEBUG_PRINTF("\n[+] Ready!"); 24 | return true; 25 | } 26 | 27 | auto oc::unload() -> bool 28 | { 29 | hooks::uninstall(); 30 | 31 | DEBUG_PRINTF("\n[!] Unloaded!"); 32 | 33 | return true; 34 | } 35 | -------------------------------------------------------------------------------- /osu-cheese-client/oc_client.hpp: -------------------------------------------------------------------------------- 1 | namespace oc 2 | { 3 | auto load() -> bool; 4 | auto unload() -> bool; 5 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/hitobject.cpp: -------------------------------------------------------------------------------- 1 | #include "hitobject.hpp" 2 | 3 | auto sdk::ho_vector::get_coming_hitobject(std::uint32_t time) -> std::pair 4 | { 5 | for (int i = 0; i < count; ++i) 6 | { 7 | if (time <= container->hitobjects[i]->time.start && (i == 0 || time > container->hitobjects[i - 1]->time.start)) 8 | return std::make_pair(container->hitobjects[i], i); 9 | } 10 | 11 | return std::make_pair(nullptr, -1); 12 | } 13 | 14 | auto sdk::ho_vector::begin() -> hitobject * 15 | { 16 | return this->container->hitobjects[0]; 17 | } 18 | 19 | auto sdk::ho_vector::end() -> hitobject * 20 | { 21 | return this->container->hitobjects[this->count]; 22 | } 23 | 24 | auto sdk::pp_phitobject_t::begin() -> hitobject * 25 | { 26 | return (*this->ptr)->ho2->ho1->ho_vec->begin(); 27 | } 28 | 29 | auto sdk::pp_phitobject_t::end() -> hitobject * 30 | { 31 | return (*this->ptr)->ho2->ho1->ho_vec->end(); 32 | } 33 | 34 | auto sdk::pp_phitobject_t::get_coming_hitobject(std::uint32_t time) -> std::pair 35 | { 36 | return (*this->ptr)->ho2->ho1->ho_vec->get_coming_hitobject(time); 37 | } 38 | 39 | auto sdk::pp_phitobject_t::count() -> std::uint32_t 40 | { 41 | return (*this->ptr)->ho2->ho1->ho_vec->count; 42 | } 43 | 44 | auto sdk::pp_phitobject_t::operator[](int index) -> hitobject * 45 | { 46 | return (*this->ptr)->ho2->ho1->ho_vec->container->hitobjects[index]; 47 | } 48 | 49 | sdk::pp_phitobject_t::operator bool() const noexcept 50 | { 51 | // not gonna macro this one 52 | // this is cancer 53 | if (!this->ptr) 54 | return false; 55 | 56 | auto ho_ptr = *this->ptr; 57 | 58 | if (!ho_ptr) 59 | return false; 60 | 61 | auto ho2_ptr = ho_ptr->ho2; 62 | 63 | if (!ho2_ptr) 64 | return false; 65 | 66 | auto ho1_ptr = ho2_ptr->ho1; 67 | 68 | if (!ho1_ptr) 69 | return false; 70 | 71 | auto ho_vec_ptr = ho1_ptr->ho_vec; 72 | 73 | if (!ho_vec_ptr) 74 | return false; 75 | 76 | auto container_ptr = ho_vec_ptr->container; 77 | 78 | if (!container_ptr) 79 | return false; 80 | 81 | return true; 82 | } 83 | -------------------------------------------------------------------------------- /osu-cheese-client/sdk/hitobject.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "osu_vec.hpp" 5 | #include 6 | 7 | namespace sdk 8 | { 9 | // osu!master\osu!\GameplayElements\HitObjects\HitObjectBase.cs 10 | enum class hit_type : std::uint32_t 11 | { 12 | Normal = 1, 13 | Slider = 2, 14 | NewCombo = 4, 15 | NormalNewCombo = 5, 16 | SliderNewCombo = 6, 17 | Spinner = 8, 18 | ColourHax = 112, 19 | Hold = 128, 20 | ManiaLong = 128 21 | }; 22 | 23 | enum class sound_type : std::uint32_t 24 | { 25 | None = 0, 26 | Normal = 1, 27 | Whistle = 2, 28 | Finish = 4, 29 | Clap = 8 30 | }; 31 | 32 | struct hitobject 33 | { 34 | private: 35 | // The 0xC is from a register but seems to be constant, perhaps this is due 36 | // to not being able to encode 0x10 into the move instruction while only being 37 | // able to encode 0x4. 38 | // mov esi, [eax+ecx+0x04] where EAX is 0xC 39 | char pad[0x4 + 0xC]; 40 | 41 | public: 42 | struct 43 | { 44 | std::int32_t start; 45 | std::int32_t end; 46 | } time; 47 | 48 | hit_type type; 49 | sound_type sound_type; 50 | std::int32_t segment_count; 51 | std::int32_t segment_length; 52 | /*double*/ char spatial_length[4]; // internally a double but it's only 4 bytes when reversed so it's padded instead since double is 8 bytes 53 | std::int32_t combo_color_offset; 54 | std::int32_t combo_color_index; 55 | std::uint32_t raw_color; 56 | sdk::vec2 position; 57 | // not sure with the rest below 58 | std::int32_t stack_count; 59 | std::int32_t last_in_combo; 60 | }; 61 | 62 | struct ho_array 63 | { 64 | private: 65 | char pad[0x8]; 66 | public: 67 | // Array of 4 byte pointers 68 | // mov ecx,[eax+ebx*4+08] 69 | hitobject * hitobjects[]; 70 | }; 71 | 72 | struct ho_vector 73 | { 74 | private: 75 | char pad[0x4]; 76 | public: 77 | ho_array * container; 78 | private: 79 | char pad1[0x4]; 80 | public: 81 | std::uint32_t count; 82 | 83 | public: 84 | auto get_coming_hitobject(std::uint32_t time) -> std::pair; 85 | auto begin() -> hitobject *; 86 | auto end() -> hitobject *; 87 | }; 88 | 89 | struct ho_1 90 | { 91 | private: 92 | // 0x44 is in register EAX but seems to be constant 93 | // mov ecx,[eax+ecx+0x04] 94 | char pad[0x04 + 0x44]; 95 | public: 96 | ho_vector * ho_vec; 97 | }; 98 | 99 | struct ho_2 100 | { 101 | private: 102 | char pad[0x3C]; 103 | public: 104 | ho_1 * ho1; 105 | }; 106 | 107 | struct hitobject_pointer 108 | { 109 | private: 110 | char pad[0x60]; 111 | public: 112 | ho_2 * ho2; 113 | }; 114 | 115 | class pp_phitobject_t : public sed::basic_ptrptr 116 | { 117 | public: 118 | auto begin() -> hitobject *; 119 | auto end() -> hitobject *; 120 | 121 | auto get_coming_hitobject(std::uint32_t time) -> std::pair; 122 | auto count() -> std::uint32_t; 123 | 124 | auto operator[](int index) -> hitobject *; 125 | operator bool() const noexcept; 126 | }; 127 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/info_player.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace sdk 9 | { 10 | union info_player_t 11 | { 12 | OC_UNS_PAD(0x17A, bool, is_replay_mode) 13 | OC_UNS_PAD(0x182, bool, async_complete) 14 | }; 15 | 16 | class pp_info_player_t : public sed::basic_ptrptr 17 | { 18 | }; 19 | 20 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/info_struct.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace sdk 8 | { 9 | union unk_game_info_a 10 | { 11 | struct { std::uint32_t beat_time; }; 12 | 13 | OC_UNS_PAD(0x30, bool, is_playing) 14 | OC_UNS_PAD(0x38, std::uint32_t, gain_thing_idk) 15 | OC_UNS_PAD(0x40, std::uint32_t, game_tick) 16 | }; 17 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/osu_vec.cpp: -------------------------------------------------------------------------------- 1 | #include "osu_vec.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "../manager/gamefield_manager.hpp" 7 | 8 | auto sdk::vec2::distance(const vec2 & to) const -> float 9 | { 10 | return std::sqrt(std::pow(to.x - this->x, 2) + std::pow(to.y - this->y, 2)); 11 | } 12 | 13 | auto sdk::vec2::view_to_field() const -> vec2 14 | { 15 | vec2 v = *this; 16 | vec2::view_to_field(v); 17 | return v; 18 | } 19 | 20 | auto sdk::vec2::view_to_field(vec2 & v) -> void 21 | { 22 | v.x = (v.x - manager::game_field::offset_x) / manager::game_field::field_ratio; 23 | v.y = (v.y - manager::game_field::offset_y) / manager::game_field::field_ratio; 24 | } 25 | 26 | auto sdk::vec2::field_to_view() const -> vec2 27 | { 28 | vec2 v = *this; 29 | vec2::field_to_view(v); 30 | return v; 31 | } 32 | 33 | auto sdk::vec2::field_to_view(vec2 & v) -> void 34 | { 35 | v.x = v.x * manager::game_field::field_ratio + manager::game_field::offset_x; 36 | v.y = v.y * manager::game_field::field_ratio + manager::game_field::offset_y; 37 | } 38 | 39 | auto sdk::vec2::magnitude() const -> float 40 | { 41 | return std::sqrt(this->dot_product(*this)); 42 | } 43 | 44 | auto sdk::vec2::normalize_towards(const vec2 & to) const -> vec2 45 | { 46 | auto dist = this->distance(to); 47 | return vec2( 48 | (to.x - this->x) / dist, 49 | (to.y - this->y) / dist 50 | ); 51 | } 52 | 53 | auto sdk::vec2::forward_towards(const vec2 & to, float fwd_distance) const -> vec2 54 | { 55 | auto norm = this->normalize_towards(to); 56 | return vec2( 57 | this->x + fwd_distance * norm.x, 58 | this->y + fwd_distance * norm.y 59 | ); 60 | } 61 | 62 | auto sdk::vec2::forward(const float direction, float fwd_distance) -> vec2 63 | { 64 | return forward(vec2::from_deg(direction), fwd_distance); 65 | } 66 | 67 | auto sdk::vec2::forward(const vec2 & direction, float fwd_distance) const -> vec2 68 | { 69 | return *this + direction * fwd_distance; 70 | } 71 | 72 | auto sdk::vec2::dot_product(const vec2 & other) const -> float 73 | { 74 | return this->x * other.x + this->y * other.y; 75 | } 76 | 77 | auto sdk::vec2::vec2vec_angle(const vec2 & other) const -> float 78 | { 79 | return std::acosf(this->dot_product(other) / (this->magnitude() * other.magnitude())) * 180.f / std::numbers::pi_v; 80 | } 81 | 82 | auto sdk::vec2::from_norm_to_deg() -> float 83 | { 84 | return std::atan2f(this->y, this->x) * 180.f / std::numbers::pi_v; 85 | } 86 | 87 | auto sdk::vec2::from_rad(float rad) -> vec2 88 | { 89 | return vec2(std::cosf(rad), std::sinf(rad)); 90 | } 91 | 92 | auto sdk::vec2::from_deg(float deg) -> vec2 93 | { 94 | return vec2::from_rad(deg * std::numbers::pi_v / 180.f); 95 | } 96 | 97 | auto sdk::vec2::operator==(const vec2 & rhs) const noexcept -> bool 98 | { 99 | return this->x == rhs.x && this->y == rhs.y; 100 | } 101 | 102 | auto sdk::vec2::operator*(const float rhs) const noexcept -> vec2 103 | { 104 | return vec2(this->x * rhs, this->y * rhs); 105 | } 106 | 107 | auto sdk::vec2::operator+(const vec2 & rhs) const noexcept -> vec2 108 | { 109 | return vec2(this->x + rhs.x, this->y + rhs.y); 110 | } 111 | 112 | auto sdk::vec2::operator+(const float rhs) const noexcept -> vec2 113 | { 114 | return vec2(this->x + rhs, this->y + rhs); 115 | } 116 | 117 | sdk::vec2::operator ImVec2() const 118 | { 119 | return ImVec2(this->x, this->y); 120 | } 121 | 122 | sdk::vec2::operator POINT() const 123 | { 124 | return POINT { .x = LONG(this->x), .y = LONG(this->y) }; 125 | } 126 | -------------------------------------------------------------------------------- /osu-cheese-client/sdk/osu_vec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace sdk 9 | { 10 | struct vec2 11 | { 12 | float x, y; 13 | 14 | vec2() 15 | : x(0.f), y(0.f) {} 16 | 17 | vec2(float x_, float y_) 18 | : x(x_), y(y_) {} 19 | 20 | vec2(int x_, int y_) 21 | : x(float(x_)), y(float(y_)) {} 22 | 23 | auto distance(const vec2 & to) const -> float; 24 | 25 | auto view_to_field() const -> vec2; 26 | static auto view_to_field(vec2 & v) -> void; 27 | auto field_to_view() const -> vec2; 28 | static auto field_to_view(vec2 & v) -> void; 29 | 30 | auto magnitude() const -> float; 31 | 32 | auto normalize_towards(const vec2 & to) const -> vec2; 33 | auto forward_towards(const vec2 & to, float fwd_distance = 1.f) const -> vec2; 34 | 35 | auto forward(const float direction /* in degrees */, float fwd_distance = 1.f) -> vec2; 36 | auto forward(const vec2 & direction, float fwd_distance = 1.f) const -> vec2; 37 | 38 | auto dot_product(const vec2 & other) const -> float; 39 | 40 | // angle to another vector 41 | auto vec2vec_angle(const vec2 & other) const -> float; 42 | 43 | auto from_norm_to_deg() -> float; // lol 44 | 45 | static auto from_rad(float rad) -> vec2; 46 | static auto from_deg(float deg) -> vec2; 47 | 48 | auto operator ==(const vec2 & rhs) const noexcept -> bool; 49 | auto operator *(const float rhs) const noexcept -> vec2; 50 | auto operator +(const vec2 & rhs) const noexcept -> vec2; 51 | auto operator +(const float rhs) const noexcept -> vec2; 52 | 53 | operator ImVec2() const; 54 | operator POINT() const; 55 | }; 56 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/player_keys.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace sdk 7 | { 8 | struct player_key 9 | { 10 | private: 11 | char unk[0xC]; 12 | public: 13 | DWORD vkey; 14 | }; 15 | static_assert(sizeof(player_key) == 0x10, "invalid player_key struct size!"); 16 | 17 | struct player_keys_t 18 | { 19 | private: 20 | char pad[0x8]; 21 | public: 22 | struct 23 | { 24 | player_key left_click; 25 | player_key right_click; 26 | player_key smoke; 27 | } osu; 28 | 29 | player_key other_keys[]; 30 | 31 | //struct 32 | //{ 33 | // player_key drum_centre_left; 34 | // player_key drum_centre_right; 35 | //} taiko; 36 | // not doing this now 37 | }; 38 | 39 | struct _PTRPK_ 40 | { 41 | private: 42 | char pad[0x8]; 43 | public: 44 | player_keys_t *ppk; 45 | }; 46 | 47 | class pp_pplayer_keys_t : public sed::basic_ptrptr<_PTRPK_> {}; 48 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/position_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "osu_vec.hpp" 6 | 7 | namespace sdk 8 | { 9 | union viewpos_info_t 10 | { 11 | OC_UNS_PAD(0x4, sdk::vec2, pos); 12 | }; 13 | 14 | class pp_viewpos_info_t : public sed::basic_ptrptr {}; 15 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/raw_info.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace sdk 5 | { 6 | union raw_mode_info_t 7 | { 8 | OC_UNS_PAD(0xC, bool, is_raw) 9 | }; 10 | 11 | class pp_raw_mode_info_t : public sed::basic_ptrptr {}; 12 | } -------------------------------------------------------------------------------- /osu-cheese-client/sdk/wnd_info.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace sdk 8 | { 9 | union wnd_info_t 10 | { 11 | OC_UNS_PAD(0xC, HWND, handle) 12 | }; 13 | 14 | class pp_wnd_info_t : public sed::basic_ptrptr {}; 15 | } -------------------------------------------------------------------------------- /osu-cheese-loader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18) 2 | 3 | project(osu-cheese-loader CXX) 4 | 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED True) 7 | 8 | add_executable(${PROJECT_NAME} 9 | "loader_main.cpp" 10 | "loader_main.hpp" 11 | ) 12 | 13 | if (EXISTS "client_path.hpp") 14 | add_executable(${PROJECT_NAME} "client_path.hpp") 15 | endif () 16 | 17 | target_link_libraries(${PROJECT_NAME} PRIVATE 18 | osu-cheese-framework 19 | osu-cheese-client 20 | ) 21 | 22 | target_include_directories(${PROJECT_NAME} PRIVATE 23 | ${osu-cheese-framework-includes} 24 | ) -------------------------------------------------------------------------------- /osu-cheese-loader/loader_main.cpp: -------------------------------------------------------------------------------- 1 | #include "loader_main.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #if __has_include("client_path.hpp") 14 | #include "client_path.hpp" 15 | #else 16 | #define DEBUG_HARDCODE_CLIENT_PATH "" 17 | #endif 18 | 19 | using info_t = std::pair; 20 | 21 | decltype(NtQueryInformationThread) * _NtQueryInformationThread = nullptr; 22 | 23 | static auto find_osu_proc(info_t & out) -> bool 24 | { 25 | sed::smart_handle proc_snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 26 | 27 | if (!proc_snap) 28 | { 29 | printf("Failed."); 30 | return false; 31 | } 32 | 33 | PROCESSENTRY32W pe { .dwSize = sizeof(pe) }; 34 | 35 | if (Process32FirstW(proc_snap, &pe)) 36 | { 37 | do 38 | { 39 | if (wcscmp(pe.szExeFile, L"osu!.exe")) 40 | continue; 41 | 42 | out = std::make_pair(sed::smart_handle(OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID)), pe.th32ProcessID); 43 | return true; 44 | 45 | } while (Process32NextW(proc_snap, &pe)); 46 | } 47 | 48 | return false; 49 | } 50 | 51 | static auto find_osu_auth(info_t & proc, std::uintptr_t & start, std::uintptr_t & end) -> bool 52 | { 53 | sed::smart_handle mod_snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32 | TH32CS_SNAPMODULE, proc.second); 54 | 55 | if (!mod_snap) 56 | return false; 57 | 58 | MODULEENTRY32W me { .dwSize = sizeof(me) }; 59 | 60 | if (Module32FirstW(mod_snap, &me)) 61 | { 62 | do 63 | { 64 | if (wcscmp(me.szModule, L"osu!auth.dll")) 65 | continue; 66 | 67 | start = reinterpret_cast(me.modBaseAddr); 68 | end = start + me.modBaseSize; 69 | return true; 70 | 71 | } while (Module32NextW(mod_snap, &me)); 72 | } 73 | 74 | return false; 75 | } 76 | 77 | static auto find_osu_auth_thread(info_t & proc, sed::suspend_guard & out, std::uintptr_t start, std::uintptr_t end) -> bool 78 | { 79 | sed::smart_handle thread_snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL); 80 | 81 | if (!thread_snap) 82 | return false; 83 | 84 | THREADENTRY32 te { .dwSize = sizeof(te) }; 85 | 86 | if (Thread32First(thread_snap, &te)) 87 | { 88 | do 89 | { 90 | if (te.th32OwnerProcessID != proc.second) 91 | continue; 92 | 93 | auto tt = sed::suspend_guard(te.th32ThreadID); 94 | if (!tt) 95 | continue; 96 | 97 | DWORD staddr { 0 }; 98 | // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ps/psquery/class.htm 99 | _NtQueryInformationThread(tt, THREADINFOCLASS(0x09), &staddr, sizeof(staddr), nullptr); 100 | 101 | if (staddr >= start && staddr <= end) 102 | { 103 | out = std::move(tt); 104 | return true; 105 | } 106 | 107 | } while (Thread32Next(thread_snap, &te)); 108 | } 109 | 110 | return false; 111 | } 112 | 113 | #define OSUCHEESE_WAIT_FOR_QUERY(fn, ...) \ 114 | while (!fn(__VA_ARGS__)) Sleep(800) 115 | 116 | // TODO: clean up, merge checks as one iteration 117 | auto main(int argc, char ** argv) -> int 118 | { 119 | const char * client_path = nullptr; 120 | 121 | if (argc < 2) 122 | { 123 | if constexpr (!DEBUG_HARDCODE_CLIENT_PATH[0]) 124 | { 125 | printf("[!] ERROR: Missing path for client!"); 126 | return 1; 127 | } 128 | else 129 | { 130 | client_path = DEBUG_HARDCODE_CLIENT_PATH; 131 | } 132 | } 133 | else 134 | { 135 | client_path = argv[1]; 136 | } 137 | 138 | printf("\n[+] Client path: %s", client_path); 139 | 140 | // NtQueryInformationThread import 141 | printf("\n[+] Importing NtQueryInformationThread... "); 142 | _NtQueryInformationThread = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationThread")); 143 | 144 | if (!_NtQueryInformationThread) 145 | { 146 | printf("Failed!"); 147 | return 1; 148 | } 149 | 150 | printf("0x%p", _NtQueryInformationThread); 151 | 152 | // Process query 153 | info_t osu_proc {}; 154 | printf("\n[+] Attaching to osu..."); 155 | OSUCHEESE_WAIT_FOR_QUERY(find_osu_proc, osu_proc); 156 | 157 | // Module query 158 | printf("\n[+] Looking for osu!auth..."); 159 | std::uintptr_t start, end; 160 | OSUCHEESE_WAIT_FOR_QUERY(find_osu_auth, osu_proc, start, end); 161 | printf(" 0x%p - 0x%p", reinterpret_cast(start), reinterpret_cast(end)); 162 | 163 | // Thread query 164 | printf("\n[+] Enumerating for osu auth thread..."); 165 | sed::suspend_guard auth_thread; 166 | OSUCHEESE_WAIT_FOR_QUERY(find_osu_auth_thread, osu_proc, auth_thread, start, end); 167 | 168 | printf("\n[+] Suspended auth thread... 0x%p - ID: %lu", static_cast(auth_thread), auth_thread.get_id()); 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /osu-cheese-loader/loader_main.hpp: -------------------------------------------------------------------------------- 1 | #pragma once -------------------------------------------------------------------------------- /osu-cheese.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32630.194 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} = {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} 9 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA} = {537F5A30-B8C4-3CD9-A070-1615782FA8EA} 10 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13} = {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13} 11 | {CB9F4BF0-F356-34D0-A083-0DED70861449} = {CB9F4BF0-F356-34D0-A083-0DED70861449} 12 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1} = {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1} 13 | {BABB151A-7580-3969-A348-49FCCC1BCFC9} = {BABB151A-7580-3969-A348-49FCCC1BCFC9} 14 | EndProjectSection 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dncomlib", "dependencies\dncomlib\dncomlib.vcxproj", "{43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}" 17 | EndProject 18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gl3w", "dependencies\gl3w_out\gl3w.vcxproj", "{537F5A30-B8C4-3CD9-A070-1615782FA8EA}" 19 | EndProject 20 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "dependencies\imgui\imgui.vcxproj", "{07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}" 21 | EndProject 22 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osu-cheese-client", "osu-cheese-client\osu-cheese-client.vcxproj", "{CB9F4BF0-F356-34D0-A083-0DED70861449}" 23 | ProjectSection(ProjectDependencies) = postProject 24 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} = {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE} 25 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA} = {537F5A30-B8C4-3CD9-A070-1615782FA8EA} 26 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13} = {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13} 27 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1} = {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1} 28 | EndProjectSection 29 | EndProject 30 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osu-cheese-framework", "framework\osu-cheese-framework.vcxproj", "{F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}" 31 | EndProject 32 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osu-cheese-loader", "osu-cheese-loader\osu-cheese-loader.vcxproj", "{BABB151A-7580-3969-A348-49FCCC1BCFC9}" 33 | ProjectSection(ProjectDependencies) = postProject 34 | {CB9F4BF0-F356-34D0-A083-0DED70861449} = {CB9F4BF0-F356-34D0-A083-0DED70861449} 35 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1} = {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1} 36 | EndProjectSection 37 | EndProject 38 | Global 39 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 40 | Debug|x64 = Debug|x64 41 | MinSizeRel|x64 = MinSizeRel|x64 42 | Release|x64 = Release|x64 43 | RelWithDebInfo|x64 = RelWithDebInfo|x64 44 | EndGlobalSection 45 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 46 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.Debug|x64.ActiveCfg = Debug|x64 47 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 48 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.Release|x64.ActiveCfg = Release|x64 49 | {66C4DA46-B9A3-329D-9FA8-DDBB0AC65567}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 50 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Debug|x64.ActiveCfg = Debug|x64 51 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Debug|x64.Build.0 = Debug|x64 52 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 53 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 54 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Release|x64.ActiveCfg = Release|x64 55 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.Release|x64.Build.0 = Release|x64 56 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 57 | {43EDBAFB-BB34-3CA5-89E2-57AA892DBCCE}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 58 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.Debug|x64.ActiveCfg = Debug|x64 59 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.Debug|x64.Build.0 = Debug|x64 60 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 61 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 62 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.Release|x64.ActiveCfg = Release|x64 63 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.Release|x64.Build.0 = Release|x64 64 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 65 | {537F5A30-B8C4-3CD9-A070-1615782FA8EA}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 66 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.Debug|x64.ActiveCfg = Debug|x64 67 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.Debug|x64.Build.0 = Debug|x64 68 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 69 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 70 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.Release|x64.ActiveCfg = Release|x64 71 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.Release|x64.Build.0 = Release|x64 72 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 73 | {07F1E2CD-3EA3-3348-924D-BA01AF1B4F13}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 74 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.Debug|x64.ActiveCfg = Debug|x64 75 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.Debug|x64.Build.0 = Debug|x64 76 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 77 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 78 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.Release|x64.ActiveCfg = Release|x64 79 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.Release|x64.Build.0 = Release|x64 80 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 81 | {CB9F4BF0-F356-34D0-A083-0DED70861449}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 82 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.Debug|x64.ActiveCfg = Debug|x64 83 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.Debug|x64.Build.0 = Debug|x64 84 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 85 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 86 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.Release|x64.ActiveCfg = Release|x64 87 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.Release|x64.Build.0 = Release|x64 88 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 89 | {F5ADDBCD-D0E8-3CD9-AD51-9F2A3F5499F1}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 90 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.Debug|x64.ActiveCfg = Debug|x64 91 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.Debug|x64.Build.0 = Debug|x64 92 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 93 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 94 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.Release|x64.ActiveCfg = Release|x64 95 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.Release|x64.Build.0 = Release|x64 96 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 97 | {BABB151A-7580-3969-A348-49FCCC1BCFC9}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 98 | EndGlobalSection 99 | GlobalSection(SolutionProperties) = preSolution 100 | HideSolutionNode = FALSE 101 | EndGlobalSection 102 | GlobalSection(ExtensibilityGlobals) = postSolution 103 | SolutionGuid = {25C04441-E8C4-39A6-99C0-A82D292685A4} 104 | EndGlobalSection 105 | EndGlobal 106 | --------------------------------------------------------------------------------