Skip to content

Commit

Permalink
readme update
Browse files Browse the repository at this point in the history
  • Loading branch information
Z committed Dec 13, 2020
1 parent 8895be5 commit 296c283
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# popcnt emulator
**Cyberpunk 2077 update**: see below!

Pintool library for running Quantum Break on pre-SSE4.2 CPUs

It's very raw and dirty, you'll probably have a very hard time building it and will probably have the game crashed eventually (when it gets to the non-patched popcnt). I'm "working" on it ("testing" it, you know ;) ).
Expand All @@ -22,3 +24,42 @@ Then running the game will look like:
Note that you'll probably have to build both x86 and x64 versions of the tool and name them "instruction_hook64.dll" and "instruction_hook32.dll" respectively.

If you wish to contact me (to ask for binaries, help or simply chat) please use the Issues tab.

## Cyberpunk 2077
**Good news**: it works. Not a 0% performance hit this time due to the different approach, but still quite playable.

**Bad news**: _very_ version-bound stuff! Requires GOG version 1.03, probably won't work on other versions (but may though). You could get past the main menu with this, but crash later.

**Not so bad news**: I will describe the way you could fix it to work with your version of the game, it is relatively easy.

### Usage:
Build only `popcnt_hotpatch` project! x64 Release mode. Adjust target paths to your preferred ones.

It builds into `icudt.dll`. Don't change that name.

Replace your game's `icudt.dll` library with this one (make a backup of the original!).

Just start the game as usual!

### For the tech-savvy fellows, here's how it was done:
This time popcnt's are everywhere! They don't just pop up at the game loading stage and not used later, which rules out all PIN-based solutions (too slow).
I've tried JIT, Trace mode and Probe. Probe could do the trick, but it refuses to hotwire code blocks less than 7 bytes long (popcnts are 4-5 bytes long).
Manual patching is out of the picture too, as there are about 120 popcnts in the game! And they are used often.

So, I did a different thing - built a DLL, which wraps a small ICU DLL packaged with the game (so the game could statically import it without patching).
This DLL is installing a global exception handler, which intercepts "Illegal instruction" exceptions and emulates popcnt in the exception handler.
Afterwards it is putting the result to the correct destination and jumps over popcnt.

This solution is versatile and could be made even more optimized and version-independent, but still imposes some overhead.
Also because the game starts throwing a lot of exceptions, attaching a debugger to it would really hit the brakes. But that's not a big issue since you probably wouldn't want to.

### Adding new fixups to the tool
If your game crashed with unhandled popcnt exception, the `hotfix.log` file will appear at the game folder with the instruction address.
Disassemble this spot and add another `HOTFIX` line to the code at the bottom (there is a comment), using other lines as an example.

Use `ctx` to access and modify registers and direct pointer access for memory (since we are inside the game's process, we don't have to `ReadProcessMemory` or something like that).

### A note about the infamous AVX crash after Prologue
This tool doesn't solve this crash because emulating the whole AVX feels a lot more tedious than just one simple instruction.

But there are fixes for it already and they work. Basically they're just NOP'ing out AVX instructions, you could do it yourself.

3 comments on commit 296c283

@mirh
Copy link
Contributor

@mirh mirh commented on 296c283 Dec 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this doesn't use pin anymore and it's a completely different thing, I would make a new repo though.

Also, am I understanding it right? You basically made a dll wrapper (just like many mods do with d3d9.dll or binkw32.dll for example) that can handle all the exceptions you wish?
And this trap-and-emulate approach is faster than pin?

@ogurets
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but it's so small and I did actually experiment with PIN a lot, it could even have dangling dependencies in the project. I'd like to make it work first, then do the cleanup.

Yes, I don't know how those d3d9.dll wrappers are made though, I've just picked the smallest library and reimplemented it (contained only 64 bytes of exported static data).

Yes, faster than PIN2 for sure. I've tried it before and it was totally unplayable. Quantum Break worked because I detached PIN after making it through the popcnt area. This time it's not an option.
Tried to handle exceptions with PIN first, but it seems it's capable only of handling it's own exceptions.

@mirh
Copy link
Contributor

@mirh mirh commented on 296c283 Dec 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://reverseengineering.stackexchange.com/questions/8846/pintool-catches-instrumented-application-exceptions
https://stackoverflow.com/questions/48847797/how-to-catch-a-crash-environment-in-intel-pin
?
Then, by all means, if this new approach manages to be both "more standalone" and faster forget about pin.. but I'm quite much disoriented after this new voodoo drop.

Please sign in to comment.