Full Changelog: v0.7...v0.8
Please note that due to some code changes in the settings file, we bumped up the settings version which will cause a settings reset on your next boot. Make sure to note down your non-default settings so you can re-apply them.
New Features
- Speedhack now works on WINE/Proton x86/x64 targets as well, not just native Linux.
- You can now speed up or slow down WINE/Proton games from the main window or hotkeys, the same way as native targets.
- No
LD_PRELOADor custom WINE necessary. - Only ntdll's
RtlQueryPerformanceCounteris hooked. Games reachQueryPerformanceCounterthrough this entry on both Proton (which computes it inline) and mainline WINE (where it calls into Nt), so scaling it here works on both without double-counting. It's also the one clock WINE never turns into a kernel wait deadline, so scaling it can't make a game hang.- Downside: clocks other than QPC aren't scaled, so games that pace off
Sleep/GetTickCount/system time won't respond and real-time waits (frame pacing, vsync, audio) stay at normal speed. Slow-motion and high multipliers can feel uneven because of this. - If you found a game that does not work with just Rtl hooking and needs Sleep pacing hooking, feel free to open up a discussion thread or issue and we'll see what we can do about it.
- Downside: clocks other than QPC aren't scaled, so games that pace off
Improvements
Speedhack
Pointer Scanner
- Pointer scan results are now shown in a sortable table instead of a plain text view.
- You can now also double click on a row to add it to your address table directly. No more copy pasting pointer bases and offsets.
- Multiple row selections (with Ctrl or Shift) can be added to address table by pressing Enter.
- A running pointer search can now be cancelled safely.
- New progress bar text indicates in what pointer searching step you are: Phase 1 searching pointers and Phase 2 resolving pointer paths.
- Cancelling during Phase 1 will just stop and you'll have an empty pointer map.
- Cancelling during Phase 2 will wind down the search, writing all of the paths libmemscan already found and then stopping from finding new ones, so you can still have some valid paths.
- New progress bar text indicates in what pointer searching step you are: Phase 1 searching pointers and Phase 2 resolving pointer paths.
- Pointer map loading is now done asynchronously, keeping the UI responsive for large maps.
Injection
- Reworked dlopen injection to include manual symbol resolution fallback.
- The injection now falls back to manually resolving dlopen from the target's libc when GDB cannot resolve the symbol (e.g. stripped binaries).
- Removed the unused "Advanced Injection" placeholder from the Settings dialog as that type of implementation is no longer necessary for ~99% of PINCE use cases (see below).
- After this change, only statically linked binaries that do not include libc/libdl as shared objects (uncommon) won't be injectable compared to the old logic that would fail on stripped binaries (common). Some examples include:
- Go binaries that are compiled with
CGO_ENABLED=0(default): fully statically linked, no libc.so in the process maps so no dlopen. This is the most likely case from the uncommon ones. - Rust binaries that target
x86_64-unknown-linux-muslwith static linking: same as above. - C/C++ programs with either
-staticor-static-pie: everything is baked into the binary so dlopen won't exist or be stripped. - Static musl builds: common in containers.
- Go binaries that are compiled with
Memory Viewer
- Breakpoint, Restore Instruction and Bookmark widgets now auto-refresh when their data changes.
- Refresh action and keybind became redundant and is now removed.
- Memory View now closes automatically when the target process exits or you detach from it.
- This is done because we need GDB attached to the process for most of the Memory View functionality.
Debugging
- Modified instructions and memory allocations are now tracked per process.
- If you jump between several processes during a session, each one now keeps its own NOP'd/edited instructions and allocated memory for the rest of the session, instead of those edits leaking across processes.
General
Bug Fixes
Memory Viewer
- Fixed broken Referenced Strings / Referenced Calls selections, so clicking a result again lists its referrers correctly.
- Fixed Referenced Strings / Referenced Calls crashing when clicking an address not present in the dissect data.
- Fixed Memory View info windows (Bookmarks, Breakpoints, Functions, Memory Regions, Restore Instructions) memory leak.
- Fixed an issue in Track Watchpoint when the list of recorded addresses shrinks while a row is selected.
- Fixed the hex editor's ASCII column writing a character's full multi-byte encoding and overwriting neighbouring bytes; only single-byte characters are accepted now.
- Fixed the disassembly view's actions (set program counter, edit/NOP instruction, toggle breakpoint and the right-click menu) throwing when no instruction was selected.
Address Table
- Fixed the value type being shared across multiple selected rows when changing types.
- Fixed a pointer chain dropping the rest of its offsets after an invalid one.
- Fixed the Manual Address dialog's live value preview showing
??for hex (0x-prefixed) length values. - Fixed AOBs being incorrectly byte-reversed when a non-host endianness was selected.
Dissect Code
Search Instructions (formerly Search Opcode)
Bookmarks
- Fixed bookmarks resolving to the wrong address.
- Fixed bookmarks being lost after loading a session without a matching process running.
- Bookmark changes made from the Memory View now correctly marks the session as unsaved.
- Bookmark recalculation is now guarded against stale/out-of-range region indices.
- Fixed the bookmark list erroring out when a bookmarked address can't be resolved in the current process.
Session
- Fixed a loaded session not remembering which process it belonged to.
- Closing PINCE or starting a new session with unsaved changes no longer proceeds when saving fails or is cancelled.
- Fixed an invalid or corrupt session file throwing on load instead of showing a load error dialog.
Memory Regions
Debugging
- Fixed an exception when attaching to a second process or launching a new one after an existing session.
- Code dissection no longer leaves database files open if one fails to open partway through.
- Fixed memory allocation mprotect call using a single page size instead of two, which could fail when the allocation straddled a page boundary.
- Improved GDB command waiting to use a condition variable instead of busy-polling, reducing CPU usage.
- Fixed value type comparison using identity check instead of equality, which could fail on some Python implementations.
- Fixed /proc/pid/maps parsing crash when a line doesn't match the expected format.
- Fixed several cases where a GDB command could hang the UI: empty IPC output, a cancelled command or the target process exiting while a command was still running.
- Fixed memory allocation's mprotect not covering allocations larger than one page.
Scanning
Settings & Hotkeys
- Fixed the language selector blanking out when the system locale has no matching translation.
- Fixed hotkey capture throwing on media/extra keys that aren't in the key-name map.
Scripting
General
- Fixed float input fields rejecting leading-dot numbers like
.5and-.5. - Fixed native Linux games launched through the Steam Runtime being misdetected as Wine/Proton.
Plus many more non-user facing bug fixes and code hardenings added.