Skip to content

ctabuyo/ols-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ols-parser

English · 中文

A small, zero-dependency C parser for WinOLS .ols project files.

Reads everything the file has: the 24-byte header, all project metadata, every Version with its ROM image and segment layout, and every Kennfeld (calibration map) with axes, scaling and cell layout.

Plain C99, kernel-style tabs, no external libraries.

Build

make

Produces one binary: ols_dump.

Use

./ols_dump        path/to/file.ols      # one line per map
./ols_dump -v     path/to/file.ols      # each map with axes, scaling, cell info
./ols_dump -q     path/to/file.ols      # header + metadata + versions only

As a library

#include "ols.h"

struct ols_ctx ctx;
if (ols_parse(buf, len, &ctx) == 0) {
    printf("ECU: %s %s  HW %s  SW %s\n",
           ctx.metadata.manufacturer, ctx.metadata.ecu_name,
           ctx.metadata.hw_number,    ctx.metadata.sw_number);

    for (size_t v = 0; v < ctx.nversions; v++)
        printf("Version %zu: %zu bytes @ 0x%08x\n",
               v, ctx.versions[v].rom_size, ctx.versions[v].base_address);

    for (size_t i = 0; i < ctx.nmaps; i++) {
        const struct ols_map *m = &ctx.maps[i];
        printf("%-5s %3dx%-3d @%08x  %s  scale=%g offset=%g\n",
               m->type, m->nx, m->ny, m->raw_address,
               m->name, m->scale, m->offset);
    }
    ols_free(&ctx);
}

OLS format — the short version

24-byte outer header

offset  size  meaning
------- ----- -----------------------------------------------------
0x00    u32   magic length prefix = 0x0000000B (decimal 11)
0x04    11    "WinOLS File"
0x0F    1     NUL
0x10    u32   format_version  (gates dozens of optional fields)
0x14    u32   declared_size
0x18    ---   payload starts here

format_version is the single most important field. It gates dozens of optional fields downstream. Modern files (≥ 200) use one wire layout, older ones another. 439+ dropped NUL terminators from strings and added interned-token sentinels for common values.

Payload — Microsoft MFC CArchive

No outer ZIP. The payload is a serialized CArchive blob. In order:

  1. Project metadata — 23 CString fields + 1 FILETIME + up to 9 schema-gated fields (make, model, ECU name, HW number, SW number, production number, engine code, checksum, flags, import comment, notes…).

  2. Magic anchors — seven 4-byte LE sentinels scanned anywhere in the file:

    name value purpose
    M1 0x42007899 Version-record fence
    M2 0x11883377 Version-array dispatch
    M3 0x98728833 Per-Version directory
    M4 0x08260064 Old-format path
    M5 0xCD23018A Project-properties extension
    M6 0x88271283 Optional comment / build fingerprint
    M7 0x84C0AD36 Optional XOR-scrambled trailer
  3. Version directory — three u32s immediately preceding M1: [numVersions - 1][versionDataStart][versionRecordSize]. Version i lives at versionDataStart + 4 + versionRecordSize*i.

  4. ROM segments (fmtVer ≥ 200) — each real ECU flash segment is anchored by a FADECAFE / CAFEAFFE sentinel pair. The 32-byte descriptor ending at that pair carries [hash, —, hash2, flashBase|0x80000000, flashEnd|0x80000000, 0xFADECAFE, 0xCAFEAFFE, —]. 18 bytes before each descriptor is the project slot — either 18 × 0xAF or a printable ASCII project tag. The first 76 bytes of each segment are WinOLS framing (index byte + inline header + proj slot + descriptor); strip them and the remainder is real flash.

    Segments are grouped into Versions whenever flash_base restarts at a lower value.

    Old-format files (fmtVer < 200) have no FADECAFE sentinels; each Version slot is the ROM image and is read directly from the version directory.

  5. Kennfeld records (maps) — a long sequence starting around offset 0x180 and ending at the first 0x98638811 (TAG_POSTZIP_HDR). Each record, on the wire:

    • CFolderRef comment (the description shown in the WinOLS tree)
    • 5 × u32: kennfeld_type, —, cell_data_type, —, cell_bits
    • CString map name (C identifier)
    • schema-gated u32s / booleans
    • 6 × f64 scaling doubles (two used, four discarded)
    • 4 × bool flags (inverse, signed, diff-vs-ref, mode)
    • 5 × u32 geometry: a276, a280, a396, a400, a408
    • CString axis label + CString unit
    • f64 scale, f64 offset, u32 ROM start, u32 ROM end
    • two axis sub-records (rows, then cols) — each a nested CFolderRef + unit + scale + offset + ROM address + type enum
      • cell width + schema-gated tail
    • trailer 01 01 01 delimits the record

    cell_data_type (offset +152) is the authoritative byte-layout enum

    enum  bytes/cell  endian
    ----  ----------  ------
     1        1        —
     2        2        BE
     3        2        LE
     4/5      4        BE / LE
     6/7      4-float  BE / LE
    10/11     8        BE / LE
    12/13     8-double BE / LE
    

    cell_bits (offset +164) is display-only and must not be used to size ROM reads.

Map dimensions come from classify_dims() which picks between a276/a280 and a396/a400 based on kennfeld_type (1 = scalar, 2 = value, 3 = curve, 5 = map).


License

Public domain / 0BSD. Do whatever you want.

About

A small, zero-dependency C parser for WinOLS `.ols` project files.

Resources

License

Stars

Watchers

Forks

Packages