Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NFSU2] Black screen hang when SingleCoreAffinity = 1 #1573

Open
bscout9956 opened this issue Jun 23, 2024 · 4 comments
Open

[NFSU2] Black screen hang when SingleCoreAffinity = 1 #1573

bscout9956 opened this issue Jun 23, 2024 · 4 comments

Comments

@bscout9956
Copy link

bscout9956 commented Jun 23, 2024

Issue: For some reason Need for Speed Underground 2 hangs on a black screen if I set SingleCoreAffinity to 1.

Tested Version: Latest as of the writing of this issue

Steps to reproduce:

  1. Install the mod
  2. Launch the game

The issue does not present itself if I switch it back to 0.
Interestingly enough, I can workaround the black screen by going into Task Manager and switching thread affinities.
But that defeats the purpose and causes crashes later on.

Specs:
AMD Ryzen 5 5600 with an RTX 3060.
OS is Windows 11 Pro Build 26100.994 (24H2).

PS:
By the way I did try to mess with the source code and I do believe it gets through the checks finding KERNEL32.DLL and CreateThread but then the game just stays there doing nothing...

INI File:
`[MAIN]
ResX = 2560 ; Use this option to control the horizontal resolution.
ResY = 1440 ; Use this option to control the vertical resolution.
FixHUD = 1 ; Corrects HUD aspect ratio.
FixFOV = 1 ; Corrects FOV aspect ratio.
Scaling = 1 ; Adjusts FOV aspect ratio to be mathematically correct. Requires FixFOV to be enabled.
HUDWidescreenMode = 1 ; Moves HUD to the edge of the screen. Change offset in "NFSUnderground2.WidescreenFix.dat" file for other aspect ratios.
FMVWidescreenMode = 1 ; FMVs will appear in fullscreen for 16:9. (1 = Cropped | 2 = Stretched)

[MISC]
SkipIntro = 1 ; Skips FMVs that play when you launch the game.
WindowedMode = 0 ; Enables windowed mode. (1 = Borderless | 2 = Border | 3 = Resizable Border | 4 = Borderless Fullscreen | 5 = Borderless Fullscreen Stretched)
DisableCutsceneBorders = 1 ; Removes letterboxing that appears during cutscenes.
CustomUserFilesDirectoryInGameDir = 1 ; User files will be stored in a specified directory (for example: "save"). Use '0' to disable.
WriteSettingsToFile = 1 ; All registry settings will be saved to "settings.ini" in your profile folder. You must input your CD key and langauge in "settings.ini" when this option is enabled.
ImproveGamepadSupport = 1 ; Adds text to buttons and assigns front-end actions. Requires an XInput gamepad. (1 = Xbox Text | 2 = PlayStation Text | 3 = PC Text | 4 = None)
LeftStickDeadzone = 10.0 ; Controls the deadzone of the left analog stick.
FPSLimit = 120 ; Allows users to control the frame rate limit. (0 = Disabled | -1 = Monitor Refresh Rate | -2 = Double Monitor Refresh Rate)
HighFPSCutscenes = 1 ; Increases the frame rate limit for cutscenes to the nearest multiple of 30 (maximum is currently 60 due to bugs)
SingleCoreAffinity = 0 ; Limits game to one CPU core to prevent crashing.
NoOpticalDriveFix = 1 ; Allows the game to run without an optical drive.
RainDropletsScale = 0.5 ; Adjusts the size of the on-screen rain droplets.

[NOSTrail]
FixNOSTrailLength = 1 ; Fixes the NOS trail length for higher FPS.
CustomNOSTrailLength = 1.5 ; Adjusts the total distance of the NOS trail. You may need to adjust this if you're playing at very high FPS (240+). The higher the SimRate & FPS difference, the longer the trail.
`

@bscout9956
Copy link
Author

bscout9956 commented Jun 26, 2024

Update (not directly related):

I discovered the game has a function called bVerifyPoolIntegrity which can be enabled by toggling a Global Variable bMemoryAutomaticVerifyPoolIntegrity (located at 0x8284FC for the v1.2 US SPEED2.exe, same ExtraOpts guys use).

By enabling this variable the game seems to perform some memory pool integrity checks (thanks Gamecube version executable) which seem to prevent crashing from my limited testing. The only downside is ever so slightly slower loading times.

I'm not sure if those memory checks are what prevent crashes or if it just makes the game go through another code path in its memory freeing code (func is void bFree() at 0x440540) and thus doesn't crash.

I tried my best to implement it and even maybe submit a Pull Request but Hooking.Patterns being undocumented and throwing asserts made me lose my patience. Plus, I'm not a fan of C++.

Anyway, I tried the following pattern but got nowhere:

uint32_t* dword_8284FC = *hook::pattern("81 FA ?? ?? ?? ?? 7C DF 8B 0D ?? ?? ?? ?? 0F B6 77 F4").count(1).get(0).get<uint32_t*>(0xA);
    injector::WriteMemory<uint8_t>(dword_8284FC, 0x01, true);
}

This is executable memory (.text) so I set it as a pointer. You probably can figure this one out though.

It does seem like a better and more reliable alternative to just making the game only access 1 thread. Could be optional anyway.

@ThirteenAG
Copy link
Owner

Can you do more testing and report back?

@bscout9956
Copy link
Author

Can you do more testing and report back?

Just did. Here's a video to better show how it behaves with the flag enabled.
https://www.youtube.com/watch?v=yHNg1r23sEA

Somehow that Specialties Shop in Beacon Hill is very happy to crash my game

@bscout9956
Copy link
Author

I've tested this further and only got 1 crash after a good while...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants