Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/caljer1/9900dis/llms.txt

Use this file to discover all available pages before exploring further.

Two annotation types control how 9900dis interprets and outputs specific lines: data hints force a word to be treated as raw data instead of an instruction, and inline comments let you add human-readable notes that survive re-runs. Together they let you progressively document a ROM without losing your work on every pass.

Data hints

What is a data hint?

The f:data hint tells 9900dis to emit a DATA directive for that word instead of attempting to decode it as a TMS9900 instruction. This is essential for ROM headers, jump tables, interrupt vectors, and any constant data that happens to share a binary pattern with a valid opcode. Without the hint, the disassembler will decode the word as whatever instruction it most closely resembles — often producing nonsense output that throws off the decoding of the words that follow.

Adding a data hint

Add f:data after the w:>XXXX field in the comment on the target line:
      	SOCB    @>028a,r2        ; pc:>0000 w:>f0a0 f:data
The instruction shown (SOCB @>028a,r2) is what the first pass decoded — it doesn’t matter. On the next run, 9900dis reads back the f:data annotation and forces that address to emit a DATA directive regardless of the word’s bit pattern:
      	DATA    >f0a0            ; pc:>0000 w:>f0a0 f:data
The f:data annotation persists in the comment column on every subsequent run, so you only need to add it once.

Effect on subsequent words

When 9900dis decodes a word as a regular instruction, it may consume one or two additional parameter words from the ROM stream (for instructions with memory-direct or immediate operands). Marking the first word as DATA prevents this consumption — the parameter words are left in the stream and decoded independently on the next pass. This often uncovers real instructions that were previously hidden as operand bytes. A common pattern when annotating a ROM header: Before (header words misread as instructions):
      	SOCB    @>028a,r2        ; pc:>0000 w:>f0a0
      	BLWP    @>6030           ; pc:>0004 w:>0420
After (first word forced to DATA, remaining words decoded correctly):
      	DATA    >f0a0            ; pc:>0000 w:>f0a0 f:data
      	DATA    >83e0            ; pc:>0002 w:>83e0 f:data
      	BLWP    @>6030           ; pc:>0004 w:>0420

How data hints are parsed

In hints.py, deconstruct_notes splits the comment field on spaces and reads the 4th token (index 3):
def deconstruct_notes(self, value):
    parts = value.split(" ")
    pc = int(parts[1][4:], 16)   # "pc:>XXXX"
    w  = int(parts[2][3:], 16)   # "w:>XXXX"
    f  = parts[3] if len(parts) > 3 else None
    return (pc, w, f)
If f equals "f:data", the annotation is stored in self.annotations[pc]. During disassembly, handleFormatHint in rom.py checks this table before any instruction decoder runs:
def handleFormatHint(self, word, rom):
    form = self.hints.format_note(self.pc - 2)
    if form == "f:data":
        return self.handleData(word, rom)
    return False
Because handleFormatHint is the first handler in the dispatch list, f:data always takes priority over instruction decoding.
f:data is currently the only recognised format hint. Other f: values — such as f:code or f:byte — are not implemented and will have no effect. The annotation will be stored but will not alter the output.

Inline comments

Adding an inline comment

Place any user note after a second semicolon on the line. Everything from the second ; to the end of the line is treated as your comment:
      	BLWP    @RESET           ; pc:>0824 w:>0420   ; Go back to title screen
The text Go back to title screen is extracted, stored, and re-emitted on every subsequent run.

Comment preservation

Comments are keyed to the PC address extracted from the pc:>XXXX field, not to the line’s position in the file. In hints.py:
segments = line.split(';')
if len(segments) >= 3:
    self.comments[pc] = segments[2].strip()
As long as the instruction at that PC address is still decoded on the next run — which it will be, unless you remove a f:data hint that was causing the word to be treated differently — the comment reappears in the output unchanged.

Comments in the output format

The full output line format is defined in rom.py at line 421:
print("{:6}\t{:24} ; pc:{} w:{} {} {}".format(
    self.hints.label(pc),
    instruction,
    self.word_to_hex(pc),
    self.word_to_hex(word),
    self.hints.format_note(pc),
    self.hints.comment(pc)
), file=listing)
This produces the following column layout:
{label:6}\t{instruction:24} ; pc:{pc} w:{word} {fmt_hint} {comment}
ColumnWidthContent
Label6 chars, left-alignedSymbol name, or empty
TabField separator
Instruction24 chars, left-alignedMnemonic and operands
;Literal separator
pc:>XXXXProgram counter in hex
w:>XXXXRaw word value in hex
Format hintf:data if set, otherwise empty
User comment\t; {text} if set, otherwise empty
Note that the user comment is stored without its leading ; in self.comments, but is emitted with a tab and semicolon prefix by hints.comment():
def comment(self, pc):
    if pc is not None and pc in self.comments.keys():
        return f"\t; {self.comments[pc]}"
    return ""
This means the second semicolon you type when annotating becomes the separator that 9900dis uses to detect and re-emit your comment on subsequent runs.

Build docs developers (and LLMs) love