mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
Convert bare .md path references in 29 files to proper [name](relative/path) markdown links for GitHub navigation.
5.4 KiB
5.4 KiB
FD/SFD Files — Function Definition Format and LVO Generation
Overview
FD files (Function Definition files) are the machine-readable specification of a library's public API. They define every function's name, LVO offset, and register argument mapping. FD files are the source of truth for generating pragma files, inline headers, and IDA LVO scripts.
File Location
NDK:fd/exec_lib.fd
NDK:fd/dos_lib.fd
NDK:fd/intuition_lib.fd
NDK:fd/graphics_lib.fd
NDK:sfd/exec_lib.sfd (SFD = extended format with C prototypes)
FD File Syntax
* "exec.library"
##base _SysBase
##bias 30
##public
Supervisor(userFunction)(A5)
ExitIntr()()
Schedule()()
Reschedule()()
Switch()()
Dispatch()()
Exception()()
InitCode(startClass,version)(D0,D1)
InitStruct(initTable,memory,size)(A1,A2,D0)
MakeLibrary(funcInit,structInit,libInit,dataSize,segList)(A0,A1,A2,D0,D1)
MakeFunctions(target,functionArray,funcDispBase)(A0,A1,A2)
FindResident(name)(A1)
InitResident(resident,segList)(A1,D1)
Alert(alertNum)(D7)
Debug(flags)(D0)
##bias 120
Forbid()()
Permit()()
##bias 132
Disable()()
Enable()()
...
Syntax Rules
| Element | Meaning |
|---|---|
* "name" |
Comment; library identity |
##base _Symbol |
Global base pointer symbol name |
##bias N |
Set current LVO offset to −N |
##public |
Following functions are public |
##private |
Following functions are private (reserved) |
FuncName(args)(regs) |
Function: name, C parameter names, register assignments |
##end |
End of file |
LVO auto-increment: After each function, the bias increases by 6 (one JMP instruction slot = 6 bytes).
SFD File Format (Extended)
SFD adds full C prototypes:
==id $Id: exec_lib.sfd,v 1.0 2003/01/01 00:00:00 Exp $
==base _SysBase
==basetype struct ExecBase *
==libname exec.library
==bias 30
==public
APTR Supervisor(ULONG (*userFunction)()) (A5)
==end
Parsing FD Files — Python Script
#!/usr/bin/env python3
"""parse_fd.py — Parse AmigaOS FD files into LVO tables.
Usage: python3 parse_fd.py exec_lib.fd [--json] [--ida]
"""
import re, sys, json, argparse
def parse_fd(path):
"""Parse an FD file and return list of (offset, name, args, regs)."""
funcs = []
bias = 30
public = True
with open(path) as f:
for line in f:
line = line.strip()
if not line or line.startswith('*'):
continue
if line.startswith('##base'):
continue
if line.startswith('##bias'):
bias = int(line.split()[1])
continue
if line == '##public':
public = True
continue
if line == '##private':
public = False
continue
if line == '##end':
break
# Parse: FuncName(args)(regs)
m = re.match(r'(\w+)\(([^)]*)\)\(([^)]*)\)', line)
if m and public:
name = m.group(1)
args = [a.strip() for a in m.group(2).split(',') if a.strip()]
regs = [r.strip() for r in m.group(3).split(',') if r.strip()]
funcs.append({
'name': name,
'lvo': -bias,
'bias': bias,
'args': args,
'regs': regs
})
bias += 6 # always advance, even for private
return funcs
def output_ida_script(funcs, base_name):
"""Generate IDA Python LVO dict."""
print(f"# Auto-generated from FD file")
print(f"LVO_{base_name} = {{")
for f in funcs:
print(f" {f['lvo']:+5d}: \"{f['name']}\",")
print("}")
def output_json(funcs):
print(json.dumps(funcs, indent=2))
def output_table(funcs):
print(f"{'LVO':>6} {'Bias':>5} {'Function':<30} {'Registers'}")
print(f"{'─'*6} {'─'*5} {'─'*30} {'─'*30}")
for f in funcs:
regs = ', '.join(f['regs']) if f['regs'] else '(none)'
print(f"{f['lvo']:>+6d} {f['bias']:>5d} {f['name']:<30} {regs}")
if __name__ == '__main__':
ap = argparse.ArgumentParser(description='Parse AmigaOS FD files')
ap.add_argument('fdfile', help='Path to .fd file')
ap.add_argument('--json', action='store_true', help='Output JSON')
ap.add_argument('--ida', action='store_true', help='Output IDA script')
args = ap.parse_args()
funcs = parse_fd(args.fdfile)
if args.json:
output_json(funcs)
elif args.ida:
output_ida_script(funcs, args.fdfile.split('/')[-1].replace('_lib.fd',''))
else:
output_table(funcs)
sys.stderr.write(f"Parsed {len(funcs)} public functions\n")
Where to Get NDK FD Files
| NDK | Source | FD path |
|---|---|---|
| NDK 3.9 | Aminet: dev/misc/NDK39.lha (free) |
NDK_3.9/Include/fd/ |
| NDK 3.2 | Hyperion (commercial, ~€30) | NDK3.2/Include_H/fd/ |
| NDK 3.1 | Commodore (archived) | NDK3.1/Include/fd/ |
Auto-Generating IDA LVO Labels
# Generate IDA script from all FD files:
for fd in NDK_3.9/Include/fd/*_lib.fd; do
python3 parse_fd.py "$fd" --ida >> all_lvos.py
done
Then in IDA: File → Script command → Run all_lvos.py
References
- NDK39:
fd/directory - api_call_identification.md — using LVOs in RE