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 skoolkit.ini.
[skoolkit]¶
Global configuration for SkoolKit 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 this section are as follows:
[skoolkit]
Assembler=skoolkit.z80.Assembler
ControlDirectiveComposer=skoolkit.skoolctl.ControlDirectiveComposer
ControlFileGenerator=skoolkit.snactl
DefaultDisassemblyStartAddress=16384
Disassembler=skoolkit.disassembler.Disassembler
HtmlTemplateFormatter=skoolkit.skoolhtml.TemplateFormatter
ImageWriter=skoolkit.image.ImageWriter
InstructionUtility=skoolkit.skoolparser.InstructionUtility
OperandEvaluator=skoolkit.z80
OperandFormatter=skoolkit.disassembler.OperandFormatter
SnapshotReader=skoolkit.snapshot
SnapshotReferenceCalculator=skoolkit.snaskool
SnapshotReferenceOperations=DJ,JR,JP,CA,RS
Most of the parameters in the [skoolkit]
section specify the objects to use
for SkoolKit’s pluggable components. The other recognised parameters are:
DefaultDisassemblyStartAddress
- the address at which to start disassembling a snapshot when no control file is provided; this is used by sna2ctl.py and sna2skool.py, and also by snapinfo.py when generating a call graphSnapshotReferenceOperations
- the instructions whose address operands are used by the snapshot reference calculator to identify entry points in routines and data blocks
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
imaker - callable that returns an instruction object
opcodes - comma-separated list of values specifying additional opcode sequences to disassemble
wrap - if True, disassemble an instruction that wraps around the 64K boundary
- 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 instruction objects created by imaker.
- 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 instruction objects created by imaker.
- 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 instruction objects created by imaker.
- 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 instruction objects created by imaker.
- 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 instruction objects created by imaker.
The imaker callable used by these methods must accept three positional arguments:
address
- the address of the instructionoperation
- the operation (e.g. ‘XOR A’, ‘DEFB 1’)data
- a sequence of byte values for the instruction (e.g. (62, 0) for ‘LD A,0’)
The opcodes list is defined by the Opcodes
configuration parameter of
sna2skool.py.
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.
Changed in version 9.3: Added the imaker and opcodes attributes to the disassembler configuration object. API methods must now return objects created by imaker.
Changed in version 8.5: Added the ability to disassemble an instruction that wraps around the 64K boundary, along with the wrap attribute on the disassembler configuration object to control this behaviour.
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.
Image writer¶
This class is responsible for constructing images and writing them to files. It must supply the following API methods, in common with skoolkit.image.ImageWriter:
- class skoolkit.image.ImageWriter(config=None, palette=None)
Initialise the image writer.
- Parameters:
config – A dictionary constructed from the contents of the [ImageWriter] section of the ref file.
palette – A dictionary constructed from the contents of the [Colours] section of the ref file. Each key is a colour name, and each value is a three-element tuple representing an RGB triplet.
If config or palette is None, empty, or missing values, default values are used.
- image_fname(fname)
Convert the fname parameter of an image macro into an image filename with an appropriate extension.
- Parameters:
fname – The fname parameter of the image macro.
- Returns:
The image filename.
- write_image(frames, img_file)
Write an image file. If this method leaves the image file empty, the file will be removed.
- Parameters:
frames – A list of
Frame
objects from which to build the image.img_file – The file object to write the image to.
- Returns:
The content with which the image macro is replaced; if None, an appropriate
<img .../>
element is used.
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 (or other addresses) in instruction operands; this is required both for ASM output and for binary 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
andREF
variables of the #FOREACH macrodeciding 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, mode, 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.
mode – The substitution mode: 1 (
@isub
), 2 (@ssub
), 3 (@rsub
), or 0 (none).warn –
A function to be called if a warning is generated when attempting to replace an address in an instruction operand with a label. The function must accept two arguments:
message - the warning message.
instruction - the instruction object.
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 as stated in the skool file; note that this will not be the same as the actual address of the instruction if it has been moved by the insertion, removal or replacement of other instructions by
@*sub
or@*fix
directiveskeep - 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
nowarn - None if the instruction has no @nowarn directive; an empty collection if it has a bare @nowarn directive; or a collection of addresses if it has a @nowarn directive with one or more values
operation - the operation (e.g. ‘XOR A’) after any
@*sub
or@*fix
directives have been applied; for an instruction in a remote entry, this is an empty stringrefs - the addresses of the instruction’s indirect referrers, as declared by a @refs directive
rrefs - the addresses of the instruction’s direct referrers to be removed, as declared by a @refs directive
sub - True if the operation was supplied by
@*sub
or@*fix
directive, False otherwise
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 toaddress_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 forref_instruction
is defined, oruse_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.
Changed in version 8.2: Added the refs and rrefs attributes to instruction objects.
Changed in version 8.1: Added the mode parameter to the substitute_labels()
method, and
changed the required signature of the warn function. Added the nowarn
and sub attributes to instruction objects.
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 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 list of byte values. For a 48K snapshot, or a 128K snapshot with a page number (0-7) specified, the list contains 65536 (64K) elements: a blank 16K ROM followed by 48K RAM. For a 128K snapshot with page equal to -1, the list contains 131072 (128K) elements: RAM banks 0-7 (16K each) in order.
- Parameters:
fname – The snapshot filename.
page – The page number (0-7) to map to addresses 49152-65535 (C000-FFFF), or -1 to return all RAM banks. This is relevant only when reading a 128K snapshot file.
- Returns:
A 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, call or otherwise refer to that entry point. This dictionary is needed by sna2skool.py for marking each entry point in a skool file with an asterisk, and listing its referrers.
The snapshot reference calculator must supply the following API function, in common with skoolkit.snaskool:
- skoolkit.snaskool.calculate_references(entries, operations)
For each instruction address in a memory map entry, calculate a list of the entries containing instructions that jump to, call or otherwise refer to that address.
- Parameters:
entries – A collection of memory map entries.
operations – A tuple of regular expression patterns. The address operand of any instruction whose operation matches one of these patterns identifies an entry point that will be marked with an asterisk in the skool file.
- 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. In its default form, this parameter is a comma-separated list
of regular expression patterns that designates ‘DJNZ’, ‘JR’, ‘JP’, ‘CALL’ and
‘RST’ operations as those whose address operands will be used to identify entry
points in the skool file:
SnapshotReferenceOperations=DJ,JR,JP,CA,RS
To use a pattern that contains a comma, an alternative (non-alphabetic) separator can be specified in the first character of the parameter value. For example:
SnapshotReferenceOperations=;DJ;JR;JP;CA;RS;LD A,\(\i\);LD \(\i\),A
This would additionally designate the ‘LD A,(nn)’ and ‘LD (nn),A’ operations
as identifying entry points. As a convenience for dealing with decimal and
hexadecimal numbers, wherever \i
appears in a pattern, it is replaced by a
pattern that matches a decimal number or a hexadecimal number preceded by
$
.
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’)
refs - the addresses of the instruction’s indirect referrers, as declared by a @refs directive
rrefs - the addresses of the instruction’s direct referrers to be removed, as declared by a @refs directive
Changed in version 8.5: The SnapshotReferenceOperations
parameter defines a list of regular
expression patterns.
Changed in version 8.2: Added the refs and rrefs attributes to instruction objects.
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.