SkoolKit components

SkoolKit relies on several components in order to function:

The objects that are used for these components can be specified in the [skoolkit] section of a file named skoolkit.ini either in the current working directory or in ~/.skoolkit. The default contents of the [skoolkit] section are as follows:

Assembler=skoolkit.z80.Assembler
ControlDirectiveComposer=skoolkit.skoolctl.ControlDirectiveComposer
ControlFileGenerator=skoolkit.snactl
Disassembler=skoolkit.disassembler.Disassembler
HtmlTemplateFormatter=skoolkit.skoolhtml.TemplateFormatter
InstructionUtility=skoolkit.skoolparser.InstructionUtility
OperandEvaluator=skoolkit.z80
OperandFormatter=skoolkit.disassembler.OperandFormatter
SnapshotReader=skoolkit.snapshot
SnapshotReferenceCalculator=skoolkit.snaskool
SnapshotReferenceOperations=DJ,JR,JP,CA,RS

Assembler

This object is responsible for converting assembly language instructions and DEFB/DEFM/DEFS/DEFW statements into byte values, or computing their size. It must supply the following API functions, in common with skoolkit.z80.Assembler:

class skoolkit.z80.Assembler
assemble(operation, address)

Convert an assembly language instruction or DEFB/DEFM/DEFS/DEFW statement into a sequence of byte values.

Parameters:
  • operation – The operation to convert (e.g. ‘XOR A’).
  • address – The instruction address.
Returns:

A sequence of byte values (empty if the instruction cannot be assembled).

get_size(operation, address)

Compute the size (in bytes) of an assembly language instruction or DEFB/DEFM/DEFS/DEFW statement.

Parameters:
  • operation – The operation (e.g. ‘XOR A’).
  • address – The instruction address.
Returns:

The instruction size, or 0 if the instruction cannot be assembled.

Control directive composer

This class is responsible for computing the type, length and sublengths of a DEFB/DEFM/DEFS/DEFW statement, or the operand bases of a regular instruction, for the purpose of composing a control directive. It must supply the following API methods, in common with skoolkit.skoolctl.ControlDirectiveComposer:

class skoolkit.skoolctl.ControlDirectiveComposer(preserve_base)

Initialise the control directive composer.

Parameters:preserve_base – Whether to preserve the base of decimal and hexadecimal values with explicit ‘d’ and ‘h’ base indicators.
compose(operation)

Compute the type, length and sublengths of a DEFB/DEFM/DEFS/DEFW statement, or the operand bases of a regular instruction.

Parameters:operation – The operation (e.g. ‘LD A,0’ or ‘DEFB 0’).
Returns:A 3-element tuple, (ctl, length, sublengths), where:
  • ctl is ‘B’ (DEFB), ‘C’ (regular instruction), ‘S’ (DEFS), ‘T’ (DEFM) or ‘W’ (DEFW)
  • length is the number of bytes in the DEFB/DEFM/DEFS/DEFW statement, or the operand base indicator for a regular instruction (e.g. ‘b’ for ‘LD A,%00000001’)
  • sublengths is a colon-separated sequence of sublengths (e.g. ‘1:c1’ for ‘DEFB 0,”a”’), or None for a regular instruction

If compose() encounters an error while parsing an operation and cannot recover, it should raise a SkoolParsingError:

class skoolkit.SkoolParsingError

Raised when an error occurs while parsing a skool file.

Control file generator

This object is reponsible for generating a dictionary of control directives from a snapshot. Each key in the dictionary is an address, and the associated value is the control directive (e.g. ‘b’ or ‘c’) for that address. The control file generator object must supply the following API function, in common with skoolkit.snactl:

skoolkit.snactl.generate_ctls(snapshot, start, end, code_map, config)

Generate control directives from a snapshot.

Parameters:
  • snapshot – The snapshot.
  • start – Start address. No control directives should be generated before this address.
  • end – End address. No control directives should be generated after this address.
  • code_map – Code map filename (may be None).
  • config

    Configuration object with the following attributes:

    • text_chars - string of characters eligible for being marked as text
    • text_min_length_code - minimum length of a string of characters eligible for being marked as text in a block identified as code
    • text_min_length_data - minimum length of a string of characters eligible for being marked as text in a block identified as data
    • words - collection of allowed words; if not empty, a string of characters should be marked as text only if it contains at least one of the words in this collection
Returns:

A dictionary of control directives.

Disassembler

This class is responsible for converting byte values into assembly language instructions and DEFB/DEFM/DEFS/DEFW statements. It must supply the following API methods, in common with skoolkit.disassembler.Disassembler:

class skoolkit.disassembler.Disassembler(snapshot, config)

Initialise the disassembler.

Parameters:
  • snapshot – The snapshot (list of 65536 byte values) to disassemble.
  • config

    Configuration object with the following attributes:

    • asm_hex - if True, produce a hexadecimal disassembly
    • asm_lower - if True, produce a lower case disassembly
    • defb_size - default maximum number of bytes in a DEFB statement
    • defm_size - default maximum number of characters in a DEFM statement
    • defw_size - default maximum number of words in a DEFW statement
defb_range(start, end, sublengths)

Produce a sequence of DEFB statements for an address range.

Parameters:
  • start – The start address.
  • end – The end address.
  • sublengths – Sequence of sublength identifiers.
Returns:

A list of tuples of the form (address, operation, bytes).

defm_range(start, end, sublengths)

Produce a sequence of DEFM statements for an address range.

Parameters:
  • start – The start address.
  • end – The end address.
  • sublengths – Sequence of sublength identifiers.
Returns:

A list of tuples of the form (address, operation, bytes).

defs_range(start, end, sublengths)

Produce a sequence of DEFS statements for an address range.

Parameters:
  • start – The start address.
  • end – The end address.
  • sublengths – Sequence of sublength identifiers.
Returns:

A list of tuples of the form (address, operation, bytes).

defw_range(start, end, sublengths)

Produce a sequence of DEFW statements for an address range.

Parameters:
  • start – The start address.
  • end – The end address.
  • sublengths – Sequence of sublength identifiers.
Returns:

A list of tuples of the form (address, operation, bytes).

disassemble(start, end, base)

Disassemble an address range.

Parameters:
  • start – The start address.
  • end – The end address.
  • base – Base indicator (‘b’, ‘c’, ‘d’, ‘h’, ‘m’ or ‘n’). For instructions with two numeric operands (e.g. ‘LD (IX+d),n’), the indicator may consist of two letters, one for each operand (e.g. ‘dh’).
Returns:

A list of tuples of the form (address, operation, bytes).

The 3-element tuples returned by these methods should have the form (address, operation, bytes), where:

  • address is the address of the instruction
  • operation is the operation (e.g. ‘XOR A’, ‘DEFB 1’)
  • bytes is a sequence of byte values for the instruction (e.g. (62, 0) for ‘LD A,0’)

The sublengths argument of the defb_range(), defm_range(), defs_range() and defw_range() methods is a sequence of 2-element tuples of the form (size, base), each of which specifies the desired size (in bytes) and number base for an item in the DEFB/DEFM/DEFS/DEFW statement. base may have one of the following values:

  • ‘b’ - binary
  • ‘c’ - character
  • ‘d’ - decimal
  • ‘h’ - hexadecimal
  • ‘m’ - negative
  • ‘n’ - default base

If the first element of sublengths has a size value of 0, then the method should produce a list of statements with default sizes (as determined by defb_size, defm_size and defw_size), using the specified base.

HTML template formatter

This class is responsible for formatting HTML templates. It must supply the following API methods, in common with skoolkit.skoolhtml.TemplateFormatter:

class skoolkit.skoolhtml.TemplateFormatter(templates)

Initialise the template formatter.

Parameters:templates – A dictionary of templates keyed by template name.
format_template(page_id, name, fields)

Format a template.

Parameters:
  • page_id – The ID of the current page.
  • name – The template name.
  • fields – A dictionary of replacement field values.
Returns:

The text of the formatted template.

Instruction utility

This object is responsible for performing various operations on the instructions in a skool file:

  • converting base and case
  • replacing addresses with labels in instruction operands; this is required for ASM output
  • generating a dictionary of references (for each instruction that refers to another instruction); this is required for hyperlinking instruction operands in HTML output
  • generating a dictionary of referrers (for each instruction that is referred to by other instructions); this is required by the special EREF and REF variables of the #FOREACH macro
  • deciding whether to set byte values; this affects the #PEEK macro and the image macros, and instruction byte values in HTML output

The object must supply the following API functions, in common with skoolkit.skoolparser.InstructionUtility:

class skoolkit.skoolparser.InstructionUtility
calculate_references(entries, remote_entries)

Generate a dictionary of references (for each instruction that refers to another instruction) and a dictionary of referrers (for each instruction that is referred to by other instructions) from the instructions in a skool file.

Parameters:
  • entries – A collection of memory map entries.
  • remote_entries – A collection of remote entries (as defined by @remote directives).
Returns:

A tuple containing the two dictionaries.

convert(entries, base, case)

Convert the base and case of every instruction in a skool file.

Parameters:
  • entries – A collection of memory map entries.
  • base – The base to convert to: 0 for no conversion, 10 for decimal, or 16 for hexadecimal.
  • case – The case to convert to: 0 for no conversion, 1 for lower case, or 2 for upper case.
set_byte_values(instruction, assemble)

Decide whether to set byte values in the memory snapshot and for an instruction.

If byte values are set in the memory snapshot, then they are available to the #PEEK macro and the image macros. If byte values are set for an instruction, then they are available for display in HTML output via the instruction[bytes] replacement field in the asm template.

Parameters:
  • instruction – The instruction.
  • assemble – The current value of the assemble property (as set by the @assemble directive).
Returns:

2 if both the snapshot and the instruction should have byte values defined, 1 if only the snapshot should, or 0 if neither should.

substitute_labels(entries, remote_entries, labels, warn)

Replace addresses with labels in the operands of every instruction in a skool file.

Parameters:
  • entries – A collection of memory map entries.
  • remote_entries – A collection of remote entries (as defined by @remote directives).
  • labels – A dictionary mapping addresses to labels.
  • warn

    A function that emits a warning. It takes four arguments:

    • fmt - a format string for the warning message; it may contain ‘{address}’ and ‘{operation}’ replacement fields.
    • instruction - the relevant instruction object.
    • subbed - whether to show the warning for an operation that has been replaced by a @*sub or @*fix directive (optional, defaults to False).
    • min_mode - the minimum ASM mode in which the warning should be displayed (optional, defaults to 0).

Memory map entries and remote entries have the following attributes:

  • ctl - the entry’s control directive (‘b’, ‘c’, ‘g’, ‘i’, ‘s’, ‘t’, ‘u’ or ‘w’ for a memory map entry; None for a remote entry)
  • instructions - a collection of instruction objects

Each instruction object has the following attributes:

  • address - the address of the instruction
  • keep - None if the instruction has no @keep directive; an empty collection if it has a bare @keep directive; or a collection of addresses if it has a @keep directive with one or more values
  • operation - the operation (e.g. ‘XOR A’), or an empty string if the instruction is in a remote entry

Each key in the references dictionary should be an instruction object, and the corresponding value should be a 3-element tuple:

(ref_instruction, address_s, use_label)
  • ref_instruction - the instruction referred to
  • address_s - the address string in the operand of the referring instruction (to be replaced by a hyperlink in HTML output)
  • use_label - whether to use a label as the link text for the hyperlink in HTML output; if no label for ref_instruction is defined, or use_label is False, the address string (address_s) will be used as the link text

Each key in the referrers dictionary should be an instruction object, and the corresponding value should be a collection of the entries that refer to that instruction.

Operand evaluator

This object is used by the assembler to evaluate instruction operands, and by the control directive composer to determine the length and sublengths of DEFB, DEFM and DEFS statements. It must supply the following API functions, in common with skoolkit.z80:

skoolkit.z80.eval_int(text)

Evaluate an integer operand.

Parameters:text – The operand.
Returns:The integer value.
Raises:ValueError if the operand is not a valid integer.
skoolkit.z80.eval_string(text)

Evaluate a string operand.

Parameters:text – The operand, including enclosing quotes.
Returns:A list of byte values.
Raises:ValueError if the operand is not a valid string.
skoolkit.z80.split_operands(text)

Split a comma-separated list of operands.

Parameters:text – The operands.
Returns:A list of individual operands.

Operand formatter

This class is used by the disassembler to format numeric instruction operands. It must supply the following API methods, in common with skoolkit.disassembler.OperandFormatter:

class skoolkit.disassembler.OperandFormatter(config)

Initialise the operand formatter.

Parameters:config

Configuration object with the following attributes:

  • asm_hex - if True, default base is hexadecimal
  • asm_lower - if True, format operands in lower case
format_byte(value, base)

Format a byte value.

Parameters:
  • value – The byte value.
  • base – The desired base (‘b’, ‘c’, ‘d’, ‘h’, ‘m’ or ‘n’).
Returns:

The formatted byte value.

format_word(value, base)

Format a word (2-byte) value.

Parameters:
  • value – The word value.
  • base – The desired base (‘b’, ‘c’, ‘d’, ‘h’, ‘m’ or ‘n’).
Returns:

The formatted word value.

is_char(value)

Return whether a byte value can be formatted as a character.

Parameters:value – The byte value.

Snapshot reader

This object is responsible for producing a 65536-element list of byte values from a snapshot file. It must supply the following API functions, in common with skoolkit.snapshot:

skoolkit.snapshot.can_read(fname)

Return whether this snapshot reader can read the file fname.

skoolkit.snapshot.get_snapshot(fname, page=None)

Read a snapshot file and produce a 65536-element list of byte values.

Parameters:
  • fname – The snapshot filename.
  • page – The page number to map to addresses 49152-65535 (C000-FFFF). This is relevant only when reading a 128K snapshot file.
Returns:

A 65536-element list of byte values.

If get_snapshot() encounters an error while reading a snapshot file, it should raise a SnapshotError:

class skoolkit.snapshot.SnapshotError

Raised when an error occurs while reading a snapshot file.

Snapshot reference calculator

This object is responsible for generating a dictionary of entry point addresses from a snapshot. Each key in the dictionary is an entry point address, and the associated value is a collection of entries that jump to or call that entry point. This dictionary is needed for listing entry point referrers in a skool file (when the ListRefs configuration parameter of sna2skool.py is 1 or 2).

The snapshot reference calculator must supply the following API function, in common with skoolkit.snaskool:

skoolkit.snaskool.calculate_references(entries, operations)

For each entry point in each routine, calculate a list of the entries containing instructions that jump to or call that entry point.

Parameters:
  • entries – A collection of memory map entries.
  • operations – A tuple of operation prefixes. Any instruction whose operation starts with one of these prefixes is regarded as a jump or call operation, and therefore identifies an entry point.
Returns:

A dictionary of entry point addresses.

The value of the operations argument is derived from the SnapshotReferenceOperations parameter in the [skoolkit] section of skoolkit.ini.

Each memory map entry has the following attributes:

  • ctl - the entry’s control directive (‘b’, ‘c’, ‘g’, ‘i’, ‘s’, ‘t’, ‘u’ or ‘w’)
  • instructions - a collection of instruction objects

Each instruction object has the following attributes:

  • address - the address of the instruction
  • bytes - the byte values of the instruction
  • label - the instruction’s label, as defined by a @label directive
  • operation - the operation (e.g. ‘XOR A’)

Component API

The following functions are provided to facilitate access to the components and other values declared in the [skoolkit] section of skoolkit.ini.

skoolkit.components.get_component(name, *args)

Return a component declared in the [skoolkit] section of skoolkit.ini.

Parameters:
  • name – The component name.
  • args – Arguments passed to the component’s constructor.
skoolkit.components.get_value(name)

Return a parameter value from the [skoolkit] section of skoolkit.ini.

Parameters:name – The parameter name.