-
Notifications
You must be signed in to change notification settings - Fork 0
03 08 Config game_info
This page explains game_info in Sprint Boost.
game_info reads known in-game values from memory (for example score, lives, counters).
Important distinction:
- By itself,
game_infodoes not change gameplay experience. - It is a foundation that enables other features.
game_info is fundamental for:
- Dynamic display values (
{gi.<key>}in text/images) -
play_statstracking and persistence - Memory-based cheats (
set_game_info/offset_game_info)
Without game_info, those systems cannot target meaningful game values.
game_info is relevant for:
boost_mode = "enhanced"
In current Sprint Boost behavior, game_info is part of the enhanced/runtime flow.
At a high level:
- You define a value key (example:
p1_lives) - You provide the game memory address where that value lives
- You choose how to decode the raw memory
- (Optional) you extract packed bits from decoded value
- (Optional) you apply a transform for display-friendly value
- (Optional) you map numeric values to labels
- Sprint Boost exposes values as
{gi.<key>}and{gi_label.<key>}
game_info depends on known memory locations for each game.
Because each game stores values differently, game_info is almost always configured in a game-level *_boost.toml file.
If a game’s memory location for a desired value is unknown:
- that value cannot be configured in
game_info - and features that rely on that value (display/play-stats/cheats) cannot use it
So memory discovery is a prerequisite for game_info use.
[game_info]
poll_ms = 1000
[game_info.values.p1_lives]
address = "0x0194"
decode = "u16"
[game_info.values.p1_lives.transform]
op = "offset"
value = -1
[game_info.values.p1_score]
address = "0x0192"
decode = "u16"
[game_info.values.p1_score.transform]
op = "mul"
value = 100This is the full supported decode list:
-
u16: reads a 16-bit unsigned value. -
u8_lo: reads the low 8-bit portion of a value. -
u8_hi: reads the high 8-bit portion of a value. -
bcd16: decodes a 16-bit BCD-encoded number. -
lo_bytes_le: combines low bytes from adjacent addresses in little-endian order.
Use the decode that matches how that game stores the value in memory.
This is the full supported transform list:
-
identity: no change (raw decoded value is used as-is). -
offset: adds/subtracts a fixed amount. -
mul: multiplies by a fixed amount. -
div: divides by a fixed amount.
Transforms convert raw memory values into player-friendly display values.
Packed fields are supported through extract on each value.
-
identity: no extraction. -
bit_and: bitmask withvalue. -
rshift: right-shift byvaluebits. -
bit_slice: extractwidthbits starting atstart.
Example:
[game_info.values.length]
address = "0x0182"
decode = "u16"
[game_info.values.length.extract]
op = "bit_and"
value = 0x07
[game_info.values.length.transform]
op = "offset"
value = 3Equivalent bit_slice form:
[game_info.values.length.extract]
op = "bit_slice"
start = 0
width = 3You can map numeric game_info values to text labels:
[game_info.values.condition]
address = "0x0182"
decode = "u16"
[game_info.values.condition.extract]
op = "bit_and"
value = 0x18
[game_info.values.condition.labels]
"0" = "dry"
"8" = "turf"
"16" = "mud"
default = "unknown"Token behavior:
-
{gi.condition}returns numeric value (0,8,16, ...) -
{gi_label.condition}returns mapped label (dry,turf,mud, ...) - if no label key matches and
defaultis not set,{gi_label.condition}resolves to?
game_info can define derived values by combining base values.
Current support note:
-
op = "sum"is the only supported derived operation right now.
Example (sum two terms into one score):
[game_info.values.score_low]
address = "0x01A9"
decode = "lo_bytes_le"
[game_info.values.score_thousands]
address = "0x01AB"
decode = "u16"
[game_info.values.score_thousands.transform]
op = "mul"
value = 1000
[game_info.derived.p1_score]
op = "sum"
terms = ["score_low", "score_thousands"]This is useful when a game stores one logical value in multiple memory parts.
Once defined, values can be used in substitutions:
[[display.layouts.hud.elements]]
type = "text"
text = "Lives: {gi.p1_lives}"
x = 20
y = 70
width = 280
height = 40
color = "#FFFFFF"
align = "left"
size = 26
[[display.layouts.hud.elements]]
type = "image"
source = "{gv.assets_images}/lives_{gi.p1_lives}.png"
fallback = "{gv.assets_images}/lives_unknown.png"
x = 20
y = 120
width = 140
height = 48
scaling = "fit"
alpha = 1.0Label-based asset example:
[[display.layouts.hud.elements]]
type = "image"
source = "{gv.assets_images}/track_{gi_label.condition}.png"
fallback = "{gv.assets_images}/track_unknown.png"
x = 20
y = 180
width = 140
height = 48
scaling = "fit"
alpha = 1.0- Default:
poll_ms = 1000 - Start with
1000unless you need faster response - Lower values update faster but can add overhead
game_info follows normal config precedence:
- Folder-level can define shared values
- Game-level usually defines or overrides game-specific memory values
In practice, game-level game_info is most common because memory addresses are game-specific.
- Start with one known value (for example lives) and verify it first.
- Add more values incrementally.
- Keep key names simple and stable (
p1_lives,p1_score,timer). - Use derived values when games split one value across multiple addresses.
- Use
{gi.<key>}when numeric output is required (stats/math). - Use
{gi_label.<key>}when label output is required (image/text naming).
Continue to: