Promote shipped IMB profile fields
This commit is contained in:
parent
2d5f5dec10
commit
d45a84038e
3 changed files with 51 additions and 6 deletions
|
|
@ -25,8 +25,10 @@ pub struct ImbInspectionReport {
|
||||||
pub target_screen_width: Option<i64>,
|
pub target_screen_width: Option<i64>,
|
||||||
pub target_screen_height: Option<i64>,
|
pub target_screen_height: Option<i64>,
|
||||||
pub scaleable: Option<bool>,
|
pub scaleable: Option<bool>,
|
||||||
|
pub horizontal_scale_modifier: Option<f64>,
|
||||||
pub max_percent_of_interface_vram: Option<f64>,
|
pub max_percent_of_interface_vram: Option<f64>,
|
||||||
pub image_rect: Option<[i64; 4]>,
|
pub image_rect: Option<[i64; 4]>,
|
||||||
|
pub image_rect_scaled: Option<[i64; 4]>,
|
||||||
pub notes: Vec<String>,
|
pub notes: Vec<String>,
|
||||||
pub entries: Vec<ImbInspectionEntry>,
|
pub entries: Vec<ImbInspectionEntry>,
|
||||||
pub malformed_lines: Vec<String>,
|
pub malformed_lines: Vec<String>,
|
||||||
|
|
@ -78,8 +80,10 @@ pub fn inspect_imb_bytes(bytes: &[u8]) -> Result<ImbInspectionReport, Box<dyn st
|
||||||
let target_screen_width = find_scalar_i64(&entries, "TGATargetScreenWidth");
|
let target_screen_width = find_scalar_i64(&entries, "TGATargetScreenWidth");
|
||||||
let target_screen_height = find_scalar_i64(&entries, "TGATargetScreenHeight");
|
let target_screen_height = find_scalar_i64(&entries, "TGATargetScreenHeight");
|
||||||
let scaleable = find_scalar_i64(&entries, "Scaleable").map(|value| value != 0);
|
let scaleable = find_scalar_i64(&entries, "Scaleable").map(|value| value != 0);
|
||||||
|
let horizontal_scale_modifier = find_scalar_f64(&entries, "HorizontalScaleModifier");
|
||||||
let max_percent_of_interface_vram = find_scalar_f64(&entries, "MaxPercentOfInterfaceVRAM");
|
let max_percent_of_interface_vram = find_scalar_f64(&entries, "MaxPercentOfInterfaceVRAM");
|
||||||
let image_rect = find_i64_quad(&entries, "ImageWH");
|
let image_rect = find_i64_quad(&entries, "ImageWH");
|
||||||
|
let image_rect_scaled = find_i64_quad(&entries, "ImageWHScaled");
|
||||||
|
|
||||||
Ok(ImbInspectionReport {
|
Ok(ImbInspectionReport {
|
||||||
line_count: text.lines().count(),
|
line_count: text.lines().count(),
|
||||||
|
|
@ -92,12 +96,14 @@ pub fn inspect_imb_bytes(bytes: &[u8]) -> Result<ImbInspectionReport, Box<dyn st
|
||||||
target_screen_width,
|
target_screen_width,
|
||||||
target_screen_height,
|
target_screen_height,
|
||||||
scaleable,
|
scaleable,
|
||||||
|
horizontal_scale_modifier,
|
||||||
max_percent_of_interface_vram,
|
max_percent_of_interface_vram,
|
||||||
image_rect,
|
image_rect,
|
||||||
|
image_rect_scaled,
|
||||||
notes: vec![
|
notes: vec![
|
||||||
"The current .imb parser preserves one whitespace-delimited key plus the remaining token list per line.".to_string(),
|
"The current .imb parser preserves one whitespace-delimited key plus the remaining token list per line.".to_string(),
|
||||||
"Integer and float projections are only populated when every token in the value lane parses cleanly.".to_string(),
|
"Integer and float projections stop at an inline semicolon comment token, so shipped comment-suffixed numeric rows still decode into typed values.".to_string(),
|
||||||
"Known profile-style keys such as `TGAName`, `TGAWidth`, `TGAHeight`, `TGATargetScreenWidth`, `TGATargetScreenHeight`, `Scaleable`, `MaxPercentOfInterfaceVRAM`, and `ImageWH` are promoted into typed report fields when present.".to_string(),
|
"Known profile-style keys such as `TGAName`, `TGAWidth`, `TGAHeight`, `TGATargetScreenWidth`, `TGATargetScreenHeight`, `Scaleable`, `HorizontalScaleModifier`, `MaxPercentOfInterfaceVRAM`, `ImageWH`, and `ImageWHScaled` are promoted into typed report fields when present.".to_string(),
|
||||||
],
|
],
|
||||||
entries,
|
entries,
|
||||||
malformed_lines,
|
malformed_lines,
|
||||||
|
|
@ -105,19 +111,31 @@ pub fn inspect_imb_bytes(bytes: &[u8]) -> Result<ImbInspectionReport, Box<dyn st
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_i64_tokens(tokens: &[String]) -> Option<Vec<i64>> {
|
fn parse_i64_tokens(tokens: &[String]) -> Option<Vec<i64>> {
|
||||||
tokens
|
let numeric_tokens = numeric_prefix_tokens(tokens);
|
||||||
|
(!numeric_tokens.is_empty())
|
||||||
|
.then_some(numeric_tokens)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|token| token.parse::<i64>().ok())
|
.map(|token| token.parse::<i64>().ok())
|
||||||
.collect::<Option<Vec<_>>>()
|
.collect::<Option<Vec<_>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_f64_tokens(tokens: &[String]) -> Option<Vec<f64>> {
|
fn parse_f64_tokens(tokens: &[String]) -> Option<Vec<f64>> {
|
||||||
tokens
|
let numeric_tokens = numeric_prefix_tokens(tokens);
|
||||||
|
(!numeric_tokens.is_empty())
|
||||||
|
.then_some(numeric_tokens)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|token| token.parse::<f64>().ok())
|
.map(|token| token.parse::<f64>().ok())
|
||||||
.collect::<Option<Vec<_>>>()
|
.collect::<Option<Vec<_>>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn numeric_prefix_tokens(tokens: &[String]) -> Vec<&str> {
|
||||||
|
tokens
|
||||||
|
.iter()
|
||||||
|
.take_while(|token| !token.starts_with(';'))
|
||||||
|
.map(|token| token.as_str())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn find_scalar_string(entries: &[ImbInspectionEntry], key: &str) -> Option<String> {
|
fn find_scalar_string(entries: &[ImbInspectionEntry], key: &str) -> Option<String> {
|
||||||
entries
|
entries
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -220,4 +238,20 @@ mod tests {
|
||||||
assert_eq!(report.scaleable, Some(true));
|
assert_eq!(report.scaleable, Some(true));
|
||||||
assert_eq!(report.max_percent_of_interface_vram, Some(0.06));
|
assert_eq!(report.max_percent_of_interface_vram, Some(0.06));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parses_comment_suffixed_numeric_rows_and_ne_profile_fields() {
|
||||||
|
let report = inspect_imb_bytes(
|
||||||
|
b"TGAName GP7L_NE\nHorizontalScaleModifier 0.75 ;384/512\nMaxPercentOfInterfaceVRAM 0.09 ;comment\nImageWHScaled 0 0 384 128\nImageWH 56 0 216 32 ;# 1 BigBoy\n",
|
||||||
|
)
|
||||||
|
.expect("imb should parse");
|
||||||
|
|
||||||
|
assert_eq!(report.horizontal_scale_modifier, Some(0.75));
|
||||||
|
assert_eq!(report.max_percent_of_interface_vram, Some(0.09));
|
||||||
|
assert_eq!(report.image_rect_scaled, Some([0, 0, 384, 128]));
|
||||||
|
assert_eq!(report.image_rect, Some([56, 0, 216, 32]));
|
||||||
|
assert_eq!(report.entries[1].float_values, Some(vec![0.75]));
|
||||||
|
assert_eq!(report.entries[2].float_values, Some(vec![0.09]));
|
||||||
|
assert_eq!(report.entries[3].integer_values, Some(vec![0, 0, 384, 128]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ This file is the short active queue for the current runtime and reverse-engineer
|
||||||
The repo now has structural inspectors for `.car`, `.lco`, `.cgo`, and `.cct`, but the binary side is still only partially semantic: the checked 1.05 corpus grounds `.car` fixed strings at `0x0c / 0x48 / 0x84` plus a second fixed stem slot at `0xa2` and a side-view resource name at `0xc0`, while `.lco` carries a stable primary stem at `0x04` and only conditional companion/body slots at `0x0c` and `0x12` when the leading stem slot is padded.
|
The repo now has structural inspectors for `.car`, `.lco`, `.cgo`, and `.cct`, but the binary side is still only partially semantic: the checked 1.05 corpus grounds `.car` fixed strings at `0x0c / 0x48 / 0x84` plus a second fixed stem slot at `0xa2` and a side-view resource name at `0xc0`, while `.lco` carries a stable primary stem at `0x04` and only conditional companion/body slots at `0x0c` and `0x12` when the leading stem slot is padded.
|
||||||
The checked 1.05 corpus now also splits `.car` auxiliary stems into `126` direct matches, `14` role-neutral roots, and only `5` truly distinct cases, while `.cgo` collapses into five stable scalar ladders instead of arbitrary floats.
|
The checked 1.05 corpus now also splits `.car` auxiliary stems into `126` direct matches, `14` role-neutral roots, and only `5` truly distinct cases, while `.cgo` collapses into five stable scalar ladders instead of arbitrary floats.
|
||||||
The early `.lco` lane block is now partially partitioned too: only offsets `0x20`, `0x34`, `0x38`, `0x3c`, `0x44`, `0x48`, and `0x54` behave like low-cardinality buckets, while the other early lanes still look high-variance.
|
The early `.lco` lane block is now partially partitioned too: only offsets `0x20`, `0x34`, `0x38`, `0x3c`, `0x44`, `0x48`, and `0x54` behave like low-cardinality buckets, while the other early lanes still look high-variance.
|
||||||
|
The side-view resource path is now grounded into `Data/2D/rt3_2IMB.PK4`, and the `.imb` parser now decodes shipped comment-suffixed numeric rows plus `_NE` profile fields such as `HorizontalScaleModifier` and `ImageWHScaled`.
|
||||||
The next honest static work is to keep promoting those fixed lanes into stable parser fields, explain the five remaining distinct auxiliary-stem cases, and decide how far the `.cgo` ladders plus the low-cardinality `.lco` lanes can be grounded without overclaiming semantics.
|
The next honest static work is to keep promoting those fixed lanes into stable parser fields, explain the five remaining distinct auxiliary-stem cases, and decide how far the `.cgo` ladders plus the low-cardinality `.lco` lanes can be grounded without overclaiming semantics.
|
||||||
Preserved checked parser detail now lives in [EngineTypes parser semantics](rehost-queue/engine-types-parser-semantics-2026-04-21.md).
|
Preserved checked parser detail now lives in [EngineTypes parser semantics](rehost-queue/engine-types-parser-semantics-2026-04-21.md).
|
||||||
Preserved checked format inventory detail now lives in [RT3 format inventory](rehost-queue/format-inventory-2026-04-21.md).
|
Preserved checked format inventory detail now lives in [RT3 format inventory](rehost-queue/format-inventory-2026-04-21.md).
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,12 @@ first `.car` / `.lco` / `.cgo` / `.cct` inspector pass landed.
|
||||||
- `7 -> 13 -> 27 -> 53` for `Mail`
|
- `7 -> 13 -> 27 -> 53` for `Mail`
|
||||||
- `.cct` remains the least ambiguous sidecar: current shipped files still look like narrow one-row
|
- `.cct` remains the least ambiguous sidecar: current shipped files still look like narrow one-row
|
||||||
text metadata.
|
text metadata.
|
||||||
|
- The side-view resource seam is no longer a loose-file dead end:
|
||||||
|
- `CarSideView_*.imb` lives inside `Data/2D/rt3_2IMB.PK4`
|
||||||
|
- engine-specific `_NE.imb` profiles such as `2D2L_NE.imb` and `GP7L_NE.imb` live there too
|
||||||
|
- the `.imb` parser now preserves comment-suffixed numeric rows in those shipped files, so
|
||||||
|
`MaxPercentOfInterfaceVRAM`, `HorizontalScaleModifier`, `ImageWH`, and `ImageWHScaled` can
|
||||||
|
all surface as typed fields instead of falling back to raw text
|
||||||
|
|
||||||
## What The Current Parser Now Owns
|
## What The Current Parser Now Owns
|
||||||
|
|
||||||
|
|
@ -73,14 +79,18 @@ first `.car` / `.lco` / `.cgo` / `.cct` inspector pass landed.
|
||||||
- scalar ladder counts by shared cargo-car family
|
- scalar ladder counts by shared cargo-car family
|
||||||
- `.cct`
|
- `.cct`
|
||||||
- tokenized identifier/value row
|
- tokenized identifier/value row
|
||||||
|
- `.imb`
|
||||||
|
- comment-aware typed numeric extraction for shipped profile rows
|
||||||
|
- `HorizontalScaleModifier`
|
||||||
|
- `ImageWHScaled`
|
||||||
|
|
||||||
## Remaining Static Questions
|
## Remaining Static Questions
|
||||||
|
|
||||||
- `.car`
|
- `.car`
|
||||||
- what the `0xa2` auxiliary stem really represents in the five remaining distinct cases:
|
- what the `0xa2` auxiliary stem really represents in the five remaining distinct cases:
|
||||||
alternate content root, paired tender/loco image root, or a narrower foreign-display alias
|
alternate content root, paired tender/loco image root, or a narrower foreign-display alias
|
||||||
- whether the trailing side-view resource can be tied cleanly to `.imb` metadata without
|
- whether the trailing side-view resource can be tied cleanly to the PK4-backed `CarSideView_*`
|
||||||
inventing frontend semantics
|
metadata and the engine-specific `_NE.imb` profiles without inventing frontend semantics
|
||||||
- `.lco`
|
- `.lco`
|
||||||
- whether the guarded companion-stem slot is a tender/fallback display family, a foreign reuse
|
- whether the guarded companion-stem slot is a tender/fallback display family, a foreign reuse
|
||||||
key, or only a subset authoring convenience
|
key, or only a subset authoring convenience
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue