├── .gitattributes ├── .gitignore ├── Bioshock Physics Unlocker.sln ├── Bioshock Physics Unlocker ├── Bioshock Physics Unlocker.vcxproj ├── Bioshock Physics Unlocker.vcxproj.filters └── main.cpp ├── LICENSE.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | *.sap 88 | 89 | # TFS 2012 Local Workspace 90 | $tf/ 91 | 92 | # Guidance Automation Toolkit 93 | *.gpState 94 | 95 | # ReSharper is a .NET coding add-in 96 | _ReSharper*/ 97 | *.[Rr]e[Ss]harper 98 | *.DotSettings.user 99 | 100 | # JustCode is a .NET coding add-in 101 | .JustCode 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | _NCrunch_* 111 | .*crunch*.local.xml 112 | nCrunchTemp_* 113 | 114 | # MightyMoose 115 | *.mm.* 116 | AutoTest.Net/ 117 | 118 | # Web workbench (sass) 119 | .sass-cache/ 120 | 121 | # Installshield output folder 122 | [Ee]xpress/ 123 | 124 | # DocProject is a documentation generator add-in 125 | DocProject/buildhelp/ 126 | DocProject/Help/*.HxT 127 | DocProject/Help/*.HxC 128 | DocProject/Help/*.hhc 129 | DocProject/Help/*.hhk 130 | DocProject/Help/*.hhp 131 | DocProject/Help/Html2 132 | DocProject/Help/html 133 | 134 | # Click-Once directory 135 | publish/ 136 | 137 | # Publish Web Output 138 | *.[Pp]ublish.xml 139 | *.azurePubxml 140 | # TODO: Comment the next line if you want to checkin your web deploy settings 141 | # but database connection strings (with potential passwords) will be unencrypted 142 | *.pubxml 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | 154 | # Windows Azure Build Output 155 | csx/ 156 | *.build.csdef 157 | 158 | # Windows Azure Emulator 159 | efc/ 160 | rfc/ 161 | 162 | # Windows Store app package directory 163 | AppPackages/ 164 | 165 | # Visual Studio cache files 166 | # files ending in .cache can be ignored 167 | *.[Cc]ache 168 | # but keep track of directories ending in .cache 169 | !*.[Cc]ache/ 170 | 171 | # Others 172 | ClientBin/ 173 | [Ss]tyle[Cc]op.* 174 | ~$* 175 | *~ 176 | *.dbmdl 177 | *.dbproj.schemaview 178 | *.pfx 179 | *.publishsettings 180 | node_modules/ 181 | orleans.codegen.cs 182 | 183 | # RIA/Silverlight projects 184 | Generated_Code/ 185 | 186 | # Backup & report files from converting an old project file 187 | # to a newer Visual Studio version. Backup files are not needed, 188 | # because we have git ;-) 189 | _UpgradeReport_Files/ 190 | Backup*/ 191 | UpgradeLog*.XML 192 | UpgradeLog*.htm 193 | 194 | # SQL Server files 195 | *.mdf 196 | *.ldf 197 | 198 | # Business Intelligence projects 199 | *.rdl.data 200 | *.bim.layout 201 | *.bim_*.settings 202 | 203 | # Microsoft Fakes 204 | FakesAssemblies/ 205 | 206 | # GhostDoc plugin setting file 207 | *.GhostDoc.xml 208 | 209 | # Node.js Tools for Visual Studio 210 | .ntvs_analysis.dat 211 | 212 | # Visual Studio 6 build log 213 | *.plg 214 | 215 | # Visual Studio 6 workspace options file 216 | *.opt 217 | 218 | # Visual Studio LightSwitch build output 219 | **/*.HTMLClient/GeneratedArtifacts 220 | **/*.DesktopClient/GeneratedArtifacts 221 | **/*.DesktopClient/ModelManifest.xml 222 | **/*.Server/GeneratedArtifacts 223 | **/*.Server/ModelManifest.xml 224 | _Pvt_Extensions 225 | 226 | # Paket dependency manager 227 | .paket/paket.exe 228 | 229 | # FAKE - F# Make 230 | .fake/ 231 | 232 | # ========================= 233 | # Operating System Files 234 | # ========================= 235 | 236 | # OSX 237 | # ========================= 238 | 239 | .DS_Store 240 | .AppleDouble 241 | .LSOverride 242 | 243 | # Thumbnails 244 | ._* 245 | 246 | # Files that might appear in the root of a volume 247 | .DocumentRevisions-V100 248 | .fseventsd 249 | .Spotlight-V100 250 | .TemporaryItems 251 | .Trashes 252 | .VolumeIcon.icns 253 | 254 | # Directories potentially created on remote AFP share 255 | .AppleDB 256 | .AppleDesktop 257 | Network Trash Folder 258 | Temporary Items 259 | .apdisk 260 | 261 | # Windows 262 | # ========================= 263 | 264 | # Windows image file caches 265 | Thumbs.db 266 | ehthumbs.db 267 | 268 | # Folder config file 269 | Desktop.ini 270 | 271 | # Recycle Bin used on file shares 272 | $RECYCLE.BIN/ 273 | 274 | # Windows Installer files 275 | *.cab 276 | *.msi 277 | *.msm 278 | *.msp 279 | 280 | # Windows shortcuts 281 | *.lnk 282 | -------------------------------------------------------------------------------- /Bioshock Physics Unlocker.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bioshock Physics Unlocker", "Bioshock Physics Unlocker\Bioshock Physics Unlocker.vcxproj", "{28592A05-EE28-4BB7-A906-2DC3855C4CD2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Debug|x64.ActiveCfg = Debug|x64 17 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Debug|x64.Build.0 = Debug|x64 18 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Debug|x86.ActiveCfg = Debug|Win32 19 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Debug|x86.Build.0 = Debug|Win32 20 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Release|x64.ActiveCfg = Release|x64 21 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Release|x64.Build.0 = Release|x64 22 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Release|x86.ActiveCfg = Release|Win32 23 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Bioshock Physics Unlocker/Bioshock Physics Unlocker.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {28592A05-EE28-4BB7-A906-2DC3855C4CD2} 23 | BioshockPhysicsUnlocker 24 | 8.1 25 | Bioshock Physics Unlocker 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v140 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | BioshockPhysicsUnlocker 74 | 75 | 76 | BioshockPhysicsUnlocker 77 | 78 | 79 | 80 | Level3 81 | Disabled 82 | true 83 | MultiThreadedDebug 84 | 85 | 86 | true 87 | 88 | 89 | copy "$(TargetPath)" "C:\Program Files (x86)\Steam\steamapps\common\bioshock\Builds\Release\$(TargetFileName)" /y 90 | 91 | 92 | Copy to Bioshock directory 93 | 94 | 95 | 96 | 97 | Level3 98 | Disabled 99 | true 100 | MultiThreadedDebug 101 | 102 | 103 | true 104 | 105 | 106 | 107 | 108 | Level3 109 | MaxSpeed 110 | true 111 | true 112 | true 113 | MultiThreaded 114 | 115 | 116 | true 117 | true 118 | true 119 | 120 | 121 | copy "$(TargetPath)" "C:\Program Files (x86)\Steam\steamapps\common\bioshock\Builds\Release\$(TargetFileName)" /y 122 | 123 | 124 | Copy to Bioshock directory 125 | 126 | 127 | 128 | 129 | Level3 130 | MaxSpeed 131 | true 132 | true 133 | true 134 | MultiThreaded 135 | 136 | 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /Bioshock Physics Unlocker/Bioshock Physics Unlocker.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Bioshock Physics Unlocker/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BIOSHOCK "Bioshock.exe" 9 | #define BACKUP "Bioshock_Backup.exe" 10 | #define TIMESTEP_SIGNATURE "\x48\x6B\x55\x6E\x72\x65\x61\x6C\x43\x68\x61\x72\x61\x63\x74\x65\x72\x50\x6F\x69\x6E\x74\x43\x6F\x6C\x6C\x65\x63\x74\x6F\x72\x40\x40\x00\x00\x00\x3A\x3A\x3A\x3A\x3A\x3A\x3A\x3A\x00\x00\x00\x00\x2E\x3F\x41\x56\x46" 11 | #define TIMESTEP_MASK "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx???????????????xxxxx" 12 | #define TIMESTEP_OFFSET 36 13 | #define MESSAGE_SLEEP_TIME 2500 14 | #define ERROR_SLEEP_TIME 7000 15 | 16 | struct ScanResult { 17 | bool found; 18 | std::streampos location; 19 | }; 20 | 21 | ScanResult scanPatchLocation(std::fstream &file, const char *search, const char *mask, unsigned int offset) { 22 | std::stringstream strings; 23 | strings << file.rdbuf(); 24 | std::string fileString = strings.str(); 25 | 26 | ScanResult patch; 27 | size_t fileLength = fileString.length(); 28 | size_t sigLength = strlen(mask); 29 | 30 | for (unsigned int i = 0; i < fileLength - sigLength; i++) { 31 | for (unsigned int j = 0; j < sigLength; j++) { 32 | if (mask[j] == '?') { continue; } 33 | if (search[j] == fileString.at(i + j)) { 34 | if (j == sigLength - 1) { 35 | patch.found = true; 36 | patch.location = i + offset; 37 | return patch; 38 | } 39 | } 40 | else { 41 | break; 42 | } 43 | } 44 | } 45 | 46 | patch.found = false; 47 | patch.location = 0; 48 | return patch; 49 | } 50 | 51 | int main() { 52 | // Try to locate Bioshock 53 | std::cout << "Opening Bioshock executable..."; 54 | std::fstream bsBinary(BIOSHOCK, std::ios::binary | std::ios::out | std::ios::in); 55 | 56 | if (!bsBinary.good()) { 57 | std::cerr << "Error! Could not find the Bioshock executable. Aborting..." << std::endl; 58 | std::this_thread::sleep_for(std::chrono::milliseconds(ERROR_SLEEP_TIME)); 59 | return EXIT_FAILURE; 60 | } 61 | else { 62 | std::cout << "Success!" << std::endl; 63 | } 64 | 65 | // Find the location in the exe to patch 66 | std::cout << "Scanning for location to patch..."; 67 | ScanResult timestepPatch = scanPatchLocation(bsBinary, TIMESTEP_SIGNATURE, TIMESTEP_MASK, TIMESTEP_OFFSET); 68 | if (!timestepPatch.found) { 69 | std::cerr << "Error! Could not find the physics timestep location to patch. Aborting..." << std::endl; 70 | std::this_thread::sleep_for(std::chrono::milliseconds(ERROR_SLEEP_TIME)); 71 | return EXIT_FAILURE; 72 | } 73 | else { 74 | std::cout << "Success!" << std::endl; 75 | } 76 | 77 | // Make a backup if we don't already have one. 78 | if (!std::experimental::filesystem::exists(BACKUP)) { 79 | std::cout << "Making a backup of Bioshock.exe..."; 80 | 81 | std::ofstream saveBackup(BACKUP, std::ios::binary); 82 | if (saveBackup.good()) { 83 | bsBinary.clear(); 84 | bsBinary.seekg(0, std::ios::beg); 85 | saveBackup << bsBinary.rdbuf(); 86 | std::cout << "Success!" << std::endl; 87 | } 88 | else { 89 | std::cerr << "WARNING: Could not create backup!" << std::endl; 90 | } 91 | } 92 | 93 | // Show the user what the timestep is set to right now. 94 | float curTimestep; 95 | bsBinary.seekg(timestepPatch.location); 96 | bsBinary.read((char*)&curTimestep, sizeof(float)); 97 | std::cout << "The physics FPS is currently: " << (1.0 / curTimestep) << " FPS" << std::endl; 98 | 99 | // User input so they can change it. 100 | std::string inputLine; 101 | int inFPS; 102 | while ((std::cout << "New physics FPS: ") && std::getline(std::cin, inputLine) && !(std::istringstream{ inputLine } >> inFPS)) { 103 | std::cerr << "Invalid choice." << std::endl; 104 | } 105 | 106 | // Actually replace it in the file 107 | float desiredTimestep = 1.0f / inFPS; 108 | bsBinary.seekp(timestepPatch.location); 109 | bsBinary.write((char*)&desiredTimestep, sizeof(float)); 110 | 111 | // cool. 112 | std::cout << "Updated physics to " << inFPS << " FPS! Quitting..." << std::endl; 113 | std::this_thread::sleep_for(std::chrono::milliseconds(MESSAGE_SLEEP_TIME)); 114 | 115 | return EXIT_SUCCESS; 116 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 TurtleHx 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Bioshock Physics Unlocker 2 | Simple patcher which lets you adjust Bioshock's physics timestep. 3 | 4 | [Video comparison](https://www.youtube.com/watch?v=PKNRgX93TCc) 5 | 6 | This has been tested with the Steam release of the game, and should also work for the version 1.0 & 1.1 retail releases. I have heard that it does not work with the Direct2Drive release of the game, presumably due to some form of DRM. 7 | 8 | ##Usage 9 | 1. Download the [latest release](https://github.com/TurtleHx/Bioshock-Physics-Unlocker/releases/latest). 10 | 2. Extract the `BioshockPhysicsUnlocker.exe` file into your Bioshock directory, typically: `C:\Program Files (x86)\Steam\steamapps\common\bioshock\Builds\Release`. 11 | 3. Run the executable and enter your desired physics framerate. 12 | 13 | ##License 14 | MIT 15 | --------------------------------------------------------------------------------