Skip to content

eeu rd Road Routing Graph

Kristiyan edited this page Oct 4, 2026 · 5 revisions

eeu.rd — Road / Routing Graph

Status: ✅ Fully cracked · 590 MB · NOT_COMPRESSED · Reference disc: 8,809,081 records · Every byte of the 24-byte header is now accounted for. A later session cracked delta_long/delta_lat via eeu.mod's own schema; a still later session cracked ALL remaining 8 header bytes the same way, this time combined with real DBAL.OUT firmware disassembly (the per-field binary descriptor format inside eeu.mod itself — see that page's own "per-field binary descriptor" section) plus full real-data validation (geographic clustering, a route-name correlation, and an exact match against eeu.typ's own entry count).

The core road database — one record per named road segment, with its coordinates and name.

Layout

  • Header: 94 bytes, ASCII SIEMENS / (C) SIEMENS AG / version strings — the same header template used by every NOT_COMPRESSED file on this disc.
  • Body: fixed 67-byte records, no gaps. (filesize - 94) / 67 divides exactly (8,809,081 on the reference disc).
  • Each record = 24-byte binary header + 43-byte NUL-padded ASCII name.

The 24-byte header

Bytes Field Status
[0] low nibble suffixID ✅ Cracked — 4 bits, 16 distinct values
[0] high nibble prefixID ✅ Cracked — 4 bits, 16 distinct values, independent of suffixID (r ≈ -0.02)
[1:4] cityID ✅ Cracked — 24-bit LE index into a real place catalog
[4] countryID ✅ Cracked (identity) — declared 8-bit field, always 0 on this disc (unpopulated)
[5:7] typeID ✅ Cracked — 16-bit LE index into eeu.typ
[7] roadInfo ✅ Cracked — 8-bit flag/enum byte, see breakdown below
[8:12] longitude (segment's own min/start corner), int32 LE, degrees = value / 100000 ✅ Verified
[12:16] latitude (segment's own min/start corner), int32 LE, degrees = value / 100000 ✅ Verified
[16:20] delta_long — ✅ CRACKED (a later session) int32 LE, same /100000 convention, always non-negative (0 violations/20,000-record full-file random sample) — a bounding-box width, not a signed vector
[20:24] delta_lat — ✅ CRACKED (a later session) same as delta_long above

delta_long/delta_lat — cracked via eeu.mod's own schema, validated at scale

eeu.mod names this table road (research/mod_reader.py's extract_blocks(), token ['rd']), with a real, ordered field list for the per-record data block:

cityAndCountryID, cityID, countryID, affixID, suffixID, prefixID,
typeID, roadInfo, highway, preferred, explicate, ramp, "name type",
interchange, min_long, min_lat, delta_long, delta_lat, name,
phoneRoadOffset, roadListIdMain

min_long/min_lat sit exactly where the already-verified longitude/ latitude fields are (bytes [8:16]), and delta_long/delta_lat come immediately after, in the same position as the 2 fields this page previously listed as "unresolved, small values" — bytes [16:20]/ [20:24].

Validated, not just position-matched: a real 20,000-record random sample across the whole 8,809,081-record file shows zero negative values for either field (consistent with a bounding-box width/height, which by definition can't be negative — no separate sign/quadrant field needed anywhere). The implied segment diagonal (this segment's real geographic extent, [longitude, longitude+delta_long] × [latitude, latitude+delta_lat], cos(lat)-corrected) has median 350m, mean 1.1km, with 96.8% under 5km and 99.9% under 50km — exactly the real-world range of real named road-segment lengths, not noise. rns510_core.py's RoadRecord now exposes delta_lon/delta_lat directly (same naming convention as its existing lon/lat), confirmed working end-to-end through the real MapProject.get_record() path, not just a standalone script.

Earlier (refuted) attempt, left here for the record: highway as a single bit of byte [0] — every one of its 8 bits is set in ~50% of records with essentially identical route-like-name rates regardless of value (research/iof_reader.py's is_route_like_name(), 20,000-record sample) — zero correlation. This was the right instinct (highway IS a real bit flag) but the wrong byte — see below for where it actually lives.

All remaining 8 header bytes — CRACKED (a still later session), via real DBAL.OUT disassembly + eeu.mod's own binary field descriptors + full real-data validation

The firmware side (as the user specifically asked): dbal/DBAL.OUT's db_road.cpp has a real, dedicated record-unpacking function, read_current_record_from_database, disassembled directly (same technique already used for eeu.iof and eeuz.fea — capstone plus a hand- rolled ELF relocation-table parser, since DBAL.OUT is a small unlinked object with no FHDD6.FLI-style disassembly wall). Its relocations name the real, in-order sequence of generic field-accessor calls it makes: countryID, cityID, prefix, suffix, rdtype, roadinfo, minLong, minLat, deltaLong→(stored as maxLong = minLong + deltaLong), deltaLat→maxLat, phoneRoadOffset, roadListIdMain — independently confirming both the real field names AND that delta_long/delta_lat get converted to a max-corner on read (fully consistent with, and extending, this page's own earlier crack).

The missing piece was eeu.mod itself: its own binary bytes, not just the field-name strings already extracted, turned out to carry a real per-field width/bit-offset descriptor — cracked this same session and validated byte-exact against eeu.ctr's already-known layout (see eeu.mod's own page for the full method). Applied to this table's own schema block:

cityAndCountryID  4 bytes  (wrapper for the 2 sub-fields below)
  cityID            24 bits, offset 0
  countryID          8 bits, offset 24
affixID           1 byte   (declared, but NOT read by the compiled
                            unpacker above -- unused on this disc)
suffixID/prefixID 1 byte   (2x 4-bit sub-fields, offsets 0 and 4)
typeID            2 bytes
roadInfo          1 byte   (6 sub-fields, offsets 0,1,2,3,4(x3),7 --
                            exactly 8 bits, zero wasted)
  highway           1 bit,  offset 0
  preferred         1 bit,  offset 1
  explicate         1 bit,  offset 2
  ramp              1 bit,  offset 3
  "name type"       3 bits, offset 4
  interchange       1 bit,  offset 7

Dropping the unused affixID, this totals exactly 8 bytes — a perfect, zero-slack fit into the previously-unresolved [0] + [1:5] + [5:8] regions, with cityAndCountryID mapping onto [1:5] and typeID+roadInfo mapping onto [5:8], leaving [0] for the suffixID/prefixID byte.

Validated directly against real file bytes, not just schema position-matching (20,000–30,000-record real random samples):

  • cityID (bytes [1:4], 24-bit): grouping records by a coarse geographic bucket (~0.5° grid cells) and checking same-bucket record pairs, 50.3% share the exact same 24-bit value — astronomically above the ~0.025% a random 24-bit field would produce by chance. Nearby roads overwhelmingly share the same cityID, exactly as a real locality reference should.
  • countryID (byte [4]): always exactly 0 across every sampled record — a real, declared field that is simply unpopulated on this disc, the same pattern already seen elsewhere on this disc (eeu.pcl, the postal-code files, eeu.cal's tree-offset trailers).
  • typeID (bytes [5:7], uint16 LE): real range 0–2571 across the sample — matching eeu.typ's own 2,574 real entries almost exactly. Closes this page's own long-standing "strong candidate, not yet tested" note. (The big-endian reading gives an implausible max of 65,287 — confirms little-endian specifically.)
  • roadInfo bit 0 = highway: route-like names (is_route_like_name()) are 89.95% of records with this bit set, vs. 0.10% with it clear — a near-perfect, massively stronger signal than the earlier byte-[0] attempt above, confirming highway is real, just on the right byte this time.
  • suffixID/prefixID (byte [0]'s 2 nibbles): both independently span the full 0–15 range and are statistically independent of each other (r ≈ -0.02) — the expected shape for 2 unrelated packed sub-fields, not one 8-bit value misread as two.
  • preferred/explicate/bits 4–6 ("name type"): internally consistent (mostly a single dominant value/high bit, matching the "declared but defaults-to-one-value" pattern seen all over this disc) but not independently cross-validated against an external source the way highway/cityID/typeID were — treat these 3 as schema-position-confirmed, not independently proven.
  • ramp/interchange: always 0 in every sample tested — plausibly genuinely rare (true grade-separated interchanges/ramps ARE a small minority of all road segments) or unpopulated like countryID; not disambiguated.

The 43-byte name field is NUL-padded ASCII and never includes the localized street-type word (e.g. VIA, CONTRADA) — those live only in eeu.typ. E.g. a road near Linosa, Sicily is stored here as the bare name "GUITGIA", not "CONTRADA GUITGIA".

Validation

Coordinates verified against two independent real locations: records near the start of the file decode to Linosa, Sicily; records ~300MB in decode to Timișoara, Romania. Both match real street names at those exact coordinates.

Practical notes

  • eeu.rd is not spatially sorted — looking up "what roads are near (lon, lat)" means scanning the whole 590MB file (or building your own index; see Road Naming Join for the in-memory numpy-vectorized approach the map viewer uses).
  • Editing an existing record (name/coordinates) is fully supported by the GUI tool (rns510_gui.py/rns510_core.py) — the unresolved header fields are preserved byte-for-byte on edit. Note: editing just lon/lat does NOT recompute delta_long/delta_lat — the segment's real geographic extent shifts with its start corner but keeps the same width/height (the existing default, now a known, documented behavior rather than an unexamined one).
  • Appending a brand-new road record works too, but is explicitly experimental: eeu.il (the name index) is updated, but the name-search trie/catalog (eeuz.rt/.rl/.prl) and the rendering tiles (eeuz.mp0/.mg1-.mg4) are not, so a new road may not render on the map display or be found by the unit's own address-entry search.

Reader code

rns510_core.py (RoadRecord, read/edit/append) — RoadRecord now exposes delta_lon/delta_lat directly alongside lon/lat. No dedicated research/ module for the header bytes themselves — this file is simple enough that the editing tool's own core module handles it directly. The byte-level crack above was derived via research/mod_reader.py's decode_field_descriptors() (the cracked per-field width/bit-offset parser) against eeu.mod's own road schema block, then validated with ad hoc scripts against real MapProject-read records (not saved as a dedicated reader — a one-off validation, not a general-purpose module).

Clone this wiki locally