├── .gitattributes ├── .gitignore ├── .gitmodules ├── LICENSE ├── includes ├── CommonTypes.h ├── FileHooks.h ├── GameLoop.h ├── ModuleList.hpp ├── Randomizer.h ├── license ├── log.h ├── plog │ ├── Appenders │ │ ├── AndroidAppender.h │ │ ├── ColorConsoleAppender.h │ │ ├── ConsoleAppender.h │ │ ├── DebugOutputAppender.h │ │ ├── EventLogAppender.h │ │ ├── IAppender.h │ │ └── RollingFileAppender.h │ ├── Converters │ │ ├── NativeEOLConverter.h │ │ └── UTF8Converter.h │ ├── Formatters │ │ ├── CsvFormatter.h │ │ ├── FuncMessageFormatter.h │ │ ├── MessageOnlyFormatter.h │ │ └── TxtFormatter.h │ ├── Init.h │ ├── Initializers │ │ └── RollingFileInitializer.h │ ├── Log.h │ ├── Logger.h │ ├── Record.h │ ├── Severity.h │ ├── Util.h │ └── WinApi.h ├── sh4 │ ├── game │ │ ├── effect │ │ │ └── particle │ │ │ │ └── spray.h │ │ ├── eileen │ │ │ └── eileen.h │ │ ├── enemy │ │ │ ├── en_battle.h │ │ │ └── en_kind.h │ │ ├── gamemain │ │ │ ├── camera │ │ │ │ └── game_camera_another_engine.h │ │ │ ├── game.h │ │ │ ├── game_demo.h │ │ │ ├── game_fileread.h │ │ │ ├── game_gi_para.h │ │ │ ├── game_item.h │ │ │ ├── game_scenelink.h │ │ │ ├── save_data.h │ │ │ └── stage_info.h │ │ ├── message │ │ │ ├── message_handle.h │ │ │ └── message_load.h │ │ ├── misc │ │ │ ├── misc_iexplanation.h │ │ │ ├── misc_itemicon.h │ │ │ └── misc_option.h │ │ ├── objs │ │ │ └── game_objset.h │ │ └── player │ │ │ ├── battle │ │ │ ├── player_battle.h │ │ │ ├── player_battle_general.h │ │ │ └── player_weapon.h │ │ │ ├── player.h │ │ │ ├── player_anime_proc.h │ │ │ ├── player_another_ui.h │ │ │ └── player_sound.h │ ├── sglib │ │ ├── animation │ │ │ ├── sg_anime.h │ │ │ ├── sg_bone.h │ │ │ └── sg_ikhandle.h │ │ ├── intersect │ │ │ └── sg_quadtree.h │ │ ├── math │ │ │ └── sg_quat.h │ │ └── renderer │ │ │ └── TErender │ │ │ ├── model3.h │ │ │ ├── sg_svmodel.h │ │ │ └── sg_temodel.h │ └── sys │ │ ├── apps │ │ ├── sf_memorystack.h │ │ ├── sf_obj.h │ │ └── sf_step.h │ │ ├── env │ │ └── sf_env.h │ │ ├── geometry │ │ ├── collision │ │ │ └── sf_cld.h │ │ ├── sf_chara.h │ │ └── sf_scene.h │ │ ├── sound │ │ └── sf_sound.h │ │ └── storage │ │ └── sf_fileread.h ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── premake5.bat ├── premake5.exe ├── premake5.lua ├── readme.md ├── resources ├── VersionInfo.h └── VersionInfo.rc └── source └── SilentHill4Randomizer ├── FileHooks.cpp ├── GameLoop.cpp ├── Randomizer.cpp ├── dllmain.cpp ├── en_kind.cpp ├── game_camera_another_engine.cpp ├── game_demo.cpp ├── game_fileread.cpp ├── game_gi_para.cpp ├── game_item.cpp ├── game_objset.cpp ├── game_scenelink.cpp ├── message_handle.cpp ├── message_load.cpp ├── misc_iexplanation.cpp ├── misc_itemicon.cpp ├── misc_option.cpp ├── player.cpp ├── player_anime_proc.cpp ├── player_another_ui.cpp ├── player_battle.cpp ├── player_battle_general.cpp ├── player_sound.cpp ├── player_weapon.cpp ├── save_data.cpp ├── sf_chara.cpp ├── sf_env.cpp ├── sf_fileread.cpp ├── sf_memorystack.cpp ├── sf_scene.cpp ├── sf_sound.cpp ├── sf_step.cpp ├── sg_anime.cpp ├── sg_bone.cpp ├── sg_quat.cpp ├── spray.cpp └── stage_info.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Releases data 2 | data/Archives 3 | data/**/*.asi 4 | 5 | #ASI Loader 6 | data/**/vorbisFile.dll 7 | data/**/d3d8.dll 8 | data/**/d3d9.dll 9 | data/**/d3d11.dll 10 | data/**/winmmbase.dll 11 | data/**/msacm32.dll 12 | data/**/dinput8.dll 13 | data/**/dsound.dll 14 | data/**/ddraw.dll 15 | data/**/xlive.dll 16 | data/**/binkw32.dll 17 | data/**/version.dll 18 | data/**/msvfw32.dll 19 | 20 | ## Ignore Visual Studio temporary files, build results, and 21 | ## files generated by popular Visual Studio add-ons. 22 | ## 23 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 24 | 25 | # User-specific files 26 | *.suo 27 | *.user 28 | *.userosscache 29 | *.sln.docstates 30 | 31 | # User-specific files (MonoDevelop/Xamarin Studio) 32 | *.userprefs 33 | 34 | # Build results 35 | [Dd]ebug/ 36 | [Dd]ebugPublic/ 37 | [Rr]elease/ 38 | [Rr]eleases/ 39 | x64/ 40 | x86/ 41 | bld/ 42 | [Bb]in/ 43 | [Oo]bj/ 44 | [Ll]og/ 45 | [Bb]uild/ 46 | 47 | !data/**/[Bb]in/ 48 | 49 | # Visual Studio 2015 cache/options directory 50 | .vs/ 51 | # Uncomment if you have tasks that create the project's static files in wwwroot 52 | #wwwroot/ 53 | 54 | # MSTest test Results 55 | [Tt]est[Rr]esult*/ 56 | [Bb]uild[Ll]og.* 57 | 58 | # NUNIT 59 | *.VisualState.xml 60 | TestResult.xml 61 | 62 | # Build Results of an ATL Project 63 | [Dd]ebugPS/ 64 | [Rr]eleasePS/ 65 | dlldata.c 66 | 67 | # .NET Core 68 | project.lock.json 69 | project.fragment.lock.json 70 | artifacts/ 71 | **/Properties/launchSettings.json 72 | 73 | *_i.c 74 | *_p.c 75 | *_i.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.pch 80 | *.pdb 81 | *.pgc 82 | *.pgd 83 | *.rsp 84 | *.sbr 85 | *.tlb 86 | *.tli 87 | *.tlh 88 | *.tmp 89 | *.tmp_proj 90 | *.log 91 | *.vspscc 92 | *.vssscc 93 | .builds 94 | *.pidb 95 | *.svclog 96 | *.scc 97 | *.exp 98 | *.lib 99 | 100 | # Chutzpah Test files 101 | _Chutzpah* 102 | 103 | # Visual C++ cache files 104 | ipch/ 105 | *.aps 106 | *.ncb 107 | *.opendb 108 | *.opensdf 109 | *.sdf 110 | *.cachefile 111 | *.VC.db 112 | *.VC.VC.opendb 113 | 114 | # Visual Studio profiler 115 | *.psess 116 | *.vsp 117 | *.vspx 118 | *.sap 119 | 120 | # TFS 2012 Local Workspace 121 | $tf/ 122 | 123 | # Guidance Automation Toolkit 124 | *.gpState 125 | 126 | # ReSharper is a .NET coding add-in 127 | _ReSharper*/ 128 | *.[Rr]e[Ss]harper 129 | *.DotSettings.user 130 | 131 | # JustCode is a .NET coding add-in 132 | .JustCode 133 | 134 | # TeamCity is a build add-in 135 | _TeamCity* 136 | 137 | # DotCover is a Code Coverage Tool 138 | *.dotCover 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # TODO: Comment the next line if you want to checkin your web deploy settings 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # The packages folder can be ignored because of Package Restore 188 | **/packages/* 189 | # except build/, which is used as an MSBuild target. 190 | !**/packages/build/ 191 | # Uncomment if necessary however generally it will be regenerated when needed 192 | #!**/packages/repositories.config 193 | # NuGet v3's project.json files produces more ignoreable files 194 | *.nuget.props 195 | *.nuget.targets 196 | 197 | # Microsoft Azure Build Output 198 | csx/ 199 | *.build.csdef 200 | 201 | # Microsoft Azure Emulator 202 | ecf/ 203 | rcf/ 204 | 205 | # Windows Store app package directories and files 206 | AppPackages/ 207 | BundleArtifacts/ 208 | Package.StoreAssociation.xml 209 | _pkginfo.txt 210 | 211 | # Visual Studio cache files 212 | # files ending in .cache can be ignored 213 | *.[Cc]ache 214 | # but keep track of directories ending in .cache 215 | !*.[Cc]ache/ 216 | 217 | # Others 218 | ClientBin/ 219 | ~$* 220 | *~ 221 | *.dbmdl 222 | *.dbproj.schemaview 223 | *.jfm 224 | *.pfx 225 | *.publishsettings 226 | orleans.codegen.cs 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | 243 | # SQL Server files 244 | *.mdf 245 | *.ldf 246 | 247 | # Business Intelligence projects 248 | *.rdl.data 249 | *.bim.layout 250 | *.bim_*.settings 251 | 252 | # Microsoft Fakes 253 | FakesAssemblies/ 254 | 255 | # GhostDoc plugin setting file 256 | *.GhostDoc.xml 257 | 258 | # Node.js Tools for Visual Studio 259 | .ntvs_analysis.dat 260 | node_modules/ 261 | 262 | # Typescript v1 declaration files 263 | typings/ 264 | 265 | # Visual Studio 6 build log 266 | *.plg 267 | 268 | # Visual Studio 6 workspace options file 269 | *.opt 270 | 271 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 272 | *.vbw 273 | 274 | # Visual Studio LightSwitch build output 275 | **/*.HTMLClient/GeneratedArtifacts 276 | **/*.DesktopClient/GeneratedArtifacts 277 | **/*.DesktopClient/ModelManifest.xml 278 | **/*.Server/GeneratedArtifacts 279 | **/*.Server/ModelManifest.xml 280 | _Pvt_Extensions 281 | 282 | # Paket dependency manager 283 | .paket/paket.exe 284 | paket-files/ 285 | 286 | # FAKE - F# Make 287 | .fake/ 288 | 289 | # JetBrains Rider 290 | .idea/ 291 | *.sln.iml 292 | 293 | # CodeRush 294 | .cr/ 295 | 296 | # Python Tools for Visual Studio (PTVS) 297 | __pycache__/ 298 | *.pyc 299 | 300 | # Cake - Uncomment if you are using it 301 | # tools/** 302 | # !tools/packages.config 303 | 304 | .vscode/* 305 | !.vscode/settings.json 306 | !.vscode/tasks.json 307 | !.vscode/launch.json 308 | !.vscode/extensions.json 309 | !.vscode/*.code-snippets 310 | 311 | # Local History for Visual Studio Code 312 | .history/ 313 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/injector"] 2 | path = external/injector 3 | url = https://github.com/thelink2012/injector 4 | [submodule "external/inireader"] 5 | path = external/inireader 6 | url = https://github.com/ThirteenAG/IniReader 7 | [submodule "external/hooking"] 8 | path = external/hooking 9 | url = https://github.com/ThirteenAG/Hooking.Patterns 10 | [submodule "external/spdlog"] 11 | path = external/spdlog 12 | url = https://github.com/gabime/spdlog 13 | [submodule "external/filewatch"] 14 | path = external/filewatch 15 | url = https://github.com/ThomasMonkman/filewatch 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 Hunter Stanton 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /includes/CommonTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | union CommonUnion { 5 | int si; 6 | unsigned int ui; 7 | void* pt; 8 | short ss[2]; 9 | unsigned short us[2]; 10 | char sc[4]; 11 | unsigned char uc[4]; 12 | float f; 13 | float fv[1]; 14 | int iv[1]; 15 | }; 16 | 17 | struct Position 18 | { 19 | float x; 20 | float y; 21 | float z; 22 | float w; 23 | }; 24 | 25 | struct FourByFourMatrix 26 | { 27 | Position matrix[4]; 28 | }; 29 | 30 | struct Color 31 | { 32 | unsigned char r; 33 | unsigned char g; 34 | unsigned char b; 35 | unsigned char a; 36 | }; -------------------------------------------------------------------------------- /includes/FileHooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sh4/game/misc/misc_option.h" 4 | 5 | 6 | struct PlayerModel { 7 | LPCSTR filename; 8 | LPCSTR cutsceneFileName; 9 | }; 10 | 11 | extern std::vector playerModels; 12 | 13 | extern injector::hook_back LoadFile; 14 | void __cdecl LoadFileHook(LPCSTR file, HANDLE* handle); -------------------------------------------------------------------------------- /includes/GameLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stdafx.h" 4 | #include "Randomizer.h" 5 | #include 6 | 7 | extern injector::hook_back GameLoop; 8 | void InitializeGameLoopFunction(); 9 | -------------------------------------------------------------------------------- /includes/ModuleList.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Stores a list of loaded modules with their names, WITHOUT extension 9 | class ModuleList 10 | { 11 | public: 12 | enum class SearchLocation 13 | { 14 | All, 15 | LocalOnly, 16 | SystemOnly, 17 | }; 18 | 19 | // Initializes module list 20 | // Needs to be called before any calls to Get or GetAll 21 | void Enumerate(SearchLocation location = SearchLocation::All) 22 | { 23 | constexpr size_t INITIAL_SIZE = sizeof(HMODULE) * 256; 24 | HMODULE* modules = static_cast(malloc(INITIAL_SIZE)); 25 | if (modules != nullptr) 26 | { 27 | typedef BOOL(WINAPI * Func)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded); 28 | 29 | HMODULE hLib = LoadLibrary(TEXT("kernel32")); 30 | assert(hLib != nullptr); // If this fails then everything is probably broken anyway 31 | 32 | Func pEnumProcessModules = reinterpret_cast(GetProcAddress(hLib, "K32EnumProcessModules")); 33 | if (pEnumProcessModules == nullptr) 34 | { 35 | // Try psapi 36 | FreeLibrary(hLib); 37 | hLib = LoadLibrary(TEXT("psapi")); 38 | if (hLib != nullptr) 39 | { 40 | pEnumProcessModules = reinterpret_cast(GetProcAddress(hLib, "EnumProcessModules")); 41 | } 42 | } 43 | 44 | if (pEnumProcessModules != nullptr) 45 | { 46 | const HANDLE currentProcess = GetCurrentProcess(); 47 | DWORD cbNeeded = 0; 48 | if (pEnumProcessModules(currentProcess, modules, INITIAL_SIZE, &cbNeeded) != 0) 49 | { 50 | if (cbNeeded > INITIAL_SIZE) 51 | { 52 | HMODULE* newModules = static_cast(realloc(modules, cbNeeded)); 53 | if (newModules != nullptr) 54 | { 55 | modules = newModules; 56 | 57 | if (pEnumProcessModules(currentProcess, modules, cbNeeded, &cbNeeded) != 0) 58 | { 59 | EnumerateInternal(modules, location, cbNeeded / sizeof(HMODULE)); 60 | } 61 | } 62 | } 63 | else 64 | { 65 | EnumerateInternal(modules, location, cbNeeded / sizeof(HMODULE)); 66 | } 67 | } 68 | } 69 | 70 | if (hLib != nullptr) 71 | { 72 | FreeLibrary(hLib); 73 | } 74 | 75 | free(modules); 76 | } 77 | } 78 | 79 | // Recreates module list 80 | void ReEnumerate(SearchLocation location = SearchLocation::All) 81 | { 82 | Clear(); 83 | Enumerate(location); 84 | } 85 | 86 | // Clears module list 87 | void Clear() 88 | { 89 | m_moduleList.clear(); 90 | } 91 | 92 | // Gets handle of a loaded module with given name, NULL otherwise 93 | HMODULE Get(const wchar_t* moduleName) const 94 | { 95 | // If vector is empty then we're trying to call it without calling Enumerate first 96 | assert(m_moduleList.size() != 0); 97 | 98 | auto it = std::find_if(m_moduleList.begin(), m_moduleList.end(), [&](const auto& e) { 99 | return _wcsicmp(moduleName, std::get<1>(e).c_str()) == 0; 100 | }); 101 | return it != m_moduleList.end() ? std::get<0>(*it) : nullptr; 102 | } 103 | 104 | // Gets handles to all loaded modules with given name 105 | std::vector GetAll(const wchar_t* moduleName) const 106 | { 107 | // If vector is empty then we're trying to call it without calling Enumerate first 108 | assert(m_moduleList.size() != 0); 109 | 110 | std::vector results; 111 | for (auto& e : m_moduleList) 112 | { 113 | if (_wcsicmp(moduleName, std::get<1>(e).c_str()) == 0) 114 | { 115 | results.push_back(std::get<0>(e)); 116 | } 117 | } 118 | 119 | return results; 120 | } 121 | 122 | private: 123 | void EnumerateInternal(HMODULE* modules, SearchLocation location, size_t numModules) 124 | { 125 | auto GetModuleFileNameW = [](HMODULE hModule) -> std::wstring 126 | { 127 | static constexpr auto INITIAL_BUFFER_SIZE = MAX_PATH; 128 | static constexpr auto MAX_ITERATIONS = 7; 129 | std::wstring ret; 130 | auto bufferSize = INITIAL_BUFFER_SIZE; 131 | for (size_t iterations = 0; iterations < MAX_ITERATIONS; ++iterations) 132 | { 133 | ret.resize(bufferSize); 134 | auto charsReturned = ::GetModuleFileNameW(hModule, &ret[0], bufferSize); 135 | if (charsReturned < ret.length()) 136 | { 137 | ret.resize(charsReturned); 138 | return ret; 139 | } 140 | else 141 | { 142 | bufferSize *= 2; 143 | } 144 | } 145 | return L""; 146 | }; 147 | 148 | const auto exeModulePath = GetModuleFileNameW(NULL).substr(0, GetModuleFileNameW(NULL).find_last_of(L"/\\")); 149 | 150 | m_moduleList.reserve(numModules); 151 | for (size_t i = 0; i < numModules; i++) 152 | { 153 | // Obtain module name, with resizing if necessary 154 | auto moduleName = GetModuleFileNameW(*modules); 155 | 156 | if (!moduleName.empty()) 157 | { 158 | auto starts_with = [](const std::wstring &big_str, const std::wstring &small_str) -> bool 159 | { 160 | return big_str.compare(0, small_str.length(), small_str) == 0; 161 | }; 162 | 163 | const wchar_t* nameBegin = wcsrchr(moduleName.c_str(), '\\') + 1; 164 | const wchar_t* dotPos = wcsrchr(nameBegin, '.'); 165 | bool isLocal = starts_with(std::wstring(moduleName), exeModulePath); 166 | 167 | if ((isLocal && location != SearchLocation::SystemOnly) || (!isLocal && location != SearchLocation::LocalOnly)) 168 | { 169 | if (dotPos != nullptr) 170 | { 171 | m_moduleList.emplace_back(*modules, std::wstring(nameBegin, dotPos), isLocal); 172 | } 173 | else 174 | { 175 | m_moduleList.emplace_back(*modules, nameBegin, isLocal); 176 | } 177 | } 178 | } 179 | 180 | modules++; 181 | } 182 | } 183 | 184 | public: std::vector< std::tuple > m_moduleList; 185 | }; -------------------------------------------------------------------------------- /includes/Randomizer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "FileHooks.h" 4 | #include 5 | 6 | struct RandomizerSettings { 7 | bool bInGameOptions; 8 | bool bRandomEnemies; 9 | bool bRandomPlayerModels; 10 | bool bRandomItems; 11 | bool bRandomDamage; 12 | bool bExtraContent; 13 | bool bEnableHauntings; 14 | bool bFastSplash; 15 | bool bFogApproaches; 16 | int iGlobalSeed; 17 | }; 18 | 19 | extern RandomizerSettings settings; 20 | 21 | extern std::mt19937 mainRng; 22 | 23 | // generates a 1 or 0 24 | extern std::uniform_int_distribution boolGenerator; 25 | 26 | // generators for vanilla enemies, items, and consumables 27 | extern std::uniform_int_distribution enemyGenerator; 28 | extern std::uniform_int_distribution consumableGenerator; 29 | extern std::uniform_int_distribution weaponGenerator; 30 | 31 | // generators for custom items/enemies/etc. 32 | extern std::uniform_int_distribution customWeaponGenerator; 33 | 34 | extern PlayerModel currentPlayerModel; 35 | 36 | void InitializeRandomness(); 37 | void ReseedRNG(unsigned int seed); -------------------------------------------------------------------------------- /includes/license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 ThirteenAG 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 | -------------------------------------------------------------------------------- /includes/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if _DEBUG 4 | #define DBGONLY(x) x 5 | #define KEYPRESS(x) if (GetAsyncKeyState(x) & 0x8000) 6 | #define SPDLOG_WCHAR_FILENAMES 7 | #include "spdlog/spdlog.h" 8 | 9 | class spd 10 | { 11 | public: 12 | static const std::shared_ptr& log() 13 | { 14 | static const auto log = spdlog::basic_logger_mt("basic_logger", spd::GetLogName(), true); 15 | spdlog::set_pattern("%v"); 16 | return log; 17 | } 18 | 19 | private: 20 | inline static const std::wstring GetLogName() 21 | { 22 | HMODULE hm = NULL; 23 | GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)&GetLogName, &hm); 24 | std::wstring ret; 25 | ret.resize(MAX_PATH); 26 | GetModuleFileNameW(hm, &ret[0], ret.size()); 27 | ret = ret.substr(0, ret.find_last_of('.')) + L".log"; 28 | return ret; 29 | } 30 | }; 31 | #else 32 | #define DBGONLY(x) 33 | #endif -------------------------------------------------------------------------------- /includes/plog/Appenders/AndroidAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | template 8 | class AndroidAppender : public IAppender 9 | { 10 | public: 11 | AndroidAppender(const char* tag) : m_tag(tag) 12 | { 13 | } 14 | 15 | virtual void write(const Record& record) 16 | { 17 | std::string str = Formatter::format(record); 18 | 19 | __android_log_print(toPriority(record.getSeverity()), m_tag, "%s", str.c_str()); 20 | } 21 | 22 | private: 23 | static android_LogPriority toPriority(Severity severity) 24 | { 25 | switch (severity) 26 | { 27 | case fatal: 28 | return ANDROID_LOG_FATAL; 29 | case error: 30 | return ANDROID_LOG_ERROR; 31 | case warning: 32 | return ANDROID_LOG_WARN; 33 | case info: 34 | return ANDROID_LOG_INFO; 35 | case debug: 36 | return ANDROID_LOG_DEBUG; 37 | case verbose: 38 | return ANDROID_LOG_VERBOSE; 39 | default: 40 | return ANDROID_LOG_UNKNOWN; 41 | } 42 | } 43 | 44 | private: 45 | const char* const m_tag; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /includes/plog/Appenders/ColorConsoleAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | template 8 | class ColorConsoleAppender : public ConsoleAppender 9 | { 10 | public: 11 | #ifdef _WIN32 12 | # ifdef _MSC_VER 13 | # pragma warning(suppress: 26812) // Prefer 'enum class' over 'enum' 14 | # endif 15 | ColorConsoleAppender(OutputStream outStream = streamStdOut) 16 | : ConsoleAppender(outStream) 17 | , m_originalAttr() 18 | { 19 | if (this->m_isatty) 20 | { 21 | CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 22 | GetConsoleScreenBufferInfo(this->m_outputHandle, &csbiInfo); 23 | 24 | m_originalAttr = csbiInfo.wAttributes; 25 | } 26 | } 27 | #else 28 | ColorConsoleAppender(OutputStream outStream = streamStdOut) 29 | : ConsoleAppender(outStream) 30 | {} 31 | #endif 32 | 33 | virtual void write(const Record& record) 34 | { 35 | util::nstring str = Formatter::format(record); 36 | util::MutexLock lock(this->m_mutex); 37 | 38 | setColor(record.getSeverity()); 39 | this->writestr(str); 40 | resetColor(); 41 | } 42 | 43 | protected: 44 | void setColor(Severity severity) 45 | { 46 | if (this->m_isatty) 47 | { 48 | switch (severity) 49 | { 50 | #ifdef _WIN32 51 | case fatal: 52 | SetConsoleTextAttribute(this->m_outputHandle, foreground::kRed | foreground::kGreen | foreground::kBlue | foreground::kIntensity | background::kRed); // white on red background 53 | break; 54 | 55 | case error: 56 | SetConsoleTextAttribute(this->m_outputHandle, static_cast(foreground::kRed | foreground::kIntensity | (m_originalAttr & 0xf0))); // red 57 | break; 58 | 59 | case warning: 60 | SetConsoleTextAttribute(this->m_outputHandle, static_cast(foreground::kRed | foreground::kGreen | foreground::kIntensity | (m_originalAttr & 0xf0))); // yellow 61 | break; 62 | 63 | case debug: 64 | case verbose: 65 | SetConsoleTextAttribute(this->m_outputHandle, static_cast(foreground::kGreen | foreground::kBlue | foreground::kIntensity | (m_originalAttr & 0xf0))); // cyan 66 | break; 67 | #else 68 | case fatal: 69 | this->m_outputStream << "\x1B[97m\x1B[41m"; // white on red background 70 | break; 71 | 72 | case error: 73 | this->m_outputStream << "\x1B[91m"; // red 74 | break; 75 | 76 | case warning: 77 | this->m_outputStream << "\x1B[93m"; // yellow 78 | break; 79 | 80 | case debug: 81 | case verbose: 82 | this->m_outputStream << "\x1B[96m"; // cyan 83 | break; 84 | #endif 85 | default: 86 | break; 87 | } 88 | } 89 | } 90 | 91 | void resetColor() 92 | { 93 | if (this->m_isatty) 94 | { 95 | #ifdef _WIN32 96 | SetConsoleTextAttribute(this->m_outputHandle, m_originalAttr); 97 | #else 98 | this->m_outputStream << "\x1B[0m\x1B[0K"; 99 | #endif 100 | } 101 | } 102 | 103 | private: 104 | #ifdef _WIN32 105 | WORD m_originalAttr; 106 | #endif 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /includes/plog/Appenders/ConsoleAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace plog 8 | { 9 | enum OutputStream 10 | { 11 | streamStdOut, 12 | streamStdErr 13 | }; 14 | 15 | template 16 | class ConsoleAppender : public IAppender 17 | { 18 | public: 19 | #ifdef _WIN32 20 | # ifdef _MSC_VER 21 | # pragma warning(suppress: 26812) // Prefer 'enum class' over 'enum' 22 | # endif 23 | ConsoleAppender(OutputStream outStream = streamStdOut) 24 | : m_isatty(!!_isatty(_fileno(outStream == streamStdOut ? stdout : stderr))) 25 | , m_outputStream(outStream == streamStdOut ? std::cout : std::cerr) 26 | , m_outputHandle() 27 | { 28 | if (m_isatty) 29 | { 30 | m_outputHandle = GetStdHandle(outStream == streamStdOut ? stdHandle::kOutput : stdHandle::kErrorOutput); 31 | } 32 | } 33 | #else 34 | ConsoleAppender(OutputStream outStream = streamStdOut) 35 | : m_isatty(!!isatty(fileno(outStream == streamStdOut ? stdout : stderr))) 36 | , m_outputStream(outStream == streamStdOut ? std::cout : std::cerr) 37 | {} 38 | #endif 39 | 40 | virtual void write(const Record& record) 41 | { 42 | util::nstring str = Formatter::format(record); 43 | util::MutexLock lock(m_mutex); 44 | 45 | writestr(str); 46 | } 47 | 48 | protected: 49 | void writestr(const util::nstring& str) 50 | { 51 | #ifdef _WIN32 52 | if (m_isatty) 53 | { 54 | WriteConsoleW(m_outputHandle, str.c_str(), static_cast(str.size()), NULL, NULL); 55 | } 56 | else 57 | { 58 | m_outputStream << util::toNarrow(str, codePage::kActive) << std::flush; 59 | } 60 | #else 61 | m_outputStream << str << std::flush; 62 | #endif 63 | } 64 | 65 | private: 66 | #ifdef __BORLANDC__ 67 | static int _isatty(int fd) { return ::isatty(fd); } 68 | #endif 69 | 70 | protected: 71 | util::Mutex m_mutex; 72 | const bool m_isatty; 73 | std::ostream& m_outputStream; 74 | #ifdef _WIN32 75 | HANDLE m_outputHandle; 76 | #endif 77 | }; 78 | } 79 | -------------------------------------------------------------------------------- /includes/plog/Appenders/DebugOutputAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | template 8 | class DebugOutputAppender : public IAppender 9 | { 10 | public: 11 | virtual void write(const Record& record) 12 | { 13 | OutputDebugStringW(Formatter::format(record).c_str()); 14 | } 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /includes/plog/Appenders/EventLogAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | template 8 | class EventLogAppender : public IAppender 9 | { 10 | public: 11 | EventLogAppender(const wchar_t* sourceName) : m_eventSource(RegisterEventSourceW(NULL, sourceName)) 12 | { 13 | } 14 | 15 | ~EventLogAppender() 16 | { 17 | DeregisterEventSource(m_eventSource); 18 | } 19 | 20 | virtual void write(const Record& record) 21 | { 22 | std::wstring str = Formatter::format(record); 23 | const wchar_t* logMessagePtr[] = { str.c_str() }; 24 | 25 | ReportEventW(m_eventSource, logSeverityToType(record.getSeverity()), static_cast(record.getSeverity()), 0, NULL, 1, 0, logMessagePtr, NULL); 26 | } 27 | 28 | private: 29 | static WORD logSeverityToType(plog::Severity severity) 30 | { 31 | switch (severity) 32 | { 33 | case plog::fatal: 34 | case plog::error: 35 | return eventLog::kErrorType; 36 | 37 | case plog::warning: 38 | return eventLog::kWarningType; 39 | 40 | case plog::info: 41 | case plog::debug: 42 | case plog::verbose: 43 | default: 44 | return eventLog::kInformationType; 45 | } 46 | } 47 | 48 | private: 49 | HANDLE m_eventSource; 50 | }; 51 | 52 | class EventLogAppenderRegistry 53 | { 54 | public: 55 | static bool add(const wchar_t* sourceName, const wchar_t* logName = L"Application") 56 | { 57 | std::wstring logKeyName; 58 | std::wstring sourceKeyName; 59 | getKeyNames(sourceName, logName, sourceKeyName, logKeyName); 60 | 61 | HKEY sourceKey; 62 | if (0 != RegCreateKeyExW(hkey::kLocalMachine, sourceKeyName.c_str(), 0, NULL, 0, regSam::kSetValue, NULL, &sourceKey, NULL)) 63 | { 64 | return false; 65 | } 66 | 67 | const DWORD kTypesSupported = eventLog::kErrorType | eventLog::kWarningType | eventLog::kInformationType; 68 | RegSetValueExW(sourceKey, L"TypesSupported", 0, regType::kDword, reinterpret_cast(&kTypesSupported), sizeof(kTypesSupported)); 69 | 70 | const wchar_t kEventMessageFile[] = L"%windir%\\Microsoft.NET\\Framework\\v4.0.30319\\EventLogMessages.dll;%windir%\\Microsoft.NET\\Framework\\v2.0.50727\\EventLogMessages.dll"; 71 | RegSetValueExW(sourceKey, L"EventMessageFile", 0, regType::kExpandSz, reinterpret_cast(kEventMessageFile), sizeof(kEventMessageFile) - sizeof(*kEventMessageFile)); 72 | 73 | RegCloseKey(sourceKey); 74 | return true; 75 | } 76 | 77 | static bool exists(const wchar_t* sourceName, const wchar_t* logName = L"Application") 78 | { 79 | std::wstring logKeyName; 80 | std::wstring sourceKeyName; 81 | getKeyNames(sourceName, logName, sourceKeyName, logKeyName); 82 | 83 | HKEY sourceKey; 84 | if (0 != RegOpenKeyExW(hkey::kLocalMachine, sourceKeyName.c_str(), 0, regSam::kQueryValue, &sourceKey)) 85 | { 86 | return false; 87 | } 88 | 89 | RegCloseKey(sourceKey); 90 | return true; 91 | } 92 | 93 | static void remove(const wchar_t* sourceName, const wchar_t* logName = L"Application") 94 | { 95 | std::wstring logKeyName; 96 | std::wstring sourceKeyName; 97 | getKeyNames(sourceName, logName, sourceKeyName, logKeyName); 98 | 99 | RegDeleteKeyW(hkey::kLocalMachine, sourceKeyName.c_str()); 100 | RegDeleteKeyW(hkey::kLocalMachine, logKeyName.c_str()); 101 | } 102 | 103 | private: 104 | static void getKeyNames(const wchar_t* sourceName, const wchar_t* logName, std::wstring& sourceKeyName, std::wstring& logKeyName) 105 | { 106 | const std::wstring kPrefix = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\"; 107 | logKeyName = kPrefix + logName; 108 | sourceKeyName = logKeyName + L"\\" + sourceName; 109 | } 110 | }; 111 | } 112 | -------------------------------------------------------------------------------- /includes/plog/Appenders/IAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | class PLOG_LINKAGE IAppender 8 | { 9 | public: 10 | virtual ~IAppender() 11 | { 12 | } 13 | 14 | virtual void write(const Record& record) = 0; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /includes/plog/Appenders/RollingFileAppender.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace plog 9 | { 10 | template > 11 | class RollingFileAppender : public IAppender 12 | { 13 | public: 14 | RollingFileAppender(const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) 15 | : m_fileSize() 16 | , m_maxFileSize() 17 | , m_maxFiles(maxFiles) 18 | , m_firstWrite(true) 19 | { 20 | setFileName(fileName); 21 | setMaxFileSize(maxFileSize); 22 | } 23 | 24 | #ifdef _WIN32 25 | RollingFileAppender(const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) 26 | : m_fileSize() 27 | , m_maxFileSize() 28 | , m_maxFiles(maxFiles) 29 | , m_firstWrite(true) 30 | { 31 | setFileName(fileName); 32 | setMaxFileSize(maxFileSize); 33 | } 34 | #endif 35 | 36 | virtual void write(const Record& record) 37 | { 38 | util::MutexLock lock(m_mutex); 39 | 40 | if (m_firstWrite) 41 | { 42 | openLogFile(); 43 | m_firstWrite = false; 44 | } 45 | else if (m_maxFiles > 0 && m_fileSize > m_maxFileSize && static_cast(-1) != m_fileSize) 46 | { 47 | rollLogFiles(); 48 | } 49 | 50 | size_t bytesWritten = m_file.write(Converter::convert(Formatter::format(record))); 51 | 52 | if (static_cast(-1) != bytesWritten) 53 | { 54 | m_fileSize += bytesWritten; 55 | } 56 | } 57 | 58 | void setFileName(const util::nchar* fileName) 59 | { 60 | util::MutexLock lock(m_mutex); 61 | 62 | util::splitFileName(fileName, m_fileNameNoExt, m_fileExt); 63 | 64 | m_file.close(); 65 | m_firstWrite = true; 66 | } 67 | 68 | #ifdef _WIN32 69 | void setFileName(const char* fileName) 70 | { 71 | setFileName(util::toWide(fileName).c_str()); 72 | } 73 | #endif 74 | 75 | void setMaxFiles(int maxFiles) 76 | { 77 | m_maxFiles = maxFiles; 78 | } 79 | 80 | void setMaxFileSize(size_t maxFileSize) 81 | { 82 | m_maxFileSize = (std::max)(maxFileSize, static_cast(1000)); // set a lower limit for the maxFileSize 83 | } 84 | 85 | void rollLogFiles() 86 | { 87 | m_file.close(); 88 | 89 | util::nstring lastFileName = buildFileName(m_maxFiles - 1); 90 | util::File::unlink(lastFileName.c_str()); 91 | 92 | for (int fileNumber = m_maxFiles - 2; fileNumber >= 0; --fileNumber) 93 | { 94 | util::nstring currentFileName = buildFileName(fileNumber); 95 | util::nstring nextFileName = buildFileName(fileNumber + 1); 96 | 97 | util::File::rename(currentFileName.c_str(), nextFileName.c_str()); 98 | } 99 | 100 | openLogFile(); 101 | m_firstWrite = false; 102 | } 103 | 104 | private: 105 | void openLogFile() 106 | { 107 | util::nstring fileName = buildFileName(); 108 | m_fileSize = m_file.open(fileName.c_str()); 109 | 110 | if (0 == m_fileSize) 111 | { 112 | size_t bytesWritten = m_file.write(Converter::header(Formatter::header())); 113 | 114 | if (static_cast(-1) != bytesWritten) 115 | { 116 | m_fileSize += bytesWritten; 117 | } 118 | } 119 | } 120 | 121 | util::nstring buildFileName(int fileNumber = 0) 122 | { 123 | util::nostringstream ss; 124 | ss << m_fileNameNoExt; 125 | 126 | if (fileNumber > 0) 127 | { 128 | ss << '.' << fileNumber; 129 | } 130 | 131 | if (!m_fileExt.empty()) 132 | { 133 | ss << '.' << m_fileExt; 134 | } 135 | 136 | return ss.str(); 137 | } 138 | 139 | private: 140 | util::Mutex m_mutex; 141 | util::File m_file; 142 | size_t m_fileSize; 143 | size_t m_maxFileSize; 144 | int m_maxFiles; 145 | util::nstring m_fileExt; 146 | util::nstring m_fileNameNoExt; 147 | bool m_firstWrite; 148 | }; 149 | } 150 | -------------------------------------------------------------------------------- /includes/plog/Converters/NativeEOLConverter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | template 8 | class NativeEOLConverter : public NextConverter 9 | { 10 | #ifdef _WIN32 11 | public: 12 | static std::string header(const util::nstring& str) 13 | { 14 | return NextConverter::header(fixLineEndings(str)); 15 | } 16 | 17 | static std::string convert(const util::nstring& str) 18 | { 19 | return NextConverter::convert(fixLineEndings(str)); 20 | } 21 | 22 | private: 23 | static std::wstring fixLineEndings(const std::wstring& str) 24 | { 25 | std::wstring output; 26 | output.reserve(str.length() * 2); 27 | 28 | for (size_t i = 0; i < str.size(); ++i) 29 | { 30 | wchar_t ch = str[i]; 31 | 32 | if (ch == L'\n') 33 | { 34 | output.push_back(L'\r'); 35 | } 36 | 37 | output.push_back(ch); 38 | } 39 | 40 | return output; 41 | } 42 | #endif 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /includes/plog/Converters/UTF8Converter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace plog 5 | { 6 | class UTF8Converter 7 | { 8 | public: 9 | static std::string header(const util::nstring& str) 10 | { 11 | const char kBOM[] = "\xEF\xBB\xBF"; 12 | 13 | return std::string(kBOM) + convert(str); 14 | } 15 | 16 | #ifdef _WIN32 17 | static std::string convert(const util::nstring& str) 18 | { 19 | return util::toNarrow(str, codePage::kUTF8); 20 | } 21 | #else 22 | static const std::string& convert(const util::nstring& str) 23 | { 24 | return str; 25 | } 26 | #endif 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /includes/plog/Formatters/CsvFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace plog 7 | { 8 | template 9 | class CsvFormatterImpl 10 | { 11 | public: 12 | static util::nstring header() 13 | { 14 | return PLOG_NSTR("Date;Time;Severity;TID;This;Function;Message\n"); 15 | } 16 | 17 | static util::nstring format(const Record& record) 18 | { 19 | tm t; 20 | useUtcTime ? util::gmtime_s(&t, &record.getTime().time) : util::localtime_s(&t, &record.getTime().time); 21 | 22 | util::nostringstream ss; 23 | ss << t.tm_year + 1900 << PLOG_NSTR("/") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mon + 1 << PLOG_NSTR("/") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mday << PLOG_NSTR(";"); 24 | ss << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_hour << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_min << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_sec << PLOG_NSTR(".") << std::setfill(PLOG_NSTR('0')) << std::setw(3) << static_cast (record.getTime().millitm) << PLOG_NSTR(";"); 25 | ss << severityToString(record.getSeverity()) << PLOG_NSTR(";"); 26 | ss << record.getTid() << PLOG_NSTR(";"); 27 | ss << record.getObject() << PLOG_NSTR(";"); 28 | ss << record.getFunc() << PLOG_NSTR("@") << record.getLine() << PLOG_NSTR(";"); 29 | 30 | util::nstring message = record.getMessage(); 31 | 32 | if (message.size() > kMaxMessageSize) 33 | { 34 | message.resize(kMaxMessageSize); 35 | message.append(PLOG_NSTR("...")); 36 | } 37 | 38 | util::nistringstream split(message); 39 | util::nstring token; 40 | 41 | while (!split.eof()) 42 | { 43 | std::getline(split, token, PLOG_NSTR('"')); 44 | ss << PLOG_NSTR("\"") << token << PLOG_NSTR("\""); 45 | } 46 | 47 | ss << PLOG_NSTR("\n"); 48 | 49 | return ss.str(); 50 | } 51 | 52 | static const size_t kMaxMessageSize = 32000; 53 | }; 54 | 55 | class CsvFormatter : public CsvFormatterImpl {}; 56 | class CsvFormatterUtcTime : public CsvFormatterImpl {}; 57 | } 58 | -------------------------------------------------------------------------------- /includes/plog/Formatters/FuncMessageFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | class FuncMessageFormatter 8 | { 9 | public: 10 | static util::nstring header() 11 | { 12 | return util::nstring(); 13 | } 14 | 15 | static util::nstring format(const Record& record) 16 | { 17 | util::nostringstream ss; 18 | ss << record.getFunc() << PLOG_NSTR("@") << record.getLine() << PLOG_NSTR(": ") << record.getMessage() << PLOG_NSTR("\n"); 19 | 20 | return ss.str(); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /includes/plog/Formatters/MessageOnlyFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace plog 6 | { 7 | class MessageOnlyFormatter 8 | { 9 | public: 10 | static util::nstring header() 11 | { 12 | return util::nstring(); 13 | } 14 | 15 | static util::nstring format(const Record& record) 16 | { 17 | util::nostringstream ss; 18 | ss << record.getMessage() << PLOG_NSTR("\n"); 19 | 20 | return ss.str(); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /includes/plog/Formatters/TxtFormatter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace plog 7 | { 8 | template 9 | class TxtFormatterImpl 10 | { 11 | public: 12 | static util::nstring header() 13 | { 14 | return util::nstring(); 15 | } 16 | 17 | static util::nstring format(const Record& record) 18 | { 19 | tm t; 20 | useUtcTime ? util::gmtime_s(&t, &record.getTime().time) : util::localtime_s(&t, &record.getTime().time); 21 | 22 | util::nostringstream ss; 23 | ss << t.tm_year + 1900 << "-" << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mon + 1 << PLOG_NSTR("-") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_mday << PLOG_NSTR(" "); 24 | ss << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_hour << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_min << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << t.tm_sec << PLOG_NSTR(".") << std::setfill(PLOG_NSTR('0')) << std::setw(3) << static_cast (record.getTime().millitm) << PLOG_NSTR(" "); 25 | ss << std::setfill(PLOG_NSTR(' ')) << std::setw(5) << std::left << severityToString(record.getSeverity()) << PLOG_NSTR(" "); 26 | ss << PLOG_NSTR("[") << record.getTid() << PLOG_NSTR("] "); 27 | ss << PLOG_NSTR("[") << record.getFunc() << PLOG_NSTR("@") << record.getLine() << PLOG_NSTR("] "); 28 | ss << record.getMessage() << PLOG_NSTR("\n"); 29 | 30 | return ss.str(); 31 | } 32 | }; 33 | 34 | class TxtFormatter : public TxtFormatterImpl {}; 35 | class TxtFormatterUtcTime : public TxtFormatterImpl {}; 36 | } 37 | -------------------------------------------------------------------------------- /includes/plog/Init.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace plog 5 | { 6 | template 7 | inline Logger& init(Severity maxSeverity = none, IAppender* appender = NULL) 8 | { 9 | static Logger logger(maxSeverity); 10 | return appender ? logger.addAppender(appender) : logger; 11 | } 12 | 13 | inline Logger& init(Severity maxSeverity = none, IAppender* appender = NULL) 14 | { 15 | return init(maxSeverity, appender); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /includes/plog/Initializers/RollingFileInitializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace plog 9 | { 10 | ////////////////////////////////////////////////////////////////////////// 11 | // RollingFileAppender with any Formatter 12 | 13 | template 14 | inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) 15 | { 16 | static RollingFileAppender rollingFileAppender(fileName, maxFileSize, maxFiles); 17 | return init(maxSeverity, &rollingFileAppender); 18 | } 19 | 20 | template 21 | inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) 22 | { 23 | return init(maxSeverity, fileName, maxFileSize, maxFiles); 24 | } 25 | 26 | ////////////////////////////////////////////////////////////////////////// 27 | // RollingFileAppender with TXT/CSV chosen by file extension 28 | 29 | namespace 30 | { 31 | inline bool isCsv(const util::nchar* fileName) 32 | { 33 | const util::nchar* dot = util::findExtensionDot(fileName); 34 | #ifdef _WIN32 35 | return dot && 0 == std::wcscmp(dot, L".csv"); 36 | #else 37 | return dot && 0 == std::strcmp(dot, ".csv"); 38 | #endif 39 | } 40 | } 41 | 42 | template 43 | inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) 44 | { 45 | return isCsv(fileName) ? init(maxSeverity, fileName, maxFileSize, maxFiles) : init(maxSeverity, fileName, maxFileSize, maxFiles); 46 | } 47 | 48 | inline Logger& init(Severity maxSeverity, const util::nchar* fileName, size_t maxFileSize = 0, int maxFiles = 0) 49 | { 50 | return init(maxSeverity, fileName, maxFileSize, maxFiles); 51 | } 52 | 53 | ////////////////////////////////////////////////////////////////////////// 54 | // CHAR variants for Windows 55 | 56 | #ifdef _WIN32 57 | template 58 | inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) 59 | { 60 | return init(maxSeverity, util::toWide(fileName).c_str(), maxFileSize, maxFiles); 61 | } 62 | 63 | template 64 | inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) 65 | { 66 | return init(maxSeverity, fileName, maxFileSize, maxFiles); 67 | } 68 | 69 | template 70 | inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) 71 | { 72 | return init(maxSeverity, util::toWide(fileName).c_str(), maxFileSize, maxFiles); 73 | } 74 | 75 | inline Logger& init(Severity maxSeverity, const char* fileName, size_t maxFileSize = 0, int maxFiles = 0) 76 | { 77 | return init(maxSeverity, fileName, maxFileSize, maxFiles); 78 | } 79 | #endif 80 | } 81 | -------------------------------------------------------------------------------- /includes/plog/Logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef PLOG_DEFAULT_INSTANCE // for backward compatibility 7 | # define PLOG_DEFAULT_INSTANCE_ID PLOG_DEFAULT_INSTANCE 8 | #endif 9 | 10 | #ifndef PLOG_DEFAULT_INSTANCE_ID 11 | # define PLOG_DEFAULT_INSTANCE_ID 0 12 | #endif 13 | 14 | namespace plog 15 | { 16 | template 17 | class PLOG_LINKAGE Logger : public util::Singleton >, public IAppender 18 | { 19 | public: 20 | Logger(Severity maxSeverity = none) : m_maxSeverity(maxSeverity) 21 | { 22 | } 23 | 24 | Logger& addAppender(IAppender* appender) 25 | { 26 | assert(appender != this); 27 | m_appenders.push_back(appender); 28 | return *this; 29 | } 30 | 31 | Severity getMaxSeverity() const 32 | { 33 | return m_maxSeverity; 34 | } 35 | 36 | void setMaxSeverity(Severity severity) 37 | { 38 | m_maxSeverity = severity; 39 | } 40 | 41 | bool checkSeverity(Severity severity) const 42 | { 43 | return severity <= m_maxSeverity; 44 | } 45 | 46 | virtual void write(const Record& record) 47 | { 48 | if (checkSeverity(record.getSeverity())) 49 | { 50 | *this += record; 51 | } 52 | } 53 | 54 | void operator+=(const Record& record) 55 | { 56 | for (std::vector::iterator it = m_appenders.begin(); it != m_appenders.end(); ++it) 57 | { 58 | (*it)->write(record); 59 | } 60 | } 61 | 62 | private: 63 | Severity m_maxSeverity; 64 | #ifdef _MSC_VER 65 | # pragma warning(push) 66 | # pragma warning(disable:4251) // needs to have dll-interface to be used by clients of class 67 | #endif 68 | std::vector m_appenders; 69 | #ifdef _MSC_VER 70 | # pragma warning(pop) 71 | #endif 72 | }; 73 | 74 | template 75 | inline Logger* get() 76 | { 77 | return Logger::getInstance(); 78 | } 79 | 80 | inline Logger* get() 81 | { 82 | return Logger::getInstance(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /includes/plog/Record.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef __cplusplus_cli 7 | #include // For PtrToStringChars 8 | #endif 9 | 10 | namespace plog 11 | { 12 | namespace detail 13 | { 14 | namespace meta 15 | { 16 | template 17 | inline T& declval() 18 | { 19 | #ifdef __INTEL_COMPILER 20 | # pragma warning(suppress: 327) // NULL reference is not allowed 21 | #endif 22 | return *reinterpret_cast(0); 23 | } 24 | 25 | template 26 | struct enableIf {}; 27 | 28 | template 29 | struct enableIf { typedef T type; }; 30 | } 31 | 32 | ////////////////////////////////////////////////////////////////////////// 33 | // Stream output operators as free functions 34 | 35 | #if PLOG_ENABLE_WCHAR_INPUT 36 | inline void operator<<(util::nostringstream& stream, const wchar_t* data) 37 | { 38 | data = data ? data : L"(null)"; 39 | 40 | # ifdef _WIN32 41 | std::operator<<(stream, data); 42 | # else 43 | std::operator<<(stream, util::toNarrow(data)); 44 | # endif 45 | } 46 | 47 | inline void operator<<(util::nostringstream& stream, wchar_t* data) 48 | { 49 | plog::detail::operator<<(stream, const_cast(data)); 50 | } 51 | 52 | inline void operator<<(util::nostringstream& stream, const std::wstring& data) 53 | { 54 | plog::detail::operator<<(stream, data.c_str()); 55 | } 56 | #endif 57 | 58 | inline void operator<<(util::nostringstream& stream, const char* data) 59 | { 60 | data = data ? data : "(null)"; 61 | 62 | #if defined(_WIN32) && defined(__BORLANDC__) 63 | stream << util::toWide(data); 64 | #elif defined(_WIN32) 65 | std::operator<<(stream, util::toWide(data)); 66 | #else 67 | std::operator<<(stream, data); 68 | #endif 69 | } 70 | 71 | inline void operator<<(util::nostringstream& stream, char* data) 72 | { 73 | plog::detail::operator<<(stream, const_cast(data)); 74 | } 75 | 76 | inline void operator<<(util::nostringstream& stream, const std::string& data) 77 | { 78 | plog::detail::operator<<(stream, data.c_str()); 79 | } 80 | 81 | #if defined(__clang__) || !defined(__GNUC__) || __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 4 // skip for GCC < 4.5 due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38600 82 | template 83 | inline typename meta::enableIf >(meta::declval())) + sizeof(T*)), void>::type operator<<(util::nostringstream& stream, const T& data) 84 | { 85 | plog::detail::operator<<(stream, static_cast >(data)); 86 | } 87 | #endif 88 | 89 | #ifdef __cplusplus_cli 90 | inline void operator<<(util::nostringstream& stream, System::String^ data) 91 | { 92 | cli::pin_ptr ptr = PtrToStringChars(data); 93 | plog::detail::operator<<(stream, static_cast(ptr)); 94 | } 95 | #endif 96 | 97 | #ifdef _WIN32 98 | namespace meta 99 | { 100 | template 101 | inline char operator<<(Stream&, const T&); 102 | 103 | template 104 | struct isStreamable 105 | { 106 | enum { value = sizeof(operator<<(meta::declval(), meta::declval())) != sizeof(char) }; 107 | }; 108 | 109 | template 110 | struct isStreamable 111 | { 112 | enum { value = true }; 113 | }; 114 | 115 | template 116 | struct isStreamable 117 | { 118 | enum { value = false }; 119 | }; 120 | 121 | template 122 | struct isStreamable 123 | { 124 | enum { value = false }; 125 | }; 126 | } 127 | 128 | template 129 | inline typename meta::enableIf::value && !meta::isStreamable::value, void>::type operator<<(std::wostringstream& stream, const T& data) 130 | { 131 | std::ostringstream ss; 132 | ss << data; 133 | stream << ss.str(); 134 | } 135 | #endif 136 | } 137 | 138 | class Record 139 | { 140 | public: 141 | Record(Severity severity, const char* func, size_t line, const char* file, const void* object, int instanceId) 142 | : m_severity(severity), m_tid(util::gettid()), m_object(object), m_line(line), m_func(func), m_file(file), m_instanceId(instanceId) 143 | { 144 | util::ftime(&m_time); 145 | } 146 | 147 | Record& ref() 148 | { 149 | return *this; 150 | } 151 | 152 | ////////////////////////////////////////////////////////////////////////// 153 | // Stream output operators 154 | 155 | Record& operator<<(char data) 156 | { 157 | char str[] = { data, 0 }; 158 | return *this << str; 159 | } 160 | 161 | #if PLOG_ENABLE_WCHAR_INPUT 162 | Record& operator<<(wchar_t data) 163 | { 164 | wchar_t str[] = { data, 0 }; 165 | return *this << str; 166 | } 167 | #endif 168 | 169 | #ifdef _WIN32 170 | Record& operator<<(std::wostream& (*data)(std::wostream&)) 171 | #else 172 | Record& operator<<(std::ostream& (*data)(std::ostream&)) 173 | #endif 174 | { 175 | m_message << data; 176 | return *this; 177 | } 178 | 179 | #ifdef QT_VERSION 180 | Record& operator<<(const QString& data) 181 | { 182 | # ifdef _WIN32 183 | return *this << data.toStdWString(); 184 | # else 185 | return *this << data.toStdString(); 186 | # endif 187 | } 188 | 189 | # if QT_VERSION < 0x060000 190 | Record& operator<<(const QStringRef& data) 191 | { 192 | return *this << data.toString(); 193 | } 194 | # endif 195 | 196 | # ifdef QSTRINGVIEW_H 197 | Record& operator<<(QStringView data) 198 | { 199 | return *this << data.toString(); 200 | } 201 | # endif 202 | #endif 203 | 204 | template 205 | Record& operator<<(const T& data) 206 | { 207 | using namespace plog::detail; 208 | 209 | m_message << data; 210 | return *this; 211 | } 212 | 213 | #ifndef __cplusplus_cli 214 | Record& printf(const char* format, ...) 215 | { 216 | using namespace util; 217 | 218 | char* str = NULL; 219 | va_list ap; 220 | 221 | va_start(ap, format); 222 | int len = vasprintf(&str, format, ap); 223 | static_cast(len); 224 | va_end(ap); 225 | 226 | *this << str; 227 | free(str); 228 | 229 | return *this; 230 | } 231 | 232 | #ifdef _WIN32 233 | Record& printf(const wchar_t* format, ...) 234 | { 235 | using namespace util; 236 | 237 | wchar_t* str = NULL; 238 | va_list ap; 239 | 240 | va_start(ap, format); 241 | int len = vaswprintf(&str, format, ap); 242 | static_cast(len); 243 | va_end(ap); 244 | 245 | *this << str; 246 | free(str); 247 | 248 | return *this; 249 | } 250 | #endif 251 | #endif //__cplusplus_cli 252 | 253 | ////////////////////////////////////////////////////////////////////////// 254 | // Getters 255 | 256 | virtual const util::Time& getTime() const 257 | { 258 | return m_time; 259 | } 260 | 261 | virtual Severity getSeverity() const 262 | { 263 | return m_severity; 264 | } 265 | 266 | virtual unsigned int getTid() const 267 | { 268 | return m_tid; 269 | } 270 | 271 | virtual const void* getObject() const 272 | { 273 | return m_object; 274 | } 275 | 276 | virtual size_t getLine() const 277 | { 278 | return m_line; 279 | } 280 | 281 | virtual const util::nchar* getMessage() const 282 | { 283 | m_messageStr = m_message.str(); 284 | return m_messageStr.c_str(); 285 | } 286 | 287 | virtual const char* getFunc() const 288 | { 289 | m_funcStr = util::processFuncName(m_func); 290 | return m_funcStr.c_str(); 291 | } 292 | 293 | virtual const char* getFile() const 294 | { 295 | return m_file; 296 | } 297 | 298 | virtual ~Record() // virtual destructor to satisfy -Wnon-virtual-dtor warning 299 | { 300 | } 301 | 302 | virtual int getInstanceId() const 303 | { 304 | return m_instanceId; 305 | } 306 | 307 | private: 308 | util::Time m_time; 309 | const Severity m_severity; 310 | const unsigned int m_tid; 311 | const void* const m_object; 312 | const size_t m_line; 313 | util::nostringstream m_message; 314 | const char* const m_func; 315 | const char* const m_file; 316 | const int m_instanceId; 317 | mutable std::string m_funcStr; 318 | mutable util::nstring m_messageStr; 319 | }; 320 | } 321 | -------------------------------------------------------------------------------- /includes/plog/Severity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace plog 5 | { 6 | enum Severity 7 | { 8 | none = 0, 9 | fatal = 1, 10 | error = 2, 11 | warning = 3, 12 | info = 4, 13 | debug = 5, 14 | verbose = 6 15 | }; 16 | 17 | #ifdef _MSC_VER 18 | # pragma warning(suppress: 26812) // Prefer 'enum class' over 'enum' 19 | #endif 20 | inline const char* severityToString(Severity severity) 21 | { 22 | switch (severity) 23 | { 24 | case fatal: 25 | return "FATAL"; 26 | case error: 27 | return "ERROR"; 28 | case warning: 29 | return "WARN"; 30 | case info: 31 | return "INFO"; 32 | case debug: 33 | return "DEBUG"; 34 | case verbose: 35 | return "VERB"; 36 | default: 37 | return "NONE"; 38 | } 39 | } 40 | 41 | inline Severity severityFromString(const char* str) 42 | { 43 | switch (std::toupper(str[0])) 44 | { 45 | case 'F': 46 | return fatal; 47 | case 'E': 48 | return error; 49 | case 'W': 50 | return warning; 51 | case 'I': 52 | return info; 53 | case 'D': 54 | return debug; 55 | case 'V': 56 | return verbose; 57 | default: 58 | return none; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /includes/plog/WinApi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _WIN32 4 | 5 | // These windows structs must be in a global namespace 6 | struct HKEY__; 7 | struct _SECURITY_ATTRIBUTES; 8 | struct _CONSOLE_SCREEN_BUFFER_INFO; 9 | struct _RTL_CRITICAL_SECTION; 10 | 11 | namespace plog 12 | { 13 | typedef unsigned long DWORD; 14 | typedef unsigned short WORD; 15 | typedef unsigned char BYTE; 16 | typedef unsigned int UINT; 17 | typedef int BOOL; 18 | typedef long LSTATUS; 19 | typedef char* LPSTR; 20 | typedef wchar_t* LPWSTR; 21 | typedef const char* LPCSTR; 22 | typedef const wchar_t* LPCWSTR; 23 | typedef void* HANDLE; 24 | typedef HKEY__* HKEY; 25 | typedef size_t ULONG_PTR; 26 | 27 | struct CRITICAL_SECTION 28 | { 29 | void* DebugInfo; 30 | long LockCount; 31 | long RecursionCount; 32 | HANDLE OwningThread; 33 | HANDLE LockSemaphore; 34 | ULONG_PTR SpinCount; 35 | }; 36 | 37 | struct COORD 38 | { 39 | short X; 40 | short Y; 41 | }; 42 | 43 | struct SMALL_RECT 44 | { 45 | short Left; 46 | short Top; 47 | short Right; 48 | short Bottom; 49 | }; 50 | 51 | struct CONSOLE_SCREEN_BUFFER_INFO 52 | { 53 | COORD dwSize; 54 | COORD dwCursorPosition; 55 | WORD wAttributes; 56 | SMALL_RECT srWindow; 57 | COORD dwMaximumWindowSize; 58 | }; 59 | 60 | namespace codePage 61 | { 62 | const UINT kActive = 0; 63 | const UINT kUTF8 = 65001; 64 | } 65 | 66 | namespace eventLog 67 | { 68 | const WORD kErrorType = 0x0001; 69 | const WORD kWarningType = 0x0002; 70 | const WORD kInformationType = 0x0004; 71 | } 72 | 73 | namespace hkey 74 | { 75 | const HKEY kLocalMachine = reinterpret_cast(static_cast(0x80000002)); 76 | } 77 | 78 | namespace regSam 79 | { 80 | const DWORD kQueryValue = 0x0001; 81 | const DWORD kSetValue = 0x0002; 82 | } 83 | 84 | namespace regType 85 | { 86 | const DWORD kExpandSz = 2; 87 | const DWORD kDword = 4; 88 | } 89 | 90 | namespace stdHandle 91 | { 92 | const DWORD kOutput = static_cast(-11); 93 | const DWORD kErrorOutput = static_cast(-12); 94 | } 95 | 96 | namespace foreground 97 | { 98 | const WORD kBlue = 0x0001; 99 | const WORD kGreen = 0x0002; 100 | const WORD kRed = 0x0004; 101 | const WORD kIntensity = 0x0008; 102 | } 103 | 104 | namespace background 105 | { 106 | const WORD kBlue = 0x0010; 107 | const WORD kGreen = 0x0020; 108 | const WORD kRed = 0x0040; 109 | const WORD kIntensity = 0x0080; 110 | } 111 | 112 | extern "C" 113 | { 114 | __declspec(dllimport) int __stdcall MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar); 115 | __declspec(dllimport) int __stdcall WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, const char* lpDefaultChar, BOOL* lpUsedDefaultChar); 116 | 117 | __declspec(dllimport) DWORD __stdcall GetCurrentThreadId(); 118 | 119 | __declspec(dllimport) BOOL __stdcall MoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName); 120 | 121 | __declspec(dllimport) void __stdcall InitializeCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); 122 | __declspec(dllimport) void __stdcall EnterCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); 123 | __declspec(dllimport) void __stdcall LeaveCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); 124 | __declspec(dllimport) void __stdcall DeleteCriticalSection(_RTL_CRITICAL_SECTION* lpCriticalSection); 125 | 126 | __declspec(dllimport) HANDLE __stdcall RegisterEventSourceW(LPCWSTR lpUNCServerName, LPCWSTR lpSourceName); 127 | __declspec(dllimport) BOOL __stdcall DeregisterEventSource(HANDLE hEventLog); 128 | __declspec(dllimport) BOOL __stdcall ReportEventW(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, void* lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCWSTR* lpStrings, void* lpRawData); 129 | 130 | __declspec(dllimport) LSTATUS __stdcall RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, DWORD samDesired, _SECURITY_ATTRIBUTES* lpSecurityAttributes, HKEY* phkResult, DWORD* lpdwDisposition); 131 | __declspec(dllimport) LSTATUS __stdcall RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData); 132 | __declspec(dllimport) LSTATUS __stdcall RegCloseKey(HKEY hKey); 133 | __declspec(dllimport) LSTATUS __stdcall RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, DWORD samDesired, HKEY* phkResult); 134 | __declspec(dllimport) LSTATUS __stdcall RegDeleteKeyW(HKEY hKey, LPCWSTR lpSubKey); 135 | 136 | __declspec(dllimport) HANDLE __stdcall GetStdHandle(DWORD nStdHandle); 137 | 138 | __declspec(dllimport) BOOL __stdcall WriteConsoleW(HANDLE hConsoleOutput, const void* lpBuffer, DWORD nNumberOfCharsToWrite, DWORD* lpNumberOfCharsWritten, void* lpReserved); 139 | __declspec(dllimport) BOOL __stdcall GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, _CONSOLE_SCREEN_BUFFER_INFO* lpConsoleScreenBufferInfo); 140 | __declspec(dllimport) BOOL __stdcall SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes); 141 | 142 | __declspec(dllimport) void __stdcall OutputDebugStringW(LPCWSTR lpOutputString); 143 | } 144 | 145 | inline void InitializeCriticalSection(CRITICAL_SECTION* criticalSection) 146 | { 147 | plog::InitializeCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); 148 | } 149 | 150 | inline void EnterCriticalSection(CRITICAL_SECTION* criticalSection) 151 | { 152 | plog::EnterCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); 153 | } 154 | 155 | inline void LeaveCriticalSection(CRITICAL_SECTION* criticalSection) 156 | { 157 | plog::LeaveCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); 158 | } 159 | 160 | inline void DeleteCriticalSection(CRITICAL_SECTION* criticalSection) 161 | { 162 | plog::DeleteCriticalSection(reinterpret_cast<_RTL_CRITICAL_SECTION*>(criticalSection)); 163 | } 164 | 165 | inline BOOL GetConsoleScreenBufferInfo(HANDLE consoleOutput, CONSOLE_SCREEN_BUFFER_INFO* consoleScreenBufferInfo) 166 | { 167 | return plog::GetConsoleScreenBufferInfo(consoleOutput, reinterpret_cast<_CONSOLE_SCREEN_BUFFER_INFO*>(consoleScreenBufferInfo)); 168 | } 169 | } 170 | #endif // _WIN32 171 | -------------------------------------------------------------------------------- /includes/sh4/game/effect/particle/spray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | #include "sh4/sys/apps/sf_obj.h" 5 | 6 | struct SplayCmnData 7 | { 8 | float PolyLen; 9 | float PolyAreaAddSpd; 10 | float PtclLifeTime; 11 | Color Rgba; 12 | float UseDragRate; 13 | }; 14 | 15 | extern void InitializeSprayFunctions(); 16 | 17 | extern sfObj* sprayObj; 18 | 19 | extern int is_spraying_hyperspray; 20 | 21 | extern Color origSprayColor; 22 | extern Color greenSprayColor; 23 | 24 | extern injector::hook_back PlayerSpray_Start; 25 | extern injector::hook_back PlayerSpray_Stop; 26 | extern injector::hook_back PlayerSpray_PosAndSpeedSet; 27 | extern injector::hook_back SupportParticle_CmnData; 28 | extern injector::hook_back SplayParticle_GeneratePosSpdSet; 29 | -------------------------------------------------------------------------------- /includes/sh4/game/eileen/eileen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct EileenWork 4 | { 5 | float* life; 6 | float* life_max; 7 | float curse_value; 8 | float curse_value_current; 9 | float curse_value_base; 10 | float total_damage; 11 | }; -------------------------------------------------------------------------------- /includes/sh4/game/enemy/en_battle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum BattleAttackKind : unsigned char 4 | { 5 | BAK_NOTHING, 6 | BAK_UNDEFINED, 7 | BAK_PLAYER_TABLE_START, 8 | BAK_PLAYER_HAND_GUN = 0x2, 9 | BAK_PLAYER_REVOLVER, 10 | BAK_PLAYER_PIPE, 11 | BAK_PLAYER_PIPE_ST, 12 | BAK_PLAYER_CUTTER, 13 | BAK_PLAYER_CUTTER_ST, 14 | BAK_PLAYER_BAT, 15 | BAK_PLAYER_BAT_ST, 16 | BAK_PLAYER_DRIVER, 17 | BAK_PLAYER_DRIVER_ST, 18 | BAK_PLAYER_SPOON, 19 | BAK_PLAYER_SPOON_ST, 20 | BAK_PLAYER_MID_MASHY, 21 | BAK_PLAYER_MID_MASHY_ST, 22 | BAK_PLAYER_MASHY_IRON, 23 | BAK_PLAYER_MASHY_IRON_ST, 24 | BAK_PLAYER_MASHY, 25 | BAK_PLAYER_MASHY_ST, 26 | BAK_PLAYER_SPADE_MASHY, 27 | BAK_PLAYER_SPADE_MASHY_ST, 28 | BAK_PLAYER_MASHY_NIBLICK, 29 | BAK_PLAYER_MASHY_NIBLICK_ST, 30 | BAK_PLAYER_PITCHER, 31 | BAK_PLAYER_PITCHER_ST, 32 | BAK_PLAYER_NIBLICK, 33 | BAK_PLAYER_NIBLICK_ST, 34 | BAK_PLAYER_PITCHING_WEDGE, 35 | BAK_PLAYER_PITCHING_WEDGE_ST, 36 | BAK_PLAYER_SAND_WEDGE, 37 | BAK_PLAYER_SAND_WEDGE_ST, 38 | BAK_PLAYER_PUTTER, 39 | BAK_PLAYER_PUTTER_ST, 40 | BAK_PLAYER_BOTTLE, 41 | BAK_PLAYER_BROKEN_BOTTLE, 42 | BAK_PLAYER_SCOOP, 43 | BAK_PLAYER_SCOOP_ST, 44 | BAK_PLAYER_HATCHET, 45 | BAK_PLAYER_HATCHET_ST, 46 | BAK_PLAYER_PICK, 47 | BAK_PLAYER_PICK_ST, 48 | BAK_PLAYER_STUNGUN, 49 | BAK_PLAYER_SPRAY, 50 | BAK_PLAYER_CHAINSAW, 51 | BAK_PLAYER_CHAINSAW_ST, 52 | BAK_PLAYER_WOOD_STICK, 53 | BAK_PLAYER_SILVER_BULLET, 54 | BAK_PLAYER_FINISH, 55 | BAK_PLAYER_SCOOP_FINISH, 56 | BAK_PLAYER_PICK_FINISH, 57 | BAK_PLAYER_CHAINSAW_FINISH, 58 | BAK_PLAYER_EIL_HANDBAG_N, 59 | BAK_PLAYER_EIL_HANDBAG_3_1, 60 | BAK_PLAYER_EIL_HANDBAG_3_2, 61 | BAK_PLAYER_EIL_HANDBAG_3_3, 62 | BAK_PLAYER_EIL_HANDBAG_FINISH, 63 | BAK_PLAYER_EIL_CLUB_N, 64 | BAK_PLAYER_EIL_CLUB_3_1, 65 | BAK_PLAYER_EIL_CLUB_3_2, 66 | BAK_PLAYER_EIL_CLUB_3_3, 67 | BAK_PLAYER_EIL_CLUB_FINISH, 68 | BAK_PLAYER_EIL_ROD_N, 69 | BAK_PLAYER_EIL_ROD_3_1, 70 | BAK_PLAYER_EIL_ROD_3_2, 71 | BAK_PLAYER_EIL_ROD_3_3, 72 | BAK_PLAYER_EIL_ROD_FINISH, 73 | BAK_PLAYER_EIL_CHAIN_N, 74 | BAK_PLAYER_EIL_CHAIN_3_1, 75 | BAK_PLAYER_EIL_CHAIN_3_2, 76 | BAK_PLAYER_EIL_CHAIN_3_3, 77 | BAK_PLAYER_EIL_CHAIN_FINISH, 78 | BAK_PLAYER_EIL_GUN_N, 79 | BAK_PLAYER_TABLE_END = 0x48, 80 | BAK_ENEMY_TABLE_START, 81 | BAK_MUSH_DEATH = 0x49, 82 | BAK_BUZZ_BLOODSUCK, 83 | BAK_BUZZ_PECK, 84 | BAK_BUZZ_DIVE, 85 | BAK_KABE_STRIKE, 86 | BAK_KABE_BRINGDOWN, 87 | BAK_KABE_SIDEBLOW, 88 | BAK_KABE_HEADBUTT, 89 | BAK_WHEEL_DASH, 90 | BAK_JIN_SCRATCH, 91 | BAK_JIN_STRIKE, 92 | BAK_JIN_STAB, 93 | BAK_JIN_BRINGDOWN, 94 | BAK_TWN_STRIKE, 95 | BAK_TWN_JUMP, 96 | BAK_TWN_TURN, 97 | BAK_HIL_WALL, 98 | BAK_HIL_FLOOR, 99 | BAK_HYENA_DASH, 100 | BAK_MULTI_HEADBUTT, 101 | BAK_FLAMES_ATT1, 102 | BAK_FLAMES_ATT2, 103 | BAK_FAT_SING, 104 | BAK_FAT_DASH, 105 | BAK_FAT_DASH2, 106 | BAK_FAT_BOMB, 107 | BAK_SCR_ATT1, 108 | BAK_SCR_ATT2, 109 | BAK_SCR_ATT4, 110 | BAK_KILLER_SHOOT, 111 | BAK_KILLER_RAPIDFIRE, 112 | BAK_KILLER_PIPE, 113 | BAK_KILLER_PIPE_ST, 114 | BAK_KILLER_CHAINSAW_STAB, 115 | BAK_KILLER_CHAINSAW_SHAKE, 116 | BAK_KILLER_BLOWOFF, 117 | BAK_ENEMY_TABLE_END = 0x6c, 118 | BAK_OTHER_TABLE_START, 119 | BAK_GHOSTSTAIN_FLICK = 0x6d, 120 | BAK_OTHER_TABLE_END = 0x6d, 121 | BAK_MAX_NUMBER 122 | }; -------------------------------------------------------------------------------- /includes/sh4/game/enemy/en_kind.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum EnemyKind : unsigned char 4 | { 5 | ENEMY_KIND_NOTHING, 6 | ENEMY_KIND_CELL, 7 | ENEMY_KIND_MUSH, 8 | ENEMY_KIND_BUZZ, 9 | ENEMY_KIND_MM, 10 | ENEMY_KIND_WALLMAN, 11 | ENEMY_KIND_WHEEL, 12 | ENEMY_KIND_JINMEN, 13 | ENEMY_KIND_TWINS, 14 | ENEMY_KIND_HIL, 15 | ENEMY_KIND_HYENA, 16 | ENEMY_KIND_MULTI, 17 | ENEMY_KIND_PICKGIRL, 18 | ENEMY_KIND_FLAMES, 19 | ENEMY_KIND_FAT, 20 | ENEMY_KIND_SCRATCH, 21 | ENEMY_KIND_KILLER, 22 | ENEMY_KIND_NURSE, 23 | ENEMY_KIND_SAMPLE, 24 | ENEMY_KIND_MAX, 25 | ENEMY_KIND_TEST00 = 0, 26 | ENEMY_KIND_ALL = 0x13 27 | }; 28 | 29 | struct EnemyFileMapping 30 | { 31 | EnemyKind kind; 32 | std::vector fileIds; 33 | unsigned int tableAddr; 34 | }; 35 | 36 | struct EnemyKindTableEntry 37 | { 38 | unsigned int* sfConstructor; 39 | unsigned int* objConstructor; 40 | unsigned int* objDestructor; 41 | unsigned int* objDraw; 42 | }; 43 | 44 | enum EnemySeKind : unsigned char 45 | { 46 | ENEMY_SE_KIND_NOTHING, 47 | ENEMY_SE_KIND_CELL, 48 | ENEMY_SE_KIND_MUSH, 49 | ENEMY_SE_KIND_BUZZ, 50 | ENEMY_SE_KIND_MM, 51 | ENEMY_SE_KIND_WALLMAN, 52 | ENEMY_SE_KIND_WHEEL, 53 | ENEMY_SE_KIND_JINMEN, 54 | ENEMY_SE_KIND_TWINS, 55 | ENEMY_SE_KIND_HIL, 56 | ENEMY_SE_KIND_HYENA, 57 | ENEMY_SE_KIND_MULTI, 58 | ENEMY_SE_KIND_PICKGIRL, 59 | ENEMY_SE_KIND_FLAMES, 60 | ENEMY_SE_KIND_FAT, 61 | ENEMY_SE_KIND_SCRATCH, 62 | ENEMY_SE_KIND_KILLER0, 63 | ENEMY_SE_KIND_KILLER1, 64 | ENEMY_SE_KIND_KILLER2, 65 | ENEMY_SE_KIND_KILLER3, 66 | ENEMY_SE_KIND_NURSE, 67 | ENEMY_SE_KIND_MAX 68 | }; 69 | 70 | extern const std::vector possibleEnemies; 71 | extern injector::hook_back EnemyKindTableGetAddress; 72 | unsigned int __cdecl EnemyKindTableGetAddressHook(EnemyKind enemyType); 73 | void InitializeEnemyKindFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/camera/game_camera_another_engine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "CommonTypes.h" 3 | 4 | extern injector::hook_back CameraEngine_SetCameraPosition; 5 | void __cdecl CameraEngine_SetCameraPositionHook(Position* pos, unsigned int ContinueMvMode); 6 | void InitializeGameCameraFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/game.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sh4/game/gamemain/game_fileread.h" 4 | #include "sh4/game/player/player.h" 5 | 6 | enum ActionLevel : int 7 | { 8 | NONE, 9 | EASY, 10 | NORMAL, 11 | HARD 12 | }; 13 | 14 | struct _GAME_WORK 15 | { 16 | int init_at_cold[1]; 17 | int logo_displayed; 18 | int init_at_warm[1]; 19 | int game_init_executed; 20 | void* warm_memory_top; 21 | int load_stage_start; 22 | int continue_play; 23 | int game_overed; 24 | int risky_continue_count; 25 | ActionLevel level; 26 | int init_at_game[1]; 27 | void* game_memory_top; 28 | GameStage stage; 29 | int scene; 30 | int prev_scene; 31 | int prev_stage; 32 | int next_stage; 33 | int next_scene; 34 | int start_door; 35 | int world; 36 | int real_scene; 37 | float current_camera_mtx[4][4]; 38 | float next_camera_mtx[4][4]; 39 | float game_camera_back[4][4]; 40 | float game_view_angle; 41 | float game_view_angle_back; 42 | float map_offset[4]; 43 | int unk; 44 | float unk2[4]; 45 | _PLAYER_WORK* player; 46 | int control; 47 | int player_pos; 48 | unsigned int next_flags; 49 | int gameover; 50 | int gameover_ok; 51 | int game_complete; 52 | int gauge; 53 | int event_disable; 54 | int eileen_status; 55 | int cynthia_status; 56 | int pause_disable_contine; 57 | unsigned int play_time; 58 | unsigned int continue_count; 59 | unsigned int killed_enemy; 60 | unsigned int held_ghost; 61 | int update_continue; 62 | int continue_item; 63 | int now_peeping; 64 | unsigned int pre_eil_timer; 65 | unsigned int eil_interval; 66 | int pre_demo_index; 67 | unsigned int pre_demo_type; 68 | unsigned int pre_door_timer; 69 | unsigned int door_interval; 70 | unsigned int pre_door_demo_no; 71 | int init_at_stage[1]; 72 | void* stage_memory_top; 73 | int stage_data_save; 74 | int init_at_scene[1]; 75 | void* scene_memory_top; 76 | void* snap_texture_load_buffer; 77 | int game_mode; 78 | int shadow_density; 79 | int door_move_disable; 80 | int fog_effect_off; 81 | int init_at_loop[1]; 82 | int game_in_action; 83 | int player_touch_door_no; 84 | int* passing_door; 85 | int work_end[1]; 86 | int open_door_sn; 87 | int open_door_dn; 88 | int close_door_se_disable; 89 | int close_door_se_reserve; 90 | }; 91 | 92 | extern _GAME_WORK* gameW; -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/game_demo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sh4/game/gamemain/game_item.h" 3 | 4 | struct DemoCharaListEntry 5 | { 6 | unsigned int chara_id; 7 | unsigned int model_id; 8 | unsigned int tex_id; 9 | unsigned int svm_id; 10 | }; 11 | 12 | extern injector::hook_back DemoGetCharacterFileInfo; 13 | DemoCharaListEntry* __cdecl DemoGetCharacterFileInfoHook(DemoCharaListEntry* entry, int chara_id); 14 | 15 | void InitializeGameDemoFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/game_fileread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum GameStage : int { 4 | GAME_STAGE_DUMMY, 5 | GAME_STAGE_3LDK, 6 | GAME_STAGE_SUBWAY, 7 | GAME_STAGE_FOREST, 8 | GAME_STAGE_WATER, 9 | GAME_STAGE_BUILDING, 10 | GAME_STAGE_HOME, 11 | GAME_STAGE_HOSPITAL, 12 | GAME_STAGE_PAST_HOME, 13 | GAME_STAGE_LAST, 14 | GAME_STAGE_TUNNEL, 15 | GAME_STAGE_SPIRAL, 16 | GAME_STAGE_TEST, 17 | GAME_STAGE_MAX 18 | }; 19 | 20 | extern std::vector stageNames; 21 | extern injector::hook_back GameFileLoadScene; 22 | extern injector::hook_back GameFileLoadStage; 23 | void __cdecl GameFileLoadSceneHook(GameStage stage, int scene); 24 | void __cdecl GameFileLoadStageHook(GameStage stage); 25 | 26 | void InitializeGameFileReadFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/game_gi_para.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sh4/game/gamemain/game_item.h" 4 | 5 | struct _ItemMsgCtrlDt 6 | { 7 | int* cmd; 8 | short id; 9 | }; 10 | 11 | struct _GetItemParamFileDt 12 | { 13 | unsigned int model_id; 14 | unsigned int tex_id; 15 | GameItem item; 16 | }; 17 | 18 | extern std::vector<_GetItemParamFileDt> item_param_fileid; 19 | extern std::vector<_GetItemParamFileDt> item_param_fileid_default; 20 | 21 | extern injector::hook_back GameGetItemParamTexId; 22 | unsigned int GameGetItemParamTexIdHook(GameItem item); 23 | 24 | extern injector::hook_back GameGetItemParamModelId; 25 | unsigned int GameGetItemParamModelIdHook(GameItem item); 26 | 27 | //extern injector::hook_back<_ItemMsgCtrlDt* (__cdecl*)(GameItem)> GameGetItemMsgCtrlDt; 28 | //_ItemMsgCtrlDt* GameGetItemMsgCtrlDtHook(GameItem item); 29 | 30 | void InitializeGameGIParaFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/game_item.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum GameItem : unsigned char 4 | { 5 | ITEM_EMPTY, 6 | ITEM_SMALL_BULLET, 7 | ITEM_LARGE_BULLET, 8 | ITEM_SILVER_BULLET, 9 | ITEM_HOLY_CANDLE, 10 | ITEM_FINISHER, 11 | ITEM_RED_CHRISM, 12 | ITEM_LOADS_PRAYER, 13 | ITEM_SAINT_MEDALLION, 14 | ITEM_HEALTH_DRINK, 15 | ITEM_AMPLE, 16 | ITEM_FIRST_AID_KIT, 17 | ITEM_HANDGUN = 0x10, 18 | ITEM_REVOLVER, 19 | ITEM_IRON_PIPE, 20 | ITEM_CUTTER_KNIFE, 21 | ITEM_METAL_BAT, 22 | ITEM_DRIVER, 23 | ITEM_DRIVER_BROKEN, 24 | ITEM_SPOON, 25 | ITEM_SPOON_BROKEN, 26 | ITEM_MID_MASHY, 27 | ITEM_MID_MASHY_BROKEN, 28 | ITEM_MASHY_IRON, 29 | ITEM_MASHY_IRON_BROKEN, 30 | ITEM_MASHY, 31 | ITEM_MASHY_BROKEN, 32 | ITEM_SPADE_MASHY, 33 | ITEM_SPADE_MASHY_BROKEN, 34 | ITEM_MASHY_NIBLICK, 35 | ITEM_MASHY_NIBLICK_BROKEN, 36 | ITEM_PITCHER, 37 | ITEM_PITCHER_BROKEN, 38 | ITEM_NIBLICK, 39 | ITEM_NIBLICK_BROKEN, 40 | ITEM_PITCHING_WEDGE, 41 | ITEM_PITCHING_WEDGE_BROKEN, 42 | ITEM_SAND_WEDGE, 43 | ITEM_SAND_WEDGE_BROKEN, 44 | ITEM_PUTTER, 45 | ITEM_PUTTER_BROKEN, 46 | ITEM_WINE_BOTTLE, 47 | ITEM_WINE_BOTTLE_BROKEN, 48 | ITEM_SCOOP, 49 | ITEM_RUSTY_HATCHET, 50 | ITEM_PICK_OF_DESPAIR, 51 | ITEM_STUN_GUN, 52 | ITEM_SPRAY, 53 | ITEM_CLUB, 54 | ITEM_CHAIN_SAW, 55 | ITEM_KEY_OF_LIBERATION = 0x3c, 56 | ITEM_COIN_OF_LYNCHSTREETLINE, 57 | ITEM_CHOCOLATE_MILK, 58 | ITEM_SHOVEL_WITH_BLOOD_CHARACTER, 59 | ITEM_RUSTY_BLOODY_KEY, 60 | ITEM_RED_PAPER_1, 61 | ITEM_RED_PAPER_2, 62 | ITEM_RED_PAPER_3, 63 | ITEM_RED_PAPER_4, 64 | ITEM_RED_PAPER_5, 65 | ITEM_RED_PAPER_6, 66 | ITEM_TORN_RED_PAPER_1, 67 | ITEM_TORN_RED_PAPER_2, 68 | ITEM_TORN_RED_PAPER_MISS, 69 | ITEM_KEY_OF_SUPERINTENDANT, 70 | ITEM_KEY_ROCKER106, 71 | ITEM_CASSETTE_TAPE, 72 | ITEM_KEY_WITH_DOLL, 73 | ITEM_CHARM_OF_SUCCUBUS, 74 | ITEM_KEY_OF_SICKROOM, 75 | ITEM_RED_ENVELOPE, 76 | ITEM_SMALL_KEY, 77 | ITEM_CYNTHIAS_PASS, 78 | ITEM_OLD_DOLL, 79 | ITEM_MASTER_KEY_TO_APART, 80 | ITEM_ARMORIAL_MEDAL, 81 | ITEM_PICK_OF_HOPE, 82 | ITEM_NAVEL_STRING, 83 | ITEM_ALESSAS_SPEAR, 84 | ITEM_DIRTY_ENVELOPE, 85 | ITEM_TOY_KEY, 86 | ITEM_1SS_COIN_DIRTY, 87 | ITEM_1SS_COIN, 88 | ITEM_SB24_KEY, 89 | ITEM_HANDLE, 90 | ITEM_DOLLS_HEAD, 91 | ITEM_DOLLS_RIGHT_ARM, 92 | ITEM_DOLLS_LEFT_ARM, 93 | ITEM_DOLLS_RIGHT_LEG, 94 | ITEM_DOLLS_LEFT_LEG, 95 | ITEM_UNDERGROUND_KEY, 96 | ITEM_PRISONERS_SHIRT, 97 | ITEM_BILLIARD_BALL, 98 | ITEM_STUFFED_CAT, 99 | ITEM_VOLLEYBALL, 100 | ITEM_SMALL_CANDLE_PACKED, 101 | ITEM_SMALL_CANDLE, 102 | ITEM_GHOSTS_KEY, 103 | ITEM_DIRTY_STONE1, 104 | ITEM_DIRTY_STONE2, 105 | ITEM_DIRTY_STONE3, 106 | ITEM_DIRTY_STONE4, 107 | ITEM_DIRTY_STONE5, 108 | ITEM_CHANNELING_STONE1, 109 | ITEM_CHANNELING_STONE2, 110 | ITEM_CHANNELING_STONE3, 111 | ITEM_CHANNELING_STONE4, 112 | ITEM_CHANNELING_STONE5, 113 | ITEM_PLATE_OF_TEMPTATION, 114 | ITEM_PLATE_OF_ORIGIN, 115 | ITEM_PLATE_OF_SURVEILLANCE, 116 | ITEM_PLATE_OF_CHAOS, 117 | ITEM_ALBERT_SPORTS_KEY, 118 | ITEM_UNIFORM, 119 | ITEM_MZ_UPPER_KEY, 120 | ITEM_TRAILER_KEY, 121 | ITEM_HANDBAG = 0x80, 122 | ITEM_SUBMACHINEGUN, 123 | ITEM_BLACKJACK, 124 | ITEM_HORSEWHIP, 125 | ITEM_CHAIN, 126 | ITEM_FIRST_LETTER = 0x88, 127 | ITEM_SCRAP_OF_BOOK, 128 | ITEM_RED_DIARY_0408, 129 | ITEM_RED_DIARY_0404, 130 | ITEM_SCRAP_OF_BIBLE, 131 | ITEM_DIARY_OF_NEIGHBOUR, 132 | ITEM_SUPERINTENDANTS_MEMO, 133 | ITEM_SUPERINTENDANTS_DIARY, 134 | ITEM_RED_DIARY_0502, 135 | ITEM_RED_DIARY_0514, 136 | ITEM_RED_DIARY_0520, 137 | ITEM_SCRAP_OF_RED_DIARY, 138 | ITEM_SCRAP_OF_RED_DIARY_2, 139 | ITEM_MIKES_LOVELETTER, 140 | ITEM_RED_DIARY_0713, 141 | ITEM_RED_DIARY_0720, 142 | ITEM_HOLY_MOTHER_21_SACRAMENTS, 143 | ITEM_RED_BOOK, 144 | ITEM_PICTURE_BOOK, 145 | ITEM_RED_DIARY_0611, 146 | ITEM_RED_DIARY_0614, 147 | ITEM_RED_DIARY_SOMETIMEAGO, 148 | ITEM_RED_DIARY_0717, 149 | ITEM_RED_DIARY_0718, 150 | ITEM_RED_DIARY_0723, 151 | ITEM_RED_DIARY_0725, 152 | ITEM_RED_DIARY_0728, 153 | ITEM_RED_DIARY_0729, 154 | ITEM_RED_DIARY_0802, 155 | ITEM_RED_DIARY_0803, 156 | ITEM_RED_DIARY_0804, 157 | ITEM_RED_DIARY_0805, 158 | ITEM_RED_DIARY_0807, 159 | ITEM_SUPERINTENDANTS_DIARY_COUT, 160 | ITEM_JOSEPHS_LETTER, 161 | ITEM_JOSEPHS_REPORT, 162 | ITEM_NURSE_MEMO, 163 | ITEM_CHILD_LETTER, 164 | ITEM_BLOODY_SHIRT, 165 | ITEM_BARTENDERS_MEMO, 166 | ITEM_BARTENDERS_MEMO2, 167 | ITEM_MEMOIRS, 168 | ITEM_JASPERS_MEMO, 169 | ITEM_BURNED_OUT_MEMO, 170 | ITEM_DOLLS_TEXT, 171 | ITEM_EXPLORERS_MEMO, 172 | ITEM_SENTINELS_DIARY, 173 | ITEM_PLATE_ABOUT_WATERWHEEL, 174 | ITEM_PRISONERS_DIARY, 175 | ITEM_REPORT_1F, 176 | ITEM_REPORT_2F, 177 | ITEM_PASSWORD_MEMO, 178 | ITEM_BRICK = 0xe4, 179 | ITEM_KILLER_PIPE, 180 | ITEM_KILLER_GUN1, 181 | ITEM_KILLER_GUN2, 182 | ITEM_KIND_MAX, 183 | ITEM_GREEN_HYPER_SPRAY, 184 | ITEM_GOLD_PIPE, 185 | ITEM_SILVER_PIPE, 186 | ITEM_KIND_CUSTOM_MAX 187 | }; 188 | 189 | 190 | enum GameItemAttribute : unsigned char 191 | { 192 | ITEM_ATTR_UNKNOWN, 193 | ITEM_ATTR_WEAPON, 194 | ITEM_ATTR_EIL_WEAPON, 195 | ITEM_ATTR_JOREI, 196 | ITEM_ATTR_RECOVERY, 197 | ITEM_ATTR_KEY, 198 | ITEM_ATTR_MEMO 199 | }; 200 | 201 | enum GameItemResult : int 202 | { 203 | ITEM_RESULT_NONE, 204 | ITEM_RESULT_USE, 205 | ITEM_RESULT_KEY, 206 | ITEM_RESULT_ATTACK, 207 | ITEM_RESULT_WEAPONCHG, 208 | ITEM_RESULT_EILEENS_WEAPON 209 | }; 210 | 211 | struct ItemPossession 212 | { 213 | float durability; 214 | unsigned short num; 215 | GameItem kind; 216 | char work; 217 | }; 218 | 219 | struct GameItemData 220 | { 221 | ItemPossession possession[10]; 222 | ItemPossession box[136]; 223 | unsigned short box_max; 224 | unsigned char handgun_ammo; 225 | unsigned char weapon_kind; 226 | char is_saint_medallion_equiped; 227 | char pad[3]; 228 | unsigned char flag_tbl[136]; 229 | }; 230 | 231 | extern std::vector possibleWeapons; 232 | extern std::vector possibleWeaponsWithExtra; 233 | extern std::unordered_map weaponSwaps; 234 | extern std::unordered_map weaponSwapsWithExtra; 235 | 236 | void InstallItemHooks(); 237 | 238 | extern injector::hook_back GameItemGet; 239 | bool __cdecl GameItemGetHook(GameItem item); 240 | 241 | /// 242 | /// Returns the item's attribute 243 | /// 244 | extern injector::hook_back GameItemGetAttr; 245 | GameItemAttribute __cdecl GameItemGetAttrHook(GameItem item); 246 | 247 | /// 248 | /// Returns whether or not the item is an Eileen weapon 249 | /// 250 | extern injector::hook_back GameItemIsEileenWeapon; 251 | int __cdecl GameItemIsEileenWeaponHook(GameItem item); 252 | 253 | /// 254 | /// Called when the item is used from the item menu 255 | /// 256 | extern injector::hook_back GameItemUseItem; 257 | GameItemResult __cdecl GameItemUseItemHook(int num); 258 | 259 | /// 260 | /// Returns whether or not the item is a weapon 261 | /// 262 | extern injector::hook_back GameItemIsWeapon; 263 | int __cdecl GameItemIsWeaponHook(GameItem item); 264 | 265 | /// 266 | /// Returns whether or not the item should be equippable 267 | /// 268 | extern injector::hook_back GameItemWeaponEquip; 269 | int __cdecl GameItemWeaponEquipHook(int num); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/game_scenelink.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // controls which sound effect is played when the door is entered 4 | enum DoorMaterial : int 5 | { 6 | DOOR_MAT_NONE, 7 | DOOR_MAT_STEEL, 8 | DOOR_MAT_WOOD, 9 | DOOR_MAT_ELEVATOR, 10 | DOOR_MAT_KOSHI, // machine translated as waist? not sure what this is in eng 11 | DOOR_MAT_LARGE, 12 | DOOR_MAT_TRAIN, 13 | DOOR_MAT_MAX 14 | }; 15 | 16 | struct Door { 17 | float bmin[3]; 18 | unsigned char door_no; 19 | unsigned char scene_no; 20 | short door_type; 21 | float bmax[3]; 22 | DoorMaterial door_material; 23 | float start_position[3]; 24 | float start_direction[3]; 25 | }; 26 | 27 | struct SceneData { 28 | int n_doors; 29 | Door doors[1]; 30 | }; 31 | 32 | struct DoorLinkData { 33 | unsigned char start_scene; 34 | unsigned char end_scene; 35 | }; 36 | 37 | struct DoorLinkTableEntry { 38 | int n_scenes; 39 | int n_doorlinks; 40 | DoorLinkData* doorlinks_data_offset; 41 | void* doorlinks_call_functions; 42 | SceneData* scene_data_offsets[1]; 43 | }; 44 | 45 | enum RLPossibleDestinations : char 46 | { 47 | BATHROOM = 2, 48 | BEDROOM = 3, 49 | UTILITY_ROOM = 4 50 | }; 51 | 52 | extern DoorLinkTableEntry* rl_connection_data; 53 | extern DoorLinkTableEntry* sb_connection_data; 54 | extern std::vector rl_possible_destinations; 55 | void InitializeGameSceneLinkFunctions(); 56 | -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/save_data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back sfMcLoad; 4 | extern injector::hook_back sfMcSaveCreate; 5 | int __cdecl sfMcLoadHook(int port, int fn, int file_no); 6 | int __cdecl sfMcSaveCreateHook(int port, int fn, int file_no); 7 | 8 | struct ExtraSaveSettings 9 | { 10 | // all the randomizer toggles + the saves seed 11 | unsigned int seed; 12 | unsigned int randomEnemies; 13 | unsigned int randomModels; 14 | unsigned int randomItems; 15 | unsigned int randomDamage; 16 | unsigned int extraContent; 17 | unsigned int fogApproaches; 18 | 19 | // any future settings or per-save stuff will go here 20 | unsigned int reserved[0x64]; 21 | }; 22 | 23 | extern ExtraSaveSettings perSaveSettings[32]; 24 | 25 | void InitializeSaveDataFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/gamemain/stage_info.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back StageInfoIsLatterHalf; 4 | 5 | extern void InitializeStageInfoFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/message/message_handle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// 4 | /// Shows a message at the specified X/Y coords 5 | /// 6 | extern injector::hook_back MessagePut; 7 | 8 | /// 9 | /// Shows a message in the subtitles style 10 | /// 11 | extern injector::hook_back MessageSubtitlesPut; 12 | 13 | /// 14 | /// Shows a message and needs to be cleared by using MessageClear 15 | /// 16 | extern injector::hook_back MessageDemoSubtitlesPut; 17 | 18 | /// 19 | /// Shows a message and requires pressing the Use button/Mouse click to dismiss 20 | /// 21 | extern injector::hook_back MessageMemoPut; 22 | 23 | /// 24 | /// Shows a message and requires pressing the Use button/Mouse click to dismiss 25 | /// 26 | extern injector::hook_back MessageExplanationPut; 27 | 28 | extern injector::hook_back sfMessagePrint; 29 | 30 | void InitializeMessageHandleFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/message/message_load.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back MessageAddress; 4 | unsigned short* MessageAddressHook(int packid, int num); 5 | 6 | /// 7 | /// Encodes a string of text into the SH4 encoded text format. 8 | /// Only tested with basic Latin chars, punctuation, and numerals, JP/KOR characters and characters with diacritics may not work 9 | /// 10 | /// The text to encode 11 | /// The encoded text 12 | char* convertMessage(const char* text); -------------------------------------------------------------------------------- /includes/sh4/game/misc/misc_iexplanation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sh4/game/gamemain/game_item.h" 3 | 4 | struct ItemMessage 5 | { 6 | int item; 7 | short name; 8 | short info; 9 | }; 10 | 11 | extern std::vector item_message_table; -------------------------------------------------------------------------------- /includes/sh4/game/misc/misc_itemicon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sh4/game/gamemain/game_item.h" 3 | 4 | struct ItemIcon 5 | { 6 | GameItem kind; 7 | char no; 8 | char image_no; 9 | char clut_no; 10 | char offset_no; 11 | }; 12 | 13 | extern std::vector small_icon_tbl; 14 | extern std::vector large_icon_tbl; 15 | -------------------------------------------------------------------------------- /includes/sh4/game/misc/misc_option.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct GameOptions 4 | { 5 | int resolution[2]; 6 | char head_motion; 7 | char hide_gauge; 8 | char hide_icon; 9 | char vibration; 10 | char sound; 11 | char bgm_vol; 12 | char se_vol; 13 | char keyconf; 14 | char brightness; 15 | char language; 16 | char subtitles; 17 | char blood_col; 18 | char noise_eff; 19 | char contrast; 20 | char cam_reverse; 21 | char move_parallel; 22 | char is_walk; 23 | char realtime_shadows; 24 | 25 | // this typically has 6 bytes of padding but we can use it to store our new settings 26 | // this will be committed to the players gamesave and doesn't cause issues when the randomizer isn't running 27 | // it is a win-win 28 | char random_enemies; 29 | char random_items; 30 | char random_models; 31 | char extra_content; 32 | char random_damage; 33 | char fog_approaches; 34 | }; 35 | 36 | extern injector::hook_back miscOptionGetPtr; 37 | 38 | struct OptionMenuItem 39 | { 40 | int change; // pointer to func ran when value changes 41 | int get_val; // pointer to func that gets value 42 | int buru_cnt; // ??? 43 | int MesId_val; // pointer to message indices for the option values 44 | int MesId_val_num; // number of possible options 45 | int MesId_item; // pointer to message index for the option name 46 | int get_expl_mes_id; // pointer to func that returns the message index for the option's "explanation text" 47 | }; 48 | 49 | void ApplyIngameOptionsPatches(); 50 | int change_random_enemies(GameOptions* opt, int num); 51 | int change_random_items(GameOptions* opt, int num); 52 | int change_random_models(GameOptions* opt, int num); 53 | int change_random_damage(GameOptions* opt, int num); 54 | int change_extra_content(GameOptions* opt, int num); 55 | int change_fog_approaches(GameOptions* opt, int num); 56 | int get_random_enemies(); 57 | int get_random_items(); 58 | int get_random_models(); 59 | int get_random_damage(); 60 | int get_extra_content(); 61 | int get_fog_approaches(); 62 | int get_random_enemies_expl(); 63 | int get_random_items_expl(); 64 | int get_random_models_expl(); 65 | int get_random_damage_expl(); 66 | int get_extra_content_expl(); 67 | int get_fog_approaches_expl(); 68 | 69 | 70 | // this is typically hardcoded in the exe 71 | extern std::vector extraOptionMenuItems; 72 | 73 | extern std::vector optionMenuTitleMessages; 74 | 75 | extern std::vector optionItemCounts; 76 | 77 | extern std::vector optionItemPtrs; -------------------------------------------------------------------------------- /includes/sh4/game/objs/game_objset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum EntryTypes : short 4 | { 5 | SceneNum = 0, 6 | ObjType = 1, 7 | SetExecutor = 2, 8 | SetConstructor = 3, 9 | SetDestructor = 4, 10 | SetRender = 5, 11 | SetAllFuncs = 6, 12 | SetEnemy = 7, 13 | SetXYZW = 8, 14 | SetRotation = 9, 15 | SetID1234 = 10, 16 | Unknown = 11, 17 | Unknown2 = 12, 18 | Unknown3 = 13, 19 | Unknown4 = 14, 20 | Unknown5 = 15, 21 | Unknown6 = 16, 22 | Unknown7 = 17, 23 | Unknown8 = 18, 24 | Unknown9 = 19, 25 | Unknown10 = 20, 26 | Unknown11 = 21, 27 | Unknown12 = 22, 28 | Unknown13 = 23, 29 | SetEventDriver = 24, 30 | Unknown14 = 25, 31 | Unknown15 = 26, 32 | Unknown16 = 27 33 | }; 34 | 35 | // loads the scene sets which contain information about the item/enemy placements, interactables, cutscene triggers, and more 36 | // this is currently unused by the randomizer, but if you want to play around with this, it will still load the scene sets from disk 37 | void LoadSceneSets(); -------------------------------------------------------------------------------- /includes/sh4/game/player/battle/player_battle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back battle_anotherworld; 4 | extern injector::hook_back normal_attack_all; 5 | extern injector::hook_back PlayerWeaponChargable; 6 | void __cdecl battle_anotherworldHook(); 7 | int __cdecl normal_attack_allHook(); 8 | int __cdecl PlayerWeaponChargableHook(GameItem item); 9 | void InitializePlayerBattleFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/player/battle/player_battle_general.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back motion_is_pipe; 4 | int motion_is_pipeHook(); 5 | void InitializePlayerBattleGeneralFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/player/battle/player_weapon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | struct WeaponTimeTableEntry 5 | { 6 | float start; 7 | float end; 8 | float se; 9 | float cancel; 10 | }; 11 | 12 | struct WeaponTableEntry 13 | { 14 | int file; 15 | unsigned int model; 16 | unsigned int model_b; 17 | unsigned int tex; 18 | unsigned int shadow; 19 | unsigned int shadow_b; 20 | }; 21 | 22 | struct WeaponParam 23 | { 24 | float charge_time; 25 | int left; 26 | int right; 27 | int left_b; 28 | int right_b; 29 | float anim_speed; 30 | }; 31 | 32 | struct SidestepAnimEntry 33 | { 34 | int left; 35 | int right; 36 | }; 37 | 38 | enum BattleAttackKind : int 39 | { 40 | BAK_NOTHING, 41 | BAK_UNDEFINED, 42 | BAK_PLAYER_TABLE_START, 43 | BAK_PLAYER_HAND_GUN = 0x2, 44 | BAK_PLAYER_REVOLVER, 45 | BAK_PLAYER_PIPE, 46 | BAK_PLAYER_PIPE_ST, 47 | BAK_PLAYER_CUTTER, 48 | BAK_PLAYER_CUTTER_ST, 49 | BAK_PLAYER_BAT, 50 | BAK_PLAYER_BAT_ST, 51 | BAK_PLAYER_DRIVER, 52 | BAK_PLAYER_DRIVER_ST, 53 | BAK_PLAYER_SPOON, 54 | BAK_PLAYER_SPOON_ST, 55 | BAK_PLAYER_MID_MASHY, 56 | BAK_PLAYER_MID_MASHY_ST, 57 | BAK_PLAYER_MASHY_IRON, 58 | BAK_PLAYER_MASHY_IRON_ST, 59 | BAK_PLAYER_MASHY, 60 | BAK_PLAYER_MASHY_ST, 61 | BAK_PLAYER_SPADE_MASHY, 62 | BAK_PLAYER_SPADE_MASHY_ST, 63 | BAK_PLAYER_MASHY_NIBLICK, 64 | BAK_PLAYER_MASHY_NIBLICK_ST, 65 | BAK_PLAYER_PITCHER, 66 | BAK_PLAYER_PITCHER_ST, 67 | BAK_PLAYER_NIBLICK, 68 | BAK_PLAYER_NIBLICK_ST, 69 | BAK_PLAYER_PITCHING_WEDGE, 70 | BAK_PLAYER_PITCHING_WEDGE_ST, 71 | BAK_PLAYER_SAND_WEDGE, 72 | BAK_PLAYER_SAND_WEDGE_ST, 73 | BAK_PLAYER_PUTTER, 74 | BAK_PLAYER_PUTTER_ST, 75 | BAK_PLAYER_BOTTLE, 76 | BAK_PLAYER_BROKEN_BOTTLE, 77 | BAK_PLAYER_SCOOP, 78 | BAK_PLAYER_SCOOP_ST, 79 | BAK_PLAYER_HATCHET, 80 | BAK_PLAYER_HATCHET_ST, 81 | BAK_PLAYER_PICK, 82 | BAK_PLAYER_PICK_ST, 83 | BAK_PLAYER_STUNGUN, 84 | BAK_PLAYER_SPRAY, 85 | BAK_PLAYER_CHAINSAW, 86 | BAK_PLAYER_CHAINSAW_ST, 87 | BAK_PLAYER_WOOD_STICK, 88 | BAK_PLAYER_SILVER_BULLET, 89 | BAK_PLAYER_FINISH, 90 | BAK_PLAYER_SCOOP_FINISH, 91 | BAK_PLAYER_PICK_FINISH, 92 | BAK_PLAYER_CHAINSAW_FINISH, 93 | BAK_PLAYER_EIL_HANDBAG_N, 94 | BAK_PLAYER_EIL_HANDBAG_3_1, 95 | BAK_PLAYER_EIL_HANDBAG_3_2, 96 | BAK_PLAYER_EIL_HANDBAG_3_3, 97 | BAK_PLAYER_EIL_HANDBAG_FINISH, 98 | BAK_PLAYER_EIL_CLUB_N, 99 | BAK_PLAYER_EIL_CLUB_3_1, 100 | BAK_PLAYER_EIL_CLUB_3_2, 101 | BAK_PLAYER_EIL_CLUB_3_3, 102 | BAK_PLAYER_EIL_CLUB_FINISH, 103 | BAK_PLAYER_EIL_ROD_N, 104 | BAK_PLAYER_EIL_ROD_3_1, 105 | BAK_PLAYER_EIL_ROD_3_2, 106 | BAK_PLAYER_EIL_ROD_3_3, 107 | BAK_PLAYER_EIL_ROD_FINISH, 108 | BAK_PLAYER_EIL_CHAIN_N, 109 | BAK_PLAYER_EIL_CHAIN_3_1, 110 | BAK_PLAYER_EIL_CHAIN_3_2, 111 | BAK_PLAYER_EIL_CHAIN_3_3, 112 | BAK_PLAYER_EIL_CHAIN_FINISH, 113 | BAK_PLAYER_EIL_GUN_N, 114 | BAK_PLAYER_TABLE_END = 0x48, 115 | BAK_ENEMY_TABLE_START, 116 | BAK_MUSH_DEATH = 0x49, 117 | BAK_BUZZ_BLOODSUCK, 118 | BAK_BUZZ_PECK, 119 | BAK_BUZZ_DIVE, 120 | BAK_KABE_STRIKE, 121 | BAK_KABE_BRINGDOWN, 122 | BAK_KABE_SIDEBLOW, 123 | BAK_KABE_HEADBUTT, 124 | BAK_WHEEL_DASH, 125 | BAK_JIN_SCRATCH, 126 | BAK_JIN_STRIKE, 127 | BAK_JIN_STAB, 128 | BAK_JIN_BRINGDOWN, 129 | BAK_TWN_STRIKE, 130 | BAK_TWN_JUMP, 131 | BAK_TWN_TURN, 132 | BAK_HIL_WALL, 133 | BAK_HIL_FLOOR, 134 | BAK_HYENA_DASH, 135 | BAK_MULTI_HEADBUTT, 136 | BAK_FLAMES_ATT1, 137 | BAK_FLAMES_ATT2, 138 | BAK_FAT_SING, 139 | BAK_FAT_DASH, 140 | BAK_FAT_DASH2, 141 | BAK_FAT_BOMB, 142 | BAK_SCR_ATT1, 143 | BAK_SCR_ATT2, 144 | BAK_SCR_ATT4, 145 | BAK_KILLER_SHOOT, 146 | BAK_KILLER_RAPIDFIRE, 147 | BAK_KILLER_PIPE, 148 | BAK_KILLER_PIPE_ST, 149 | BAK_KILLER_CHAINSAW_STAB, 150 | BAK_KILLER_CHAINSAW_SHAKE, 151 | BAK_KILLER_BLOWOFF, 152 | BAK_ENEMY_TABLE_END = 0x6c, 153 | BAK_OTHER_TABLE_START, 154 | BAK_GHOSTSTAIN_FLICK = 0x6d, 155 | BAK_OTHER_TABLE_END = 0x6d, 156 | BAK_MAX_NUMBER 157 | }; 158 | 159 | struct AttackTableEntry { 160 | BattleAttackKind normal; 161 | BattleAttackKind strong; 162 | }; 163 | 164 | extern void InitializePlayerWeaponFunctions(); 165 | 166 | extern injector::hook_back PlayerWeaponGetStartTime; 167 | extern injector::hook_back PlayerWeaponGetEndTime; 168 | 169 | extern std::vector _gun; 170 | extern std::vector _steelpipe; 171 | extern std::vector _cutter; 172 | extern std::vector _bottle_b; 173 | extern std::vector _scoop; 174 | extern std::vector _axe; 175 | extern std::vector _pick; 176 | extern std::vector _stun; 177 | extern std::vector _spray; 178 | extern std::vector _chain; 179 | extern std::vector wp_time_table; 180 | 181 | extern std::vector wp_table; 182 | 183 | extern std::vector wp_param; 184 | 185 | extern std::vector attack_tbl; 186 | 187 | extern std::vector sidestep_anim; -------------------------------------------------------------------------------- /includes/sh4/game/player/player.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | #include "sh4/game/gamemain/game_item.h" 5 | #include "sh4/sglib/animation/sg_anime.h" 6 | #include "sh4/sys/apps/sf_obj.h" 7 | #include "sh4/sys/geometry/sf_chara.h" 8 | #include "sh4/sys/geometry/collision/sf_cld.h" 9 | 10 | struct _PLAYER_WORK { 11 | int num; 12 | int type; 13 | float life; 14 | float str; 15 | float def; 16 | float tire; 17 | int dull_count; 18 | int dulls; 19 | int dull_motion; 20 | int invincible; 21 | GameItem wp_last; 22 | float life_max; 23 | float str_max; 24 | float def_max; 25 | float ampule_time; 26 | int draw_flag; 27 | Position pos; 28 | Position v_pos; 29 | Position eyerot; 30 | Position prev_pos; 31 | Position rot; 32 | Position prev_rot; 33 | Position v_rot; 34 | sfCharacter chara; 35 | float field24_0x198[6]; 36 | sfCharacter* obj; 37 | sgAnime* anim; 38 | sgAnime* anim_frame; 39 | int field28_0x1bc; 40 | sfCldObject cld_obj; 41 | sfObj* ch_obj; 42 | int battle_stat; 43 | int holy_stat; 44 | float power_attack; 45 | int damage; 46 | int gotmode; 47 | int hold; 48 | int hold_kind; 49 | float hold_time; 50 | int gun_ikset; 51 | float gun_angle; 52 | sfObj* target; 53 | int target_mode; 54 | GameItem weapon_kind; 55 | sfCharacter weapon_chr; 56 | Position weapon_pos; 57 | sfCharacter* wp_chr; 58 | sfObj* wp_obj; 59 | sfCldObject weapon_cld; 60 | sfCldObject* wp_cld; 61 | int cld_entry; 62 | GameItem holy_kind; 63 | int autolock; 64 | int sword_stat; 65 | int enemy_near; 66 | int anime_process; 67 | int anime_sub; 68 | int anim_ctrl; 69 | int slot_frame; 70 | int link_anim; 71 | int slot_link; 72 | float anim_speed; 73 | float hit_reduce; 74 | int auto_search; 75 | int pos_f; 76 | Position pos_bak; 77 | Position rot_bak; 78 | Position last_neck; 79 | int advance_only; 80 | int who; 81 | char field70_0x410[16]; 82 | }; 83 | 84 | extern injector::hook_back PlayerDamage; 85 | int __cdecl PlayerDamageHook(int num, float damage); 86 | void InitializePlayerFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/player/player_anime_proc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern std::vector motion_battle; -------------------------------------------------------------------------------- /includes/sh4/game/player/player_another_ui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct PlayerUI 4 | { 5 | float move; 6 | float speed; 7 | float rot; 8 | float side; 9 | float vert; 10 | float f_dir; 11 | float f_move; 12 | float f_push[4]; 13 | int item; 14 | int shoot; 15 | int curse; 16 | int finisher; 17 | int select; 18 | int silent; 19 | int access; 20 | float run; 21 | int battle; 22 | int power; 23 | int power_last; 24 | int backstep; 25 | float anim_speed; 26 | int retarget; 27 | int rstick; 28 | int stopping; 29 | float stick_rot; 30 | int search_view; 31 | float camera_x; 32 | float camera_y; 33 | }; 34 | 35 | extern PlayerUI* playerUI; 36 | extern int* motion_stop; 37 | 38 | void InitializePlayerAnotherUIFunctions(); -------------------------------------------------------------------------------- /includes/sh4/game/player/player_sound.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sh4/game/gamemain/game.h" 3 | 4 | struct PlayerSEFlags 5 | { 6 | unsigned char r_foot; 7 | unsigned char l_foot; 8 | unsigned char tire; 9 | unsigned char die; 10 | unsigned char b_general; 11 | unsigned char b_g_val; 12 | unsigned char weapon; 13 | unsigned char weapon_val; 14 | unsigned char wall; 15 | int weapon_slot; 16 | float player_pan; 17 | float player_vol; 18 | float gaoh_time; 19 | }; 20 | 21 | extern PlayerSEFlags* flags; 22 | extern injector::hook_back se_call_swing; 23 | extern injector::hook_back set_attack_se; 24 | extern injector::hook_back set_battle_loop_se; 25 | void set_attack_seHook(int unk, _PLAYER_WORK* pWork); 26 | void InitializePlayerSoundFunctions(); 27 | -------------------------------------------------------------------------------- /includes/sh4/sglib/animation/sg_anime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | #include "sh4/sglib/animation/sg_bone.h" 5 | #include "sh4/sglib/animation/sg_ikhandle.h" 6 | 7 | struct sgAnmData { 8 | unsigned int type_id; 9 | short total_time; 10 | short loop; 11 | int reserved_a; 12 | int reserved_b; 13 | unsigned int data[1]; 14 | }; 15 | 16 | struct sgAnime { 17 | sgAnmData* play_data[4]; 18 | sgBone* transforms; 19 | int n_transforms; 20 | sgIKHandle* ik_handles; 21 | sgBone* object_space; 22 | void (*post_func)(void*); 23 | Position* reals; 24 | int n_reals; 25 | Position* vectors; 26 | int n_vectors; 27 | int current_time; 28 | int time_add; 29 | unsigned char play_status[4]; 30 | unsigned short flag; 31 | unsigned short construct_check; 32 | }; 33 | 34 | extern void InitializeSgAnimeFunctions(); 35 | extern injector::hook_back sgAnimeCurrentFloatFrame; -------------------------------------------------------------------------------- /includes/sh4/sglib/animation/sg_bone.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | 5 | struct sgBone { 6 | Position rot; 7 | Position trans; 8 | Position scale; 9 | Position abs_rot; 10 | Position abs_trans; 11 | sgBone* parent; 12 | sgBone* child_list; 13 | sgBone* child_sibling; 14 | unsigned short last; 15 | unsigned short flag; 16 | float partly_blend_rate; 17 | float field11_0x64; 18 | float field12_0x68; 19 | float field13_0x6c; 20 | }; 21 | 22 | extern void InitializeSgBoneFunctions(); 23 | 24 | extern injector::hook_back sgBoneGetAbsRot; 25 | extern injector::hook_back sgBoneGetAbsMatrix; 26 | extern injector::hook_back sgBoneGetEuclideanDistance; 27 | -------------------------------------------------------------------------------- /includes/sh4/sglib/animation/sg_ikhandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum sgIKSolveResult : unsigned char 4 | { 5 | SG_IK_RESULT_NONE = 0, 6 | SG_IK_RESULT_OK = 1, 7 | SG_IK_RESULT_BEYOND = 2 8 | }; 9 | 10 | struct sgIKHandle 11 | { 12 | float acceleration[4][2]; 13 | float damping_ratio; 14 | int* bone; 15 | int* start; 16 | int* end; 17 | void* solver; 18 | sgIKSolveResult solve_result; 19 | float reach_constrain; 20 | float close_constrain; 21 | int* next; 22 | }; -------------------------------------------------------------------------------- /includes/sh4/sglib/intersect/sg_quadtree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct sgQTNode { 4 | int dummy; 5 | }; 6 | 7 | struct sgQTBounding { 8 | float center[4]; 9 | float radius; 10 | }; 11 | 12 | struct sgQTObject { 13 | struct sgQTBounding bounding_ball; 14 | struct sgQTObject* next; 15 | struct sgQTObject* prev; 16 | }; -------------------------------------------------------------------------------- /includes/sh4/sglib/math/sg_quat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | 5 | extern void InitializeSgQuatFunctions(); 6 | 7 | extern injector::hook_back sgQuatFromAxisAngle; 8 | extern injector::hook_back sgQuatMul; 9 | extern injector::hook_back sgQuatMulVector; 10 | extern injector::hook_back sgQuatGetEuclideanDistance; 11 | -------------------------------------------------------------------------------- /includes/sh4/sglib/renderer/TErender/model3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Model { 4 | unsigned int id; 5 | unsigned int revision; 6 | unsigned int initial_matrices_offset; 7 | unsigned int n_skeletons; 8 | unsigned int skeleton_structure_offset; 9 | unsigned int n_skeleton_pairs; 10 | unsigned int skeleton_pairs_offset; 11 | unsigned int default_pcms_offset; 12 | unsigned int n_vu1_parts; 13 | unsigned int vu1_parts_offset; 14 | unsigned int n_vu0_parts; 15 | unsigned int vu0_parts_offset; 16 | unsigned int n_texture_blocks; 17 | unsigned int texture_blocks_offset; 18 | unsigned int n_text_poses; 19 | unsigned int text_poses_offset; 20 | unsigned int text_pos_params_offset; 21 | unsigned int n_cluster_nodes; 22 | unsigned int cluster_nodes_offset; 23 | unsigned int n_clusters; 24 | unsigned int clusters_offset; 25 | unsigned int n_func_data; 26 | unsigned int func_data_offset; 27 | unsigned int hit_offset; 28 | unsigned int box_offset; 29 | unsigned int flag; 30 | unsigned int relative_matrices_offset; 31 | unsigned int relative_transes_offset; 32 | unsigned int hits_offset; 33 | unsigned int reserved_1d; 34 | unsigned int tanmparams; 35 | unsigned int textureextras; 36 | }; -------------------------------------------------------------------------------- /includes/sh4/sglib/renderer/TErender/sg_svmodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct sgSVModel 4 | { 5 | void* model; 6 | float* local_matrices; 7 | int flag; 8 | }; -------------------------------------------------------------------------------- /includes/sh4/sglib/renderer/TErender/sg_temodel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | #include "sh4/sglib/renderer/TErender/model3.h" 5 | 6 | struct sgTEModel { 7 | Model* model; 8 | void* texture; 9 | void* texture_global; 10 | Position* matrices; 11 | float* weights; 12 | Position* tex_crops; 13 | void (*texture_load_func)(int*, int, int, float*); 14 | int equip_flag; 15 | }; -------------------------------------------------------------------------------- /includes/sh4/sys/apps/sf_memorystack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void InitializeSfMemoryFunctions(); -------------------------------------------------------------------------------- /includes/sh4/sys/apps/sf_obj.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | 5 | struct sfObj { 6 | CommonUnion fwork[256]; 7 | CommonUnion* work; 8 | void* sfObjFunc; 9 | CommonUnion* work_pt0; 10 | CommonUnion* work_pt1; 11 | unsigned short step; 12 | unsigned short step_s; 13 | unsigned short kind; 14 | unsigned short pad; 15 | CommonUnion* sys_work; 16 | CommonUnion* scene_work; 17 | int* event_work; 18 | CommonUnion* objhit_work; 19 | void* sfObjDestructor; 20 | short flag; 21 | short thread_no; 22 | }; -------------------------------------------------------------------------------- /includes/sh4/sys/apps/sf_step.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back sfStepGet; 4 | 5 | void InitializeSfStepFunctions(); -------------------------------------------------------------------------------- /includes/sh4/sys/env/sf_env.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CommonTypes.h" 4 | 5 | extern void InitializeSfEnvFunctions(); 6 | 7 | // gets the current frames per second as a floating point value 8 | extern injector::hook_back sfSysEnvFps; -------------------------------------------------------------------------------- /includes/sh4/sys/geometry/collision/sf_cld.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sh4/sglib/intersect/sg_quadtree.h" 4 | #include "sh4/sglib/animation/sg_bone.h" 5 | 6 | 7 | struct sfCldLine 8 | { 9 | float start[4]; 10 | float end[4]; 11 | }; 12 | 13 | struct sfCldSphere 14 | { 15 | float center[4]; 16 | float radius; 17 | }; 18 | 19 | struct sfCldAABB 20 | { 21 | float bmin[4]; 22 | float bmax[4]; 23 | }; 24 | 25 | struct sfCldOBB 26 | { 27 | float mat[4][4]; 28 | float half_w[4]; 29 | }; 30 | 31 | struct sfOffsetAABB 32 | { 33 | sfCldAABB aabb; 34 | float offset[4]; 35 | }; 36 | 37 | union sfCldBody 38 | { 39 | sfCldOBB obb; 40 | sfCldAABB aabb; 41 | sfOffsetAABB offset_aabb; 42 | sfCldLine line; 43 | sfCldSphere sphere; 44 | }; 45 | 46 | struct sfCldPart 47 | { 48 | sfCldBody world_hit; 49 | sfCldBody local_hit; 50 | unsigned char hit_type; 51 | unsigned char pad[3]; 52 | int hit_kind; 53 | sgBone* parent; 54 | void* data; 55 | void* parent_cld; 56 | }; 57 | 58 | struct sfCldObject { 59 | sgQTObject tree_object; 60 | sgQTNode* stay_node; 61 | sfCldPart* parts; 62 | unsigned char n_parts; 63 | unsigned char pad[3]; 64 | void* data; 65 | char unk[34]; 66 | }; -------------------------------------------------------------------------------- /includes/sh4/sys/geometry/sf_chara.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sh4/sglib/animation/sg_anime.h" 4 | #include "sh4/sglib/renderer/TErender/sg_temodel.h" 5 | #include "sh4/sglib/renderer/TErender/sg_svmodel.h" 6 | 7 | struct sfCharacter { 8 | sgBone root; 9 | sgAnime anime_work; 10 | sgTEModel model_work; 11 | sgSVModel sv_model; 12 | sgAnime* anime; 13 | unsigned short flag; 14 | }; 15 | 16 | extern void InitializeSfCharacterFunctions(); 17 | extern injector::hook_back sfCharacterBone; 18 | -------------------------------------------------------------------------------- /includes/sh4/sys/geometry/sf_scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back sfSceneSetFogColor; 4 | void __cdecl sfSceneSetFogColorHook(Color* color); 5 | 6 | extern injector::hook_back sfSceneSetFogPower; 7 | void __cdecl sfSceneSetFogPowerHook(float nearPow, unsigned char nearPow2, float farPow, unsigned char farPow2); 8 | 9 | void InitializeSfSceneFunctions(); -------------------------------------------------------------------------------- /includes/sh4/sys/sound/sf_sound.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back sfSeCallEx; 4 | void InitializeSfSoundFunctions(); -------------------------------------------------------------------------------- /includes/sh4/sys/storage/sf_fileread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern injector::hook_back sfFileLoad; 4 | void InitializeSfFileLoadFunctions(); -------------------------------------------------------------------------------- /includes/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | float GetFOV(float f, float ar) 4 | { 5 | return atan2(tan(atan2(tan(f * 0.5f) / (4.0f / 3.0f), 1.0f)) * (ar), 1.0f); 6 | } 7 | 8 | float GetFOV2(float f, float ar) 9 | { 10 | return f * (2.0f * ((180.0f / (float)M_PI) * (atan(tan(((float)M_PI / 180.0f) * ((2.0f * ((180.0f / (float)M_PI) * (atan(tan(((float)M_PI / 180.0f) * (90.0f * 0.5f)) / (4.0f / 3.0f))))) * 0.5f)) * (ar)))) * (1.0f / 90.0f)); 11 | } 12 | 13 | float AdjustFOV(float f, float ar) 14 | { 15 | return std::round((2.0f * atan(((ar) / (4.0f / 3.0f)) * tan(f / 2.0f * ((float)M_PI / 180.0f)))) * (180.0f / (float)M_PI) * 100.0f) / 100.0f; 16 | } 17 | 18 | void CreateThreadAutoClose(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) 19 | { 20 | CloseHandle(CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)); 21 | } 22 | 23 | bool IsUALPresent() 24 | { 25 | ModuleList dlls; 26 | dlls.Enumerate(ModuleList::SearchLocation::LocalOnly); 27 | for (auto& e : dlls.m_moduleList) 28 | { 29 | if (GetProcAddress(std::get(e), "DirectInput8Create") != NULL && GetProcAddress(std::get(e), "DirectSoundCreate8") != NULL && GetProcAddress(std::get(e), "InternetOpenA") != NULL) 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | std::tuple GetDesktopRes() 36 | { 37 | HMONITOR monitor = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTONEAREST); 38 | MONITORINFO info = {}; 39 | info.cbSize = sizeof(MONITORINFO); 40 | GetMonitorInfo(monitor, &info); 41 | int32_t DesktopResW = info.rcMonitor.right - info.rcMonitor.left; 42 | int32_t DesktopResH = info.rcMonitor.bottom - info.rcMonitor.top; 43 | return std::make_tuple(DesktopResW, DesktopResH); 44 | } 45 | 46 | void GetResolutionsList(std::vector& list) 47 | { 48 | DISPLAY_DEVICE dd; 49 | dd.cb = sizeof(DISPLAY_DEVICE); 50 | DWORD deviceNum = 0; 51 | while (EnumDisplayDevices(NULL, deviceNum, &dd, 0)) { 52 | DISPLAY_DEVICE newdd = { 0 }; 53 | newdd.cb = sizeof(DISPLAY_DEVICE); 54 | DWORD monitorNum = 0; 55 | DEVMODE dm = { 0 }; 56 | while (EnumDisplayDevices(dd.DeviceName, monitorNum, &newdd, 0)) 57 | { 58 | for (auto iModeNum = 0; EnumDisplaySettings(NULL, iModeNum, &dm) != 0; iModeNum++) 59 | { 60 | auto str = format("%dx%d", dm.dmPelsWidth, dm.dmPelsHeight); 61 | list.emplace_back(str); 62 | } 63 | monitorNum++; 64 | } 65 | deviceNum++; 66 | } 67 | 68 | if (list.empty()) 69 | { 70 | list = { "160x120", "240x160", "320x240", "400x240", "480x320", "640x360", "640x480", 71 | "768x480", "800x600", "854x480", "960x540", "960x640", "1024x576", "1024x768", 72 | "1152x864", "1280x720", "1280x800", "1280x1024", "1280x1080", "1360x768", "1366x768", 73 | "1400x1050", "1440x900", "1600x900", "1600x1200", "1680x1050", "1920x1080", "1920x1200", 74 | "2048x1080", "2048x1152", "2048x1536", "2560x1080", "2560x1440", "2560x1600", "2560x2048", 75 | "3200x1800", "3200x2048", "3200x2400", "3440x1440", "3840x1080", "3840x1600", "3840x2160", 76 | "3840x2400", "4096x2160", "4096x3072", "5120x2160", "5120x2880", "5120x3200", "5120x4096", 77 | "6400x4096", "6400x4800", "7680x4320", "7680x4800" }; 78 | } 79 | 80 | std::sort(list.begin(), list.end(), [](const std::string& lhs, const std::string& rhs) { 81 | int32_t x1, y1, x2, y2; 82 | sscanf_s(lhs.c_str(), "%dx%d", &x1, &y1); 83 | sscanf_s(rhs.c_str(), "%dx%d", &x2, &y2); 84 | return (x1 != x2) ? (x1 < x2) : (x1 * y1 < x2 * y2); 85 | }); 86 | list.erase(std::unique(std::begin(list), std::end(list)), list.end()); 87 | } 88 | 89 | std::string format(const char *fmt, ...) 90 | { 91 | va_list args; 92 | va_start(args, fmt); 93 | std::vector v(1024); 94 | while (true) 95 | { 96 | va_list args2; 97 | va_copy(args2, args); 98 | int res = vsnprintf(v.data(), v.size(), fmt, args2); 99 | if ((res >= 0) && (res < static_cast(v.size()))) 100 | { 101 | va_end(args); 102 | va_end(args2); 103 | return std::string(v.data()); 104 | } 105 | size_t size; 106 | if (res < 0) 107 | size = v.size() * 2; 108 | else 109 | size = static_cast(res) + 1; 110 | v.clear(); 111 | v.resize(size); 112 | va_end(args2); 113 | } 114 | } 115 | 116 | HICON CreateIconFromBMP(UCHAR* data) 117 | { 118 | BITMAPINFOHEADER* bmih = (BITMAPINFOHEADER*)(data + sizeof(BITMAPFILEHEADER)); 119 | HICON hIcon = 0; 120 | ICONINFO ii = {}; 121 | ULONG n = bmih->biWidth * bmih->biHeight; 122 | PULONG lpBits = new ULONG[n]; 123 | PULONG p = lpBits; 124 | if (ii.hbmColor = CreateBitmap(bmih->biWidth, bmih->biHeight, 1, bmih->biBitCount, (data + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)))) 125 | { 126 | if (ii.hbmMask = CreateBitmap(bmih->biWidth, bmih->biHeight, 1, 1, 0)) 127 | { 128 | hIcon = CreateIconIndirect(&ii); 129 | DeleteObject(ii.hbmMask); 130 | } 131 | DeleteObject(ii.hbmColor); 132 | } 133 | delete[] lpBits; 134 | return hIcon; 135 | } 136 | 137 | HICON CreateIconFromResourceICO(UINT nID, int32_t cx, int32_t cy) 138 | { 139 | HMODULE hm; 140 | GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)&GetDesktopRes, &hm); 141 | return (HICON)LoadImage(hm, MAKEINTRESOURCE(nID), IMAGE_ICON, cx, cy, LR_SHARED); 142 | } 143 | 144 | std::string RegistryWrapper::filter; 145 | std::string RegistryWrapper::section; 146 | CIniReader RegistryWrapper::RegistryReader; 147 | std::map RegistryWrapper::DefaultStrings; 148 | std::set> RegistryWrapper::PathStrings; -------------------------------------------------------------------------------- /includes/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _WIN32_WINNT 0x0600 // Windows Vista 4 | 5 | #include 6 | -------------------------------------------------------------------------------- /premake5.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 -------------------------------------------------------------------------------- /premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterStanton/SilentHill4Randomizer/e4b35e0358e3121b1075c390387171f7f27f5d86/premake5.exe -------------------------------------------------------------------------------- /premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "SilentHill4Randomizer" 2 | configurations { "Release", "Debug" } 3 | platforms { "Win32" } 4 | architecture "x32" 5 | location "build" 6 | objdir ("build/obj") 7 | buildlog ("build/log/%{prj.name}.log") 8 | buildoptions {"-std:c++latest", "/MP"} 9 | 10 | kind "SharedLib" 11 | language "C++" 12 | targetdir "data/%{prj.name}/scripts" 13 | targetextension ".asi" 14 | characterset ("UNICODE") 15 | staticruntime "On" 16 | 17 | defines { "rsc_CompanyName=\"Silent Hill 4\"" } 18 | defines { "rsc_FileDescription=\"A randomizer for Silent Hill 4: The Room.\"" } 19 | defines { "rsc_LegalCopyright=\"MIT License\""} 20 | defines { "rsc_FileVersion=\"1.0.0.0\"", "rsc_ProductVersion=\"1.0.0.0\"" } 21 | defines { "rsc_InternalName=\"%{prj.name}\"", "rsc_ProductName=\"%{prj.name}\"", "rsc_OriginalFilename=\"%{prj.name}.asi\"" } 22 | defines { "rsc_UpdateUrl=\"https://github.com/HunterStanton/SilentHill4Randomizer\"" } 23 | 24 | files { "source/%{prj.name}/*.cpp" } 25 | files { "Resources/*.rc" } 26 | files { "external/hooking/Hooking.Patterns.h", "external/hooking/Hooking.Patterns.cpp" } 27 | files { "includes/stdafx.h", "includes/stdafx.cpp", "includes/sh4/*.h" } 28 | includedirs { "includes" } 29 | includedirs { "external/hooking" } 30 | includedirs { "external/injector/include" } 31 | includedirs { "external/inireader" } 32 | includedirs { "external/spdlog/include" } 33 | includedirs { "external/filewatch" } 34 | 35 | local dxsdk = os.getenv "DXSDK_DIR" 36 | if dxsdk then 37 | includedirs { dxsdk .. "/include" } 38 | libdirs { dxsdk .. "/lib/x86" } 39 | else 40 | includedirs { "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/include" } 41 | libdirs { "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/lib/x86" } 42 | end 43 | 44 | pbcommands = { 45 | "setlocal EnableDelayedExpansion", 46 | --"set \"path=" .. (gamepath) .. "\"", 47 | "set file=$(TargetPath)", 48 | "FOR %%i IN (\"%file%\") DO (", 49 | "set filename=%%~ni", 50 | "set fileextension=%%~xi", 51 | "set target=!path!!filename!!fileextension!", 52 | "if exist \"!target!\" copy /y \"!file!\" \"!target!\"", 53 | ")" } 54 | 55 | function setpaths (gamepath, exepath, scriptspath) 56 | scriptspath = scriptspath or "scripts/" 57 | if (gamepath) then 58 | cmdcopy = { "set \"path=" .. gamepath .. scriptspath .. "\"" } 59 | table.insert(cmdcopy, pbcommands) 60 | postbuildcommands (cmdcopy) 61 | debugdir (gamepath) 62 | if (exepath) then 63 | debugcommand (gamepath .. exepath) 64 | dir, file = exepath:match'(.*/)(.*)' 65 | debugdir (gamepath .. (dir or "")) 66 | end 67 | end 68 | targetdir ("data/%{prj.name}/" .. scriptspath) 69 | end 70 | 71 | filter "configurations:Debug*" 72 | defines "DEBUG" 73 | symbols "On" 74 | 75 | filter "configurations:Release*" 76 | defines "NDEBUG" 77 | optimize "On" 78 | 79 | project "SilentHill4Randomizer" 80 | setpaths("C:/Program Files (x86)/GOG Galaxy/Games/Silent Hill 4/", "Silent Hill 4.exe") -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Silent Hill 4 Randomizer 2 | 3 | A randomizer for Silent Hill 4: The Room, for the *GOG version* of the game. The randomizer offers several features to change up the gameplay of Silent Hill 4 to create brand new gameplay scenarios and challenges that weren't possible in the original game. It also has an option for restoring the "cut" hauntings from the PS2 version of the game. 4 | 5 | This is intended for use with the GOG re-release of the game. Support for the older retail version is planned but not yet implemented. 6 | 7 | ## Features 8 | 9 | * Randomized enemy spawns - you never know what is going to be in the next room 10 | * Randomized weapon/consumable item pickups 11 | * Randomized player model - play as Henry, early Henry, Eileen, or Nurse Eileen 12 | * Randomized doors - certain areas now have doors randomized to destroy your muscle memory 13 | * Randomized damage for those who like a challenge 14 | * Deterministic randomness with support for setting a custom seed, so you can share seeds and experience the same randomized version of Silent Hill 4 every time for speedrunning or competition purposes 15 | * New items in the random loot pool from previous Silent Hill games as well as items cut from Silent Hill 4 16 | * Restores the "cut" hauntings from the PS2 version 17 | * Easy configuration via an .ini file or the in-game "Extra Options" menu which now contains all the randomizer settings (and they save to your save file!) 18 | 19 | ## New Content 20 | 21 | The randomizer adds new content *if* "Extra Content" and "Random Items" are both enabled in the options menu and as such are **completely optional**. These items seek to give a function to some previously nonfunctional, cut content in Silent Hill 4 as well as bring back some older weapons from previous Silent Hill titles. Because some like to keep the loot pool in a vanilla state, the new items are not obtainable unless using both of these toggles. 22 | 23 | * Gold Pipe (Silent Hill 3) 24 | 25 | * Silver Pipe (Silent Hill 3) 26 | 27 | * Green Hyper Spray (Silent Hill 2) 28 | 29 | * Lord's Prayer (cut from Silent Hill 4) 30 | 31 | * Red Chrism (cut from Silent Hill 4) 32 | 33 | ## Installation 34 | 35 | Use the [Ultimate ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases) (32-bit version as Silent Hill 4 is a 32-bit game), rename the DLL to dsound.dll, then extract the contents of the [latest release](https://github.com/HunterStanton/SilentHill4Randomizer/releases) into the Silent Hill 4 game directory. You should end up with a /scripts/ folder and a couple new .bin files inside /data/. 36 | 37 | If you are only interested in restoring the hauntings, disable all the randomizer settings in the .ini file, but ensure that `RestoreHauntings` is set to 1 or use [Steam006's Silent Hill 4 fix](https://community.pcgamingwiki.com/files/file/1332-silent-hill-4-pc-fix-by-steam006/) which now includes the hauntings fix. 38 | 39 | ##### Performance Note 40 | 41 | The randomizer raises the maximum amount of memory that can be allocated in a room from roughly 67MB to roughly 134MB, meaning the system requirements are slightly higher than the vanilla game. You may run into out-of-memory crashes on minspec systems or virtual machines with 512MB of RAM or less. 42 | 43 | ## Demo 44 | 45 | [![Silent Hill 4 Randomizer demo video](https://img.youtube.com/vi/yhN_v3E4eDw/0.jpg)](https://www.youtube.com/watch?v=yhN_v3E4eDw) 46 | 47 | ## Known Issues 48 | 49 | - During the first encounter with the Sniffer dogs in Subway world, a frozen enemy with no collision might appear 50 | - During the Andrew DeSalvo ghost hallway in the Water Prison, the animations may become very glitchy. This will persist until you leave the room 51 | - Certain enemies (such as Wall Men) do not get randomized due to instability that can occur when randomizing them 52 | - If you do not put the randomizer_x.bin files inside the /data/ directory, you will appear invisible, certain menus will appear white, and the game may be prone to crashing 53 | - If playing as an Eileen model, she will still use Henry's SFX 54 | - Randomized player models inside of cutscenes will appear very corrupted. A future version will have a toggle to disable randomizing player models inside of cutscenes for those who wish to avoid seeing this 55 | - The new weapons can not be charged and make no SFX 56 | - When playing as an Eileen player model, she has no collision with the actual Eileen 57 | 58 | ## Planned Additions 59 | 60 | - More player models (Jasper, etc.) 61 | - Randomization of Eileen/Cynthia's in-game models 62 | - SFX that is correct for each player model 63 | - Additional blood colors for the blood color setting 64 | 65 | ##### Potential future additions, if determined to be feasible 66 | 67 | * Randomized ghost models 68 | 69 | * Randomized door codes, water prison puzzle solution 70 | 71 | * Random HUD colors (health bar, item outline colors, etc.) 72 | 73 | * More weapons from older Silent Hill games 74 | 75 | ## Contributing 76 | 77 | If you have fixed a bug in the code, implemented a new randomization feature, or want to change things for some reason, feel free to submit a pull request and I will give it a review. 78 | 79 | For reporting bugs, please make a GitHub issue. Please include the randomizer log (which can be found in `/scripts/randomizer.log`) in the issue so I can better identify where/how the issue is occurring. 80 | 81 | ## Special Thanks 82 | 83 | * ThirteenAG, thelink2012, gabime, Thomas Monkman, and contributors to those libraries for creating the libraries used for hooking, logging, and INI parsing used to create this plugin 84 | * roocker666 - doing some research on how the game stores room layouts in the executable and sending it to me 85 | -------------------------------------------------------------------------------- /resources/VersionInfo.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterStanton/SilentHill4Randomizer/e4b35e0358e3121b1075c390387171f7f27f5d86/resources/VersionInfo.h -------------------------------------------------------------------------------- /resources/VersionInfo.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HunterStanton/SilentHill4Randomizer/e4b35e0358e3121b1075c390387171f7f27f5d86/resources/VersionInfo.rc -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/FileHooks.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "FileHooks.h" 3 | #include "Randomizer.h" 4 | #include 5 | 6 | std::vector playerModels = { 7 | // vanilla 8 | {".\\data\\henry01.bin", ".\\data\\henhk.bin"}, 9 | 10 | // early/prototype Henry + Eileen 11 | {".\\data\\randomizer_early_henry.bin", ".\\data\\randomizer_early_henry_cutscene.bin"}, 12 | //{".\\data\\randomizer_early_eileen.bin", ".\\data\\randomizer_early_eileen_cutscene.bin"}, // disable for now until I can figure out how to reposition the bone the weapon attaches to 13 | 14 | // Eileen + Eileen nurse 15 | {".\\data\\randomizer_eileen.bin", ".\\data\\eihk.bin"}, 16 | {".\\data\\randomizer_eileen_sexy.bin", ".\\data\\eohk.bin"}, 17 | 18 | // {".\\data\\randomizer_jasper.bin", ".\\data\\geik.bin"} // same deal as with early Eileen 19 | }; 20 | 21 | // replacement files that don't need special handling logic 22 | std::unordered_map replacementFiles = { 23 | {".\\data\\snap_title.bin", ".\\data\\randomizer_snap_title.bin"}, 24 | {".\\data\\item_l.bin", ".\\data\\randomizer_item_l.bin"}, 25 | {".\\data\\wp_model.bin", ".\\data\\randomizer_wp_model.bin"}, 26 | {".\\data\\system_load.bin", ".\\data\\randomizer_system_load.bin"}, 27 | {".\\data\\cynhk.bin", ".\\data\\henhk.bin"}, 28 | }; 29 | 30 | PlayerModel currentPlayerModel = playerModels[0]; 31 | 32 | // didn't want to dig super deep in the game code so this is the basic file reading function 33 | injector::hook_back LoadFile; 34 | void __cdecl LoadFileHook(LPCSTR file, HANDLE* handle) 35 | { 36 | // player model + cutscene model replacements 37 | if (strcmp(file, ".\\data\\henry01.bin") == 0) 38 | { 39 | if (settings.bInGameOptions) 40 | { 41 | if (miscOptionGetPtr.fun()->random_models == 0) 42 | { 43 | PLOG(plog::info) << "Loading file " << file; 44 | return LoadFile.fun(file, handle); 45 | } 46 | } 47 | else if (settings.bRandomPlayerModels == false) 48 | { 49 | PLOG(plog::info) << "Loading file " << file; 50 | return LoadFile.fun(file, handle); 51 | } 52 | 53 | 54 | PLOG(plog::info) << "Loading file " << currentPlayerModel.filename; 55 | return LoadFile.fun(currentPlayerModel.filename, handle); 56 | } 57 | 58 | if (strcmp(file, ".\\data\\henhk.bin") == 0) 59 | { 60 | if (settings.bInGameOptions) 61 | { 62 | if (miscOptionGetPtr.fun()->random_models == 0) 63 | { 64 | PLOG(plog::info) << "Loading file " << file; 65 | return LoadFile.fun(file, handle); 66 | } 67 | } 68 | else if (settings.bRandomPlayerModels == false) 69 | { 70 | PLOG(plog::info) << "Loading file " << file; 71 | return LoadFile.fun(file, handle); 72 | } 73 | 74 | 75 | PLOG(plog::info) << "Loading file " << currentPlayerModel.cutsceneFileName; 76 | return LoadFile.fun(currentPlayerModel.cutsceneFileName, handle); 77 | } 78 | 79 | // file replacements for randomizer (weapon models, item icons, etc.) 80 | if (replacementFiles.contains(file)) 81 | { 82 | PLOG(plog::info) << "Loading replacement file " << replacementFiles[file] << " over original file " << file; 83 | return LoadFile.fun(replacementFiles[file], handle); 84 | } 85 | 86 | PLOG(plog::info) << "Loading file " << file; 87 | return LoadFile.fun(file, handle); 88 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/GameLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "GameLoop.h" 2 | #include "sh4/game/gamemain/game.h" 3 | #include "sh4/game/message/message_handle.h" 4 | #include "sh4/game/message/message_load.h" 5 | 6 | 7 | injector::hook_back GameLoop; 8 | // std::string formattedStr; 9 | // int frame = 0; 10 | 11 | void GameLoopHook() 12 | { 13 | /* 14 | if (gameW->game_init_executed == 1) 15 | { 16 | formattedStr = std::format("Frame: {0}", frame); 17 | sfMessagePrint.fun((unsigned short*)convertMessage(formattedStr.c_str()), 0x12a, 0x152); 18 | frame++; 19 | } 20 | */ 21 | return; 22 | } 23 | 24 | void InitializeGameLoopFunction() 25 | { 26 | GameLoop.fun = injector::MakeCALL(0x004150f4, GameLoopHook, true).get(); 27 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/Randomizer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/enemy/en_kind.h" 4 | #include "sh4/game/gamemain/game_item.h" 5 | #include "sh4/game/gamemain/game_scenelink.h" 6 | #include "sh4/game/gamemain/save_data.h" 7 | #include 8 | #include "plog/Initializers/RollingFileInitializer.h" 9 | 10 | std::mt19937 mainRng = std::mt19937(std::time(0)); 11 | std::uniform_int_distribution enemyGenerator(0, possibleEnemies.size() - 1); 12 | std::uniform_int_distribution consumableGenerator(ITEM_SMALL_BULLET, ITEM_FIRST_AID_KIT); 13 | std::uniform_int_distribution playerModelGenerator(0, playerModels.size() - 1); 14 | 15 | 16 | void InitializeRandomness() 17 | { 18 | // if global seed is not set, it will be -1 19 | // global seed -1 == "random" global seed 20 | if (settings.iGlobalSeed == -1) 21 | { 22 | settings.iGlobalSeed = std::time(0); 23 | } 24 | 25 | // shuffle both weapon pools 26 | std::shuffle(possibleWeapons.begin(), possibleWeapons.end(), mainRng); 27 | std::shuffle(possibleWeaponsWithExtra.begin(), possibleWeaponsWithExtra.end(), mainRng); 28 | 29 | // replace weapon spawns with unique weapons, avoiding duplicates 30 | for (auto& item : weaponSwaps) { 31 | item.second = possibleWeapons.front(); 32 | possibleWeapons.erase(possibleWeapons.begin()); 33 | } 34 | for (auto& item : weaponSwapsWithExtra) { 35 | item.second = possibleWeaponsWithExtra.front(); 36 | possibleWeaponsWithExtra.erase(possibleWeaponsWithExtra.begin()); 37 | } 38 | /* 39 | // shuffle apartment rooms 40 | std::shuffle(rl_possible_destinations.begin(), rl_possible_destinations.end(), mainRng); 41 | for (int i = 0; i < rl_possible_destinations.size(); i++) 42 | { 43 | // set up all the link destinations 44 | rl_connection_data->doorlinks_data_offset[i].end_scene = rl_possible_destinations[i]; 45 | 46 | // find the scene data for the scene that that the door is normally in 47 | // and update the door number so the inside door functions properly 48 | for (int j = 0; j < rl_connection_data->n_scenes; j++) 49 | { 50 | if (rl_connection_data->scene_data_offsets[j]->n_doors == 1) 51 | { 52 | if (rl_connection_data->scene_data_offsets[j]->doors[0].scene_no == rl_possible_destinations[i]) 53 | { 54 | rl_connection_data->scene_data_offsets[j]->doors[0].door_no = i + 1; 55 | } 56 | } 57 | } 58 | } 59 | */ 60 | 61 | // roll random player model 62 | 63 | currentPlayerModel = playerModels[playerModelGenerator(mainRng)]; 64 | 65 | PLOG(plog::info) << "Setting a random playermodel " << currentPlayerModel.filename; 66 | 67 | HANDLE hFile = CreateFile(L"..\\save\\sh4_randomizer_per_save_settings.sav", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 68 | if (hFile != INVALID_HANDLE_VALUE) 69 | { 70 | DWORD dwBytesRead; 71 | ReadFile(hFile, &perSaveSettings, sizeof(perSaveSettings), &dwBytesRead, NULL); 72 | CloseHandle(hFile); 73 | } 74 | else 75 | { 76 | PLOG(plog::warning) << "Failed to open sh4_randomizer_per_save_settings.sav for reading. Global randomizer settings and seed will always be used."; 77 | } 78 | 79 | } 80 | void ReseedRNG(unsigned int seed) 81 | { 82 | mainRng.seed(seed + settings.iGlobalSeed); 83 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include 3 | #include 4 | #include 5 | #include "plog/Initializers/RollingFileInitializer.h" 6 | #include "Randomizer.h" 7 | #include "FileHooks.h" 8 | #include "GameLoop.h" 9 | #include "sh4/game/enemy/en_kind.h" 10 | #include "sh4/game/gamemain/camera/game_camera_another_engine.h" 11 | #include "sh4/game/gamemain/game.h" 12 | #include "sh4/game/gamemain/game_demo.h" 13 | #include "sh4/game/gamemain/game_fileread.h" 14 | #include "sh4/game/gamemain/game_item.h" 15 | #include "sh4/game/gamemain/game_gi_para.h" 16 | #include "sh4/game/gamemain/game_scenelink.h" 17 | #include "sh4/game/gamemain/save_data.h" 18 | #include "sh4/game/effect/particle/spray.h" 19 | #include "sh4/game/misc/misc_option.h" 20 | #include "sh4/game/misc/misc_itemicon.h" 21 | #include "sh4/game/misc/misc_iexplanation.h" 22 | #include "sh4/game/message/message_load.h" 23 | #include "sh4/game/gamemain/stage_info.h" 24 | #include "sh4/game/message/message_handle.h" 25 | #include "sh4/sglib/math/sg_quat.h" 26 | #include "sh4/game/objs/game_objset.h" 27 | #include "sh4/game/player/player.h" 28 | #include "sh4/game/player/player_anime_proc.h" 29 | #include "sh4/game/player/player_another_ui.h" 30 | #include "sh4/game/player/player_sound.h" 31 | #include "sh4/game/player/battle/player_weapon.h" 32 | #include "sh4/game/player/battle/player_battle.h" 33 | #include "sh4/game/player/battle/player_battle_general.h" 34 | #include "sh4/sys/apps/sf_memorystack.h" 35 | #include "sh4/sys/apps/sf_step.h" 36 | #include "sh4/sys/storage/sf_fileread.h" 37 | #include "sh4/sys/geometry/sf_scene.h" 38 | #include "sh4/sys/sound/sf_sound.h" 39 | #include "sh4/sys/env/sf_env.h" 40 | 41 | // global vars 42 | RandomizerSettings settings = { 0 }; 43 | _GAME_WORK* gameW; 44 | 45 | void Init() 46 | { 47 | 48 | // 00430ac8 49 | // 00430093 50 | 51 | // seed random 52 | std::srand(std::time(0)); 53 | 54 | plog::init(plog::info, "randomizer.log", 1000000, 1); 55 | PLOG(plog::info) << "Silent Hill 4 Randomizer initializing..."; 56 | 57 | CIniReader iniReader("randomizer.ini"); 58 | 59 | settings.bInGameOptions = iniReader.ReadInteger("GAME", "EnableInGameOptions", 0) != 0; 60 | 61 | settings.bEnableHauntings = iniReader.ReadInteger("GAME", "RestoreHauntings", 1) != 0; 62 | 63 | settings.bFastSplash = iniReader.ReadInteger("VIDEO", "FastSplash", 1) != 0; 64 | 65 | settings.iGlobalSeed = iniReader.ReadInteger("RANDOMIZER", "GlobalSeed", -1); 66 | 67 | settings.bFogApproaches = iniReader.ReadInteger("GAME", "FogApproaches", 0) != 0; 68 | 69 | 70 | 71 | gameW = injector::auto_pointer(0x00fd5a60); 72 | 73 | InitializeSgBoneFunctions(); 74 | InitializeSfCharacterFunctions(); 75 | InitializeSgAnimeFunctions(); 76 | InitializeSprayFunctions(); 77 | InitializePlayerWeaponFunctions(); 78 | InitializeSfEnvFunctions(); 79 | InitializeSgQuatFunctions(); 80 | InitializeStageInfoFunctions(); 81 | InitializePlayerBattleFunctions(); 82 | InitializeGameDemoFunctions(); 83 | InitializeMessageHandleFunctions(); 84 | InitializeGameFileReadFunctions(); 85 | InitializeEnemyKindFunctions(); 86 | InitializePlayerFunctions(); 87 | InitializeSfSceneFunctions(); 88 | InitializeSfFileLoadFunctions(); 89 | InitializeGameGIParaFunctions(); 90 | InitializeSfMemoryFunctions(); 91 | InitializePlayerBattleGeneralFunctions(); 92 | InitializePlayerSoundFunctions(); 93 | InitializePlayerAnotherUIFunctions(); 94 | InitializeSfSoundFunctions(); 95 | InitializeSfStepFunctions(); 96 | InitializeGameSceneLinkFunctions(); 97 | InitializeSaveDataFunctions(); 98 | InitializeGameCameraFunctions(); 99 | InitializeGameLoopFunction(); 100 | InitializeRandomness(); 101 | 102 | 103 | 104 | LoadSceneSets(); 105 | 106 | if (settings.bInGameOptions) 107 | { 108 | ApplyIngameOptionsPatches(); 109 | } 110 | else 111 | { 112 | settings.bRandomEnemies = iniReader.ReadInteger("RANDOMIZER", "RandomEnemies", 1) != 0; 113 | settings.bRandomPlayerModels = iniReader.ReadInteger("RANDOMIZER", "RandomPlayerModel", 1) != 0; 114 | settings.bRandomItems = iniReader.ReadInteger("RANDOMIZER", "RandomItems", 1) != 0; 115 | settings.bRandomDamage = iniReader.ReadInteger("RANDOMIZER", "RandomDamage", 1) != 0; 116 | } 117 | 118 | InstallItemHooks(); 119 | 120 | 121 | auto pattern = hook::pattern("E8 0D FE FF FF"); 122 | LoadFile.fun = injector::MakeCALL(pattern.count(2).get(1).get(0), LoadFileHook, true).get(); 123 | pattern = hook::pattern("E8 42 FE FF FF"); 124 | LoadFile.fun = injector::MakeCALL(pattern.count(3).get(1).get(0), LoadFileHook, true).get(); 125 | 126 | if (settings.bFastSplash) 127 | { 128 | // removes an fdivr instruction to shorten splash screens but not make them too short 129 | injector::WriteMemory(0x00518eb4, 0x90, true); 130 | injector::WriteMemory(0x00518eb5, 0x90, true); 131 | injector::WriteMemory(0x00518eb6, 0x90, true); 132 | injector::WriteMemory(0x00518eb7, 0x90, true); 133 | injector::WriteMemory(0x00518eb8, 0x90, true); 134 | injector::WriteMemory(0x00518eb9, 0x90, true); 135 | } 136 | 137 | 138 | if (settings.bEnableHauntings) 139 | { 140 | // removes bit shifting and weird math operations that make certain "rolls" impossible in the haunting RNG 141 | // probably should replace this with a pattern search instead of fixed addresses 142 | injector::MakeNOP(0x547e4a, 12); 143 | } 144 | PLOG(plog::info) << "Silent Hill 4 Randomizer initialized"; 145 | } 146 | 147 | CEXP void InitializeASI() 148 | { 149 | std::call_once(CallbackHandler::flag, []() 150 | { CallbackHandler::RegisterCallback(Init, hook::pattern("8B 0D ? ? ? ? 6A 00 50 51")); }); 151 | } 152 | 153 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) 154 | { 155 | if (reason == DLL_PROCESS_ATTACH) 156 | { 157 | if (!IsUALPresent()) 158 | { 159 | InitializeASI(); 160 | } 161 | } 162 | return TRUE; 163 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/en_kind.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/enemy/en_kind.h" 4 | #include "sh4/sys/storage/sf_fileread.h" 5 | #include "sh4/game/misc/misc_option.h" 6 | #include 7 | 8 | 9 | const std::vector possibleEnemies = { 10 | {ENEMY_KIND_MUSH, {0xf000f066, 0xf000f067}, 0x00615368}, 11 | {ENEMY_KIND_BUZZ, {0xf000f0b9}, 0x00615378}, 12 | {ENEMY_KIND_JINMEN, {0xf000f071}, 0x006153b8}, 13 | {ENEMY_KIND_TWINS, {0xf000f0bd}, 0x006153c8 }, 14 | {ENEMY_KIND_HIL, {0xf000f06e}, 0x006153d8}, 15 | {ENEMY_KIND_HYENA, {0xf000f068}, 0x006153e8}, 16 | {ENEMY_KIND_KILLER, {0xf000f072, 0xf000f193}, 0x00615448} }; 17 | 18 | injector::hook_back EnemyKindTableGetAddress; 19 | unsigned int __cdecl EnemyKindTableGetAddressHook(EnemyKind enemyType) 20 | { 21 | if (settings.bInGameOptions) 22 | { 23 | if (miscOptionGetPtr.fun()->random_enemies == 0) 24 | { 25 | return EnemyKindTableGetAddress.fun(enemyType); 26 | } 27 | } 28 | else if (settings.bRandomEnemies == false) 29 | { 30 | return EnemyKindTableGetAddress.fun(enemyType); 31 | } 32 | 33 | // shuffle all basic enemy types, no ghosts, no wall monster replacements, no boss replacements, no ghost replacements 34 | if (enemyType == ENEMY_KIND_HYENA || enemyType == ENEMY_KIND_MUSH || enemyType == ENEMY_KIND_JINMEN || enemyType == ENEMY_KIND_TWINS || enemyType == ENEMY_KIND_NURSE) 35 | { 36 | EnemyFileMapping enemy = possibleEnemies[enemyGenerator(mainRng)]; 37 | PLOG(plog::info) << "Spawning enemy type: " << enemy.kind; 38 | return enemy.tableAddr; 39 | } 40 | 41 | PLOG(plog::info) << "Spawning enemy type: " << enemyType; 42 | return EnemyKindTableGetAddress.fun(enemyType); 43 | } 44 | 45 | void InitializeEnemyKindFunctions() 46 | { 47 | EnemyKindTableGetAddress.fun = injector::MakeCALL(0x004852c7, EnemyKindTableGetAddressHook, true).get(); 48 | EnemyKindTableGetAddress.fun = injector::MakeCALL(0x004623b1, EnemyKindTableGetAddressHook, true).get(); 49 | EnemyKindTableGetAddress.fun = injector::MakeCALL(0x004853aa, EnemyKindTableGetAddressHook, true).get(); 50 | EnemyKindTableGetAddress.fun = injector::MakeCALL(0x0052c634, EnemyKindTableGetAddressHook, true).get(); 51 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/game_camera_another_engine.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/gamemain/camera/game_camera_another_engine.h" 4 | #include "sh4/game/gamemain/game.h" 5 | 6 | injector::hook_back CameraEngine_SetCameraPosition; 7 | 8 | void __cdecl CameraEngine_SetCameraPositionHook(Position* pos, unsigned int ContinueMvMode) 9 | { 10 | if (gameW != NULL && gameW->player != NULL) 11 | { 12 | pos->x = gameW->player->pos.x; 13 | pos->y = gameW->player->pos.y; 14 | pos->z = gameW->player->pos.z; 15 | } 16 | CameraEngine_SetCameraPosition.fun(pos, ContinueMvMode); 17 | return; 18 | } 19 | 20 | void InitializeGameCameraFunctions() 21 | { 22 | //CameraEngine_SetCameraPosition.fun = injector::MakeCALL(0x0050355e, CameraEngine_SetCameraPositionHook, true).get(); 23 | //CameraEngine_SetCameraPosition.fun = injector::MakeCALL(0x005036c2, CameraEngine_SetCameraPositionHook, true).get(); 24 | //CameraEngine_SetCameraPosition.fun = injector::MakeCALL(0x005036db, CameraEngine_SetCameraPositionHook, true).get(); 25 | } 26 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/game_demo.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/gamemain/game_demo.h" 4 | #include "sh4/sys/storage/sf_fileread.h" 5 | 6 | injector::hook_back DemoGetCharacterFileInfo; 7 | 8 | DemoCharaListEntry* demo_chara_list; 9 | 10 | // gets the 3D model, texture, etc. for a character in a cutscene (referred to as a "demo" by the game) 11 | DemoCharaListEntry* __cdecl DemoGetCharacterFileInfoHook(DemoCharaListEntry* entry, int chara_id) 12 | { 13 | DemoCharaListEntry* retEntry = DemoGetCharacterFileInfo.fun(entry, chara_id); 14 | return retEntry; 15 | } 16 | 17 | void InitializeGameDemoFunctions() 18 | { 19 | demo_chara_list = injector::auto_pointer(0x0062ced8); 20 | DemoGetCharacterFileInfo.fun = injector::MakeCALL(0x004f1f63, DemoGetCharacterFileInfoHook, true).get(); 21 | } 22 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/game_fileread.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/gamemain/game_fileread.h" 4 | #include "sh4/game/enemy/en_kind.h" 5 | #include "sh4/sys/storage/sf_fileread.h" 6 | #include 7 | #include 8 | 9 | // printable names for the games stages, based on the names from the enum 10 | std::vector stageNames = 11 | { 12 | "GAME_STAGE_DUMMY", 13 | "GAME_STAGE_3LDK", 14 | "GAME_STAGE_SUBWAY", 15 | "GAME_STAGE_FOREST", 16 | "GAME_STAGE_WATER", 17 | "GAME_STAGE_BUILDING", 18 | "GAME_STAGE_HOME", 19 | "GAME_STAGE_HOSPITAL", 20 | "GAME_STAGE_PAST_HOME", 21 | "GAME_STAGE_LAST", 22 | "GAME_STAGE_TUNNEL", 23 | "GAME_STAGE_SPIRAL", 24 | "GAME_STAGE_TEST", 25 | "GAME_STAGE_MAX" 26 | 27 | }; 28 | 29 | // hook for logging room loading for debugging purposes 30 | injector::hook_back GameFileLoadScene; 31 | void __cdecl GameFileLoadSceneHook(GameStage stage, int scene) 32 | { 33 | 34 | // reseed RNG based on scene + stage number 35 | ReseedRNG(stage + scene); 36 | 37 | PLOG(plog::info) << "Loading scene " << scene << " on stage " << stageNames[stage]; 38 | 39 | // load enemy .bin files so they will spawn 40 | // do not load anything extra on 3LDK, TUNNEL, or LAST 41 | if (stage != GAME_STAGE_3LDK && stage != GAME_STAGE_TUNNEL && stage != GAME_STAGE_LAST) 42 | { 43 | for (int i = 0; i < possibleEnemies.size(); i++) 44 | { 45 | for (int j = 0; j < possibleEnemies[i].fileIds.size(); j++) 46 | { 47 | sfFileLoad.fun(possibleEnemies[i].fileIds[j]); 48 | } 49 | } 50 | } 51 | 52 | GameFileLoadScene.fun(stage, scene); 53 | return; 54 | } 55 | 56 | // hook for logging room loading for debugging purposes 57 | injector::hook_back GameFileLoadStage; 58 | void __cdecl GameFileLoadStageHook(GameStage stage) 59 | { 60 | 61 | PLOG(plog::info) << "Loading global files for stage " << stageNames[stage]; 62 | 63 | // ensure that large item icons are globally loaded 64 | sfFileLoad.fun(0xf000f008); 65 | 66 | GameFileLoadStage.fun(stage); 67 | return; 68 | } 69 | 70 | void InitializeGameFileReadFunctions() 71 | { 72 | GameFileLoadScene.fun = injector::MakeCALL(0x004f0068, GameFileLoadSceneHook, true).get(); 73 | GameFileLoadScene.fun = injector::MakeCALL(0x004efe18, GameFileLoadSceneHook, true).get(); 74 | GameFileLoadStage.fun = injector::MakeCALL(0x004fa5d0, GameFileLoadStageHook, true).get(); 75 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/game_objset.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/objs/game_objset.h" 3 | #include 4 | 5 | void LoadSceneSets() 6 | { 7 | std::vector halfSets = { L"3ldk", L"subway", L"forest", L"water", L"building" }; 8 | std::vector standaloneSets = { L"home", L"hospital", L"pasthome", L"last", L"tunnel", L"spiral" }; 9 | 10 | for (int i = 0; i < halfSets.size(); i++) 11 | { 12 | std::wstring concatted_stdstr = L".\\randomizer\\scene_sets\\" + halfSets[i] + L"_1sthalf.set"; 13 | LPCWSTR concatted = concatted_stdstr.c_str(); 14 | HANDLE file = CreateFile(concatted, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 15 | DWORD fileSize = GetFileSize(file, NULL); 16 | LPVOID fileBuffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_READWRITE); 17 | DWORD bytesRead; 18 | if (!ReadFile(file, fileBuffer, fileSize, &bytesRead, NULL)) 19 | { 20 | PLOG(plog::error) << "Could not load scene set " << concatted_stdstr; 21 | } 22 | else 23 | { 24 | CloseHandle(file); 25 | PLOG(plog::info) << "Successfully loaded scene set " << concatted_stdstr; 26 | injector::WriteMemory(0x006553a8 + (4 * i), *(int*)&fileBuffer, true); 27 | } 28 | } 29 | 30 | for (int i = 0; i < standaloneSets.size(); i++) 31 | { 32 | std::wstring concatted_stdstr = L".\\randomizer\\scene_sets\\" + standaloneSets[i] + L".set"; 33 | LPCWSTR concatted = concatted_stdstr.c_str(); 34 | HANDLE file = CreateFile(concatted, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 35 | DWORD fileSize = GetFileSize(file, NULL); 36 | LPVOID fileBuffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_READWRITE); 37 | DWORD bytesRead; 38 | if (!ReadFile(file, fileBuffer, fileSize, &bytesRead, NULL)) 39 | { 40 | PLOG(plog::error) << "Could not load scene set " << concatted_stdstr; 41 | } 42 | else 43 | { 44 | CloseHandle(file); 45 | PLOG(plog::info) << "Successfully loaded scene set " << concatted_stdstr; 46 | injector::WriteMemory(0x006553bc + (4 * i), *(int*)&fileBuffer, true); 47 | } 48 | } 49 | 50 | for (int i = 0; i < halfSets.size(); i++) 51 | { 52 | std::wstring concatted_stdstr = L".\\randomizer\\scene_sets\\" + halfSets[i] + L"_2ndhalf.set"; 53 | LPCWSTR concatted = concatted_stdstr.c_str(); 54 | HANDLE file = CreateFile(concatted, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 55 | DWORD fileSize = GetFileSize(file, NULL); 56 | LPVOID fileBuffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_READWRITE); 57 | DWORD bytesRead; 58 | if (!ReadFile(file, fileBuffer, fileSize, &bytesRead, NULL)) 59 | { 60 | PLOG(plog::error) << "Could not load scene set " << concatted_stdstr; 61 | } 62 | else 63 | { 64 | CloseHandle(file); 65 | PLOG(plog::info) << "Successfully loaded scene set " << concatted_stdstr; 66 | injector::WriteMemory(0x006553dc + (4 * i), *(int*)&fileBuffer, true); 67 | } 68 | } 69 | 70 | for (int i = 0; i < standaloneSets.size(); i++) 71 | { 72 | std::wstring concatted_stdstr = L".\\randomizer\\scene_sets\\" + standaloneSets[i] + L".set"; 73 | LPCWSTR concatted = concatted_stdstr.c_str(); 74 | HANDLE file = CreateFile(concatted, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 75 | DWORD fileSize = GetFileSize(file, NULL); 76 | LPVOID fileBuffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_READWRITE); 77 | DWORD bytesRead; 78 | if (!ReadFile(file, fileBuffer, fileSize, &bytesRead, NULL)) 79 | { 80 | PLOG(plog::error) << "Could not load scene set " << concatted_stdstr; 81 | } 82 | else 83 | { 84 | CloseHandle(file); 85 | PLOG(plog::info) << "Successfully loaded scene set " << concatted_stdstr; 86 | injector::WriteMemory(0x006553f0 + (4 * i), *(int*)&fileBuffer, true); 87 | } 88 | } 89 | 90 | return; 91 | } 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/game_scenelink.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/gamemain/game_scenelink.h" 3 | #include 4 | 5 | DoorLinkTableEntry* rl_connection_data; 6 | DoorLinkTableEntry* sb_connection_data; 7 | 8 | std::vector rl_possible_destinations = { 9 | BATHROOM, BEDROOM, UTILITY_ROOM 10 | }; 11 | 12 | 13 | void InitializeGameSceneLinkFunctions() 14 | { 15 | rl_connection_data = injector::auto_pointer(0x0063b190); 16 | sb_connection_data = injector::auto_pointer(0x0063b3b0); 17 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/message_handle.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/message/message_handle.h" 4 | #include 5 | 6 | injector::hook_back MessagePut; 7 | 8 | injector::hook_back MessageSubtitlesPut; 9 | 10 | injector::hook_back MessageDemoSubtitlesPut; 11 | 12 | injector::hook_back MessageMemoPut; 13 | 14 | injector::hook_back MessageExplanationPut; 15 | 16 | injector::hook_back sfMessagePrint; 17 | 18 | void InitializeMessageHandleFunctions() 19 | { 20 | MessagePut.fun = injector::auto_pointer(0x0050b580); 21 | MessageSubtitlesPut.fun = injector::auto_pointer(0x0050c2a0); 22 | MessageDemoSubtitlesPut.fun = injector::auto_pointer(0x0050b1c0); 23 | MessageMemoPut.fun = injector::auto_pointer(0x0050c340); 24 | MessageExplanationPut.fun = injector::auto_pointer(0x0050c300); 25 | sfMessagePrint.fun = injector::auto_pointer(0x00559e70); 26 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/message_load.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/message/message_load.h" 3 | #include 4 | 5 | // color codes 6 | // \x01\xFF blue 7 | // \x01\XFE red 8 | // \x01\xFD green 9 | // \x01\x20 white 10 | 11 | // new options menu text 12 | 13 | const char* randomEnemies = convertMessage("Random Enemies"); 14 | const char* randomItems = convertMessage("Random Items"); 15 | const char* randomModels = convertMessage("Random Models"); 16 | const char* randomDamage = convertMessage("Random Damage"); 17 | const char* extraContent = convertMessage("Extra Content"); 18 | const char* theFogApproaches = convertMessage("The Fog Approaches"); 19 | const char* randomEnemiesExpl = convertMessage("Randomizes the enemies encountered\r\nin each room. Can cause crashes, so\r\ndon't forget to save often."); 20 | const char* randomItemsExpl = convertMessage("Randomizes the weapons and consumable items\r\npicked up. Does not randomize quest\r\nitems or the Torch to prevent softlocks."); 21 | const char* randomModelsExpl = convertMessage("Randomizes the player model."); 22 | const char* randomDamageExpl = convertMessage("Randomly adds extra damage on top\r\nof all damage received.\x01\xFE Only recommended\r\nfor experienced players.\x01\x20"); 23 | const char* extraContentExpl = convertMessage("Enables extra items/weapons in the loot pool.\r\nOnly effective if \"Random Items\" is enabled."); 24 | const char* theFogApproachesExpl = convertMessage("Feel like you are in downtown Silent Hill\r\neverywhere you go. Adds thick white fog\r\neverywhere."); 25 | 26 | // custom weapons 27 | 28 | const char* greenHyperSpray = convertMessage("\x01\x20Hyper Spray\x01\x20"); 29 | const char* greenHyperSprayDescription = convertMessage("\x01\xFDHyper Spray \x01\xFF[weapon]\x01\x20\r\nSuspicious spray can.\r\nEffect unknown."); 30 | 31 | const char* goldPipe = convertMessage("Gold Pipe"); 32 | const char* goldPipeDescription = convertMessage("\x01\xFFGold Pipe [weapon]\x01\x20\r\nIt looks snazzy, but it's not strong\r\nat all. Well, maybe I can sell it."); 33 | 34 | const char* silverPipe = convertMessage("Silver Pipe"); 35 | const char* silverPipeDescription = convertMessage("\x01\xFFSilver Pipe [weapon]\x01\x20\r\nHow gorgeous! No stronger than the\r\nsteel pipe, though. Good against\r\nvampires and werewolves."); 36 | 37 | const char* lordsPrayer = convertMessage("Lord's Prayer"); 38 | const char* lordsPrayerDescription = convertMessage("\x01\xFFLord's Prayer [Eileen consumable]\x01\x20\r\nA prayer written in an ancient language.\r\nLifts Eileen's curse slightly."); 39 | 40 | const char* redChrism = convertMessage("Red Chrism"); 41 | const char* redChrismDescription = convertMessage("\x01\xFFRed Chrism [Eileen consumable]\x01\x20\r\nA strange red liquid inside an ancient-looking bottle.\r\nHeavily lifts Eileen's curse."); 42 | 43 | // text replacements 44 | 45 | const char* newStartMessage = convertMessage("Some parts of this game may be\r\nconsidered violent or cruel.\r\n\r\nSilent Hill 4 Randomizer is active."); 46 | 47 | std::map textMap = { 48 | { 2000, randomEnemies}, 49 | { 2001, randomItems }, 50 | { 2002, randomModels}, 51 | { 2003, extraContent }, 52 | { 2004, randomDamage}, 53 | { 2005, theFogApproaches}, 54 | { 2100, randomEnemiesExpl }, 55 | { 2101, randomItemsExpl}, 56 | { 2102, randomModelsExpl }, 57 | { 2103, extraContentExpl}, 58 | { 2104, randomDamageExpl }, 59 | { 2105, theFogApproachesExpl }, 60 | { 2020, greenHyperSpray}, 61 | { 2021, greenHyperSprayDescription }, 62 | { 2022, goldPipe}, 63 | { 2023, goldPipeDescription }, 64 | { 2024, silverPipe }, 65 | { 2025, silverPipeDescription }, 66 | { 2026, lordsPrayer }, 67 | { 2027, lordsPrayerDescription }, 68 | { 2028, redChrism }, 69 | { 2029, redChrismDescription }, 70 | }; 71 | 72 | 73 | char* convertMessage(const char* text) 74 | { 75 | int len = strlen(text); 76 | char* encodedString = new char[len + 0x6]; // length of string + 6 msg control chars 77 | 78 | // control chars for beginning-of-message 79 | encodedString[0] = 0x00; 80 | encodedString[1] = 0x80; 81 | 82 | // TODO: Fix the issue that can occur where a garbage character might appear at the end of the string 83 | for (int i = 0; i < strlen(text); i++) 84 | { 85 | if (text[i] == 0x20) 86 | { 87 | // spaces are 0x00 88 | encodedString[i + 2] = 0x00; 89 | continue; 90 | } 91 | 92 | // handle line breaks 93 | if (text[i] == 0xA) 94 | { 95 | encodedString[i + 2] = 0xFD; 96 | continue; 97 | } 98 | if (text[i] == 0xD) 99 | { 100 | encodedString[i + 2] = 0xFF; 101 | continue; 102 | } 103 | 104 | if (text[i] == 0xF7) 105 | { 106 | encodedString[i + 2] = 0x00; 107 | continue; 108 | } 109 | 110 | 111 | encodedString[i + 2] = 0x100 - text[i]; 112 | } 113 | 114 | // control chars indicating end-of-message 115 | encodedString[len + 2] = 0xFF; 116 | encodedString[len + 3] = 0xFF; 117 | encodedString[len + 4] = 0x00; 118 | encodedString[len + 5] = 0x80; 119 | 120 | return encodedString; 121 | } 122 | 123 | 124 | injector::hook_back MessageAddress; 125 | unsigned short* MessageAddressHook(int packid, int num) 126 | { 127 | // TODO: Support localization so custom text can be added for more than just English 128 | // As of now changing the language of SH4 will still show all the custom text in English 129 | 130 | // splash screen text 131 | if (packid == 0 && num == 0xc5) 132 | { 133 | return (unsigned short*)newStartMessage; 134 | } 135 | 136 | if (num > 1999) 137 | { 138 | if (textMap.find(num) != textMap.end()) 139 | { 140 | return (unsigned short*)textMap[num]; 141 | } 142 | } 143 | 144 | return MessageAddress.fun(packid, num); 145 | } 146 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/misc_iexplanation.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/misc/misc_iexplanation.h" 3 | #include 4 | 5 | std::vector item_message_table = { 6 | {ITEM_EMPTY,0x0,0x1}, 7 | {ITEM_SMALL_BULLET,0x2,0x3}, 8 | {ITEM_LARGE_BULLET,0x6,0x7}, 9 | {ITEM_SILVER_BULLET,0xA,0xB}, 10 | {ITEM_RED_CHRISM,2028,2029}, 11 | {ITEM_HOLY_CANDLE,0x12,0x13}, 12 | {ITEM_LOADS_PRAYER,2026,2027}, 13 | {ITEM_FINISHER,0xFE,0xFF}, 14 | {ITEM_SAINT_MEDALLION,0x1B,0x1C}, 15 | {ITEM_HEALTH_DRINK,0x1F,0x20}, 16 | {ITEM_AMPLE,0x182,0x183}, 17 | {ITEM_FIRST_AID_KIT,0x23,0x24}, 18 | {ITEM_HANDGUN,0x27,0x28}, 19 | {ITEM_REVOLVER,0x29,0x2A}, 20 | {ITEM_IRON_PIPE,0x2D,0x2E}, 21 | {ITEM_CUTTER_KNIFE,0x31,0x32}, 22 | {ITEM_METAL_BAT,0x35,0x36}, 23 | {ITEM_DRIVER,0x39,0x3A}, 24 | {ITEM_DRIVER_BROKEN,0x39,0x3D}, 25 | {ITEM_SPOON,0x41,0x42}, 26 | {ITEM_SPOON_BROKEN,0x41,0x45}, 27 | {ITEM_MID_MASHY,0x48,0x49}, 28 | {ITEM_MID_MASHY_BROKEN,0x48,0x4C}, 29 | {ITEM_MASHY_IRON,0x4F,0x50}, 30 | {ITEM_MASHY_IRON_BROKEN,0x4F,0x53}, 31 | {ITEM_MASHY,0x56,0x57}, 32 | {ITEM_MASHY_BROKEN,0x56,0x5A}, 33 | {ITEM_SPADE_MASHY,0x5D,0x5E}, 34 | {ITEM_SPADE_MASHY_BROKEN,0x5D,0x61}, 35 | {ITEM_MASHY_NIBLICK,0x64,0x65}, 36 | {ITEM_MASHY_NIBLICK_BROKEN,0x64,0x68}, 37 | {ITEM_PITCHER,0x6B,0x6C}, 38 | {ITEM_PITCHER_BROKEN,0x6B,0x6F}, 39 | {ITEM_NIBLICK,0x72,0x73}, 40 | {ITEM_NIBLICK_BROKEN,0x72,0x76}, 41 | {ITEM_PITCHING_WEDGE,0x79,0x7A}, 42 | {ITEM_PITCHING_WEDGE_BROKEN,0x79,0x7D}, 43 | {ITEM_SAND_WEDGE,0x80,0x81}, 44 | {ITEM_SAND_WEDGE_BROKEN,0x80,0x84}, 45 | {ITEM_PUTTER,0x87,0x88}, 46 | {ITEM_PUTTER_BROKEN,0x87,0x8B}, 47 | {ITEM_WINE_BOTTLE,0x8E,0x8F}, 48 | {ITEM_WINE_BOTTLE_BROKEN,0x92,0x93}, 49 | {ITEM_SCOOP,0x97,0x98}, 50 | {ITEM_RUSTY_HATCHET,0x9B,0x9C}, 51 | {ITEM_PICK_OF_DESPAIR,0x9F,0xA0}, 52 | {ITEM_STUN_GUN,0xA3,0xA4}, 53 | {ITEM_SPRAY,0xA7,0xA8}, 54 | {ITEM_CLUB,0xFA,0xFB}, 55 | {ITEM_CHAIN_SAW,0xAB,0xAC}, 56 | {ITEM_KEY_OF_LIBERATION,0xAF,0xB0}, 57 | {ITEM_COIN_OF_LYNCHSTREETLINE,0xB1,0xB2}, 58 | {ITEM_CHOCOLATE_MILK,0xB3,0xB4}, 59 | {ITEM_SHOVEL_WITH_BLOOD_CHARACTER,0xB5,0xB6}, 60 | {ITEM_RUSTY_BLOODY_KEY,0xB7,0xB8}, 61 | {ITEM_RED_PAPER_1,0xB9,0xBA}, 62 | {ITEM_RED_PAPER_2,0xB9,0xBA}, 63 | {ITEM_RED_PAPER_3,0xB9,0xBA}, 64 | {ITEM_RED_PAPER_4,0xB9,0xBA}, 65 | {ITEM_RED_PAPER_5,0xB9,0xBA}, 66 | {ITEM_RED_PAPER_6,0xB9,0xBA}, 67 | {ITEM_TORN_RED_PAPER_1,0xC5,0xC6}, 68 | {ITEM_TORN_RED_PAPER_2,0xC5,0xC6}, 69 | {ITEM_TORN_RED_PAPER_MISS,0xC5,0xC6}, 70 | {ITEM_KEY_OF_SUPERINTENDANT,0xC7,0xC8}, 71 | {ITEM_KEY_ROCKER106,0xC9,0xCA}, 72 | {ITEM_CASSETTE_TAPE,0xCC,0xCD}, 73 | {ITEM_KEY_WITH_DOLL,0xCE,0xCF}, 74 | {ITEM_CHARM_OF_SUCCUBUS,0xD0,0xD1}, 75 | {ITEM_KEY_OF_SICKROOM,0x18A,0x18B}, 76 | {ITEM_RED_ENVELOPE,0xD6,0xD7}, 77 | {ITEM_SMALL_KEY,0xD8,0xD9}, 78 | {ITEM_CYNTHIAS_PASS,0xDB,0xDC}, 79 | {ITEM_OLD_DOLL,0xDD,0xDE}, 80 | {ITEM_MASTER_KEY_TO_APART,0xDF,0xE0}, 81 | {ITEM_ARMORIAL_MEDAL,0xE1,0xE2}, 82 | {ITEM_PICK_OF_HOPE,0xE3,0xE4}, 83 | {ITEM_NAVEL_STRING,0xE5,0xE6}, 84 | {ITEM_ALESSAS_SPEAR,0xD2,0xD3}, 85 | {ITEM_DIRTY_ENVELOPE,0x0,0x0}, 86 | {ITEM_TOY_KEY,0x103,0x104}, 87 | {ITEM_1SS_COIN_DIRTY,0x106,0x107}, 88 | {ITEM_1SS_COIN,0x10B,0x10C}, 89 | {ITEM_SB24_KEY,0x10F,0x110}, 90 | {ITEM_HANDLE,0x113,0x114}, 91 | {ITEM_DOLLS_HEAD,0x118,0x119}, 92 | {ITEM_DOLLS_RIGHT_ARM,0x11D,0x11E}, 93 | {ITEM_DOLLS_LEFT_ARM,0x127,0x128}, 94 | {ITEM_DOLLS_RIGHT_LEG,0x12C,0x12D}, 95 | {ITEM_DOLLS_LEFT_LEG,0x131,0x132}, 96 | {ITEM_UNDERGROUND_KEY,0x186,0x187}, 97 | {ITEM_PRISONERS_SHIRT,0xF6,0xF7}, 98 | {ITEM_BILLIARD_BALL,0x136,0x137}, 99 | {ITEM_STUFFED_CAT,0x13C,0x13D}, 100 | {ITEM_VOLLEYBALL,0x142,0x143}, 101 | {ITEM_SMALL_CANDLE_PACKED,0x148,0x149}, 102 | {ITEM_SMALL_CANDLE,0x148,0x149}, 103 | {ITEM_GHOSTS_KEY,0x14E,0x14F}, 104 | {ITEM_DIRTY_STONE1,0x165,0x166}, 105 | {ITEM_DIRTY_STONE2,0x165,0x166}, 106 | {ITEM_DIRTY_STONE3,0x165,0x166}, 107 | {ITEM_DIRTY_STONE4,0x165,0x166}, 108 | {ITEM_DIRTY_STONE5,0x165,0x166}, 109 | {ITEM_CHANNELING_STONE1,0x16A,0x16B}, 110 | {ITEM_CHANNELING_STONE2,0x16A,0x16B}, 111 | {ITEM_CHANNELING_STONE3,0x16A,0x16B}, 112 | {ITEM_CHANNELING_STONE4,0x16A,0x16B}, 113 | {ITEM_CHANNELING_STONE5,0x16A,0x16B}, 114 | {ITEM_PLATE_OF_TEMPTATION,0x151,0x152}, 115 | {ITEM_PLATE_OF_ORIGIN,0x156,0x157}, 116 | {ITEM_PLATE_OF_SURVEILLANCE,0x15B,0x15C}, 117 | {ITEM_PLATE_OF_CHAOS,0x160,0x161}, 118 | {ITEM_ALBERT_SPORTS_KEY,0xF1,0xF2}, 119 | {ITEM_UNIFORM,0x18C,0x18D}, 120 | {ITEM_MZ_UPPER_KEY,0x190,0x191}, 121 | {ITEM_TRAILER_KEY,0xED,0xEE}, 122 | {ITEM_HANDBAG,0xE8,0xE9}, 123 | {ITEM_SUBMACHINEGUN,0x16E,0x16F}, 124 | {ITEM_BLACKJACK,0x173,0x174}, 125 | {ITEM_HORSEWHIP,0x178,0x179}, 126 | {ITEM_CHAIN,0x17D,0x17E}, 127 | {ITEM_GREEN_HYPER_SPRAY, 2020, 2021 }, 128 | {ITEM_GOLD_PIPE, 2022, 2023 }, 129 | {ITEM_SILVER_PIPE, 2024, 2025}, 130 | }; -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/misc_itemicon.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/misc/misc_itemicon.h" 3 | #include 4 | 5 | #pragma region icon tables 6 | 7 | // icons for inventory slots 8 | std::vector small_icon_tbl = { 9 | {ITEM_EMPTY,0x0,0x0,0x0,0x0}, 10 | {ITEM_SMALL_BULLET,0xE,0x1,0x1,0xE}, 11 | {ITEM_LARGE_BULLET,0xD,0x1,0x1,0xD}, 12 | {ITEM_SILVER_BULLET,0xC,0x2,0x2,0xC}, 13 | {ITEM_RED_CHRISM,0xA,0x3,0x3,0xA}, 14 | {ITEM_HOLY_CANDLE,0x6,0x7,0x7,0x6}, 15 | {ITEM_LOADS_PRAYER,0xC,0x3,0x3,0xC}, 16 | {ITEM_FINISHER,0x1,0x5,0x5,0x1}, 17 | {ITEM_SAINT_MEDALLION,0xF,0x1,0x1,0xF}, 18 | {ITEM_HEALTH_DRINK,0xB,0x2,0x2,0xB}, 19 | {ITEM_AMPLE,0xA,0x5,0x5,0xA}, 20 | {ITEM_FIRST_AID_KIT,0xC,0x1,0x1,0xC}, 21 | {ITEM_HANDGUN,0x0,0x7,0x7,0x0}, 22 | {ITEM_REVOLVER,0xF,0x2,0x2,0xF}, 23 | {ITEM_IRON_PIPE,0x1,0x7,0x7,0x1}, 24 | {ITEM_CUTTER_KNIFE,0x7,0x7,0x7,0x7}, 25 | {ITEM_METAL_BAT,0x2,0x7,0x7,0x2}, 26 | {ITEM_DRIVER,0xC,0x7,0x7,0xC}, 27 | {ITEM_DRIVER_BROKEN,0xD,0x7,0x7,0xD}, 28 | {ITEM_SPOON,0xC,0x7,0x7,0xE}, 29 | {ITEM_SPOON_BROKEN,0xE,0x7,0x7,0xD}, 30 | {ITEM_MID_MASHY,0xF,0x7,0x7,0xF}, 31 | {ITEM_MID_MASHY_BROKEN,0x0,0x1,0x1,0x0}, 32 | {ITEM_MASHY_IRON,0xF,0x7,0x7,0xF}, 33 | {ITEM_MASHY_IRON_BROKEN,0x1,0x1,0x1,0x1}, 34 | {ITEM_MASHY,0xF,0x7,0x7,0xF}, 35 | {ITEM_MASHY_BROKEN,0x2,0x1,0x1,0x2}, 36 | {ITEM_SPADE_MASHY,0xF,0x7,0x7,0xF}, 37 | {ITEM_SPADE_MASHY_BROKEN,0x3,0x1,0x1,0x3}, 38 | {ITEM_MASHY_NIBLICK,0xF,0x7,0x7,0xF}, 39 | {ITEM_MASHY_NIBLICK_BROKEN,0x4,0x1,0x1,0x4}, 40 | {ITEM_PITCHER,0xF,0x7,0x7,0xF}, 41 | {ITEM_PITCHER_BROKEN,0x5,0x1,0x1,0x5}, 42 | {ITEM_NIBLICK,0xF,0x7,0x7,0xF}, 43 | {ITEM_NIBLICK_BROKEN,0x6,0x1,0x1,0x6}, 44 | {ITEM_PITCHING_WEDGE,0xF,0x7,0x7,0xF}, 45 | {ITEM_PITCHING_WEDGE_BROKEN,0x7,0x1,0x1,0x7}, 46 | {ITEM_SAND_WEDGE,0xF,0x7,0x7,0xF}, 47 | {ITEM_SAND_WEDGE_BROKEN,0x8,0x1,0x1,0x8}, 48 | {ITEM_PUTTER,0x9,0x1,0x1,0x9}, 49 | {ITEM_PUTTER_BROKEN,0xA,0x1,0x1,0xA}, 50 | {ITEM_WINE_BOTTLE,0x7,0x3,0x3,0x7}, 51 | {ITEM_WINE_BOTTLE_BROKEN,0x8,0x3,0x3,0x8}, 52 | {ITEM_SCOOP,0x4,0x7,0x7,0x4}, 53 | {ITEM_RUSTY_HATCHET,0x3,0x7,0x7,0x3}, 54 | {ITEM_PICK_OF_DESPAIR,0x8,0x7,0x7,0x8}, 55 | {ITEM_STUN_GUN,0xA,0x7,0x7,0xA}, 56 | {ITEM_SPRAY,0x9,0x7,0x7,0x9}, 57 | {ITEM_CLUB,0xD,0x4,0x4,0xD}, 58 | {ITEM_CHAIN_SAW,0xB,0x7,0x7,0xB}, 59 | {ITEM_KEY_OF_LIBERATION,0xE,0x4,0x4,0xE}, 60 | {ITEM_COIN_OF_LYNCHSTREETLINE,0x2,0x2,0x2,0x2}, 61 | {ITEM_CHOCOLATE_MILK,0x0,0x3,0x3,0x0}, 62 | {ITEM_SHOVEL_WITH_BLOOD_CHARACTER,0x6,0x2,0x2,0x6}, 63 | {ITEM_RUSTY_BLOODY_KEY,0x0,0x2,0x2,0x0}, 64 | {ITEM_RED_PAPER_1,0x5,0x2,0x2,0x5}, 65 | {ITEM_RED_PAPER_2,0x5,0x2,0x2,0x5}, 66 | {ITEM_RED_PAPER_3,0x5,0x2,0x2,0x5}, 67 | {ITEM_RED_PAPER_4,0x5,0x2,0x2,0x5}, 68 | {ITEM_RED_PAPER_5,0x5,0x2,0x2,0x5}, 69 | {ITEM_RED_PAPER_6,0x5,0x2,0x2,0x5}, 70 | {ITEM_TORN_RED_PAPER_1,0x9,0x2,0x2,0x9}, 71 | {ITEM_TORN_RED_PAPER_2,0x9,0x2,0x2,0x9}, 72 | {ITEM_TORN_RED_PAPER_MISS,0x9,0x2,0x2,0x9}, 73 | {ITEM_KEY_OF_SUPERINTENDANT,0x8,0x2,0x2,0x8}, 74 | {ITEM_KEY_ROCKER106,0xD,0x2,0x2,0xD}, 75 | {ITEM_CASSETTE_TAPE,0x5,0x7,0x7,0x5}, 76 | {ITEM_KEY_WITH_DOLL,0x4,0x3,0x3,0x4}, 77 | {ITEM_CHARM_OF_SUCCUBUS,0xE,0x2,0x2,0xE}, 78 | {ITEM_KEY_OF_SICKROOM,0x1,0x3,0x3,0x1}, 79 | {ITEM_RED_ENVELOPE,0x0,0x0,0x0,0x0}, 80 | {ITEM_SMALL_KEY,0x7,0x2,0x2,0x7}, 81 | {ITEM_CYNTHIAS_PASS,0xA,0x2,0x2,0xA}, 82 | {ITEM_OLD_DOLL,0x3,0x3,0x3,0x3}, 83 | {ITEM_MASTER_KEY_TO_APART,0x5,0x3,0x3,0x5}, 84 | {ITEM_ARMORIAL_MEDAL,0x3,0x2,0x2,0x3}, 85 | {ITEM_PICK_OF_HOPE,0x4,0x2,0x2,0x4}, 86 | {ITEM_NAVEL_STRING,0x2,0x3,0x3,0x2}, 87 | {ITEM_ALESSAS_SPEAR,0x1,0x6,0x6,0x1}, 88 | {ITEM_DIRTY_ENVELOPE,0x0,0x0,0x0,0x0}, 89 | {ITEM_TOY_KEY,0x6,0x5,0x5,0x6}, 90 | {ITEM_1SS_COIN_DIRTY,0x8,0x5,0x5,0x8}, 91 | {ITEM_1SS_COIN,0x7,0x5,0x5,0x7}, 92 | {ITEM_SB24_KEY,0x0,0x5,0x5,0x0}, 93 | {ITEM_HANDLE,0x2,0x5,0x5,0x2}, 94 | {ITEM_DOLLS_HEAD,0x8,0x4,0x4,0x8}, 95 | {ITEM_DOLLS_RIGHT_ARM,0x9,0x4,0x4,0x9}, 96 | {ITEM_DOLLS_LEFT_ARM,0xA,0x4,0x4,0xA}, 97 | {ITEM_DOLLS_RIGHT_LEG,0xB,0x4,0x4,0xB}, 98 | {ITEM_DOLLS_LEFT_LEG,0xC,0x4,0x4,0xC}, 99 | {ITEM_UNDERGROUND_KEY,0x0,0x6,0x6,0x0}, 100 | {ITEM_PRISONERS_SHIRT,0x3,0x5,0x5,0x3}, 101 | {ITEM_BILLIARD_BALL,0x6,0x4,0x4,0x6}, 102 | {ITEM_STUFFED_CAT,0xF,0x4,0x4,0xF}, 103 | {ITEM_VOLLEYBALL,0x7,0x4,0x4,0x7}, 104 | {ITEM_SMALL_CANDLE_PACKED,0x5,0x4,0x4,0x5}, 105 | {ITEM_SMALL_CANDLE,0x5,0x4,0x4,0x5}, 106 | {ITEM_GHOSTS_KEY,0x9,0x5,0x5,0x9}, 107 | {ITEM_DIRTY_STONE1,0x2,0x6,0x6,0x1}, 108 | {ITEM_DIRTY_STONE2,0x2,0x6,0x6,0x1}, 109 | {ITEM_DIRTY_STONE3,0x2,0x6,0x6,0x1}, 110 | {ITEM_DIRTY_STONE4,0x2,0x6,0x6,0x1}, 111 | {ITEM_DIRTY_STONE5,0x2,0x6,0x6,0x1}, 112 | {ITEM_CHANNELING_STONE1,0x4,0x5,0x5,0x4}, 113 | {ITEM_CHANNELING_STONE2,0x4,0x5,0x5,0x4}, 114 | {ITEM_CHANNELING_STONE3,0x4,0x5,0x5,0x4}, 115 | {ITEM_CHANNELING_STONE4,0x4,0x5,0x5,0x4}, 116 | {ITEM_CHANNELING_STONE5,0x4,0x5,0x5,0x4}, 117 | {ITEM_PLATE_OF_TEMPTATION,0xB,0x5,0x5,0xB}, 118 | {ITEM_PLATE_OF_ORIGIN,0xC,0x5,0x5,0xC}, 119 | {ITEM_PLATE_OF_SURVEILLANCE,0xD,0x5,0x5,0xD}, 120 | {ITEM_PLATE_OF_CHAOS,0xE,0x5,0x5,0xE}, 121 | {ITEM_ALBERT_SPORTS_KEY,0x0,0x4,0x4,0x0}, 122 | {ITEM_UNIFORM,0x3,0x6,0x6,0x3}, 123 | {ITEM_MZ_UPPER_KEY,0x1,0x3,0x3,0x1}, 124 | {ITEM_TRAILER_KEY,0x6,0x3,0x3,0x6}, 125 | {ITEM_HANDBAG,0x9,0x3,0x3,0x9}, 126 | {ITEM_SUBMACHINEGUN,0x4,0x4,0x4,0x4}, 127 | {ITEM_BLACKJACK,0x3,0x4,0x4,0x3}, 128 | {ITEM_HORSEWHIP,0x5,0x5,0x5,0x5}, 129 | {ITEM_CHAIN,0xF,0x5,0x5,0xF}, 130 | {ITEM_GREEN_HYPER_SPRAY,0x9,0x0,0x0,0x9 }, 131 | { ITEM_GOLD_PIPE,0x1,0x0,0x0,0x1 }, 132 | { ITEM_SILVER_PIPE,0x0,0x0,0x0,0x0 }, 133 | }; 134 | 135 | // larger icons for item box 136 | std::vector large_icon_tbl = { 137 | {ITEM_EMPTY,0x0,0x0,0x0,0x0}, 138 | {ITEM_SMALL_BULLET,0xA,0x1,0x1,0x0}, 139 | {ITEM_LARGE_BULLET,0x9,0x1,0x1,0x0}, 140 | {ITEM_SILVER_BULLET,0x4,0x2,0x2,0x0}, 141 | {ITEM_RED_CHRISM,0x12,0x2,0x2,0x0}, 142 | {ITEM_HOLY_CANDLE,0x6,0x0,0x0,0x0}, 143 | {ITEM_LOADS_PRAYER,0x0,0x3,0x3,0x0}, 144 | {ITEM_FINISHER,0x1,0x4,0x4,0x0}, 145 | {ITEM_SAINT_MEDALLION,0xB,0x1,0x1,0x0}, 146 | {ITEM_HEALTH_DRINK,0x3,0x2,0x2,0x0}, 147 | {ITEM_AMPLE,0xA,0x4,0x4,0x0}, 148 | {ITEM_FIRST_AID_KIT,0x8,0x1,0x1,0x0}, 149 | {ITEM_HANDGUN,0x0,0x0,0x0,0x0}, 150 | {ITEM_REVOLVER,0x7,0x2,0x2,0x0}, 151 | {ITEM_IRON_PIPE,0x1,0x0,0x0,0x0}, 152 | {ITEM_CUTTER_KNIFE,0x7,0x0,0x0,0x0}, 153 | {ITEM_METAL_BAT,0x2,0x0,0x0,0x0}, 154 | {ITEM_DRIVER,0xC,0x0,0x0,0x0}, 155 | {ITEM_DRIVER_BROKEN,0xD,0x0,0x0,0x0}, 156 | {ITEM_SPOON,0xC,0x0,0x0,0x0}, 157 | {ITEM_SPOON_BROKEN,0xE,0x0,0x0,0x0}, 158 | {ITEM_MID_MASHY,0xF,0x0,0x0,0x0}, 159 | {ITEM_MID_MASHY_BROKEN,0x10,0x0,0x0,0x0}, 160 | {ITEM_MASHY_IRON,0xF,0x0,0x0,0x0}, 161 | {ITEM_MASHY_IRON_BROKEN,0x11,0x0,0x0,0x0}, 162 | {ITEM_MASHY,0xF,0x0,0x0,0x0}, 163 | {ITEM_MASHY_BROKEN,0x12,0x0,0x0,0x0}, 164 | {ITEM_SPADE_MASHY,0xF,0x0,0x0,0x0}, 165 | {ITEM_SPADE_MASHY_BROKEN,0x13,0x0,0x0,0x0}, 166 | {ITEM_MASHY_NIBLICK,0xF,0x0,0x0,0x0}, 167 | {ITEM_MASHY_NIBLICK_BROKEN,0x0,0x1,0x1,0x0}, 168 | {ITEM_PITCHER,0xF,0x0,0x0,0x0}, 169 | {ITEM_PITCHER_BROKEN,0x1,0x1,0x1,0x0}, 170 | {ITEM_NIBLICK,0xF,0x0,0x0,0x0}, 171 | {ITEM_NIBLICK_BROKEN,0x2,0x1,0x1,0x0}, 172 | {ITEM_PITCHING_WEDGE,0xF,0x0,0x0,0x0}, 173 | {ITEM_PITCHING_WEDGE_BROKEN,0x3,0x1,0x1,0x0}, 174 | {ITEM_SAND_WEDGE,0xF,0x0,0x0,0x0}, 175 | {ITEM_SAND_WEDGE_BROKEN,0x4,0x1,0x1,0x0}, 176 | {ITEM_PUTTER,0x5,0x1,0x1,0x0}, 177 | {ITEM_PUTTER_BROKEN,0x6,0x1,0x1,0x0}, 178 | {ITEM_WINE_BOTTLE,0xF,0x2,0x2,0x0}, 179 | {ITEM_WINE_BOTTLE_BROKEN,0x10,0x2,0x2,0x0}, 180 | {ITEM_SCOOP,0x4,0x0,0x0,0x0}, 181 | {ITEM_RUSTY_HATCHET,0x3,0x0,0x0,0x0}, 182 | {ITEM_PICK_OF_DESPAIR,0x8,0x0,0x0,0x0}, 183 | {ITEM_STUN_GUN,0xA,0x0,0x0,0x0}, 184 | {ITEM_SPRAY,0x9,0x0,0x0,0x0}, 185 | {ITEM_CLUB,0x11,0x3,0x3,0x0}, 186 | {ITEM_CHAIN_SAW,0xB,0x0,0x0,0x0}, 187 | {ITEM_KEY_OF_LIBERATION,0x12,0x3,0x3,0x0}, 188 | {ITEM_COIN_OF_LYNCHSTREETLINE,0xE,0x1,0x1,0x0}, 189 | {ITEM_CHOCOLATE_MILK,0x8,0x2,0x2,0x0}, 190 | {ITEM_SHOVEL_WITH_BLOOD_CHARACTER,0x12,0x1,0x1,0x0}, 191 | {ITEM_RUSTY_BLOODY_KEY,0xC,0x1,0x1,0x0}, 192 | {ITEM_RED_PAPER_1,0x11,0x1,0x1,0x0}, 193 | {ITEM_RED_PAPER_2,0x11,0x1,0x1,0x0}, 194 | {ITEM_RED_PAPER_3,0x11,0x1,0x1,0x0}, 195 | {ITEM_RED_PAPER_4,0x11,0x1,0x1,0x0}, 196 | {ITEM_RED_PAPER_5,0x11,0x1,0x1,0x0}, 197 | {ITEM_RED_PAPER_6,0x11,0x1,0x1,0x0}, 198 | {ITEM_TORN_RED_PAPER_1,0x1,0x2,0x2,0x0}, 199 | {ITEM_TORN_RED_PAPER_2,0x1,0x2,0x2,0x0}, 200 | {ITEM_TORN_RED_PAPER_MISS,0x1,0x2,0x2,0x0}, 201 | {ITEM_KEY_OF_SUPERINTENDANT,0x0,0x2,0x2,0x0}, 202 | {ITEM_KEY_ROCKER106,0x5,0x2,0x2,0x0}, 203 | {ITEM_CASSETTE_TAPE,0x5,0x0,0x0,0x0}, 204 | {ITEM_KEY_WITH_DOLL,0xC,0x2,0x2,0x0}, 205 | {ITEM_CHARM_OF_SUCCUBUS,0x6,0x2,0x2,0x0}, 206 | {ITEM_KEY_OF_SICKROOM,0x9,0x2,0x2,0x0}, 207 | {ITEM_RED_ENVELOPE,(char)0xFF,0x5,0x5,0x0}, 208 | {ITEM_SMALL_KEY,0x13,0x1,0x1,0x0}, 209 | {ITEM_CYNTHIAS_PASS,0x2,0x2,0x2,0x0}, 210 | {ITEM_OLD_DOLL,0xB,0x2,0x2,0x0}, 211 | {ITEM_MASTER_KEY_TO_APART,0xD,0x2,0x2,0x0}, 212 | {ITEM_ARMORIAL_MEDAL,0xF,0x1,0x1,0x0}, 213 | {ITEM_PICK_OF_HOPE,0x10,0x1,0x1,0x0}, 214 | {ITEM_NAVEL_STRING,0xA,0x2,0x2,0x0}, 215 | {ITEM_ALESSAS_SPEAR,0x11,0x4,0x4,0x0}, 216 | {ITEM_DIRTY_ENVELOPE,(char)0xFF,0x5,0x5,0x0}, 217 | {ITEM_TOY_KEY,0x6,0x4,0x4,0x0}, 218 | {ITEM_1SS_COIN_DIRTY,0x8,0x4,0x4,0x0}, 219 | {ITEM_1SS_COIN,0x7,0x4,0x4,0x0}, 220 | {ITEM_SB24_KEY,0x0,0x4,0x4,0x0}, 221 | {ITEM_HANDLE,0x2,0x4,0x4,0x0}, 222 | {ITEM_DOLLS_HEAD,0xC,0x3,0x3,0x0}, 223 | {ITEM_DOLLS_RIGHT_ARM,0xD,0x3,0x3,0x0}, 224 | {ITEM_DOLLS_LEFT_ARM,0xE,0x3,0x3,0x0}, 225 | {ITEM_DOLLS_RIGHT_LEG,0xF,0x3,0x3,0x0}, 226 | {ITEM_DOLLS_LEFT_LEG,0x10,0x3,0x3,0x0}, 227 | {ITEM_UNDERGROUND_KEY,0x10,0x4,0x4,0x0}, 228 | {ITEM_PRISONERS_SHIRT,0x3,0x4,0x4,0x0}, 229 | {ITEM_BILLIARD_BALL,0xA,0x3,0x3,0x0}, 230 | {ITEM_STUFFED_CAT,0x13,0x3,0x3,0x0}, 231 | {ITEM_VOLLEYBALL,0xB,0x3,0x3,0x0}, 232 | {ITEM_SMALL_CANDLE_PACKED,0x9,0x3,0x3,0x0}, 233 | {ITEM_SMALL_CANDLE,0x9,0x3,0x3,0x0}, 234 | {ITEM_GHOSTS_KEY,0x9,0x4,0x4,0x0}, 235 | {ITEM_DIRTY_STONE1,0x12,0x4,0x4,0x0}, 236 | {ITEM_DIRTY_STONE2,0x12,0x4,0x4,0x0}, 237 | {ITEM_DIRTY_STONE3,0x12,0x4,0x4,0x0}, 238 | {ITEM_DIRTY_STONE4,0x12,0x4,0x4,0x0}, 239 | {ITEM_DIRTY_STONE5,0x12,0x4,0x4,0x0}, 240 | {ITEM_CHANNELING_STONE1,0x4,0x4,0x4,0x0}, 241 | {ITEM_CHANNELING_STONE2,0x4,0x4,0x4,0x0}, 242 | {ITEM_CHANNELING_STONE3,0x4,0x4,0x4,0x0}, 243 | {ITEM_CHANNELING_STONE4,0x4,0x4,0x4,0x0}, 244 | {ITEM_CHANNELING_STONE5,0x4,0x4,0x4,0x0}, 245 | {ITEM_PLATE_OF_TEMPTATION,0xB,0x4,0x4,0x0}, 246 | {ITEM_PLATE_OF_ORIGIN,0xC,0x4,0x4,0x0}, 247 | {ITEM_PLATE_OF_SURVEILLANCE,0xD,0x4,0x4,0x0}, 248 | {ITEM_PLATE_OF_CHAOS,0xE,0x4,0x4,0x0}, 249 | {ITEM_ALBERT_SPORTS_KEY,0x4,0x3,0x3,0x0}, 250 | {ITEM_UNIFORM,0x13,0x4,0x4,0x0}, 251 | {ITEM_MZ_UPPER_KEY,0x9,0x2,0x2,0x0}, 252 | {ITEM_TRAILER_KEY,0xE,0x2,0x2,0x0}, 253 | {ITEM_HANDBAG,0x11,0x2,0x2,0x0}, 254 | {ITEM_SUBMACHINEGUN,0x7,0x3,0x3,0x0}, 255 | {ITEM_BLACKJACK,0x8,0x3,0x3,0x0}, 256 | {ITEM_HORSEWHIP,0x5,0x4,0x4,0x0}, 257 | {ITEM_CHAIN,0xF,0x4,0x4,0x0}, 258 | {ITEM_GREEN_HYPER_SPRAY,0x9,0x5,0x5,0x0}, 259 | {ITEM_GOLD_PIPE,0x1,0x5,0x5,0x0}, 260 | {ITEM_SILVER_PIPE,0x0,0x5,0x5,0x0}, 261 | }; 262 | 263 | #pragma endregion 264 | 265 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/misc_option.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/misc/misc_option.h" 3 | #include "sh4/game/message/message_load.h" 4 | #include 5 | 6 | 7 | std::vector extraOptionMenuItems = { 8 | // vanilla settings 9 | { 10 | 0x524a20, 11 | 0x413ca0, 12 | 0, 13 | 0x654c2c, 14 | 7, 15 | 42, 16 | 0x523150}, 17 | {0x524af0, 18 | 0x413cb0, 19 | 0, 20 | 0x654c18, 21 | 2, 22 | 43, 23 | 0x525480}, 24 | {0x524e40, 25 | 0x413cd0, 26 | 0, 27 | 0x654c18, 28 | 2, 29 | 47, 30 | 0x5254a0}, 31 | {0x524da0, 32 | 0x413cc0, 33 | 0, 34 | 0x654c48, 35 | 3, 36 | 44, 37 | 0x00525490}, 38 | {0x524760, 39 | 0x413c40, 40 | 0, 41 | 0x654c18, 42 | 2, 43 | 33, 44 | 0x00525430}, 45 | {0x524830, 46 | 0x413c50, 47 | 0, 48 | 0x654c18, 49 | 2, 50 | 34, 51 | 0x00525440}, 52 | {0x524f20, 53 | 0x413cf0, 54 | 0, 55 | 0x654c18, 56 | 2, 57 | 120, 58 | 0x525470}, 59 | 60 | // new randomizer settings 61 | { 62 | (int)&change_random_enemies, 63 | (int)&get_random_enemies, 64 | 0, 65 | 0x654c18, 66 | 2, 67 | 2000, 68 | (int)&get_random_enemies_expl}, 69 | 70 | {(int)&change_random_items, 71 | (int)&get_random_items, 72 | 0, 73 | 0x654c18, 74 | 2, 75 | 2001, 76 | (int)&get_random_items_expl}, 77 | 78 | {(int)&change_random_models, 79 | (int)&get_random_models, 80 | 0, 81 | 0x654c18, 82 | 2, 83 | 2002, 84 | (int)&get_random_models_expl}, 85 | 86 | {(int)&change_random_damage, 87 | (int)&get_random_damage, 88 | 0, 89 | 0x654c18, 90 | 2, 91 | 2004, 92 | (int)&get_random_damage_expl}, 93 | 94 | {(int)&change_extra_content, 95 | (int)&get_extra_content, 96 | 0, 97 | 0x654c18, 98 | 2, 99 | 2003, 100 | (int)&get_extra_content_expl}, 101 | 102 | {(int)&change_fog_approaches, 103 | (int)&get_fog_approaches, 104 | 0, 105 | 0x654c18, 106 | 2, 107 | 2005, 108 | (int)&get_fog_approaches_expl}, 109 | 110 | // exit button 111 | { 112 | 0x524f90, 113 | 0x51eb10, 114 | 0, 115 | 0x654c54, 116 | 1, 117 | 48, 118 | 0x401010} }; 119 | 120 | std::vector optionMenuTitleMessages = { 121 | 0x6E, 122 | 0x6F, 123 | 0x70 124 | }; 125 | 126 | std::vector optionItemCounts = { 127 | 7, 128 | 7, 129 | (int)extraOptionMenuItems.size() 130 | }; 131 | 132 | std::vector optionItemPtrs = { 133 | 0x00654cc0, 134 | 0x00654d88, 135 | *(int*)&extraOptionMenuItems 136 | }; 137 | 138 | void ApplyIngameOptionsPatches() 139 | { 140 | // to anyone reading this code and wondering what is happening with these patches: 141 | // SH4 hardcodes its menus. These pointers point to structures containing information about the individual menu items such as display name, description, etc. 142 | // By overwriting the original pointer with a pointer to our custom extraOptionMenuItems structure we can add new items to existing menus 143 | injector::WriteMemory(0x00523dae, *(int*)&optionItemPtrs, true); 144 | injector::WriteMemory(0x005264a1, *(int*)&optionItemPtrs, true); 145 | injector::WriteMemory(0x0052623e, *(int*)&optionItemPtrs, true); 146 | injector::WriteMemory(0x00526322, *(int*)&optionItemPtrs, true); 147 | 148 | // Adjust the menu item counts so our new items will appear 149 | injector::WriteMemory(0x00523da0, *(int*)&optionMenuTitleMessages, true); 150 | injector::WriteMemory(0x00523d91, *(int*)&optionItemCounts, true); 151 | injector::WriteMemory(0x00523d33, *(int*)&optionItemCounts, true); 152 | 153 | // adjust spacing on options menu so more items can fit 154 | // in the future the move would be to create an "Option 4 (Randomizer)" menu to fit all the randomizer stuff 155 | // slotting it into extra feels weird 156 | injector::WriteMemory(0x00523db8, 0x20, true); 157 | injector::WriteMemory(0x00523e0b, 0x15, true); 158 | 159 | // move menu title text to Y pos 0 160 | injector::WriteMemory(0x005259bb, 0x0, true); 161 | injector::WriteMemory(0x005259d0, 0x0, true); 162 | 163 | // hide arrows 164 | injector::MakeNOP(0x0052671f, 5, true); 165 | injector::MakeNOP(0x005267e1, 5, true); 166 | 167 | // move explanation text closer to the bottom of the screen 168 | injector::WriteMemory(0x0052664f, 370, true); 169 | 170 | 171 | 172 | miscOptionGetPtr.fun = injector::auto_pointer(0x005230c0); 173 | 174 | // hook to display custom text without needing to provide new message bins 175 | MessageAddress.fun = injector::MakeCALL(0x0050b594, MessageAddressHook, true).get(); 176 | MessageAddress.fun = injector::MakeCALL(0x0050c30a, MessageAddressHook, true).get(); 177 | MessageAddress.fun = injector::MakeCALL(0x0050b1cb, MessageAddressHook, true).get(); 178 | MessageAddress.fun = injector::MakeCALL(0x0050b2ae, MessageAddressHook, true).get(); 179 | MessageAddress.fun = injector::MakeCALL(0x0050b5ce, MessageAddressHook, true).get(); 180 | MessageAddress.fun = injector::MakeCALL(0x0050c2aa, MessageAddressHook, true).get(); 181 | MessageAddress.fun = injector::MakeCALL(0x0050c34a, MessageAddressHook, true).get(); 182 | MessageAddress.fun = injector::MakeCALL(0x005573ed, MessageAddressHook, true).get(); 183 | } 184 | 185 | injector::hook_back miscOptionGetPtr; 186 | 187 | // game calls the change functions with two params, a ptr to the options struct and the new option index 188 | // naming convention following what the game itself uses 189 | int change_random_enemies(GameOptions* opt, int num) 190 | { 191 | Sleep(100); 192 | opt->random_enemies = ((opt->random_enemies + -1 + num) % num); 193 | return 0; 194 | } 195 | 196 | int get_random_enemies() 197 | { 198 | return miscOptionGetPtr.fun()->random_enemies; 199 | } 200 | 201 | int get_random_enemies_expl() 202 | { 203 | return 2100; 204 | } 205 | 206 | int change_random_items(GameOptions* opt, int num) 207 | { 208 | Sleep(100); 209 | opt->random_items = ((opt->random_items + -1 + num) % num); 210 | return 0; 211 | } 212 | 213 | int get_random_items() 214 | { 215 | return miscOptionGetPtr.fun()->random_items; 216 | } 217 | 218 | int get_random_items_expl() 219 | { 220 | return 2101; 221 | } 222 | 223 | int change_random_models(GameOptions* opt, int num) 224 | { 225 | Sleep(100); 226 | opt->random_models = ((opt->random_models + -1 + num) % num); 227 | return 0; 228 | } 229 | 230 | int get_random_models() 231 | { 232 | return miscOptionGetPtr.fun()->random_models; 233 | } 234 | 235 | int get_random_models_expl() 236 | { 237 | return 2102; 238 | } 239 | 240 | int change_random_damage(GameOptions* opt, int num) 241 | { 242 | Sleep(100); 243 | opt->random_damage = ((opt->random_damage + -1 + num) % num); 244 | return 0; 245 | } 246 | 247 | int get_random_damage() 248 | { 249 | return miscOptionGetPtr.fun()->random_damage; 250 | } 251 | 252 | int get_random_damage_expl() 253 | { 254 | return 2104; 255 | } 256 | 257 | int change_extra_content(GameOptions* opt, int num) 258 | { 259 | Sleep(100); 260 | opt->extra_content = ((opt->extra_content + -1 + num) % num); 261 | return 0; 262 | } 263 | 264 | int get_extra_content() 265 | { 266 | return miscOptionGetPtr.fun()->extra_content; 267 | } 268 | 269 | int get_extra_content_expl() 270 | { 271 | return 2103; 272 | } 273 | 274 | int change_fog_approaches(GameOptions* opt, int num) 275 | { 276 | Sleep(100); 277 | opt->fog_approaches = ((opt->fog_approaches + -1 + num) % num); 278 | return 0; 279 | } 280 | 281 | int get_fog_approaches() 282 | { 283 | return miscOptionGetPtr.fun()->fog_approaches; 284 | } 285 | 286 | int get_fog_approaches_expl() 287 | { 288 | return 2105; 289 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/player.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/gamemain/game.h" 3 | #include "sh4/game/misc/misc_option.h" 4 | #include "sh4/game/player/player.h" 5 | #include "Randomizer.h" 6 | #include 7 | 8 | // random damage algorithm has 50% chance of increasing damage by a range of percentage values 9 | // percent increase is dependent on difficulty 10 | // 0-25% on easy 11 | // 0-50% on medium 12 | // 0-100% on hard 13 | injector::hook_back PlayerDamage; 14 | int __cdecl PlayerDamageHook(int num, float damage) 15 | { 16 | if (settings.bInGameOptions) 17 | { 18 | if (miscOptionGetPtr.fun()->random_damage == 1) 19 | { 20 | float percentChange; 21 | switch (gameW->level) 22 | { 23 | case EASY: 24 | percentChange = (rand() % 26) / 100.0; 25 | break; 26 | case NORMAL: 27 | percentChange = (rand() % 51) / 100.0; 28 | break; 29 | case HARD: 30 | percentChange = (rand() % 101) / 100.0; 31 | break; 32 | default: 33 | percentChange = (rand() % 26) / 100.0; 34 | break; 35 | } 36 | if (rand() % 2 == 0) { 37 | damage += damage * percentChange; 38 | } 39 | } 40 | return PlayerDamage.fun(num, damage); 41 | } 42 | else if (settings.bRandomDamage) 43 | { 44 | float percentChange; 45 | switch (gameW->level) 46 | { 47 | case EASY: 48 | percentChange = (rand() % 26) / 100.0; 49 | break; 50 | case NORMAL: 51 | percentChange = (rand() % 51) / 100.0; 52 | break; 53 | case HARD: 54 | percentChange = (rand() % 101) / 100.0; 55 | break; 56 | default: 57 | percentChange = (rand() % 26) / 100.0; 58 | break; 59 | } 60 | if (rand() % 2 == 0) { 61 | damage += damage * percentChange; 62 | } 63 | } 64 | return PlayerDamage.fun(num, damage); 65 | } 66 | 67 | void InitializePlayerFunctions() 68 | { 69 | PlayerDamage.fun = injector::MakeCALL(0x00450a77, PlayerDamageHook, true).get(); 70 | PlayerDamage.fun = injector::MakeCALL(0x005391c4, PlayerDamageHook, true).get(); 71 | PlayerDamage.fun = injector::MakeCALL(0x005391eb, PlayerDamageHook, true).get(); 72 | PlayerDamage.fun = injector::MakeCALL(0x005392ab, PlayerDamageHook, true).get(); 73 | PlayerDamage.fun = injector::MakeCALL(0x0053e6e8, PlayerDamageHook, true).get(); 74 | PlayerDamage.fun = injector::MakeCALL(0x0053eacd, PlayerDamageHook, true).get(); 75 | PlayerDamage.fun = injector::MakeCALL(0x0053ee0e, PlayerDamageHook, true).get(); 76 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/player_anime_proc.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/player/player_anime_proc.h" 3 | #include 4 | 5 | // list of pointers to anim tables for various weapons 6 | static int motion_handgun = 0x006953c8; 7 | static int motion_pipe = 0x00695508; 8 | static int motion_cutter = 0x006955a8; 9 | static int motion_bottle_broken = 0x00695968; 10 | static int motion_scoop = 0x00695828; 11 | static int motion_axe = 0x00695468; 12 | static int motion_pick = 0x006958c8; 13 | static int motion_stun = 0x00695648; 14 | static int motion_spray = 0x006956e8; 15 | static int motion_chain = 0x00695788; 16 | 17 | std::vector motion_battle = { 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 | motion_handgun, motion_handgun, motion_pipe, 20 | motion_cutter, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 21 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 22 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 23 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_cutter, 24 | motion_bottle_broken, motion_scoop, motion_axe, motion_pick, motion_stun, motion_spray, 25 | motion_pipe, motion_chain, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 26 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 27 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 28 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 29 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 30 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 31 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 32 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 33 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 34 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 35 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 36 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 37 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 38 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 39 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 40 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 41 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 42 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 43 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 44 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 45 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 46 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 47 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 48 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 49 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 50 | motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, motion_pipe, 51 | // hyper spray 52 | motion_spray, 53 | // gold pipe 54 | motion_pipe, 55 | // silver pipe 56 | motion_pipe 57 | }; -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/player_another_ui.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/player/player_another_ui.h" 3 | #include "sh4/game/gamemain/game.h" 4 | #include "Randomizer.h" 5 | #include 6 | 7 | PlayerUI* playerUI; 8 | int* motion_stop; 9 | 10 | void InitializePlayerAnotherUIFunctions() 11 | { 12 | playerUI = injector::auto_pointer(0x010a1a00); 13 | motion_stop = injector::auto_pointer(0x010a1914); 14 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/player_battle.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include 4 | #include "CommonTypes.h" 5 | #include "sh4/game/gamemain/game.h" 6 | #include "sh4/game/effect/particle/spray.h" 7 | #include "sh4/sys/geometry/sf_chara.h" 8 | #include "sh4/sys/env/sf_env.h" 9 | #include "sh4/sglib/animation/sg_bone.h" 10 | #include "sh4/sglib/math/sg_quat.h" 11 | #include "sh4/game/player/battle/player_battle.h" 12 | #include "sh4/game/player/player_another_ui.h" 13 | #include "sh4/game/player/battle/player_weapon.h" 14 | 15 | injector::hook_back battle_anotherworld; 16 | injector::hook_back normal_attack_all; 17 | injector::hook_back PlayerWeaponChargable; 18 | 19 | sfObj* sprayObj; 20 | 21 | int __cdecl normal_attack_allHook() 22 | { 23 | int ret = normal_attack_all.fun(); 24 | 25 | // take away 1 unit of health on every spray 26 | if (gameW->player->weapon_kind == ITEM_GREEN_HYPER_SPRAY) 27 | { 28 | if (gameW->player->life < 0.01f) 29 | { 30 | gameW->player->life = 0.0f; 31 | } 32 | else 33 | { 34 | gameW->player->life = gameW->player->life - 0.01f; 35 | } 36 | } 37 | 38 | return ret; 39 | } 40 | 41 | void __cdecl battle_anotherworldHook() 42 | { 43 | 44 | sprayObj = injector::ReadMemory(0x00fcdf80, true); 45 | 46 | // call original battle_anotherworld 47 | // this shouldn't cause any problems because the Spray checks are done at the end of the func 48 | battle_anotherworld.fun(); 49 | 50 | GameItem kind = gameW->player->weapon_kind; 51 | int battleStat = gameW->player->battle_stat; 52 | 53 | int* is_spraying = injector::auto_pointer(0x010a1e9c); 54 | Position* quatPtr = injector::auto_pointer(0x006112e0); 55 | Position* quatPtr2 = injector::auto_pointer(0x006112c0); 56 | 57 | // copy the original spray can logic and modify it so it works for the Hyper Spray(s) 58 | if (battleStat != 0) 59 | { 60 | if (kind == ITEM_GREEN_HYPER_SPRAY) 61 | { 62 | if (battleStat == 3) 63 | { 64 | // if player is spraying hyper spray, do the original spray FX stuff 65 | float frame = sgAnimeCurrentFloatFrame.fun(gameW->player->anim_frame); 66 | float curFps = sfSysEnvFps.fun(); 67 | float startTime = PlayerWeaponGetStartTime.fun(kind, 0); 68 | float endTime = PlayerWeaponGetEndTime.fun(kind, 0); 69 | 70 | if ((startTime + 0.1 < curFps * frame) && (endTime > curFps * frame) && (gameW->player->anim_ctrl == 0x23 || gameW->player->anim_ctrl == 0x24)) 71 | { 72 | Position temp = { 35.0, 15.0, 12.0, 1.0 }; 73 | FourByFourMatrix temp2 = { 0 }; 74 | Position absRot = { 0,0,0,0 }; 75 | Position angleQuat = { 0,0,0,0 }; 76 | Position sprayPos = { 0,0,0,0 }; 77 | Position vectorMultipliedQuat = { 0,0,0,0 }; 78 | sgBone* bone = sfCharacterBone.fun(gameW->player->obj, 0x19); 79 | 80 | 81 | // calculate where to draw the spray cloud (Henry's right hand bone, bone 0x19, is roughly where the spray should spawn) 82 | sgBoneGetEuclideanDistance.fun(bone, &temp2); 83 | sgBoneGetAbsMatrix.fun(&sprayPos, &temp2, &temp); 84 | sgBoneGetAbsRot.fun(bone, &absRot); 85 | sgQuatFromAxisAngle.fun(&angleQuat, quatPtr, 0.7853982f); 86 | sgQuatMul.fun(&absRot, &absRot, &angleQuat); 87 | sgQuatMulVector.fun(&vectorMultipliedQuat, &absRot, quatPtr2); 88 | sgQuatGetEuclideanDistance.fun(&vectorMultipliedQuat, &vectorMultipliedQuat); 89 | 90 | 91 | vectorMultipliedQuat.x = vectorMultipliedQuat.x * 1400.0f; 92 | vectorMultipliedQuat.y = vectorMultipliedQuat.y * 1400.0f; 93 | vectorMultipliedQuat.z = vectorMultipliedQuat.z * 1400.0f; 94 | PlayerSpray_PosAndSpeedSet.fun(&sprayPos, &vectorMultipliedQuat, 0); 95 | 96 | if (*is_spraying == 0) 97 | { 98 | *is_spraying = 1; 99 | is_spraying_hyperspray = 1; 100 | auto data = SupportParticle_CmnData.fun(sprayObj); 101 | data->Rgba = greenSprayColor; 102 | PlayerSpray_Start.fun(0); 103 | return; 104 | } 105 | } 106 | } 107 | if (*is_spraying == 1) 108 | { 109 | *is_spraying = 0; 110 | is_spraying_hyperspray = 0; 111 | auto data = SupportParticle_CmnData.fun(sprayObj); 112 | data->Rgba = greenSprayColor; 113 | PlayerSpray_Stop.fun(0); 114 | return; 115 | } 116 | } 117 | } 118 | 119 | return; 120 | } 121 | 122 | int __cdecl PlayerWeaponChargableHook(GameItem item) 123 | { 124 | if (item == ITEM_EMPTY) { 125 | return item; 126 | } 127 | return (0.0 < wp_param[item - 16].charge_time); 128 | } 129 | 130 | void InitializePlayerBattleFunctions() 131 | { 132 | battle_anotherworld.fun = injector::MakeCALL(0x0053933c, battle_anotherworldHook, true).get(); 133 | normal_attack_all.fun = injector::MakeJMP(0x0053d5c7, normal_attack_allHook, true).get(); 134 | 135 | PlayerWeaponChargable.fun = injector::MakeCALL(0x0053b188, PlayerWeaponChargableHook, true).get(); 136 | PlayerWeaponChargable.fun = injector::MakeCALL(0x0053cbac, PlayerWeaponChargableHook, true).get(); 137 | PlayerWeaponChargable.fun = injector::MakeCALL(0x0053ce82, PlayerWeaponChargableHook, true).get(); 138 | PlayerWeaponChargable.fun = injector::MakeCALL(0x0053d144, PlayerWeaponChargableHook, true).get(); 139 | PlayerWeaponChargable.fun = injector::MakeCALL(0x0053d4f3, PlayerWeaponChargableHook, true).get(); 140 | PlayerWeaponChargable.fun = injector::MakeCALL(0x00540a97, PlayerWeaponChargableHook, true).get(); 141 | PlayerWeaponChargable.fun = injector::MakeCALL(0x00540ef3, PlayerWeaponChargableHook, true).get(); 142 | 143 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/player_battle_general.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/player/battle/player_battle_general.h" 3 | #include "sh4/game/gamemain/game.h" 4 | #include "Randomizer.h" 5 | #include 6 | 7 | injector::hook_back motion_is_pipe; 8 | int motion_is_pipeHook() 9 | { 10 | switch (gameW->player->weapon_kind) 11 | { 12 | case ITEM_GREEN_HYPER_SPRAY: 13 | return 0; 14 | case ITEM_SILVER_PIPE: 15 | case ITEM_GOLD_PIPE: 16 | return 1; 17 | default: 18 | return motion_is_pipe.fun(); 19 | } 20 | } 21 | 22 | void InitializePlayerBattleGeneralFunctions() 23 | { 24 | motion_is_pipe.fun = injector::MakeCALL(0x0053d5b9, motion_is_pipeHook, true).get(); 25 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/player_sound.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include 4 | #include "sh4/game/player/player_sound.h" 5 | #include "sh4/game/player/player_another_ui.h" 6 | #include "sh4/game/gamemain/game.h" 7 | #include "sh4/sys/sound/sf_sound.h" 8 | 9 | PlayerSEFlags* flags; 10 | 11 | injector::hook_back se_call_swing; 12 | injector::hook_back set_attack_se; 13 | injector::hook_back set_battle_loop_se; 14 | void __cdecl set_attack_seHook(int unk, _PLAYER_WORK* pWork) 15 | { 16 | // PlayerSESetWeapon calls this function and puts the pWork pointer into EDI 17 | // So we move it onto the stack so we can do our own logic 18 | // wanted to avoid inline ASM but unless I rewrite all the functions involved from scratch, there is no way 19 | __asm { 20 | mov pWork, edi; 21 | } 22 | GameItem weaponKind = pWork->weapon_kind; 23 | set_attack_se.fun(unk, pWork); 24 | 25 | if (weaponKind == ITEM_SILVER_PIPE || weaponKind == ITEM_GOLD_PIPE) 26 | { 27 | if (*motion_stop == 0) 28 | { 29 | float vol = flags->player_vol; 30 | if ((gameW->stage == GAME_STAGE_LAST && gameW->scene == 2) && (1.0f < flags->player_vol)) 31 | { 32 | vol = 1.0f; 33 | } 34 | sfSeCallEx.fun(0x9c62, vol, flags->player_pan, 0, 1); 35 | 36 | // move pWork pointer into EAX as that is what se_call_swing expects 37 | // works fine, need to make sure it doesn't cause any other issues 38 | __asm { 39 | mov eax, pWork; 40 | } 41 | 42 | se_call_swing.fun(0x7); 43 | return; 44 | } 45 | } 46 | 47 | if (weaponKind == ITEM_GREEN_HYPER_SPRAY) 48 | { 49 | set_battle_loop_se.fun(0xa028); 50 | return; 51 | } 52 | } 53 | 54 | void InitializePlayerSoundFunctions() 55 | { 56 | set_attack_se.fun = injector::MakeCALL(0x00536936, set_attack_seHook, true).get(); 57 | set_attack_se.fun = injector::MakeCALL(0x00536946, set_attack_seHook, true).get(); 58 | set_battle_loop_se.fun = injector::auto_pointer(0x00535f80); 59 | se_call_swing.fun = injector::auto_pointer(0x00536250); 60 | 61 | flags = injector::auto_pointer(0x010a1d60); 62 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/save_data.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/game/gamemain/save_data.h" 4 | #include "sh4/game/message/message_load.h" 5 | #include "sh4/game/message/message_handle.h" 6 | #include "sh4/sys/apps/sf_step.h" 7 | #include 8 | 9 | injector::hook_back sfMcLoad; 10 | injector::hook_back sfMcSaveCreate; 11 | injector::hook_back print_load_stat_s; 12 | 13 | ExtraSaveSettings perSaveSettings[32]; 14 | 15 | const char* seedMsg = convertMessage("Randomizer seed: 0"); 16 | 17 | int __cdecl sfMcLoadHook(int port, int fn, int file_no) 18 | { 19 | PLOG(plog::info) << "Loading save file " << file_no << " on port " << port; 20 | 21 | if (perSaveSettings[file_no].seed != 0) 22 | { 23 | PLOG(plog::info) << "File has randomizer seed " << perSaveSettings[file_no].seed; 24 | settings.iGlobalSeed = perSaveSettings[file_no].seed; 25 | } 26 | 27 | return sfMcLoad.fun(port, fn, file_no); 28 | }; 29 | 30 | int __cdecl sfMcSaveCreateHook(int port, int fn, int file_no) 31 | { 32 | 33 | perSaveSettings[file_no].seed = settings.iGlobalSeed; 34 | 35 | std::ofstream outfile; 36 | outfile.open(".\\save\\sh4_randomizer_per_save_settings.sav", std::ios::binary); 37 | outfile.write((char*)&perSaveSettings, sizeof(perSaveSettings)); 38 | outfile.close(); 39 | 40 | PLOG(plog::info) << "Saving save file " << file_no << " on port " << port; 41 | return sfMcSaveCreate.fun(port, fn, file_no); 42 | } 43 | 44 | void print_load_stat_sHook(int port, int cur, int disp) 45 | { 46 | print_load_stat_s.fun(port, cur, disp); 47 | if (disp != 0) 48 | { 49 | if (perSaveSettings[cur].seed != 0) 50 | { 51 | if (sfStepGet.fun() < 0x65) 52 | { 53 | std::string formattedString = std::format("Seed: {0}", perSaveSettings[cur].seed); 54 | seedMsg = convertMessage(formattedString.c_str()); 55 | sfMessagePrint.fun((unsigned short*)seedMsg, 0x12a, 0x152); 56 | PLOG(plog::info) << "Printing print " << cur << " " << disp; 57 | } 58 | 59 | } 60 | } 61 | return; 62 | } 63 | 64 | void InitializeSaveDataFunctions() 65 | { 66 | sfMcLoad.fun = injector::MakeCALL(0x00571d7e, sfMcLoadHook, true).get(); 67 | sfMcLoad.fun = injector::MakeCALL(0x00571dab, sfMcLoadHook, true).get(); 68 | 69 | sfMcSaveCreate.fun = injector::MakeCALL(0x00571651, sfMcSaveCreateHook, true).get(); 70 | sfMcSaveCreate.fun = injector::MakeCALL(0x00571690, sfMcSaveCreateHook, true).get(); 71 | 72 | 73 | print_load_stat_s.fun = injector::MakeCALL(0x005708fc, print_load_stat_sHook, true).get(); 74 | print_load_stat_s.fun = injector::MakeCALL(0x0057295a, print_load_stat_sHook, true).get(); 75 | 76 | 77 | 78 | }; 79 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_chara.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sys/geometry/sf_chara.h" 3 | #include 4 | 5 | injector::hook_back sfCharacterBone; 6 | 7 | void InitializeSfCharacterFunctions() 8 | { 9 | sfCharacterBone.fun = injector::auto_pointer(0x0055c370); 10 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_env.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sys/env/sf_env.h" 3 | #include 4 | 5 | injector::hook_back sfSysEnvFps; 6 | 7 | void InitializeSfEnvFunctions() 8 | { 9 | sfSysEnvFps.fun = injector::auto_pointer(0x0055ae60); 10 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_fileread.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sys/storage/sf_fileread.h" 3 | #include 4 | 5 | injector::hook_back sfFileLoad; 6 | void InitializeSfFileLoadFunctions() 7 | { 8 | // increase buffer size for wp_model.bin 9 | injector::WriteMemory(0x0069fab0, 0x400000, true); 10 | 11 | sfFileLoad.fun = injector::auto_pointer(0x00573470); 12 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_memorystack.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sys/apps/sf_memorystack.h" 3 | #include 4 | 5 | void InitializeSfMemoryFunctions() 6 | { 7 | // double sfMemoryStack size to allow more data loaded at once 8 | // the game normally only allows roughly 67mb, but by doubling this it prevents crashes related to exceeding this memory in large scenes when using the enemy randomizer 9 | injector::WriteMemory(0x00551f98, 0x8000000, true); 10 | injector::WriteMemory(0x00551fa9, 0x2000000, true); 11 | injector::WriteMemory(0x00551fc5, 0x8000000, true); 12 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_scene.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "CommonTypes.h" 4 | #include "sh4/game/gamemain/game.h" 5 | #include "sh4/game/gamemain/game_fileread.h" 6 | #include "sh4/game/misc/misc_option.h" 7 | #include "sh4/sys/geometry/sf_scene.h" 8 | #include 9 | 10 | injector::hook_back sfSceneSetFogColor; 11 | void __cdecl sfSceneSetFogColorHook(Color* color) 12 | { 13 | if (settings.bInGameOptions == true) 14 | { 15 | if (miscOptionGetPtr.fun()->fog_approaches == 1) 16 | { 17 | if (gameW->stage != GAME_STAGE_LAST && gameW->stage != GAME_STAGE_3LDK && gameW->stage != GAME_STAGE_TUNNEL && gameW->stage != GAME_STAGE_SPIRAL) 18 | { 19 | color->r = 255; 20 | color->g = 255; 21 | color->b = 255; 22 | } 23 | } 24 | } 25 | else 26 | { 27 | if (settings.bFogApproaches == true) 28 | { 29 | if (gameW->stage != GAME_STAGE_LAST && gameW->stage != GAME_STAGE_3LDK && gameW->stage != GAME_STAGE_TUNNEL && gameW->stage != GAME_STAGE_SPIRAL) 30 | { 31 | color->r = 255; 32 | color->g = 255; 33 | color->b = 255; 34 | } 35 | } 36 | } 37 | return sfSceneSetFogColor.fun(color); 38 | } 39 | 40 | injector::hook_back sfSceneSetFogPower; 41 | void __cdecl sfSceneSetFogPowerHook(float nearPow, unsigned char nearPow2, float farPow, unsigned char farPow2) 42 | { 43 | if (settings.bInGameOptions == true) 44 | { 45 | if (miscOptionGetPtr.fun()->fog_approaches == 1) 46 | { 47 | // do not override fog on the tunnel cutscenes, Henry's apartment, or in the final boss arena 48 | // it just looks weird and in the case of the final boss arena, is unplayable 49 | // TODO: figure out where else the fog shouldn't be applied 50 | if (gameW->stage != GAME_STAGE_LAST && gameW->stage != GAME_STAGE_3LDK && gameW->stage != GAME_STAGE_TUNNEL && gameW->stage != GAME_STAGE_SPIRAL) 51 | { 52 | PLOG(plog::info) << "Overriding fog for scene " << gameW->scene << " in stage " << stageNames[gameW->stage]; 53 | return sfSceneSetFogPower.fun(750, 1, 5000, 0xA0); 54 | } 55 | } 56 | } 57 | else 58 | { 59 | if (settings.bFogApproaches == true) 60 | { 61 | if (gameW->stage != GAME_STAGE_LAST && gameW->stage != GAME_STAGE_3LDK && gameW->stage != GAME_STAGE_TUNNEL && gameW->stage != GAME_STAGE_SPIRAL) 62 | { 63 | PLOG(plog::info) << "Overriding fog for scene " << gameW->scene << " in stage " << stageNames[gameW->stage]; 64 | return sfSceneSetFogPower.fun(750, 1, 5000, 0xA0); 65 | } 66 | } 67 | } 68 | return sfSceneSetFogPower.fun(nearPow, nearPow2, farPow, farPow2); 69 | } 70 | 71 | void InitializeSfSceneFunctions() 72 | { 73 | sfSceneSetFogColor.fun = injector::MakeCALL(0x004d748c, sfSceneSetFogColorHook, true).get(); 74 | sfSceneSetFogColor.fun = injector::MakeCALL(0x004d83fc, sfSceneSetFogColorHook, true).get(); 75 | sfSceneSetFogColor.fun = injector::MakeCALL(0x004f13de, sfSceneSetFogColorHook, true).get(); 76 | sfSceneSetFogColor.fun = injector::MakeCALL(0x004f1493, sfSceneSetFogColorHook, true).get(); 77 | sfSceneSetFogColor.fun = injector::MakeCALL(0x004f15cf, sfSceneSetFogColorHook, true).get(); 78 | sfSceneSetFogColor.fun = injector::MakeCALL(0x004f1e7a, sfSceneSetFogColorHook, true).get(); 79 | sfSceneSetFogColor.fun = injector::MakeCALL(0x0054c343, sfSceneSetFogColorHook, true).get(); 80 | sfSceneSetFogColor.fun = injector::MakeCALL(0x0054c625, sfSceneSetFogColorHook, true).get(); 81 | 82 | sfSceneSetFogPower.fun = injector::MakeCALL(0x004d74be, sfSceneSetFogPowerHook, true).get(); 83 | sfSceneSetFogPower.fun = injector::MakeCALL(0x004d842e, sfSceneSetFogPowerHook, true).get(); 84 | sfSceneSetFogPower.fun = injector::MakeCALL(0x004f13f4, sfSceneSetFogPowerHook, true).get(); 85 | sfSceneSetFogPower.fun = injector::MakeCALL(0x004f14ab, sfSceneSetFogPowerHook, true).get(); 86 | sfSceneSetFogPower.fun = injector::MakeCALL(0x0054c33a, sfSceneSetFogPowerHook, true).get(); 87 | sfSceneSetFogPower.fun = injector::MakeCALL(0x0055e4b7, sfSceneSetFogPowerHook, true).get(); 88 | sfSceneSetFogPower.fun = injector::MakeCALL(0x0055e577, sfSceneSetFogPowerHook, true).get(); 89 | sfSceneSetFogPower.fun = injector::MakeCALL(0x0055e5ac, sfSceneSetFogPowerHook, true).get(); 90 | sfSceneSetFogPower.fun = injector::MakeCALL(0x0055e5e8, sfSceneSetFogPowerHook, true).get(); 91 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_sound.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sys/sound/sf_sound.h" 3 | #include "Randomizer.h" 4 | #include 5 | 6 | injector::hook_back sfSeCallEx; 7 | void InitializeSfSoundFunctions() 8 | { 9 | sfSeCallEx.fun = injector::auto_pointer(0x0056c9b0); 10 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sf_step.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Randomizer.h" 3 | #include "sh4/sys/apps/sf_step.h" 4 | 5 | // gets the current step in the game's state machine 6 | // steps are used in the UI, loading, etc. loops to know when actions have completed so new actions can take place 7 | // I am still not sure of the exact mechanisms involved when multiple state machines are active at once 8 | injector::hook_back sfStepGet; 9 | 10 | void InitializeSfStepFunctions() 11 | { 12 | sfStepGet.fun = injector::auto_pointer(0x00555c40); 13 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sg_anime.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sglib/animation/sg_anime.h" 3 | #include 4 | 5 | injector::hook_back sgAnimeCurrentFloatFrame; 6 | 7 | void InitializeSgAnimeFunctions() 8 | { 9 | sgAnimeCurrentFloatFrame.fun = injector::auto_pointer(0x00417fd0); 10 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sg_bone.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sglib/animation/sg_bone.h" 3 | #include 4 | 5 | injector::hook_back sgBoneGetAbsRot; 6 | injector::hook_back sgBoneGetAbsMatrix; 7 | injector::hook_back sgBoneGetEuclideanDistance; 8 | 9 | void InitializeSgBoneFunctions() 10 | { 11 | sgBoneGetAbsRot.fun = injector::auto_pointer(0x00419ff0).get(); 12 | sgBoneGetAbsMatrix.fun = injector::auto_pointer(0x004217b0).get(); 13 | sgBoneGetEuclideanDistance.fun = injector::auto_pointer(0x0041a060).get(); 14 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/sg_quat.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/sglib/math/sg_quat.h" 3 | #include 4 | 5 | injector::hook_back sgQuatFromAxisAngle; 6 | injector::hook_back sgQuatMul; 7 | injector::hook_back sgQuatMulVector; 8 | injector::hook_back sgQuatGetEuclideanDistance; 9 | 10 | void InitializeSgQuatFunctions() 11 | { 12 | sgQuatFromAxisAngle.fun = injector::auto_pointer(0x00421b30); 13 | sgQuatMul.fun = injector::auto_pointer(0x005741d0); 14 | sgQuatMulVector.fun = injector::auto_pointer(0x00574300); 15 | sgQuatGetEuclideanDistance.fun = injector::auto_pointer(0x0041ac30); 16 | } -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/spray.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/effect/particle/spray.h" 3 | #include "sh4/sys/apps/sf_obj.h" 4 | #include 5 | 6 | injector::hook_back PlayerSpray_Start; 7 | injector::hook_back PlayerSpray_Stop; 8 | injector::hook_back PlayerSpray_PosAndSpeedSet; 9 | injector::hook_back SupportParticle_CmnData; 10 | injector::hook_back SplayParticle_GeneratePosSpdSet; 11 | 12 | Color origSprayColor = { 0x78, 0x78, 0x78, 0x18 }; 13 | Color greenSprayColor = { 0x00, 0xFF, 0x00, 0x1e }; 14 | 15 | int is_spraying_hyperspray = 0; 16 | 17 | void SplayParticle_GeneratePosSpdSetHook(sfObj* obj, Position* pos, Position* speed) 18 | { 19 | // recolor the spray particles if Hyper Spray is being used 20 | // TODO: fix this enormous hack and give the Hyperspray its own unique sfObj 21 | auto data = SupportParticle_CmnData.fun(obj); 22 | if (is_spraying_hyperspray) 23 | { 24 | data->Rgba = greenSprayColor; 25 | } 26 | else 27 | { 28 | data->Rgba = origSprayColor; 29 | } 30 | return SplayParticle_GeneratePosSpdSet.fun(obj, pos, speed); 31 | } 32 | 33 | void InitializeSprayFunctions() 34 | { 35 | PlayerSpray_Start.fun = injector::auto_pointer(0x0043b260); 36 | PlayerSpray_Stop.fun = injector::auto_pointer(0x0043b290); 37 | PlayerSpray_PosAndSpeedSet.fun = injector::auto_pointer(0x0043b230); 38 | SupportParticle_CmnData.fun = injector::auto_pointer(0x0043b920); 39 | SplayParticle_GeneratePosSpdSet.fun = injector::MakeCALL(0x0043b24d, SplayParticle_GeneratePosSpdSetHook, true).get(); 40 | } 41 | -------------------------------------------------------------------------------- /source/SilentHill4Randomizer/stage_info.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "sh4/game/gamemain/stage_info.h" 3 | #include 4 | 5 | injector::hook_back StageInfoIsLatterHalf; 6 | 7 | void InitializeStageInfoFunctions() 8 | { 9 | StageInfoIsLatterHalf.fun = injector::auto_pointer(0x004fc830); 10 | } --------------------------------------------------------------------------------