eeu mod Database Schema - krcenov/RNS510-Map-Viewer GitHub Wiki

eeu.mod β€” Database Schema Dictionary

Status: βœ… Cracked β€” the single most valuable file examined in this entire project. Β· 40 KB Β· NOT_COMPRESSED

This file is the disc's own full database schema / data dictionary, built by the original authoring tool. Its own first two strings are literally Arriba and 5.3 β€” almost certainly the real internal name of Navteq/Siemens/Continental's own map-database compiler. Independently corroborated in a later session, from a completely different angle: EDB/POI/POI.DB3's own build metadata names the real internal codebase arriba2/arriba2_VW directly (ClearCase source-control paths) β€” the tool that built that database, not the map compiler that built this one, confirming Arriba is Siemens/ Continental's real name for the whole navigation-core toolchain, not just this specific component.

Container

94-byte header (record_count_lo16, see Header Trailer Fields, correctly reads 0 β€” this is not a fixed-record file, same situation as eeu.il). The body is a dense run of NUL-terminated ASCII strings interleaved with short binary runs.

What it contains

A plain printable-ASCII-run-terminated-by-NUL scan of the whole body finds exactly 1,605 strings, organized as one block per real table:

[table name][fieldHeader]
[stamp / copyright / db_release / db_version / comp_version / dbID / fileID / rec_cnt / byte_cnt]
[...that table's own real data fields...]
[short file-extension marker]

All 36 expected file-extension tokens appear, in the same order this project already independently confirmed those files' identities in β€” strong corroboration the extraction is correct, not coincidental:

Block (table name) β†’ File
Arriba/... (character repertoire + language table) eeu.abc
country/... eeu.ctr
state/... eeu.stt
county/... eeu.cny
city/... eeu.cty
road/... eeu.rd
rtype/... eeu.typ
affix/... eeu.aff
"Ordinary Map File"/... (parcels, segments, nodes, shapes, turn restrictions, lanes, ADAS/truck speed limits, intersection+junction views, traffic signs, ...) eeuz.mp0/.mg1-.mg4 (+mpa/mpb, not present as real files here)
seginfo/... eeu.si
feature/... eeuz.fea
catalogList/... eeu.cal
cityTree/... eeuz.ct
cityList/... eeuz.cl
roadTree/... eeuz.rt
roadList/... eeuz.rl
roadListNames/... eeuz.prl
postalcodeTree/... eeu.pot (empty on this disc)
postalcodeList/... eeu.pol (empty on this disc)
postalcodeListSeparate/... eeu.pmm
postalcodeListMergeCity/... eeu.pmc
postalcodeListMergePostalcode/... eeu.pmp (empty on this disc)
timeinfo/... eeu.ti
intersectionOffsetFile/... eeu.iof
intersectionListFile/... eeu.il
"tmc file"/... eeu.tmc
catalog/... eeu.cat
phCatalog/... eeuz.pca
phCity/... eeuz.pct
phRoad/... eeuz.prd

eeu.pcl has no corresponding block at all β€” not just an empty one like .pmp/.pol/.pot get. Its real purpose was tracked down in a later session, not through this file but through the disc's own files.cfg β€” see Phoneme Cluster List.

Confirmed corrections and extensions to already-cracked files

Directly cross-referencing this schema against work already done elsewhere resolved several previously-open questions:

  • eeuz.pct's "group" field mystery is fully solved: the real fields are .../phonemeRoadOffset/ phonemeRoadCount β€” a pointer into eeuz.prd, not a "language-variant grouping key." Validated directly against real eeuz.prd content for 4 example cities.

  • eeu.ctr's 2 "trailing zero bytes" are named speedUnit/drivingSide (both zero-valued for every country on this disc).

  • eeuz.rl's previously-unresolved trailing flag byte and always-zero bytes[4:7] are named hasHouseNumbers and a packed minNumber/maxNumber range β€” consistent with the flag's own already-measured 71%/29% split.

  • eeu.il's 7 still-unresolved prefix bytes include a named vnodeID field β€” a real, disc-confirmed "virtual node id" reference, and a promising, not yet pursued lead for the long-standing topology node-id↔coordinate mapping problem, since the MAP_COMPRESSED tile schema independently references left_node/right_node on its own segment records. A later session, from the FIRMWARE side (the separate factory firmware disc β€” README Β§2.6, out of scope for this wiki): found a complete, real, NAMED resolution pipeline for exactly this β€” db_vid_get_map_id_V000/ db_vid_get_pcl_id_V000 ("vid" = virtual id) resolve a vnodeID to its owning map/parcel; db_find_node/db_node(i_toNode, &vNode) then loads the real VNode struct (confirmed field vsegIDs[]); readNodeMP0__9RoutePathUiR5VNode reads a VNode directly from an .mp0 MAP_COMPRESSED tile while building a RoutePath; a real maneuver-generator subsystem (mv_*, source path navicore/common/ mnvr/mv_vnode.cpp) consumes these for actual turn-by-turn guidance β€” confirming VNode is genuinely the cross-tile routing graph node, not a rendering-only construct. Names only, byte-level encoding still unrecovered β€” but gives a concrete validation path (cross-check a guessed vnodeID bit-split against this page's own ParcelHeader directory below) that didn't exist before. See research/ swl_5238_reader.py for the full writeup.

  • eeu.cal's always-0xFFFFFFFF trailer is named cityTreeOffset/postalcodeTreeOffset (2Γ— uint16, both the 0xFFFF "unset" sentinel for every country/continent entry).

  • eeu.cny β€” corrected field names (countyID/stateID/timeinfoID), see its own page.

  • The "Ordinary Map File" block is the MAP_COMPRESSED tile schema and is the largest single block (615 field names). left_node/right_node on a segment record is a strong, not-yet-pursued lead for finally closing the topology node-id↔coordinate mapping gap β€” not attempted this session, given the scope of that undertaking on its own.

  • eeu.si is named seginfo, with real fields rank, class, divided, toll_vignette, toll_road, restclass, urban, route_num_type, paved, ... β€” a genuine road-classification table. Opened in a later session: most of its 20 real fields were cracked, but the hoped-for link to eeu.rd's own bytes[1:5] turned out not to hold up β€” decoding that field with eeu.si's own exact bit layout produces values filling the full available range rather than eeu.si's own bounded ranges. The real seginfoID foreign key more likely lives on the MAP_COMPRESSED tile format's own segment records instead (see that page for the corrected lead). A later session attempted exactly this (goal: real per-segment road styling in the map viewer). Real progress, not a crack: found a genuine, previously undocumented 3rd tile region right after the topology table ends β€” real, visibly grouped byte structure, confirmed non-empty and similarly-shaped on 9 real tiles, with its own byte length correlating with point count at ~8.95 bytes/point. Almost certainly (part of) eeu.mod's own seg_list/attr_list region, but the exact per-record boundary/field layout wasn't pinned down precisely enough to test a candidate seginfoID byte position against eeu.si's own real value ranges. A direct record-boundary search was then tried and found inconclusive β€” a real, documented methodological trap: a backtracking search for a tag β†’ record-length rule that consumes a tile's tail with zero leftover "succeeds" trivially (too many byte partitions sum to the right total to mean anything), and even a more constrained "uniform 8-byte records" search that also numerically "succeeds" decodes to obvious garbage after the first few records β€” exact byte-consumption alone isn't a strong enough test here, unlike other cracks this project has made. See research/map_compressed_reader.py's decode_topology() docstring for the full writeup. A later session, from the FIRMWARE side (a separate factory firmware disc the user provided, research/swl_5238_reader.py): the running application's own embedded debug strings directly confirm this field group is real and actively used, naming exact versioned accessor functions β€” db_seg_rank_V004, db_seg_speed_V004, db_seg_tunnel_V004, db_seg_node_V004, db_seg_unique_vid_V005, db_seg_plural_junction_V005, db_seg_is_part_of_freeway_intersection_V005, and an EXACT name match for eeu.mod's own fields, db_seg_marker_left_V004/ db_seg_marker_right_V004. Strong independent confirmation the field names are real, not just an authoring-tool convention β€” but their own compiled code wasn't located or disassembled (same load-base wall), so this remains a confirmed lead, not a byte-offset crack. A direct attempt to recover the load base was then made and REFUTED: no \x7fELF magic survives anywhere in the 0-24MB region, and a lis/ addi string-cross-reference scan (39,715 candidate absolute-address pairs, tested against 7 known accessor-name strings including db_seg_marker_left_V004 itself) found no consistent load base β€” each string's own top candidates are unrelated to every other string's. Most likely explanation: these are DWARF-.debug_str-like debug-only strings, structurally never referenced by executing code β€” a real, structural dead end for this technique, not an unexplored gap. See research/swl_5238_reader.py for the full writeup. A fresh record-boundary attempt, directly informed by the field list above (seginfoID_ext_count as a principled explanation for the variable record length), a still-later session: suggestive but NOT a crack. A plain unaligned-2-byte-window frequency scan of the 83-point reference tile's own tail found one value (13708) dominating 74/83 records β€” bounded within eeu.si's own real range, and looking that record up gives plausible (not contradictory) real field values β€” but the SAME test on 2 more independent reference tiles did NOT replicate cleanly (no single dominant value on either, and one shows the same byte pattern as a likely artifact on the first tile). Honest conclusion: a real, new lead, not a confirmed crack. That exact next step (a proper seginfoID_ext_count-driven parser) was then attempted directly, same session β€” and a single-count-field model is now EXHAUSTIVELY REFUTED, computationally. A joint search over every plausible (base length, count-byte offset, extension size, id offset) combination, requiring exact whole-tail consumption under record_length = base + count_value Γ— extension_size: zero configurations succeed, at any count cap up to 15. Root cause, confirmed directly: the single most plausible count-byte position (real small-count-like value distribution) reads the identical value on 3 consecutive real records whose true lengths are 8, 8, and 11 bytes β€” no single formula tied to any fixed byte position can explain that. Real conclusion: the tail's true record format needs MULTIPLE independently-variable fields (plausible candidates: seg_marker_ left/seg_marker_right/restr_left/restr_right each independently present or absent, not one shared toggle) β€” a genuinely bigger parsing problem, closer in scope to what it took to crack eeu.tmc's own variable-field-count chain_count structure, than a quick continuation can responsibly solve. The user then provided real, human-verified ground truth from their own RNS510 unit running this exact disc β€” 3 precisely- located real road segments via the map viewer's edge-pick tool: 2 independent points on the A1/Trakia motorway near Sofia (confirmed divided) plus a contrast point on Vladimir Bashev street, Sofia (confirmed one-way, non-divided). 3 independent shortcut methods were tested against this ground truth and ALL REFUTED: a seginfoID-lookup approach came back weak for divided and BACKWARDS for toll_vignette (lower than baseline on a real Bulgarian motorway, which legally requires a vignette β€” a clean refutation, not noise); a positional/distributional scan across ~150 candidate positions found one survivor that failed a basic internal- consistency check (its own statistics swung wildly between the first and second half of a single real road's own tail region) β€” a multiple-comparisons artifact, correctly caught rather than reported as a discovery. A real, well-earned wall for any shortcut approach, now backed by real ground truth. A real, working per-ID-length parser was then built by hand β€” genuine progress: the same 2-byte leading id at a record's start always implies the same record length (learned on the fly, not assumed), and every valid record ends in exactly 00 00 β€” a real terminator that avoids the earlier over-permissive trap. New reusable functions: seg_tail_region()/parse_seg_tail_records(). Converges fast (~2,000 steps, unseeded) on real mg4 tiles; its length distribution (71% plain 8-byte records) matches the already-established "junctions get bigger records" pattern from the local topology crack. 6 more real, human-verified ground-truth points from the user's own RNS510 unit then let this parser's own 8-vs-9-byte signal be tested directly against KNOWN divided/non-divided status β€” cleanly refuted as a "divided" indicator: a confirmed non-divided road (A6, still under construction) and a confirmed divided one (Hemus/A2) show nearly identical signatures, while another confirmed divided road (A1) looks completely different from both. Real, honest result using precise ground truth β€” the parser structure itself is still real, it's just not divided that this particular signal tracks. A different signal from the same parser, tried right after β€” the most promising lead in this file region so far: whether an 8-byte record's byte2 or byte3 is EXACTLY ZERO. A1 and Hemus (both CONFIRMED divided, precise matches) show it on 0 of 273 combined 8-byte records (0.0%, exactly); A6 (CONFIRMED non-divided) shows it on 11 of 89 (12.4%); a 3rd, less-certain sample (A2-west, imprecise tile match) shows 96 of 137 (70.1%) β€” same qualitative direction (nonzero), higher magnitude. A real presence/absence pattern, not just a magnitude shift β€” but NOT yet a crack, since only 2 tiles have both a precise match and confirmed status. One more precisely-matched divided-road ground-truth point would confirm or break the "0.0% is a hard rule" hypothesis. Refined, same session: a systematic per-byte sweep found bytes 1, 2, AND 3 (not just 2/3) each independently show this exact 0.0% pattern; byte4's own small "leak" on A1 turned out to be numeric coincidence, not real signal β€” the refined signal is bytes 1-3 specifically. A specific semantic explanation (turn restrictions at real intersections) was tested against this project's own already-cracked local topology/junction data and CLEANLY REFUTED β€” junction-dense tiles showed LESS signal, not more. A genuine POSITIVE crack: the trailing "value" field (bytes 4-7) is very likely eeu.mod's own named length field β€” a real distance in DECIMETERS, confirmed by comparing its distribution against real point-to-point distances from this project's own already-cracked coordinate geometry (maximum values match within 1-5% on 2 independent tiles) β€” the first field this project can actually NAME in this record. See research/map_compressed_reader.py's decode_topology() docstring for the full account, including all 9 ground-truth points gathered this session, for a future session to reuse.

  • mp0's own tail β€” first real crack, a later session. The Vladimir Bashev tail (14,393 bytes) is NOT one uniform structure β€” it splits into distinct zones. A dominant recurring 2-byte tag (f1 44, found in ~1 of every 15 bytes overall) marks a middle zone (tail bytes 3,788-12,312, 8,524 bytes) with a real, exhaustively-validated record format: 7 bytes normally ([tag][0x44][0x00][idx: u16 LE][subidx][ value]), 11 bytes for a "special" case with 4 extra bytes inserted right after the constant 0x00 β€” directly analogous to mg4's own bigger junction records. Proved via a backward dynamic program (every position must reach the zone's own exact end through a chain of 7s and 11s, or fail entirely β€” no partial credit): 949 records, exact, zero-leftover coverage of the whole 8,524-byte zone (477 width-7 + 472 width-11). idx climbs steadily through exactly 3 resets, matching this tile's 3 real, named streets (Vladimir Bashev/ Svetlostruy/San Martin) one-for-one β€” strong independent confirmation idx is a genuine per-street running counter, with street boundaries encoded purely by the counter resetting (no separate header needed to detect them). Paired subidx=0/subidx=1 records sharing the same idx show correlated value bytes, the shape of a forward/backward attribute pair β€” the real-world meaning of value is not yet identified. Cross-checked against Vladimir Bashev's own confirmed one-way status β€” cleanly refuted: idx values missing a subidx=1 record scatter randomly through the range (not clustered into a contiguous run, which a real one-way stretch should show), so subidx more likely marks a sparse per-segment attribute than direction of travel.

  • mp0 zone 3 β€” a real, plausible SPEED-LIMIT crack. Zone 3 (tail bytes 12,312-14,393) splits into 3 further sub-zones. Sub-zone 3a (822 bytes) has its own validated record format (same exhaustive-DP technique as zone 2, 131 records, zero leftover bytes): a type byte deterministically selects a 6- or 7-byte record width, and the byte right before the terminator lands on exactly one of 4 values β€” 30, 40, 50, 80 β€” all real, standard km/h speed limits, a plausible on-disk match for the firmware's own known db_seg_speed_V004 accessor (not yet ground-truth-confirmed). Sub-zone 3b (196 bytes) is a clean monotonic list of multiples of 4, not yet identified β€” a later session REFUTED the "scaled point/vertex index" hypothesis on a 2nd tile (resulting indices exceed that tile's real point count). Sub-zone 3c (1,056 bytes) starts as small signed deltas then shifts character partway through β€” a later session found the "large, repeating values" were a MISALIGNMENT ARTIFACT: the true record width changes to 3 bytes ([value: s16][0x04 terminator]) partway through, and reading it with the wrong 2-byte stride produces exactly this kind of confusing drift. DP-validated: 34 real 3-byte (plus a few 6/7-byte "special") records, zero leftover bytes. A 3rd sub-region (2 monotonically-increasing u16 sequences read as pairs) sits between the deltas and this record run β€” none of the 3 regions are semantically named yet. Zone 1 (tail bytes 0-3,788) remains completely uncharacterized. Full writeup: research/ map_compressed_reader.py's decode_topology() docstring, "FIRST REAL CRACK of a chunk of mp0's own tail structure" and the zone-3 UPDATE immediately after it.

  • mp0 zone 2 β€” (tag, subidx) slots characterized by value distribution, one clean binary flag found. tag=0xf4, subidx=1 (70 records) has only 2 distinct values ever (0xcc: 43, 0xe1: 27, a 61%/39% split) β€” the cleanest categorical slot in the zone, a real candidate for a boolean road property (one-way is an obvious guess given this tile's confirmed one-way street). 2 other slots look like small enums with a dominant value; 2 more (f1/0, f1/1) are clearly numeric. 2 independent attempts to localize which idx values belong to Vladimir Bashev specifically both failed β€” point-index- with-topology-shift landed on uninformative no-data records, and an edge-ordinal check turned out to rely on an artifact of Python's own sort order rather than a real structural correspondence β€” so this guess remains untestable for now. Real fix needed: recover the topology table's own raw on-disk record order and test whether idx tracks that, not point index.

  • mp0 zone 1 β€” a real numeric-record crack PLUS a genuine, independently-verified Bulgarian place-name string table. 446 records exactly match this project's own already-confirmed mg4 8-byte seg_list layout ([id(2)][byte2(1)][byte3(1)][value(4, ends in 00 00)]) via exhaustive DP β€” 98.5% exact coverage, widths 6-14, 8-byte dominant (56.7%). The remaining bytes aren't records at all β€” they're a small, human-readable name table continuing seamlessly across the artificial zone1/zone2 boundary: 13^ZHK IZTOK (a real Sofia residential-complex name), 13^HLADILNIKA (a real Sofia neighborhood), 13^TSENTAR/13^CENTRUM (2 transliterations of "Center"), each in the form <binary header><lang-index digits>^ <NAME>\0. The 13 prefix is independently, exactly confirmed: eeu.abc's own already-cracked language table has index 13 == bul (Bulgarian), checked directly against the real file β€” the prefix is the language index written as literal ASCII digits, not a raw byte. Almost certainly district/ neighborhood labels (not the street's own name), consistent with a "which area is this tile in" lookup.

    Header partially cracked, a later session β€” one field real and validated. Found the same convention in 2 more tiles (25 real entries total), including a 2nd independently confirmed language index: 24^ = eng (English, eeu.abc index 24), correctly on English-only entries (24^SOFIA AIRPORT CENTER) and paired with Bulgarian on bilingual ones (13^TERMINAL 2/24^TERMINAL 2). The header is a fixed 17 bytes: [X: u16 LE][Y: u16 LE][0x01][0x00][ZZ: 1 byte][WW: 1 byte][9 zero bytes].

  • Re-validated at scale, a later session β€” a real off-by-one bug caught and fixed, then X fully cracked. Testing at scale (2,055 entries, 400 Bulgaria-region tiles) first looked like a near-total formula failure β€” the bug was in this project's own earlier claim, not the data: WW actually equals len(text) exactly (no -1), re-confirmed against the original sample. With the fix: 91.2% match exactly; excluding a different, coincidentally-matching record type (phonetic/pronunciation transcriptions) raises this to 95.8%. X is now FULLY explained: the entry's own total byte length (header + text + NUL) rounded up to the next odd integer β€” zero exceptions across 1,834 validated entries.

  • The remaining 4.2% was a SECOND bug (fixed to 100%), and Y/ZZ encode a real HIGHWAY-SIGN structure. The regex's own {3,40} length cap was truncating longer multi-destination strings (e.g. the real 47-character 13^MEZDRA/13^KREMIKOVTSI/13^KALOTINA/13^BELGRAD), matching a spurious later point and reading garbage as its header β€” widened to {3,200}, now 100.0% exact match on both WW and X. With clean data: Y links PAIRS of entries into a route↔destination relationship, and ZZ's family (16/17 vs 4/5) encodes which role a string plays β€” 172 of 203 same-tile Y-sharing pairs (84.7%) show one entry in each family, confirmed by the actual text: family-4 entries are real road/route designators (13^A3/13^E79, 65^DN6, bare numbers like 13^9/13^E87), family-16 entries are real destination place names (SOFIA, PLOVDIV, BUCURESTI). Unpaired entries (unique Y) are overwhelmingly family-16 (98.4%) β€” the "standalone place name" default. Not perfectly clean (31 of 203 pairs share the same family); Y's own numeric value beyond "is it shared" is still unidentified. Y-vs-zone-2-idx tested, genuinely inconclusive (every tile's own idx range turned out 100% dense, making simple membership uninformative).

  • The entries this table's regex deliberately excludes (phonetic transcriptions) closed an OLD open question in eeu.abc's own (flag_a, flag_b) write-up β€” see that page for the full confirmation that (4,8) is the phonetic/pronunciation-transcription slot.

  • mp0 zone 2 GENERALIZED to multiple tiles β€” one real correction. decode_mp0_zone2() re-derives the format without hardcoding Vladimir Bashev's own 0x44 middle byte, auto-detecting each tile's own dominant tag. Tested on 5 more Sofia-area tiles: 4 succeeded structurally (516-819-record dense runs, same shape); a naive "first occurrence" boundary-finder failed on 2 of them β€” fixed by requiring several consecutive anchors to already show the 7-or-11-byte stride. Correction: the original write-up implied 0x44 was a fixed attribute-type tag; other tiles show their OWN dominant middle byte and their OWN per-slot tag values (0xf4 never recurs β€” other tiles show 0xf2/0xe8/0xf5/0xeb instead), confirming id is a genuine per-street identifier, not a record-type marker.

  • A real bug found fixing that boundary, then zone 3a (speed-limit candidate) generalized on top of it. Chaining decode_mp0_zone3a() right after zone 2's own "end" found a genuine over-permissive-trap bug: on the original tile, "end" landed 4 bytes past the true boundary (the last real record's own trailing bytes coincidentally also satisfied the 11-byte check, producing an implausible subidx=133). Fixed with a subidx <= 10 guard β€” re-verified this changes nothing about the already-validated 949-record result. With that fix, zone 3a reproduces the original speed distribution exactly and generalizes to 4 of 5 more tiles β€” including a Sofia-airport tile showing a wider but still clean multiple-of-10-km/h range (0,20,40,50,60,70,80), a nice extra real-world sanity check.

  • The district-name table, the zone-2 candidate-flag-slot finder, and the zone-3a candidate speed-limit finder are all now wired into the map viewer's point-pick panel (EXPERIMENTAL, mp0 only, structure validated / real-world meaning not claimed) β€” per this session's standing rule that every real discovery gets implemented in the viewer, not left as research-docs-only. The district-name row now uses mcr.group_district_name_signs() to join Y-paired route/destination entries into one readable "9/E87 -> BURGAS/SOFIA"-style label instead of 2 separate-looking strings.

  • A REAL (not experimental) "pronunciation guide(s)" panel row. mcr.extract_pronunciations() parses the entries the district-name table deliberately excludes (phonetic transcriptions) into clean name/pronunciation pairs β€” real, confirmed TTS data (see eeu.abc's own (flag_a,flag_b) crack), exactly what a real GPS unit uses for voice announcements. Unlike most of this session's other mp0 panel rows, this one isn't labeled EXPERIMENTAL β€” the field meaning is genuinely confirmed.

  • eeuz.fea's own feature block is the single largest in the whole schema (~77 real fields) β€” a MapHeader (real bounding box + parcel/tile grid dimensions + multiple zoom scales) β†’ ParcelHeader {offset, byteCnt, byteCntZip} β†’ FeatureDataHeader structure with type-specific geometry (line/poly/point/road), each carrying delta_long/delta_lat fields. ParcelHeader's 3 uint32 fields independently confirm and name the already-cracked 12-byte directory index triple on eeuz.fea's own page β€” found two different ways in the same session. The schema's delta_long/delta_lat fields are also the most promising lead yet for that file's own still-open coordinate problem (coordinates are relative deltas, not absolute values) β€” though this sits in real tension with that page's own "hash table, not a spatial grid" finding, not yet reconciled. See that page for the full picture.

The per-field binary descriptor β€” CRACKED (a much later session), triple-validated against eeu.ctr's already-known exact byte widths

A still later session, while trying to crack eeu.rd's remaining 8 unresolved header bytes, went back to this "what's not cracked" paragraph and built the general parser that was flagged as a natural next step. The per-field descriptor sits in the gap between one field's name and the NEXT field's name (a trailing descriptor for the field just named, not a leading one for the field about to be named) and has the shape:

[2 bytes: a type tag β€” ff ff for most scalar/string leaf fields]
[4 bytes LE: the field's real byte width]
[4 bytes LE: the SAME width, repeated]
[variable trailing bytes β€” a flag/sub-tag, or for bit-packed fields,
 [bit_width][bit_offset][flag] instead of occupying a whole byte]

Validated exactly, not just plausibly, against eeu.ctr's own already-fully-cracked, byte-exact layout (country block): the descriptor's repeated 4-byte value reads 1, 35, 3, 2, 1, 1 for countryID/name/isoCode/iso2Code/speedUnit/drivingSide respectively β€” an EXACT match to that file's own independently- validated real field widths (sequential index, 35-byte name, 3-byte ISO alpha-3, 2-byte alpha-2, 2 trailing zero bytes), with zero discrepancies across all 6 fields.

Bit-packed fields (declared byte-width 0 in this encoding) carry their real size differently, via a [bit_width][bit_offset] trailer instead of occupying a whole byte. Applied to eeu.rd's own road block, this exactly explains 2 previously-separate-looking groups: cityID (24 bits, offset 0) + countryID (8 bits, offset 24) pack perfectly into the 4-byte field declared as cityAndCountryID immediately before them; and highway/preferred/explicate/ramp (1 bit each, offsets 0–3) + "name type" (3 bits, offset 4) + interchange (1 bit, offset 7) pack perfectly β€” with ZERO bits wasted β€” into the single byte declared as roadInfo. See eeu.rd's own page for the full, independently real-data-validated byte-level crack this unlocked (every one of its remaining 8 unresolved header bytes now accounted for).

Not fully resolved: the descriptor's leading 2-byte tag varies (ff ff for most leaf fields, small sequential-looking values for wrapper/struct- level entries like data/countryID-as-record-marker) and its exact meaning wasn't pinned down; nor was a full explanation for cases where eeu.mod's declared width appears to exceed what a specific disc's real compact on-disk packing uses (treated as the schema's own generic/ upper-bound declaration, not a contradiction).

Reader code

research/mod_reader.py β€” extract_strings(), extract_blocks(), decode_field_descriptors() (the cracked per-field width/bit-offset parser described above).

⚠️ **GitHub.com Fallback** ⚠️