7.4 File formats and records¶
Six inputs feed the stores. Each gets a page, laid out the same way so that a reader can compare formats and a maintainer adding one (7.8) knows what to write.
| Page | Input | Produced by | Fills |
|---|---|---|---|
| 7.4.1 sjasmplus SLD | --sld file, version 1 |
sjasmplus | source map, labels, identity (by convention) |
7.4.2 sjasmplus --sym / --exp |
NAME: EQU 0x0000ABCD lines |
sjasmplus | labels |
| 7.4.3 The z88dk map | <stem>.map, with -debug line records |
z88dk (z80asm) |
labels and source map, identity from section binaries |
| 7.4.4 z88dk listings | <file>.lis |
z88dk (z80asm --list) |
source map (replaces a module's map records), embedded texts |
7.4.5 NextBuild Memory.txt |
8000: ._Main lines |
Boriel ZX Basic zxbc -M, via NextBuild |
labels |
| 7.4.6 The annotations file | .jdp: label and comment records |
the user, in JNEXT | the user's labels and comments (a third store) |
The reverse direction, the skoolkit control files and Ghidra symbol files jnext writes, is 7.4.7.
Boriel ZX Basic writes no SLD. Its only output jnext reads is Memory.txt
(7.4.5), a list of labels with no source positions, so a BASIC program built
with NextBuild has symbols and no source lines unless an SLD is produced by some
other tool.
The symbol table the formats fill¶
There is one SymbolTable (src/debug/symbol_table.*), owned by the backend. The Qt panels, the DSL's
@name, the GDB server's monitor sym and --map all read it, so a symbol loaded by one client shows
in every other. How the formats differ is only in what they put in it.
- Keyed by memory and address.
add_label(name, addr, space, bind_at_load, c_symbol)stores a label that is paged (assembled for oneFetchSourcesuch asPage{20}, naming the address only while that memory supplies it) or unpaged (naming it in every memory: the sjasmplus EQU, Simple and NextBuild loaders make these). There is no address-only lookup:lookup(space, addr)finds the paged label with exactly that key, else the unpaged one ataddr(MemSpace::cpu()is "no memory known" and reaches unpaged labels only). The backend'slookup(addr)asks withsource_page(addr), the same identity the source map and the gutter use (7.1), so every consumer (the Disassembly, the Call Stack, the Breakpoints,monitor sym ADDR) names an address by what is mapped there now;disasm_text::symbol_namer()is that rule as a function for the panels. The first label of a key wins and, apart, the first of a name. - A name resolves to an address and, through
find_name()andresolve_key(), to the memory it was assembled for; the breakpoint dialogs keep that page.SymbolTable::resolve()turns an address field's text into an address: hex first (4000,$4000,0x4000), else a symbol;@namealways means the symbol, so a program variable namedFEis still reachable. - Name-only values.
add_value()stores a size, an offset or a section bound:find_name()andlookup_name()resolve it, but it never names an address, so a constant is never shown in a disassembly (a z88dk; constline, an SLD+struct_defrecord). - Binding at load. A z88dk symbol of a section that names no page is stored with
bind_at_loadand no memory;SymbolTable::bind(space_of)gives it the RAM pagespace_of(addr)names (ROM, DivMMC and the other overlays leave it unpaged; an empty function unbinds it). The backend binds with the one function the source half uses,emu.predict_fetch: atload_map()(every success), at the sidecar<stem>.map(a tape included, at the attach), and for the user's store at every program load (7.4.3, rule 4). - Combining.
SymbolTable::merge(other)is the one way to combine two tables: it adds the other's labels whose key is still free, its names and name-only values not yet taken, so the first table wins throughout (rowSYMPG-12). The sidecar store is assembled with it (7.3). - C names. A z88dk C symbol also has its C name (
c_name_to_key_,shown_name(),lookup_assembler(); 7.4.3);merge()carries the C names for the labels the receiving table does not own, andclear()empties them (rowsZ88CN-01to-16). - Rows.
SYMPG-*andSLDL-*(source_map_test: pages, SLD labels),Z88SYM-01to-09andSRCDBG-SYM-18to-22(the z88dk placement),SYM-19to-32(debugger_backend_test: the EQU and--maploaders).
The layout of a format page¶
- The producer, its version and the command.
- The producer's writer, cited by tree and
file:line, so a change in the tool can be checked against it. - The grammar of a record.
- The parser's rules, each with the jnext function that applies it.
- Space and extent: which memory a record belongs to and how many bytes it covers. These two decide whether a format can be supported at all.
- Identity, if the format can carry a program identity.
- What is skipped, and why.
- A real excerpt from a committed fixture, with its path. The fixtures are
normalised (install paths, temporary names and compile dates are replaced:
test/fixtures/z88dk/README.md, "Normalisation and trimming"). Where no public producer writes a record and no fixture exists, the excerpt is labelled synthetic and says which test it comes from. - The rows that pin it.
Which citations are where¶
Producer sources are cited as <tree> <path>:<line>:
sjasmplusis~/src/spectrum/sjasmplusat v1.23.1, commit46aae3f.z88dk 2.4is~/src/spectrum/z88dk-original-2.4at4d530b6eb7(v2.4) andz88dk masteris~/src/spectrum/z88dk-original-97731e4e29at97731e4e29(v2.4-2883-g97731e4e29), master before the debug-record fixes of 2026-11-04 and -05, which~/src/spectrum/z88dk-original-latest(0f0a1cf70e) has. These are the installs the z88dk fixtures were made with (test/fixtures/z88dk/*/PROVENANCEfiles).- Boriel ZX Basic and NextBuild are read on GitHub:
boriel-basic/zxbasicat29f0b2f0ceandem00k/NextBuildat364b2d13c5, both on 2026-11-01. The URLs are indoc/REFERENCES.md.