fix: KO parser for actual firmware format

Firmware sends: "KO2: 0B+02->4C+00"
Parser expected: "KO0: trigger=2A mod=02 -> result=4C resmod=00"

Rewrote parse_ko_lines to match real format:
  <trigger_hex>+<mod_hex>-><result_hex>+<mod_hex>
Also skips "KO 0 deleted" and "KOSET 1:OK" lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mae PUGIN 2026-04-07 11:25:01 +02:00
parent 803505113b
commit 7b6f25a5ad

View file

@ -52,47 +52,46 @@ pub fn parse_td_lines(lines: &[String]) -> Vec<[u16; 4]> {
} }
/// Parse KO (Key Override) lines into arrays of [trigger, mod, result, res_mod]. /// Parse KO (Key Override) lines into arrays of [trigger, mod, result, res_mod].
/// Format: "KO0: trigger=2A mod=02 -> result=4C resmod=00" /// Format: "KO2: 0B+02->4C+00"
pub fn parse_ko_lines(lines: &[String]) -> Vec<[u8; 4]> { pub fn parse_ko_lines(lines: &[String]) -> Vec<[u8; 4]> {
let mut result = Vec::new(); let mut result = Vec::new();
for line in lines { for line in lines {
// Only process lines starting with "KO" let trimmed = line.trim();
let starts_with_ko = line.starts_with("KO"); // Only process lines matching "KO<digit>:"
if !starts_with_ko { if !trimmed.starts_with("KO") { continue; }
continue; let colon = match trimmed.find(':') {
} Some(i) => i,
None => continue,
};
// Skip non-data lines like "KO 0 deleted", "KOSET 1:OK"
let index_str = &trimmed[2..colon];
if index_str.contains(' ') || index_str.parse::<u8>().is_err() { continue; }
// Helper: extract hex value after a keyword like "trigger=" let after_colon = trimmed[colon + 1..].trim();
let parse_hex = |key: &str| -> u8 { // Format: "0B+02->4C+00"
let key_position = line.find(key); let arrow = match after_colon.find("->") {
Some(i) => i,
let after_key = match key_position { None => continue,
Some(i) => {
let rest = &line[i + key.len()..];
let first_token = rest.split_whitespace().next();
first_token
}
None => None,
}; };
let parsed_value = match after_key { let left = &after_colon[..arrow]; // "0B+02"
Some(s) => { let right = &after_colon[arrow + 2..]; // "4C+00"
let without_prefix = s.trim_start_matches("0x");
u8::from_str_radix(without_prefix, 16).ok() let parse_pair = |s: &str| -> (u8, u8) {
let parts: Vec<&str> = s.split('+').collect();
if parts.len() == 2 {
let a = u8::from_str_radix(parts[0].trim(), 16).unwrap_or(0);
let b = u8::from_str_radix(parts[1].trim(), 16).unwrap_or(0);
(a, b)
} else {
(0, 0)
} }
None => None,
}; };
parsed_value.unwrap_or(0) let (trigger, trig_mod) = parse_pair(left);
}; let (result_key, res_mod) = parse_pair(right);
result.push([trigger, trig_mod, result_key, res_mod]);
let trigger = parse_hex("trigger=");
let modifier = parse_hex("mod=");
let result_key = parse_hex("result=");
let result_mod = parse_hex("resmod=");
result.push([trigger, modifier, result_key, result_mod]);
} }
result result