Resolve the field->DBF-class mapping follow-up: traced eeu.iof's offset/type/count and eeu.rd's roadInfo bits to their real DBFIntegerSpecial/DBFBitComponent vtable methods via relocations, both matching this project's own already-shipped bit layouts exactly. Scanned all ~1600 eeu.mod field descriptors across all 36 tables -- zero fields need the codec's variable-length cases, so eeu.mod's existing byte_width/bit_width/bit_offset descriptors were already a complete, correct recipe; the field->class mapping task is dropped as unnecessary.
Correct the 'external field-reader' wall: it was wrong. 621 DBF* class symbols (DBFInteger/DBFIntegerSpecial/DBFBitComponent/...) are real, defined code in DBAL.OUT's own .text, not external -- the indirect vtable calls just render opaquely in Ghidra's pseudocode. Proven via .rela.text relocations against each class's _vt$ClassName symbol, resolving unpack_intersection_offset_rec's 3 field reads to real named functions. Found the actual generic integer codec (9 real encoding schemes) and the bit-field shift/mask logic. Not yet done: mapping each field name to its concrete DBF class (likely eeu.mod's own still-undecoded type-tag byte).
Resolve the k-d tree edge-scale 'proven wall': it was a 4-byte reader offset bug, found via eeu.mod's schema. Full tree traversal now reaches 100% of nodes/leaves; edge uses the disc-wide /100000-degree convention. Wire find_tile_for_coord_kdtree()/build_kdtree_bbox_index() into the viewer as the primary (structural, no-decompression) bbox source, with the cached content-decode path as fallback.
kd-tree edge calibration: trace query architecture (map_search/pcl_sect_cover/pcl_found), confirm db_upack_kd_sub/top_node/info hit the same external-schema wall as eeu.rd/eeu.iof, and prove via connected-component analysis that no tested byte layout reconstructs one tree
Document the geo-index disk cache: why the k-d tree wasn't swapped in yet, and the safe fix that was
Crack MAP_COMPRESSED's geo-index prefix: a real k-d tree, via DBAL.OUT disassembly Reconciles with (doesn't replace) the earlier R-tree symbols found in FHDD6.FLI -- likely 2 genuinely different subsystems. The actual on-disk structure in this region, confirmed via fully-resolvable DBAL.OUT code (db_kd_search, kd_pdecend/kd_rdecend, db_page_kd_subtree, db_upack_kd_top_node/sub_node), is a k-d tree: a 28-byte mapHeader (validated via an exact pcl_cnt match to the file's real tile count, plus an independent node-array-size prediction landing within 4 bytes of the real table_start) followed by interleaved 13-byte node records. kd_info's 7 bits and lo_index/hi_index's dual-purpose (node index vs. subtree cache-slot id) encoding are both traced directly from real code, not inferred. edge is confirmed to be the real split coordinate by tracing exactly where it's written during tree descent; its own numeric scale remains open. Preserves the earlier scan_native_geo_hints() findings as a separate, still-valid, not-yet-reconciled signal in the same byte region.
Document DBAL.OUT full decompilation, research/dbal.py, and the definitive external-reader confirmation
Document confirmed-highway rendering using eeu.rd's cracked highway bit
Crack all remaining eeu.rd header bytes via eeu.mod's own binary field descriptors + DBAL.OUT disassembly Disassembled db_road.cpp's read_current_record_from_database in DBAL.OUT to get the real field read order and names (countryID, cityID, prefix, suffix, rdtype, roadinfo), confirming delta_long/delta_lat get converted to a max-corner on read. The real unlock was eeu.mod itself: its binary bytes (not just the field-name strings already extracted) carry a real per-field width/bit-offset descriptor, cracked this session and validated byte-exact against eeu.ctr's own known layout. Applied to eeu.rd's schema block and validated against real file data: cityID (bytes[1:4], 24-bit) shows 50.3% same-value match among geographically nearby records vs ~0.025% expected by chance; typeID (bytes[5:7]) ranges 0-2571, matching eeu.typ's 2,574 real entries almost exactly; roadInfo bit0 (highway) correlates with route-like names at 89.95% vs 0.10%; suffixID/prefixID (byte[0]'s two nibbles) are independent and both span the full 0-15 range. All 8 previously unresolved header bytes are now accounted for, with zero bits wasted in the roadInfo byte's 6 packed sub-fields.
Crack eeuz.fea's relative point-geometry format via real DBAL.OUT disassembly Disassembled db_feature.cpp's real handler chain (db_fea_read_parcels_V005 -> parseExtractedParcel -> FeaCoordReceiverInternal::getCoordinates()) using capstone plus a hand-rolled ELF relocation-table parser to resolve every global reference to its real linker symbol name. Fully cracked the per-point delta format: 4-byte records (int16 BE dx, int16 BE dy), cumulative 16-bit accumulators, each point scaled by a per-layer factor from a FeaLayerPropertiesInternal struct. Also found strong, disassembly-proven evidence that the absolute anchor is NOT part of this decode path at all: init()'s own code zeroes the accumulators and stores its 2 float params into fields getCoordinates() never reads (traced to an accuracy/unit-conversion ratio, not a coordinate). Combined with the type's own name (LocalPoint, not GeoPoint) and this project's already-exhaustive refutation of any absolute coordinate embedded in entry bytes, the most consistent reading is that an external caller (likely rendering code, using a tile/ viewport position it already has) supplies the real anchor -- meaning further progress may require tracing into FHDD6.FLI, which has its own known disassembly wall.
Document eeu.iof nearby-streets lookup now wired into search-result jumps
Crack eeu.iof's type field via real DBAL.OUT disassembly Disassembled 5 real functions (unpack_intersection_offset_rec, db_get_minor_road_list_type/_offset/_count, db_get_crossstreet_offset) directly from dbal/V010_015/DBAL.OUT using capstone -- this small unlinked ET_REL object has full .text content in-file, unlike FHDD6.FLI's disassembly wall. Confirms the real struct IOF_Record and the real in-memory field mapping, and cracks type's actual role: a validity gate (type must be 0 for offset to be valid) plus a tri-state cache-resolution flag (type==1 means the stored count is provisional and gets recomputed from a live IntersectionList cache). Also refutes the natural "type selects minor-road vs cross-street list" guess -- cross-street lookups go through a completely separate in-memory hash cache.
Document road-search jump zoom now using eeu.rd's cracked delta_long/delta_lat
Crack eeu.rd's delta_long/delta_lat: a real segment bounding-box extent eeu.mod's own schema names this table's real fields in order: ...min_long, min_lat, delta_long, delta_lat, name... -- min_long/ min_lat sit exactly where the already-verified longitude/latitude fields are, putting delta_long/delta_lat exactly at the 2 fields previously listed as "unresolved, small values" (bytes[16:20]/[20:24]). Validated at real scale (20,000-record random sample across the whole 8.8M-record file): zero negative values for either field, implied segment diagonal median 350m / mean 1.1km, 96.8% under 5km, 99.9% under 50km -- exactly the real-world range of named road-segment lengths. Also checked the firmware side directly (user asked specifically): dbal confirms real db_road.cpp/db_road_list.cpp/db_road_cache.cpp/ db_road_sel_char.cpp source files and one accessor (db_road_NameListDataByIndex_V004), but unlike eeu.si's rich db_seg_* catalog, no further per-field road-classification accessors were found -- the firmware confirms the handler exists but doesn't hand over a field-by-field breakdown. The remaining 14 eeu.mod field names (cityAndCountryID through interchange) packing into 8 still-unresolved bytes remains open; highway as a single bit of byte[0] tested and refuted (zero correlation with route-like names across all 8 bits).
Close eeu.iof's anchor-list-ordering question: comprehensively refuted Tested 5 more orderings beyond the earlier alphabetical check, on a real 60-anchor random sample: distance from the anchor, the list's own eeu.rd index (ascending/descending), compass bearing, and name length (ascending/descending). Every one scores 0/60 exact matches. List order is most likely a construction-time artifact rather than anything recoverable from the entries' own content.
Document an inconclusive first attempt at eeuz.fea's delta-coordinate lead Located Iasi's own name table precisely inside its entry (byte 1336) and inspected the 20 bytes immediately before it -- naively read as category/type/flags/feaPointCnt, the 4th byte is 7, implausible for a single city label, and no small int16 value resembles a plausible coordinate delta. Doesn't refute the theory itself (the anchor was a guess), but is real evidence against "geometry sits directly adjacent to the name table" and toward entries possibly not carrying point geometry at all. Documented so a future session doesn't repeat this exact first probe.
Refute eeu.ti's monthorweek/starthour/startminute as literal per-zone data Checking the DST fields against the 11 non-DST "simple default" records (not just the 2 DST zones against each other) seals it: every non-DST record -- including ones with every duration field zero, i.e. no real transition event at all -- also carries starthour=3. A byte genuinely storing a transition hour could never appear unchanged there. monthorweek similarly only takes 2 values across the whole dataset (100 non-DST, 108 DST, regardless of spring/fall) -- more consistent with a template/subtype discriminator than real calendar data. Also updates Unexamined-Files.md's stale "partially cracked" note for eeu.ti to match its now-fuller (though still refined) status.
Document two eeu.tmc leads tested and ruled out/inconclusive vseg_id as a direct eeu.si cross-reference (bytes 1+3 combined as a 16-bit value) is REFUTED: only 35.9-44.7% of combined values land in eeu.si's real confirmed seginfoID range (0-24,352), matching the ~37.2% rate pure chance predicts -- not a real signal. byte 7's excess-8-biased nibble pattern shows no correlation with the cracked arm candidate (flat across all 16 values) and only a weak, inconclusive trend against no_of_segments -- documented as open.
Crack eeu.tmc segment_chain byte 4's high nibble: same shape as byte 2 byte[4] has 96 distinct values total (= 6 x 16), and its high nibble takes only 6 discrete values {0,1,2,8,9,10} -- zero violations across all 310,888 real minimal records -- exactly (flag<<3)|val3 with flag a real ~50/50 bit and val3 another 3-valued field (0,1,2) whose marginal distribution is nearly identical to byte[2]'s own "side" candidate, yet provably statistically independent of it. Consistent with a matched START/END pair -- eeu.mod's exception sub-structure is the obvious candidate. Also documents two new, untested leads for a future session: byte[1]'s high-nibble decay pattern (consistent with being the high byte of vseg_id) and byte[7]'s excess-8-biased nibbles.
Crack eeu.tmc segment_chain byte 2: 2 independent bit-packed sub-fields eeu.mod's schema lists start and vseg_id as separate fields, but the prior pass treated bytes[1:4] as one undifferentiated 3-byte blob and never tried splitting them individually. Byte 2's own 48 distinct values are exactly (high_nibble<<4)|low_nibble: high nibble spans all 16 values 0-15 uniformly, low nibble only ever 0, 1, or 2 (skewed ~65/33/2%, identically in both the p and n direction, ruling out redundancy with the already-known p/n split). 16 x 3 = 48, an exact combinatorial match, zero violations across all 310,888 real minimal records, independently consistent in every one of the 44 tables. The two sub-fields are also statistically independent of each other -- the classic signature of two separately-assigned fields sharing a byte. Best candidates by schema position/range: high nibble = start (a junction arm index), low bits = side (plausibly carriageway division). Candidate names unconfirmed, but the bit-level split itself is exact, not a trend.
Document a full sweep validating ISO-open across all 27 firmware discs Follow-up check after shipping direct-from-ISO opening: swept every firmware ISO in this repo (27 distinct discs spanning this project's full range of eras/variants). All resolved correctly in under 0.35s each with zero exceptions, including real cases find_file()'s own docstring calls out but hadn't been exercised end-to-end before -- North-America per-variant NARBY/PROG/ paths and the older FHDD.FLI (no "6") naming. The 2 non-firmware discs in the archive correctly reported "not found" rather than crashing.
Document opening firmware directly from an ISO, no extraction
Document boot-screen cycling in the Simulator tab
Update screenshot: fixed grid-overlap truncation bug
Document connecting the Simulator's leaf classes to real decompiled source Real leaf class names that also happen to be one of this firmware's decompilable classes (standalone or streamed) now render as clickable buttons that jump to real decompiled source, instead of staying plain labels for everything. Narrow in practice (most leaf names aren't independently recoverable) but genuinely works on the reference firmware. Also documents a real gap this caught and fixed: a package can have both real sub-packages and real direct classes at the same level, which the drill-down previously only showed one or the other of.
Document drillable menu navigation in the Simulator tab The menu grid now descends through the real vdo/rns/app/* package tree level by level (breadcrumb + Back button) instead of stopping at one flat level, bottoming out at real leaf class names. Added a screenshot showing the drilled-in vdo/rns/app/nav view.
Document the first visual Simulator prototype (boot -> menu -> select) With Java-recovery scaling attempts exhausted for now, pivoted to the original end goal: rns510_firmware_viewer.py now has a Simulator tab assembling real recovered assets (boot screen, button icon) and real structural data (vdo/rns/app/* package names with real class counts) into an actual clickable mockup, with real screenshots as proof. Explicitly not real menu logic -- no recovered navigation bytecode behind it -- and the tab says so on-screen, not just in the wiki.
Document two scaling attempts tried and ruled out Checked all other firmware component images (RADIO.FLI, DAB.FLI, GATEWAY.FLI, SWL.FLI, MPEGAPPS.FLI, etc.) for any embedded Java -- zero in all of them, confirming the Jeode layer lives exclusively in FHDD6.FLI. Also tried tolerating a constant pool that breaks partway through (salvaging entries parsed before the break instead of requiring the whole pool clean). Looked promising at first (produces plausible -looking bytes) but real decompile attempts through CFR reveal why the strict requirement in reconstruct_class_signatures() is correct: once pool consistency breaks, surviving index values can resolve to the wrong entry type elsewhere (ClassCastException in CFR). Confirmed zero net-new real recoveries when actually tested, not just checked for whether bytes came out.
Document recovering real field/method signatures for 29 partial classes Scaled up the cutoff formula into real tooling: truncate each of the 156 distinct streamed-class names (found across all 21 firmware builds) to its intact constant pool, then mine real field/method signatures from Fieldref/Methodref entries that self-reference the class -- a common, naturally-occurring pattern -- and synthesize a minimal decompilable class carrying them (abstract methods need no real bytecode). Recovers real signatures for 29 classes, including genuinely interesting application data: VehicleClampStatusEvent's ignition clamp 15/30/50 states, real RDS radio fields in FMListEntryInfo, real touchscreen calibration data in CalibrationPoint. Clearly labeled as signatures-only (no real method bodies) wherever shown.
Find the formula: streamed-class cutoff scales with constant pool length Scanning all 21 firmware builds in this repo turned up 156 distinct real streamed-class names total (not just the original 7), 30 with enough cross-build samples to measure a reliable cutoff. Correlated each class's cutoff against several structural properties: constant-pool byte length wins clearly (r=0.985) over entry count, UTF8 byte count, or UTF8 entry count. Linear fit: cutoff ~= cp_end + 44 (slope ~1.0, r^2~0.97), with real classes scattered +-25-50 bytes around that line -- strong but not perfect; Mp3ActionEvent specifically sits much closer to cp_end+0 across all 20 of its own builds. Confirms the dominant factor is each class's own constant-pool length, not an unrelated fixed buffer size -- exactly what you'd expect if the real mechanism walks and copies the full constant pool correctly, then reliably captures only a small, roughly -fixed amount beyond it. This is now operationalized in research/firmware_java_reader.py as StreamedClassInfo.trustworthy_prefix_estimate, shown in the viewer's class list.