# Ghidra's pseudocode of a Watcom function leaves out arguments and stores that the disassembly shows

## Symptoms

A function's pseudocode shows fewer arguments than its callers pass, or reads registers that
were never set. A value the port computes from the pseudocode is wrong, and nothing in the
pseudocode explains why. A string that the program obviously uses has no user in `decomp.c`.

In Hardwar the pseudocode of `crater_lights_place` (`0x44b9c8`) showed each light's colour and
radius being passed on, so the port drew the lights at their stored height of 0, below the
crater floors. The disassembly showed that the function copies the stored position to a vector
on the stack, writes the radius shifted right by 3 over its height, and passes that vector in a
register to the next call (*observed*).

## Cause

Watcom C passes the first four arguments in EAX, EDX, EBX and ECX (`__watcall`). Ghidra's
default convention for a 32-bit Windows program passes them on the stack. With the wrong
convention the decompiler does not see the register arguments, so it drops them and treats the
stores that fill them as dead. A pointer to a string loaded into EAX before a call is lost the
same way (*observed* in Hardwar and in POD).

## What to do

For any Watcom function the port depends on, read the disassembly and check every register set
before each call. The pseudocode is a guide to the shape of the function only.

```bash
./gameframe run ghidra-run GAME.EXE disasm analysis/notes/lights.asm 0x44b9c8        # the whole function
./gameframe run ghidra-run GAME.EXE disasm analysis/notes/span.asm 0x44b9c8-0x44ba40 # a range, in order
./gameframe run refs GAME.EXE 0x535f43 --functions analysis/export/GAME.EXE/functions.tsv   # users of a string
./gameframe run ghidra-run GAME.EXE callargs analysis/notes/srand.tsv regs=watcom srand  # every call's EAX, EDX, EBX, ECX
```

`callargs regs=watcom` reads, for every call to a function, the constant each register gets
before the call in the same block. It finds the seeds, ids and sizes a Watcom program passes
in registers, which the pseudocode leaves out.

Set the calling convention of the functions you trace to `__watcall` in Ghidra, or give them
custom storage, and decompile again (`docs/working/ghidra.md`). Record the real arguments in
the topic document. Keep the `.asm` files in `analysis/`: they reproduce the program's code.

## Tried

- Trusting the pseudocode's argument list: the crater lights hung at height 0 until the
  disassembly was read.
