QuakeC.Progs (QuakeC v0.2.2)

Copy Markdown View Source

A compiled QuakeC program, progs.dat, read: Quake's version 6, and FTE's version 7 with 16- or 32-bit statements.

  • statements — a tuple of {op, a, b, c}; jump distances are signed
  • functions — a tuple of %{first:, parm_start:, locals:, name:, parm_sizes:}; first below zero is builtin number -first, and 0 a builtin bound by its name
  • strings — the string table; a string value is an offset into it
  • texts — %{offset => string} for every string starting in the table
  • globals — the initial global values, a tuple of floats and integers by slot
  • global_defs, field_defs — %{name => {type, offset}}, type one of :void, :string, :float, :vector, :entity, :field, :function, :pointer, :integer
  • entity_fields — how many slots an entity's fields take
  • function_names — %{name => index}
  • digest — the SHA-256 of the file, naming the program (and its replacements, replace/2)
  • crc — the header's check value of the program's global and field layout: 5927 for Quake's, 54730 for QuakeWorld's

Summary

Functions

The index of function name as FTE's ED_FindFunction finds it: a name may follow a program number and : (0:name), the number read as C's atoi reads it; this program is number 0, so another number finds nothing.

The index of function name, or nil.

The program in data, the bytes of a progs.dat.

The program with each function of names run by the host in place of its QuakeC body: the function becomes a builtin bound by its name (first 0), so every call of it, from the program or from QuakeC.Exec, runs builtins.call(host, name, argc) with the arguments in the parameter slots. A name the program lacks is passed over. The program's digest names the replacements too, so its compiled code is its own.

The string at offset offset of the table.

Types

t()

@type t() :: %QuakeC.Progs{
  crc: term(),
  digest: term(),
  entity_fields: term(),
  field_defs: term(),
  function_names: term(),
  functions: term(),
  global_defs: term(),
  globals: term(),
  statements: term(),
  strings: term(),
  texts: term()
}

Functions

find_function(progs, name)

@spec find_function(t(), String.t()) :: non_neg_integer() | nil

The index of function name as FTE's ED_FindFunction finds it: a name may follow a program number and : (0:name), the number read as C's atoi reads it; this program is number 0, so another number finds nothing.

function(progs, name)

@spec function(t(), String.t()) :: non_neg_integer() | nil

The index of function name, or nil.

parse(data)

@spec parse(binary()) :: {:ok, t()} | {:error, :not_progs | :compressed}

The program in data, the bytes of a progs.dat.

replace(progs, names)

@spec replace(t(), [String.t()]) :: t()

The program with each function of names run by the host in place of its QuakeC body: the function becomes a builtin bound by its name (first 0), so every call of it, from the program or from QuakeC.Exec, runs builtins.call(host, name, argc) with the arguments in the parameter slots. A name the program lacks is passed over. The program's digest names the replacements too, so its compiled code is its own.

progs = QuakeC.Progs.replace(progs, ["Player::UseDown"])

string(progs, offset)

@spec string(t(), non_neg_integer()) :: String.t()

The string at offset offset of the table.