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.

Equates let you name fixed addresses or constants — typically memory-mapped hardware registers or well-known ROM entry points. 9900dis substitutes the equate name wherever that value appears as an operand in subsequent runs, making listings far more readable without you having to remember what >8800 refers to.

Defining an equate

Equates are free-standing lines in the listing with the following format:
VDPIO	EQU	>E000
The fields are tab-separated:
FieldExampleDescription
SymbolVDPIO1–6 word characters
KeywordEQUMust be uppercase
Value>E000> followed by exactly 4 hex digits
You can add equate lines anywhere in the listing file. On the next run, 9900dis moves them to the top of the output (immediately after the AORG directive) and preserves them on every subsequent run.

How equates are substituted

After re-running, any instruction operand whose resolved value matches the equate is replaced with the symbol name. Before:
      	MOVB    @>8800,r1        ; pc:>0010 w:>d801
      	MOVB    @>8C00,r2        ; pc:>0014 w:>d802
After (with equates defined):
      	MOVB    @VDPRD,r1        ; pc:>0010 w:>d801
      	MOVB    @VDPWD,r2        ; pc:>0014 w:>d802
Substitution happens inside hex_or_label() in rom.py. Equates are checked before labels, so an equate always wins if both are defined for the same value.

Equate format rules

The equate parser in hints.py uses the regex:
equpat = re.compile(r"(\w{1,6})\s+EQU\s+>(\w{4}).*")
This enforces the following rules:
  • Symbol: 1–6 word characters (\w{1,6}) — letters, digits, underscores only.
  • Keyword: EQU — must be uppercase; equ or Equ are not recognised.
  • Value: > followed by exactly 4 hex digits — >XXXX. Values shorter or longer than 4 hex digits will not match.
  • Standalone lines: equates must appear on their own lines. They cannot be placed on the same line as an instruction.

Where to place equates

You can insert equate lines anywhere in the listing file and 9900dis will find them. On each run, the disassembler rewrites the listing and emits all collected equates at the top, directly after the AORG directive:
for value, symbol in self.hints.all_equates():
    print(
        "{}\tEQU\t{}".format(symbol, self.word_to_hex(value)),
        file=listing
    )
This means the equates you add mid-file will be hoisted to the top automatically, keeping the listing tidy.

Common use cases

The TI-99/4A exposes its VDP, sound chip, and speech chip through fixed memory addresses. Equates make these instantly recognisable:
VDPRD	EQU	>8800
VDPWD	EQU	>8C00
SOUND	EQU	>8400
SPCHRD	EQU	>9000
SPCHWD	EQU	>9400
When a ROM entry point is called from many sites but you want it treated as a fixed constant (rather than tracking the label through the listing), define it as an equate:
KSCAN	EQU	>000E
VMBW	EQU	>0046
VMBR	EQU	>004A
These are system ROM workspace addresses and utility entry points that appear frequently in cartridge ROMs.
Numeric constants embedded in the ROM — screen dimensions, tile counts, timer values — can be named to make their purpose clear:
ROWS	EQU	>0018
COLS	EQU	>0020

Full example

Starting from a raw first-pass listing:
	AORG    >6000

      	MOVB    @>8800,r1        ; pc:>6000 w:>d801
      	MOV     @>8C00,r2        ; pc:>6004 w:>0282
      	MOVB    r3,@>8C00        ; pc:>6008 w:>d083
      	MOVB    @>8400,r0        ; pc:>600C w:>d800
Add equates anywhere in the file:
	AORG    >6000
VDPRD	EQU	>8800
VDPWD	EQU	>8C00
SOUND	EQU	>8400

      	MOVB    @>8800,r1        ; pc:>6000 w:>d801
      	MOV     @>8C00,r2        ; pc:>6004 w:>0282
      	MOVB    r3,@>8C00        ; pc:>6008 w:>d083
      	MOVB    @>8400,r0        ; pc:>600C w:>d800
After re-running 9900dis, the output becomes:
	AORG    >6000
VDPRD	EQU	>8800
VDPWD	EQU	>8C00
SOUND	EQU	>8400

      	MOVB    @VDPRD,r1        ; pc:>6000 w:>d801
      	MOV     @VDPWD,r2        ; pc:>6004 w:>0282
      	MOVB    r3,@VDPWD        ; pc:>6008 w:>d083
      	MOVB    @SOUND,r0        ; pc:>600C w:>d800
Every occurrence of >8800, >8C00, and >8400 — as source or destination operands — is replaced with the equate symbol.
Add equates before your first annotation pass so they take effect immediately on the first re-run. Hardware register names in particular will propagate throughout the listing and make subsequent annotation work much easier.

Build docs developers (and LLMs) love