Repository navigation
patchmanager: fix signature patches reporting neither on or off - #873
Merged
Merged
Conversation
Do not cache file offsets as data_offset_ptr in standalone mode, and apply JSON offset after locating the signature so short replacements work. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to GitHub Issue or related Pull Request, if one exists
None
Description of change
Patch Manager showed valid signature patches as broken: "Bad patch; patch is neither on or off" instead of Enabled/Disabled, so they could not be toggled.
SignaturePatch::to_memoryhad two bugs. In the configurator it cached a file offset asdata_offset_ptr, so status checksmemcmp'd a fake address. It also passed JSONoffsetintofind_patternwhile still indexing the signature/replacement from 0, which mis-aligned every patch withoffset != 0. This change locates the signature start, appliesoffsetafterward, compares only the replacement window, and leaves the pointer null sois_patch_activere-resolves fromdata_offset.Not proposed as built-in patches. The JSON below is the reproduction case: each entry uses
offset > 0and a replacement shorter than the signature.Testing
Reproduced in Patch Manager against
bm2dx.dllusing the signature JSON below. Before the fix, every patch reported "neither on or off". After the fix, each patch locates, shows Disabled/Enabled, and toggling writes only the replacement bytes atsignature_match + offset.Demo
Signature JSON used to reproduce (offset + short replacement)
[ { "info": "streaming / getcm patches (type=signature)", "gameCode": "LDJ", "notes": "Each site uses a unique signature (usage=0 only)." }, { "type": "group", "id": "streaming-getcm", "name": "Streaming getcm", "description": "Enable all children so streaming.common merges without Banner FS and getcm can fire without visiting Test Mode.", "gameCode": "LDJ" }, { "name": "Streaming: merge common without Banner", "description": "NOP jz in streaming.common callback so CM work table is filled even when Banner FS is still null.", "caution": "Required. Without this, early common responses are discarded and getcm stays empty.", "gameCode": "LDJ", "type": "signature", "group": "streaming-getcm", "dllName": "bm2dx.dll", "signature": "E8????????4885C00F84????????488D0D????????488D15????????41B848080000", "replacement": "909090909090", "offset": 8, "usage": 0 }, { "name": "Streaming: scheduler without Banner (common)", "description": "NOP jz after Banner getter on the common branch of the periodic scheduler.", "caution": "Enable with the getcm scheduler sibling. Unique via imul of common-interval dword.", "gameCode": "LDJ", "type": "signature", "group": "streaming-getcm", "dllName": "bm2dx.dll", "signature": "E8????????4885C0742469057E791C0AE8030000", "replacement": "9090", "offset": 8, "usage": 0 }, { "name": "Streaming: scheduler without Banner (getcm)", "description": "NOP jz after Banner getter on the getcm branch of the periodic scheduler.", "caution": "Enable with the common scheduler sibling. Unique via imul of getcm-interval dword. Without this, getcm never schedules while Banner FS is null.", "gameCode": "LDJ", "type": "signature", "group": "streaming-getcm", "dllName": "bm2dx.dll", "signature": "E8????????4885C07424690574B91D0AE8030000", "replacement": "9090", "offset": 8, "usage": 0 }, { "name": "Streaming: fall into getcm after common", "description": "NOP jmp-after-common so the same scheduler tick can evaluate getcm instead of returning early.", "caution": "Pair with Banner scheduler skips (or a live Banner FS).", "gameCode": "LDJ", "type": "signature", "group": "streaming-getcm", "dllName": "bm2dx.dll", "signature": "891D????????E9????????E8????????4885C074246905", "replacement": "9090909090", "offset": 6, "usage": 0 }, { "name": "Streaming: getcm interval 1s #1", "description": "Default getcm poll interval 1800s to 1s (first init store).", "caution": "Enable #1 and #2 together. Trailing BF3C000000 distinguishes this init site.", "gameCode": "LDJ", "type": "signature", "group": "streaming-getcm", "dllName": "bm2dx.dll", "signature": "C705????????18150000C705????????08070000C705????????201C0000BF3C000000", "replacement": "01000000", "offset": 16, "usage": 0 }, { "name": "Streaming: getcm interval 1s #2", "description": "Default getcm poll interval 1800s to 1s (second init store).", "caution": "Enable #1 and #2 together. Trailing 448925 distinguishes this init site.", "gameCode": "LDJ", "type": "signature", "group": "streaming-getcm", "dllName": "bm2dx.dll", "signature": "C705????????18150000C705????????08070000C705????????201C0000448925", "replacement": "01000000", "offset": 16, "usage": 0 } ]