-
Notifications
You must be signed in to change notification settings - Fork 186
Address Table and Sessions
The address table is where useful scan results go after you find them. It lets you watch values, edit them, freeze them, group them and save them into a .pct table for later.
Scanning finds possible addresses. The address table is where you figure out which ones are actually worth keeping.
The table has five columns:
-
Freeze: checkbox for freezing a value or toggling a script entry -
Description: your label, likeHealth,Ammo,Money -
Address: address, expression or pointer chain -
Type: how PINCE reads and writes the value -
Value: the current value read from the target
Double click a normal row to edit it. Which editor opens depends on the column:
-
Description: rename the row -
Address: edit the address or pointer chain -
Type: change value type, length, signed/hex display or endianness -
Value: write a new value to memory
Rows can also have children. This is mostly for groups, structures and keeping related values together.
The common ways to add entries are:
- Double click a scan result
- Select scan results and press the down arrow button to copy them to the address table
- Click
Add Address Manually - Send a script from Libpince Engine with
Send to cheat table - Add a structure from the Structures window
- Paste rows copied from another table
The fastest beginner workflow is usually:
- Scan until the result count is small
- Add a few likely results to the table
- Change or freeze them one by one
- Delete the ones that do nothing
- Rename the good ones
Do not keep every scan result. A small table with tested entries is much nicer than a huge table full of random values.
The Address column does not have to be a raw address.
It can be:
- A plain address, like
0x7ffff1234560 - A module expression, like
libgame.so+0x1234 - A GDB-style expression, like
$rax+0x20 - A pointer chain made with the
Pointercheckbox inAdd Address Manually - A relative child address, like
+0x4, when the row is under a parent with a resolved address
If an address resolves cleanly, PINCE reads the value and updates the Value column. If it cannot resolve or read it, you will usually see ?? or an unchanged value.
Green addresses are static according to PINCE. Static is usually better than heap, but it does not automatically mean the value is useful. It can still be a display copy or some temporary cached value.
For more expression examples, see GDB Expressions. For pointer chains, see Pointers.
Type decides how PINCE interprets the bytes at the address.
The normal types are:
-
Int8,Int16,Int32,Int64: whole numbers with 1, 2, 4 or 8 bytes -
Float32,Float64: decimal/float values -
String_ASCII,String_UTF8,String_UTF16,String_UTF32: text with a chosen encoding -
ByteArray: raw bytes with a length
Integer rows can be displayed as unsigned, signed or hexadecimal. This only changes display/write parsing, not where the value lives.
Strings and ByteArray entries have a length. If you edit a string or byte array value with a different length, PINCE may update the stored length for that row.
Struct rows are special. They are created by the Structures tool, carry an address and group fields below them. A struct parent has no readable value of its own.
Finding an address is only the first half. You still need to test it.
Good tests:
- Change the value and see if the game reacts
- Freeze it and see if the game stops changing it
- Let the game change it naturally and see if the row updates
- Go through a loading screen, menu, death, respawn or level change
- Restart the game if you are checking if an entry survives between runs
Bad signs:
- Editing it changes the table but not the game
- It works once then stops updating
- It changes a UI number but gameplay does not care
- Freezing it breaks unrelated values
- The address becomes unreadable after a scene change
If the value only works until restart, you probably need a pointer chain or code injection instead of keeping the raw address.
Freezing does not magically lock the game variable. PINCE reads the current shown value when you enable freeze, stores that value and writes it back every freeze interval.
The default freeze interval is 100 ms. You can change it in Settings -> General -> Freeze Interval. The range is 100 ms to 10000 ms.
This means freeze is not instant. If the game changes and checks the value before PINCE writes it back, the game can still react first.
Example:
- You have
50health frozen - The enemy does
100damage in one hit - The game checks death right after applying damage
- PINCE writes
50back a moment later, but you are already dead
For simple ammo/money values, normal freeze usually works fine. For fast logic like health, timers or physics, finding the code that writes the value can be better.
The small area just to the right of the freeze checkbox cycles freeze modes while the row is frozen.
Modes are:
- No arrow: keep the captured value exactly
- up arrow: allow increases, block decreases
- down arrow: allow decreases, block increases
The arrow modes are ratchets.
With up arrow, PINCE lets the value rise. When it sees a higher value, it updates the frozen value to that higher number and keeps freezing from there. This is good for money or score where gains should stay but spending should not.
With down arrow, PINCE lets the value fall. When it sees a lower value, it updates the frozen value to that lower number and keeps freezing from there. This is useful for values where bigger is bad.
Script entries do not use freeze modes. Their checkbox runs script code instead.
Script entries are address table rows backed by Libpince Engine code.
They are created from Libpince Engine with Send to cheat table or Ctrl+Shift+T. When you toggle the row, PINCE runs the script instead of freezing a memory address.
Scripts can have sections:
[ENABLE]
# code that runs when checked
[DISABLE]
# code that runs when unchecked
The tags are case-insensitive and surrounding whitespace is ignored. If a script has no tags, the whole script runs when enabled and nothing runs when disabled.
The script namespace is created the first time you enable it and kept for that table entry. Variables made in [ENABLE] can be used later in [DISABLE] during the same PINCE session.
If [ENABLE] fails, PINCE unchecks the row again.
Groups are for keeping the table readable.
Useful group ideas:
PlayerInventoryPositionTimersDebug scriptsBroken / needs update
Right click selected rows and use Add to a new group to move them into a new group. Use Create a new group to create an empty group.
Toggle including children is useful when a group contains multiple freezes or scripts you want to enable together.
Right click an address table row for actions.
Editing:
-
Description: rename selected rows -
Address: edit address, expression or pointer chain -
Type: change how the row is read -
Value: write a new value -
Edit script: open a script entry in Libpince Engine
Display:
-
Show as hexadecimal: display integer values in hex -
Show as unsigned: display integer values as unsigned decimal -
Show as signed: display integer values as signed decimal -
View as structure: view the selected address using a saved structure
Debugging:
-
Browse this memory region: open Memory Viewer hex view at this address -
Disassemble this address: open Memory Viewer disassembly at this address -
Find out what writes to this address: catch code that changes it -
Find out what reads this address: catch code that reads it -
Find out what accesses this address: catch reads and writes
Pointers:
-
Pointer scan for this address: start a pointer scan from this value -
Open pointer scanner: open the pointer scanner window when available
Table editing:
-
Cut,Copy,Paste: move rows around -
Paste inside: paste rows as children of the selected row -
Delete: remove rows -
Add to a new group: group selected rows -
Create a new group: create an empty group
Some actions only appear when they make sense. For example, integer display actions only appear for integer rows, script rows only show script-related actions and debugger actions need an attached process.
Common shortcuts:
-
Enter: edit value -
Ctrl+Enter: edit description -
Ctrl+Alt+Enter: edit address -
Alt+Enter: edit type -
Space: toggle selected rows -
Ctrl+Space: toggle selected rows and their children -
Ctrl+B: browse memory region -
Ctrl+D: disassemble address -
Del: delete selected rows -
Ctrl+C,Ctrl+X,Ctrl+V: copy, cut and paste rows -
V: paste inside selected row -
R: refresh the address table
The address table updates periodically when auto-update is enabled. You can change this from settings.
PINCE caches resolved address expressions for performance. The cache is cleared automatically when the process changes, when the target stops and after user run GDB or Libpince Engine commands/scripts that may change expressions, symbols, mappings or convenience variables.
The refresh button forces an immediate update and clears the expression cache manually. Use it if a pointer, expression or symbol still looks stale.
If the target process is not attached, rows can still exist in the table, but live values cannot be read.
A session is a .pct cheat table file.
It saves:
- Address table rows, including groups, pointer chains, types, values, freeze states and script entries
- Bookmarks and comments
- Session notes
- Structure definitions
- Process name
It does not save a live process snapshot. It does not keep the game running, restore memory, restore allocated code caves or magically make heap addresses valid again.
Loading a .pct restores the table data. You still need to attach to the right process for values to resolve and update.
Use the folder button or Ctrl+O to load a session. Use the disk button or Ctrl+S to save one.
PINCE tracks unsaved changes and asks before closing or loading another table.
Session files have a version number. Current sessions are version 3. Older sessions are migrated when loaded if PINCE still understands their format.
A good table usually has:
- Clear descriptions
- Working pointer chains or stable expressions instead of temporary heap addresses
- Groups for related entries
- Notes explaining anything non-obvious
- Scripts only when a normal value edit/freeze is not enough
A bad table usually has hundreds of untested scan results named No Description.
If you are making a table to share, test it after restarting the game. If it only works in the same run where you scanned it, it is probably not ready yet.