The ROM contains three related resource tables with eight-byte headers. Each header has a four-byte signature, a two-byte field seen as zero, and a 16-bit entry count. The entry width depends on the signature, so choose the parser from that signature rather than guessing from a filename. Several columns still have no established meaning. [1][2][3]
| Resource | Signature | Entry size | What is established |
|---|---|---|---|
.znbl | JNBL | Wiki says five bytes | Two early 16-bit values; a trailing field is not resolved. |
.zncl | JNCL | Eight bytes | First four bytes undetermined; second four have been observed as zero. |
.znll | JNLL | Twelve bytes | Final four bytes point to a string elsewhere in the same file. |
For JNLL, string pointers are relative to the file start and the target strings are UTF-16LE terminated by a zero code unit. Check a pointer against the actual file length before reading. For JNBL, the wiki says “five bytes” while assigning a two-byte interval to the final field at offsets 4–5. That conflicts with a five-byte stride, so a parser should preserve the raw entry and verify its stride against a known ROM sample instead of trusting either interpretation automatically. [1][2][3]
To understand how one of these tables affects a menu, find the routine that loads it and the message or graphic each record refers to. Leave unknown fields labelled as such until a comparison between builds or a trace through the original code explains them. The tables alone do not describe a complete rendered page. [1][2][3]
Shared ZN header and per-family entry offsets
ZNBL and ZNCL resources occur alongside many menus in the ROM, but the wiki does not establish their complete role. ZNLL resources appear to hold placeholder or localised menu text. The resources found with one menu may differ from those used by another. [1] [2] [3]
| File offset | Width | Header field |
|---|---|---|
| 0x00 | 4 bytes | JNBL, JNCL or JNLL, according to family |
| 0x04 | 2 bytes | Unidentified field observed as 0x0000 |
| 0x06 | 16-bit integer | Number of entries |
| Family | Offset within entry | Width or interval | What the wiki establishes |
|---|---|---|---|
| JNBL | 0x00 | 16-bit integer | Unknown |
| JNBL | 0x02 | 16-bit integer | Unknown |
| JNBL | 0x04–0x05 | Two-byte interval in the field table | Unknown; possibly flags |
| JNCL | 0x00–0x03 | 4 bytes | Unknown |
| JNCL | 0x04–0x07 | 4 bytes | Reported as possibly always zero; unconfirmed |
| JNLL | 0x00–0x07 | 8 bytes | Unknown |
| JNLL | 0x08 | 32-bit integer | File-relative offset of the associated string |
JNBL's stride is unresolved: the prose specifies five bytes per entry, while its last field spans offsets 0x04–0x05, which would require at least six bytes. The entry size therefore needs to be checked against a sample or the original reader. JNCL's stated stride is eight bytes; JNLL's is twelve. JNCL's possible zero field remains unconfirmed, so do not require zero when reading unfamiliar samples. [1] [2] [3]
A JNLL string offset is relative to the beginning of the whole file, not the current entry or text section. Its destination is UTF-16LE text ending in a zero 16-bit code unit. Validate both the pointer and the entire terminated string against the resource extent; an entry count alone does not bound a string read. [3]
