SkoolKit is the bunch of data files, libraries and scripts that are used to generate the Skool Disassemblies (both the HTML versions and the ASM versions). You could think of SkoolKit as one (or more) of the following:
SkoolKit is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See the file 'COPYING' for the full text of the licence.
SkoolKit requires Python 2.x, version 2.5 or later. (SkoolKit has not been tested with Python 3.x; it almost certainly will not work.) If you're running Linux or *BSD, you probably already have Python installed. If you're running Windows, you can get Python here.
In addition to the stock Python distribution, SkoolKit also requires one of the following image-processing libraries:
Either one will do. gdmodule seems to be slower than PIL, but it creates
smaller image files. gdmodule is available in Debian, Ubuntu, openSUSE and
Mandriva as python-gd
; it is apparently not packaged for Fedora. It is also
available in FreeBSD and NetBSD as graphics/py-gd
, and in OpenBSD as
py-gd
. PIL is available in Debian, Ubuntu, openSUSE, Mandriva and Fedora as
python-imaging
. It is also available in FreeBSD and NetBSD as
graphics/py-imaging
, and in OpenBSD as py-Imaging
. Windows users will
probably want to use PIL, since it has downloads readily available.
SkoolKit will use gdmodule in preference to PIL if it is available.
Throughout this document, commands that must be entered in a terminal window ('Command Prompt' in Windows) are shown on a line beginning with a dollar sign ($), like this:
On Linux/*BSD, the commands may be entered exactly as they are shown (without
the dollar sign, of course). On Windows, the dot-slash (./
) prefix should be
omitted. (The dot-slash prefix may also be omitted on Linux/*BSD if you have
the current working directory in your PATH
, but that is not the norm.)
To generate the HTML version of the Skool Disassemblies, use the
skool2html.py
script. Open a terminal window, change to the directory
containing SkoolKit, and enter this command:
A few seconds later (or minutes, depending on the speed of your machine), the
HTML version of the Skool Disassemblies will be ready in the
skool-disassemblies
subdirectory (which will have been created if it didn't
already exist).
skool2html.py
supports many options; run it with no arguments to see a list:
So, to write only the disassembly files and memory maps for Skool Daze:
To generate ASM files for Skool Daze or Back to Skool, use the skool2asm.py
script. Open a terminal window, change to the directory containing SkoolKit,
and enter this command:
A few seconds later, an ASM file for Skool Daze will be ready: sd.asm
.
To create an ASM file for Back to Skool:
skool2asm.py
supports many options; run it with no arguments to see a list:
See ASM modes and directives for a description of the @ssub and @rsub substitution modes, and the @ofix, @bfix and @rfix bugfix modes.
The following subsections explain at a high level the two phases involved in
transforming a skool
file (and its related ref
files) into HTML or ASM
format: parsing and rendering. These subsections also introduce some terminology
that will be used in later sections.
In the first phase, the skool
file is parsed. Parsing a skool
file entails
reading each line of the file, and processing any relevant
skool directives and ASM directives that are
found along the way.
After a skool directive or ASM directive has been processed, it is discarded, so
that it cannot be 'seen' during the rendering phase. The purpose of the skool
directives and ASM directives is to transform the skool
file into something
suitable for rendering (in either HTML or ASM format) later on.
Whether a particular skool directive or ASM directive is processed depends on the mode in which the parsing is being done: HTML mode or ASM mode.
HTML mode is used when the target output format is HTML (as opposed to ASM). In HTML mode, all skool directives are processed, but most ASM directives are ignored (because they are irrelevant to the purpose of creating the HTML disassemblies). The only ASM directives that are processed in HTML mode are those that introduce two different versions of a section of code or data: one that applies for HTML output, and another that applies for ASM output.
ASM mode is used when the target output format is ASM (as opposed to HTML). In ASM mode, all skool directives and ASM directives are processed.
In the second phase, the skool
file (stripped of all its skool directives and
ASM directives during the parsing phase) is 'rendered' - as either HTML or ASM,
depending on the mode.
HTML mode is used to render the skool
file (and its related ref
files) as
a bunch of HTML files. During rendering, any skool macros found
along the way are 'expanded' to the required HTML markup.
ASM mode is used to render the skool
file as a single, assembler-ready ASM
file. During rendering, any skool macros found along the way are
'reduced' to some appropriate plain text.
SkoolKit contains several data files. The following subsections describe those files, their purpose, and their format.
sd.skool
contains all the assembly language instructions for the main
routines and data blocks in Skool Daze.
sd.ref
contains all the data required to generate the non-code parts of the
HTML version of the Skool Daze disassembly, including:
bts.skool
contains all the assembly language instructions for the main
routines and data blocks in Back to Skool.
bts.ref
contains all the data required to generate the non-code parts of the
HTML version of the Back to Skool disassembly, including:
skool.ref
contains data required to generate the non-code parts of the HTML
versions of the disassemblies that are either common to both games or not
game-specific, such as the glossary.
start.skool
contains the assembly language instructions for the startup
routines for both Skool Daze and Back to Skool. They are placed here because
they don't really fit in the main skool files (sd.skool
and bts.skool
).
load.skool
contains the assembly language instructions for the tape loader
routines for both Skool Daze and Back to Skool.
save.skool
contains the assembly language instructions for the tape saver
routines for both Skool Daze and Back to Skool.
changelog.ref
contains the changelog entries.
The skool
files (sd.skool
, bts.skool
and the others) must be in a
certain format to ensure that they are processed correctly by skool2html.py
and skool2asm.py
. The rules are as follows:
1. Entries (an 'entry' being a routine or data block) must be separated by blank lines, and an entry must not contain any blank lines.
2. Lines in an entry may start with one of ';*!bcgituwz
', where:
;
' begins a comment line*
' denotes an entry point in a routine!
' denotes an entry point in a routineb
' denotes the first instruction in a data blockc
' denotes the first instruction in a code block (routine)g
' denotes the first instruction in a game status buffer entryi
' denotes an ignored entryt
' denotes the first instruction in a data block that contains textu
' denotes the first instruction in an unused code or data blockw
' denotes the first instruction in a data block that contains (only) two-byte values (words)z
' denotes the first instruction in a data block that contains (only) zeroes
' begins a line that does not require any of the markers listed above
If a non-comment line starts with any other character (e.g. 'a
' in
load.skool
), it is to distinguish it from another non-comment line with the
same address.
The format of a non-comment line is:
where:
C
is one of the characters listed above ('*!bcgituwz
')#####
is an address (e.g. 24576)INSTRUCTION
is an instruction (e.g. 'LD A,(HL)
')comment
is a comment (which may be blank)The comment for a single instruction may span multiple lines thus:
A comment may also be associated with more than one instruction by the use of braces ('{' and '}') to indicate the start and end points, thus:
Lines that start with '*
' or '!
' will have their addresses shown in bold
in the HTML versions of the disassemblies, and will have labels generated for
them in the ASM versions. '!
' is used only in load.skool
to distinguish
one entry point from another with '*
' and the same address.
3. Tables (grids) have their own markup syntax. See #TABLE for details.
4. Entry headers are a sequence of comment lines broken into three sections:
The sections are separated by an empty comment line. For example:
The ref
files (sd.ref
, bts.ref
, skool.ref
and changelog.ref
) are
formatted into sections separated by section names inside square brackets, like
this:
The contents of each section follow no particular format. They may be parsed as free text, a list of key-value pairs, or something else depending on the context.
Sections in the ref
files may contain macros that will be expanded before
rendering. The ref file macros recognised by SkoolKit are described in the
following subsections.
The ::
macro is used to include the contents of another section in the
current section.
For example (in sd.ref
and bts.ref
):
This will copy the contents of the section named Bug-WaitingForEinstein
(defined in skool.ref
) into the current section.
The bts:
macro is expanded only in Back to Skool mode; in Skool Daze mode it
is replaced with an empty string. Conversely, the sd:
macro is expanded only
in Skool Daze mode; in Back to Skool mode it is replaced with an empty string.
For example (in skool.ref
):
In Skool Daze mode, this expands to:
But in Back to Skool mode, it expands to:
The f:
macro expands to a filename path computed from the names of variables
in the FileInfo
object (defined in skoolhtml.py
).
For example (in changelog.ref
):
Here, ${f:sd_dir/playarea_tiles
} expands to the path of the 'Play area
tiles' page in the Skool Daze disassembly, defined by the sd_dir
and
playarea_tiles
variables of the FileInfo
object.
The f:
macro can also be used to call methods of the FileInfo
object. For
example (in changelog.ref
):
Here, ${f:sd_dir/asm_path/asm_fname(64939)
} expands to the path of the file
containing the disassembly of the data block at 64939 in the Skool Daze
disassembly; that path is defined by the following elements:
sd_dir
(a variable in the FileInfo
object)asm_path
(a variable in the FileInfo
object)asm_fname(64939)
(the result of calling FileInfo.asm_fname()
with the argument '64939')
The v:
macro expands to the value of a game variable (defined in the
[Game]
section of sd.ref
or bts.ref
).
For example (in skool.ref
):
Here, ${v:SRBAddress
} expands to the value of the game variable SRBAddress
(defined as '32524' in the [Game]
section in sd.ref
, and as '32512' in the
[Game]
section in bts.ref
).
The skool
files (sd.skool
, bts.skool
and the others) contain some
directives that are processed during the parsing phase. These 'skool directives'
are described in the following subsections.
These directives are used to define a section of a skool
file that should be
parsed in Back to Skool mode but ignored in Skool Daze mode (!bts+begin
,
!bts+end
), or vice versa (!sd+begin
, !sd+end
).
For example (in load.skool
):
The result here is that in Skool Daze mode only these lines are processed:
whereas in Back to Skool mode only these lines are processed:
The !defb
directive defines bytes to be inserted into the memory snapshot
for the skool
file being parsed. This is used in sd.skool
to define the
bytes for the routines that occupy the space for the unused animatory states
104-126 and 232-254, so that those animatory states will not appear blank on the
'Animatory states' page.
For example:
The !defb
directive is required here because the parser (in
skoolparser.py
) will only convert the DEFB
, DEFW
, DEFM
and DEFS
assembler directives into a sequence of bytes; it does not convert assembly
language instructions into the equivalent byte values (it is not a Z80
assembler).
The !refs
directive is used to define empty entries that will not appear in
the memory map for the skool
file being parsed, but which JR
/JP
/CALL
instructions should be hyperlinked to (because they are defined in some other
skool
file).
For example (in start.skool
):
This defines an empty entry for the routine at 26880 in Skool Daze, so that any
JR
/JP
/CALL
instruction with 26880 as the operand can be hyperlinked to
the entry for that routine (which is defined in sd.skool
). Further down in
start.skool
we see:
which defines empty entries for the routines at 20709, 21746 and 21920 in Back to Skool.
The skool
files (sd.skool
, bts.skool
and the others) and the ref
files (sd.ref
, bts.ref
and skool.ref
) contain some macros that are
either 'expanded' to an appropriate piece of HTML markup (when rendering in HTML
mode), or 'reduced' to an appropriate piece of plain text (when rendering in ASM
mode). The skool macros recognised by SkoolKit are described in the following
subsections.
In HTML mode, the #AS
macro expands to a hyperlink (<a>
element) to an
image on the 'Animatory states' page.
state
is the animatory state numberlink text
is the link text to use (default is state
)
In ASM mode, the #AS
macro reduces to the link text.
For example (from sd.skool
):
In HTML mode, this instance of the #AS
macro expands to a hyperlink to
the image of animatory state 16 (EINSTEIN standing/walking, phase 1) on the
'Animatory states' page.
In ASM mode, this instance of the #AS
macro reduces to '16'.
In HTML mode, the #ASIMG
macro expands to an <img>
element for the image
of an animatory state.
num
is the animatory state number (0-255)scale
is the required scale of the image (default=2)mask
is 1 if the image should show the mask (by displaying the transparent background in green), or 0 if not (default=1)attribute
is the required attribute byte for the image (default=120)
The #ASIMG
macro is not supported in ASM mode.
If an image file matching the required properties doesn't already exist, it will be created.
For example (from bts.ref
):
In HTML mode, this instance of the #ASIMG
macro expands to an <img>
element for the image for animatory state 21 (BOY WANDER sitting on the floor)
at 4 times the original size.
In HTML mode, the #ASM
macro expands to a hyperlink (<a>
element) to the
disassembly page for a routine or data block. The routine or data block need
not exist in the current skool
file.
address
is the address of the routine or data block#anchor
is the named anchor to link to on the disassembly page(link text)
is the link text to use (default=address
)
In ASM mode, the #ASM
macro reduces to the link text.
For example (from the entry at 58144 in bts.skool
):
In HTML mode, this instance of the #ASM
macro expands to a hyperlink to the
disassembly page for the startup routine at 33204 for Back to Skool (which is
defined in start.skool
), with 'startup routine' as the link text.
In ASM mode, this instance of the #ASM
macro reduces to 'startup routine'.
See also #R.
In HTML mode, the #ASTILE
macro expands to an HTML <img>
element for the
image of an animatory state tile.
state
is the animatory state number (0-255)row
is the row number (0-3) of the tile in the 4x3 matrix of tiles that make up the animatory statecol
is the column number (0-2) of the tileattr
is the required attribute byte for the image (default=120)mask
is 1 if the image should show the mask (by displaying the transparent background in green), or 0 if not (default=1)scale
is the required scale of the image (default=4)
The #ASTILE
macro is not supported in ASM mode.
If an image file matching the required properties doesn't already exist, it will be created.
In HTML mode, the #BOX
macro expands to an <img>
element for the image of
a box graphic (such as the game logo or the score box, which are 64x24 pixels).
address
is the address of the attribute and graphic data for the boxscale
is the required scale of the image (default=2)attribute
is the required attribute byte for the image (default is to use the attribute bytes at address
)
The #BOX
macro is not supported in ASM mode.
If an image file matching the required properties doesn't already exist, it will be created.
For example (from sd.skool
):
In HTML mode, this instance of the #BOX
macro expands to an <img>
element
for the image of the Skool Daze score box.
In HTML mode, the #BUG
macro expands to a hyperlink (<a>
element) to the
'Bugs' page, or to a specific entry on that page.
#name
is the named anchor of a bug (if linking to a specific one)link text
is the link text to use (default is 'bug')
In ASM mode, the #BUG
macro reduces to the link text.
For example (from sd.skool
):
In HTML mode, this instance of the #BUG
macro expands to a hyperlink to the
entry for 'MR CREAK and the empty class' on the 'Bugs' page for Skool Daze.
In ASM mode, this instance of the #BUG
macro reduces to 'bug'.
In HTML mode, the #C
macro expands to the HTML entity reference for the
copyright symbol (©
).
In ASM mode, the #C
macro reduces to '(c)'.
For example (from sd.skool
):
In HTML mode, the #CBUF
macro expands to a hyperlink (<a>
element) to the
character buffer documentation page, or to a specific entry on that page.
#name
is the named anchor of a character buffer entry description (if linking to a specific one)link text
is the link text to use (default is name
if given, or 'buffer')
In ASM mode, the #CBUF
macro reduces to the link text.
For example (in sd.skool
):
In HTML mode, this instance of the #CBUF
macro expands to a hyperlink to the
character buffer documentation page with the link text 'character buffer
documentation'.
In ASM mode, this instance of the #CBUF
macro reduces to 'character buffer
documentation'.
In HTML mode, the #D
macro expands to the title of an entry (a routine or
data block) in the memory map.
address
is the address of the entry.
In ASM mode, the #D
macro reduces to the title of the entry.
For example (in sd.skool
):
In HTML mode, this instance of the #D
macro (in the last line) expands to
the title of the routine at 27126 in Skool Daze.
In ASM mode, this instance of the #D
macro reduces to the title of the
routine at 27126 in Skool Daze.
In HTML mode, the #EREFS
macro expands to a comma-separated sequence of
hyperlinks (<a>
elements) to the disassembly pages for the routines that
jump to or call a given address.
address
is the address to search for references to
The #EREFS
macro is not supported in ASM mode.
The #EREFS
macro is not used in any of the stock SkoolKit data files, but it
was used while the Skool Disassemblies were under development.
In HTML mode, the #FACT
macro expands to a hyperlink (<a>
element) to the
'Trivia' page, or to a specific entry on that page.
#name
is the named anchor of a trivia entry (if linking to a specific one)link text
is the link text to use (default is 'fact')
The #FACT
macro is not supported in ASM mode.
In HTML mode, the #FONT
macro expands to an <img>
element for the image
of the skool font (as used on the 'Other graphics' page).
The #FONT
macro is not supported in ASM mode.
The image of the skool font will be created if it doesn't already exist.
In HTML mode, the #GBUF
macro expands to a hyperlink (<a>
element) to the
'Game status buffer' page, or to a specific entry on that page.
address
is the address of the entry to link to (if any)link text
is the link text to use (default is address
if given, or 'game status buffer')
In ASM mode, the #GBUF
macro reduces to the link text.
For example (from bts.skool
):
In HTML mode, the #KEYTABLE
macro expands to a hyperlink (<a>
element) to
the 'Keypress table' page, or to a specific entry on that page.
#name
is the named anchor of the entry on the keypress table page to link to (if any)link text
is the link text to use (default is 'keypress table')
In ASM mode, the #KEYTABLE
macro reduces to 'keypress table documentation'.
For example (from sd.skool
):
In HTML mode, the #LESSON
macro expands to a hyperlink (<a>
element) to
the page for a lesson.
num
is the lesson number
In ASM mode, the #LESSON
macro reduces to the lesson number.
For example (from sd.skool
):
In HTML mode, this instance of the #LESSON
macro (in the last line) expands
to a hyperlink to the page for lesson 224.
In ASM mode, this instance of the #LESSON
macro reduces to '224'.
In HTML mode, the #LOAD
macro expands to a hyperlink (<a>
element) to the
disassembly page for one of the tape loading routines.
address
is the address of the tape loading routine (23831, 32768 or 32815)#name
is the named anchor of an item on the disassembly page to link to (if any)link text
is the link text to use (default is address
)
In ASM mode, the #LOAD
macro reduces to the link text.
For example (from save.skool
):
In HTML mode, this instance of the #LOAD
macro expands to a hyperlink to the
disassembly page for the tape loading routine at 32815 with link text 'load
routine'.
In ASM mode, this instance of the #LOAD
macro reduces to 'load routine'.
In HTML mode, the #MSG
macro expands to a hyperlink (<a>
element) to the
disassembly page for the data block containing a specific message.
or
num
is the message number (applicable only in Back to Skool)address
is the address of the messagelink text
is the link text to use (default is num
or address
)
In ASM mode, the #MSG
macro reduces to the link text.
For example (from bts.skool
):
In HTML mode, this instance of the #MSG
macro expands to a hyperlink to the
disassembly page for the data block containing message 21 (at 61267).
In ASM mode, this instance of the #MSG
macro reduces to '21'.
In HTML mode, the #MUTABLE
macro expands to an <img>
element for the
image of a mutable object in Back to Skool (i.e. a door, a window, a cup, or
the spot on the tree where the bike is chained).
address
is the address of the mutable object's UDG reference tablepadding
is the amount of padding (number of tiles) to use around the matrix of UDGs for the mutable object (default=0)
The #MUTABLE
macro is not supported in ASM mode.
If an image file matching the required properties doesn't already exist, it will be created.
For example (from bts.skool
):
In HTML mode, this instance of the #MUTABLE
macro expands to an <img>
element for the image of the top-floor window when shut (with no padding).
In HTML mode, the #NAME
macro expands to an anchor (<a>
) element with a
given name.
name
is the name of the anchor
In ASM mode, the #NAME
macro reduces to an empty string.
For example (from bts.skool
):
In HTML mode, this instance of the #NAME
macro expands to an anchor element
named 'staircaseMatrix'.
In ASM mode, this instance of the #NAME
macro reduces to an empty string.
In HTML mode, the #P
macro expands to two adjacent br
elements:
<br /><br />
.
In ASM mode, the #P
macro reduces to an empty string.
For example (from bts.skool
):
In HTML mode, this instance of the #P
macro, along with the others in the
entry for the routine at 24684 in Back to Skool, is used to separate the (long)
description into paragraphs.
In ASM mode, this instance of the #P
macro, along with the others, is
reduced to an empty string.
In HTML mode, the #PATILE
macro expands to an <img>
element for the image
of a play area tile.
x
is the x-coordinate of the tiley
is the y-coordinate of the tilescale
is the required scale of the image (default=4)
The #PATILE
macro is not supported in ASM mode.
If an image with the required properties doesn't already exist, it will be created.
In HTML mode, the #POKE
macro expands to a hyperlink (<a>
element) to the
'Pokes' page, or to a specific entry on that page.
#name
is the named anchor of a poke (if linking to a specific one)link text
is the link text to use (default is 'poke')
The #POKE
macro is not supported in ASM mode.
For example (from bts.ref
):
In HTML mode, this instance of the #POKE
macro expands to a hyperlink to the
entry for 'Ring the bell' on the 'Pokes' page for Back to Skool, with link text
'ring the bell'.
In HTML mode, the #POKES
macro is used to POKE values into the current
memory snapshot.
address
is the address to POKEbyte
is the value to POKE address
withlength
is the number of addresses to POKE (default=1)step
is the address increment to use after each POKE (if length
>1; default=1)
The #POKES
macro is not supported in ASM mode.
For example (in bts.ref
):
In HTML mode, this instance of the #POKES
macro does POKE 47254,255
,
which fixes the graphic glitch in the animatory state of EINSTEIN lying down.
The #ASIMG
macro (see #ASIMG) further down then expands to an img
element for the image of the fixed animatory state.
In HTML mode, the #POPS
macro removes the current memory snapshot and
replaces it with the one that was previously saved by a #PUSHS
macro.
The #POPS
macro is not supported in ASM mode.
In HTML mode, the #PT
macro expands to a hyperlink (<a>
element) to the
disassembly page containing a character's personal timetable.
num
is the number of the characterlink text
is the link text to use (default=num
)
The #PT
macro is not supported in ASM mode.
For example (from sd.ref
):
In HTML mode, this instance of the #PT
macro expands to a hyperlink to the
disassembly page containing the personal timetable for MR ROCKITT (whose
character number is 164), with the link text 'personal timetable'.
As a skool
file is being parsed, a memory snapshot is built up from all the
DEFB
, DEFW
, DEFM
and DEFS
instructions, and also any !defb
directives (see !defb). After the file has been parsed, the memory snapshot is
used to build images of the skool graphic elements (animatory states, score box
etc.) for the HTML disassemblies.
In HTML mode, the #PUSHS
macro saves the current snapshot, and replaces it
with an identical copy with a given name.
name
is the snapshot name
The #PUSHS
macro is not supported in ASM mode.
The new snapshot may then be modified by using the #POKES
macro. The
snapshot name is used to indicate that the current snapshot is a modified
version of the original (which has no name).
For example (in bts.ref
):
In HTML mode, this instance of the #PUSHS
macro creates a new snapshot
(copied from the original) named 'eh2'. This snapshot is then modified with a
#POKES
macro. Further on, the #ASIMG
macro (see #ASIMG) will
expand to an <img>
element for the image of animatory state 54 (scaled up by
a factor of 4) built from the current snapshot ('eh2').
In HTML mode, the #R
macro expands to a hyperlink (<a>
element) to the
disassembly page for a routine or data block, or to a line at a given address
within that page. The routine or data block being referred to must exist in the
skool
file.
address
is the address of a routine or data block (or an entry point thereof)#name
is the named anchor of an item on the disassembly pagelink text
is the link text to use (default is address
)
In ASM mode, the #R
macro reduces to the label for address
, or to
address
if no label is found.
For example (from sd.skool
):
In HTML mode, this instance of the #R
macro expands to a hyperlink to the
disassembly page for the routine at 25820 in Skool Daze.
In ASM mode, this instance of the #R
macro reduces to 'LSCROLL8' (the label
for the routine at 25820).
See also #ASM.
In HTML mode, the #REFS
macro expands to a comma-separated sequence of
hyperlinks (<a>
elements) to the disassembly pages for the routines that
jump to or call a given routine, or jump to or call any entry point within that
routine.
address
is the address of the routine to search for references to
The #REFS
macro is not supported in ASM mode.
The #REFS
macro is not used in any of the stock SkoolKit data files, but it
was used while the Skool Disassemblies were under development.
In HTML mode, the #REG
macro expands to a styled <span>
element
containing a register name.
reg
is the name of the register (e.g. 'A', 'BC')
In ASM mode, the #REG
macro reduces to the name of the register.
The register name must contain 1, 2 or 3 of the following characters:
For example (from sd.skool
):
In HTML mode, the #SAVE
macro expands to a hyperlink (<a>
element) to the
disassembly page for the tape saver routine.
#name
is the named anchor of an item on the disassembly pagelink text
is the link text to use (default='save routine')
In ASM mode, the #SAVE
macro reduces to the link text.
For example (from sd.skool
):
In HTML mode, this instance of the #SAVE
macro expands to a hyperlink to the
disassembly page for the tape saver routine with link text 'save routine'.
In ASM mode, this instance of the #SAVE
macro reduces to 'save routine'.
In HTML mode, the #SCR
macro expands to an <img>
element for the image
constructed from the display file and attribute bytes of the current memory
snapshot (in turn constructed from the contents of the skool
file).
The #SCR
macro is not supported in ASM mode.
The screenshot image will be created if it doesn't already exist.
For example (from save.skool
):
In HTML mode, the #SKOOL
macro expands to an <img>
element for an image
of the play area (or a portion of the play area).
x
and y
are the play area coordinates of the top-left tilew
and h
are the width and height of the portion of the play areascale
is the required scale of the image (default=2)showChars
is 1 if the game characters are to be displayed in the image, 0 if not (default=0)showX
is the size of the interval at which x-coordinates should be displayed at the top and bottom of the image, or 0 if none should be displayed (default=0)
The #SKOOL
macro is not supported in ASM mode.
If an image of the play area matching the requirements doesn't already exist, it will be created.
For example (from bts.ref
):
In HTML mode, the first instance of the #SKOOL
macro here expands to an
<img>
element for an image of the left half of the play area of Back to
Skool, with scale 1, no game characters displayed, and x-coordinates shown at
0, 8, 16, 24 and so on.
In HTML mode, the #SPACE
macro expands to one or more '
'
expressions.
num
is the number of spaces required
In ASM mode, the #SPACE
macro reduces to num
spaces.
For example (from sd.skool
):
In HTML mode, this instance of the #SPACE
macro expands to:
In ASM mode, this instance of the #SPACE
macro reduces to a string
containing 8 spaces.
In HTML mode, the #START
macro expands to a hyperlink (<a>
element) to
the disassembly page for the startup routine.
#name
is the named anchor of an item on the disassembly pagelink text
is the link text to use (default is the address of the startup routine)
The #START
macro is not supported in ASM mode.
For example (from load.skool
):
In HTML mode, this instance of the #START macro expands to a hyperlink to the disassembly page for the startup routine (24288 in Skool Daze, 33204 in Back to Skool), with the address of that routine as the link text.
The #TABLE
macro marks the beginning of a table; TABLE#
is used to mark
the end. Between these markers, the rows of the table are defined.
class
is the CSS class to use for the <table>
elementclass1
, class2
etc. are the CSS classes to use for columns 1, 2 etc.The rows in a table must start with '{ ' and end with ' }'. The cells in a row must be separated by ' | '.
For example (from the routine at 29052 in bts.skool
):
This table has two rows and two columns, and will have the CSS class 'data'.
By default, cells will be rendered as <td>
elements. To specify that a
<th>
element should be used instead, use the =h
indicator before the cell
contents:
It is also possible to specify colspan
and rowspan
attributes using the
=c
and =r
indicators:
Finally, the =t
indicator specifies that a cell should be transparent (i.e.
inherit its parent element's background colour).
If a cell requires more than one indicator, the indicators should be separated by commas:
In ASM mode, tables are rendered as plain text, using dashes (-
) and pipes
(|
) for the borders, and plus signs (+
) where a horizontal border meets
a vertical border.
ASM mode also supports the :w
indicator in the #TABLE
macro's arguments.
The :w
indicator marks a column as a candidate for having its width reduced
(by wrapping the text it contains) so that the table will be no more than 79
characters wide when rendered. For example:
See also #UDGTABLE.
In HTML mode, the #TAP
macro expands to a hyperlink (<a>
element) to the
disassembly page for a command list.
num
is the command list number
In ASM mode, the #TAP
macro reduces to the command list number.
For example (from sd.skool
):
In HTML mode, this instance of the #TAP
macro expands to a hyperlink to the
disassembly page for command list 206 in Skool Daze.
In ASM mode, this instance of the #TAP
macro reduces to '206'.
In HTML mode, the #TAPS
macro expands to a comma-separated list of
hyperlinks (<a>
elements) to the disassembly pages for the command lists
that contain a given routine address.
address
is the routine address
The #TAPS
macro is not supported in ASM mode.
The #TAPS
macro is not used in any of the stock SkoolKit data files, but it
was used while the Skool Disassemblies were under development.
In ASM mode, the #TIME
macro expands to the following string:
(with the timestamp replaced by the current time).
The #TIME
macro is not supported in HTML mode.
In HTML mode, the #UDG
macro expands to an <img>
element for the image of
a UDG (an 8x8 block of pixels).
address
is the base address of the UDG bytesattribute
is the attribute byte to usescale
is the required scale of the image (default=4)step
is the interval between successive bytes of the UDG (default=1)increment
will be added to each UDG byte before constructing the image (default=0)
The #UDG
macro is not supported in ASM mode.
If an image of the UDG matching the required properties doesn't already exist, it will be created.
For example (from bts.skool
):
In HTML mode, this instance of the #UDG
macro expands to an <img>
element
for the image of the safe key UDG, with attribute byte 6 (INK 6: PAPER 0).
The #UDGTABLE
macro is used to mark the beginning of a table that will
contain images. It is used instead of the #TABLE
macro to indicate up-front
that the table should not be rendered in ASM mode.
See #TABLE.
The two main skool
files (sd.skool
and bts.skool
) contain directives
that are processed when parsing in ASM mode. Exactly how a directive is
processed (and whether it is executed) depends on the 'substitution mode' and
'bugfix mode' in which the skool
file is being parsed.
There are three substitution modes: @isub
, @ssub
, and @rsub
. These
modes are described in the following subsections.
In @isub
mode, @isub
directives are executed, but @ssub
, and @rsub
directives are not. The main purpose of @isub
mode is to make the minimum
number of instruction substitutions necessary to produce an ASM file that
assembles.
For example (from sd.skool
):
This @isub
directive ensures that 'LD A,(m)' is replaced by the valid
instruction 'LD A,(32512)'.
@isub
mode is invoked by default when running skool2asm.py
.
In @ssub
mode, @isub
and @ssub
directives are executed, but @rsub
directives are not. The main purpose of @ssub
mode is to replace LSBs, MSBs
and full addresses in the operands of instructions with labels, to make the
code amenable to some degree of relocation, but without actually removing or
inserting any code.
For example (from sd.skool
):
This @ssub
directive replaces 'LD (27016),A' with 'LD (27015+1),A'; the
'27015' will be replaced by the label for that address before rendering. (27016
cannot be replaced by a label, since it is not the address of an instruction.)
@ssub
mode is invoked by passing the '-s
' option to skool2asm.py
.
In @rsub
mode, @isub
, @ssub
and @rsub
directives are executed. The
main purpose of @rsub
mode is to make code unconditionally relocatable, even
if that requires the removal of existing code or the insertion of new code.
For example (from sd.skool
):
This @rsub
block directive inserts two instructions that ensure that the
address in bytes 99 and 100 of the character's buffer has the correct MSB as
well as the correct LSB, regardless of where the code originally at 25317
now lives.
@rsub
mode is invoked by passing the '-r
' option to skool2asm.py
.
@rsub
mode also implies @ofix
mode; see below for a description of
@ofix
mode and the other bugfix modes.
There are three bugfix modes: @ofix
, @bfix
and @rfix
. These
modes are described in the following subsections.
In @ofix
mode, @ofix
directives are executed, but @bfix
and @rfix
directives are not. The main purpose of @ofix
mode is to fix instructions
that have faulty operands.
For example (from sd.skool
):
These @ofix
block directives fix the faulty operand of the CALL instruction
at 27872.
@ofix
mode is invoked by passing the '-f1
' option to skool2asm.py
.
In @bfix
mode, @ofix
and @bfix
directives are executed, but @rfix
directives are not. The main purpose of @bfix
mode is to fix bugs by
replacing instructions, but without changing the start address of any routines,
routine entry points, or data blocks.
For example (from bts.skool
):
@bfix
mode is invoked by passing the '-f2
' option to skool2asm.py
.
In @rfix
mode, @ofix
, @bfix
and @rfix
directives are executed. The
purpose of @rfix
mode is to fix bugs that cannot be fixed without moving
code around (to make space for the fix).
For example (from sd.skool
):
These @rfix
block directives insert some instructions to fix the bug in
Skool Daze where ERIC can be hit by BOY WANDER's pellet even when he's sitting
on the floor or lying down.
@rfix
mode is invoked by passing the '-f3
' option to skool2asm.py
.
@rfix
mode implies @rsub
mode (see @rsub mode).
The ASM directives recognised by SkoolKit are described in the following subsections.
The @bfix
directive is used to make an instruction substitution in @bfix
mode.
INSTRUCTION
is the replacement instruction
For example (from sd.skool
):
The @bfix
block directives are used to define a block of lines that will be
inserted or removed in @bfix
mode.
The syntax for defining a block that will be inserted in @bfix
mode is:
The syntax for defining a block that will be removed in @bfix
mode is:
Typically, though, it is desirable to define a block that will be removed in
@bfix
mode right next to the block that should be inserted in its place. That
may be done thus:
which is equivalent to:
For example (from bts.skool
):
These @bfix
block directives fix the bug where ERIC cannot be pushed out of
his seat by changing the instruction at 26211 from 'SET 7,(HL)
' to
'LD (HL),128
'.
The @ignoremrcua
directive is used to suppress any warnings that would
otherwise be reported concerning addresses not converted to labels in the
mid-routine comment above the next instruction.
For example (from bts.skool
):
If the @ignoremrcua
directive were not present, warnings would be printed
(during the rendering phase) about the comment containing addresses (32522,
32600) that cannot be converted to labels.
The @ignoreua
directive is used to suppress any warnings that would otherwise
be reported concerning addresses not converted to labels in the comment for the
next instruction.
For example (from sd.skool
):
If the @ignoreua
directive were not present, a warning would be printed
(during the rendering phase) about the comment containing an address (62818)
that cannot be converted to a label.
The @isub
directive is used to make an instruction substitution in @isub
mode.
INSTRUCTION
is the replacement instruction
For example (in sd.skool
):
The @isub
block directives are used to define a block of lines that will be
inserted or removed in @isub
mode.
The syntax is equivalent to that for the
@bfix
block directives.
The @keep
directive is used to prevent the substitution of a label for the
operand in the next instruction (but only when the instruction has not been
replaced using an @isub
or @ssub
directive).
For example (in sd.skool
):
If the @keep
directive were not present, the operand (24576) of the 'LD BC'
instruction would be replaced with a label (because there is a routine at
24576); however, the operand is meant to be a pure data value, not a variable or
routine address.
The @label
directive sets the label for the next instruction.
LABEL
is the label to apply
For example (from sd.skool
):
This sets the label for the routine at 24576 to 'RSCROLL'.
See also @rlabel.
The @nolabel
directive is used to prevent the next instruction from having
a label automatically generated.
For example (from bts.skool
):
The @nolabel
directive here prevents the instruction at 31610 from being
labelled in @bfix
mode (because no label is required; instead, the previous
instruction at 31607 will be labelled).
The output from this section of bts.skool
in @bfix
mode will be:
And the output when not in @bfix
mode will be:
The @nowarn
directive is used to suppress any warnings that would otherwise
be reported for the next instruction concerning:
LD
operand being replaced with a routine label (if the instruction has not been replaced using @isub
or @ssub
)
For example (from sd.skool
):
If this @nowarn
directive were not present, a warning would be printed
(during the parsing phase) about the operand (25404) being replaced with a
routine label (which would be inappropriate if 25404 were intended to be a pure
data value).
For another example (also from sd.skool
):
If this @nowarn
directive were not present, a warning would be printed
(during the parsing phase, if not in @ofix
mode) about the operand (27633)
not being replaced with a label (usually you would want the operand of a CALL
instruction to be replaced with a label, but not in this case).
The @ofix
directive is used to make an instruction substitution in @ofix
mode.
INSTRUCTION
is the replacement instruction (with a corrected operand)
The stock skool
files distributed with SkoolKit do not make use of this
directive; instead they use the
@ofix
block directives.
Anyway, an example usage would be:
which would replace the operand of the 'JR NZ' instruction with 26067.
The @ofix
block directives are used to define a block of lines that will be
inserted or removed in @ofix
mode.
The syntax is equivalent to that for the
@bfix
block directives.
The @org
directive inserts an ORG
assembler directive.
ADDRESS
is the ORG
address
The @rem
directive is used to make an illuminating comment about a nearby
section or other ASM directive in a skool
file. The directive is ignored by
the parser.
COMMENT
is a suitably illuminating comment.
For example (from bts.skool
):
If this @rem
directive were not present, I might one day be tempted to
remove the @org
directive that follows, having forgotten why it's actually
extremely important.
The @rfix
block directives are used to define a block of lines that will be
inserted or removed in @rfix
mode.
The syntax is equivalent to that for the
@bfix
block directives.
The @rlabel
directive sets the label for the next instruction, but only when
parsing in @rsub
mode.
LABEL
is the label to apply
For example (from sd.skool
):
This sets the label for the instruction at 31892 to 'DINSTEP', so that the
operand of the 'JR Z,31892' instruction (which is included only in @rsub
mode) a few lines up can be converted to that label.
See also @label.
The @rsub
directive is used to make an instruction substitution in @rsub
mode.
INSTRUCTION
is the replacement instruction
For example (from sd.skool
):
The @rsub
block directives are used to define a block of lines that will be
inserted or removed in @rsub
mode.
The syntax is equivalent to that for the
@bfix
block directives.
The @ssub
directive is used to make an instruction substitution in @ssub
mode.
INSTRUCTION
is the replacement instruction
For example (from sd.skool
):
The @start
directive indicates where to start parsing the skool
file for
the purpose of generating ASM output. Everything before the @start
directive
is ignored.
SkoolKit includes a utility script called sna2skool.py
that can be used to
convert a 48K SNA or Z80 snapshot into a skool
file. To try it out, copy a
Z80 snapshot of Skool Daze (call it skool_daze.z80
) to the directory
containing SkoolKit, and then run the following command from that directory:
Now take a look at sd-blank.skool
. As you can see, by default,
sna2skool.py
disassembles everything from 16384 to 65535, treating it all as
code. Needless to say, this is not particularly useful - unless you have no
idea where the code and data blocks are yet, and want to use this disassembly
to find out.
Once you have figured out where the code and data blocks are, it would be handy
if you could supply sna2skool.py
with this information, so that it can
disassemble the blocks accordingly. That is where the control file comes in.
A control file contains a list of start addresses of code and data blocks. Each address is marked with a 'control directive', which is a single letter that indicates what the block contains:
b
' indicates a data blockc
' indicates a code blockg
' indicates a game status buffer entryi
' indicates a block that should be ignoredt
' indicates a block containing textu
' indicates an unused block of memoryw
' indicates a block containing words (two-byte values)z
' indicates an unused block containing all zeroes(If these letters remind you of the valid characters that may appear in the first column of each line of a skool file, that is no coincidence.)
For example:
This control file declares that:
So if we had a control file for Skool Daze, we could produce a much more
useful skool
file. As it happens, SkoolKit includes one: sd.ctl
. You can
use it with sna2skool.py
thus:
This time, sd-blank.skool
is split up into meaningful blocks, with code as
code, data as data (DEFBs), and text as text (DEFMs). Much nicer.
The next step is to create an HTML disassembly from this skool
file:
Now open html/sd-blank/index.html
in a web browser. There's not much there,
but it's a base from which you can start adding comments to sd-blank.skool
(remembering to use skool macros where appropriate to insert
hyperlinks and images) and create your own Skool Daze disassembly.
To replace the word 'sd-blank' in the page titles, we need to give the game a
name. This can be done by creating a ref
file called sd-blank.ref
that
contains the following lines:
Then run skool2html.py
again to re-generate the HTML.
To create a skeleton skool disassembly for Back to Skool too, use the supplied
bts.ctl
file with a snapshot of the game (call it back_to_skool.z80
):
Open html/bts-blank/index.html
to start browsing this newborn disassembly.
Of course, there is no reason to limit yourself to the Skool games. There are many other classic Spectrum games out there waiting to be disassembled.
If you'd rather create an assembler-ready ASM file from a snapshot,
sna2skool.py
can do that with the '-a
' option:
The following bugs in SkoolKit do not (currently) affect the HTML or ASM rendering, so there is no pressing need to fix them.
1. If the last entry in a skool
file has an end comment (i.e. a comment
after the last instruction), it is not picked up in the parsing phase, and so
will not be rendered.
2. If a table (defined between #TABLE
and TABLE#
markers) contains a cell
with rowspan > 1 and its contents are wrapped, adjacent cells with rowspan = 1
are rendered incorrectly in ASM mode.
3. In verbose ('-v
') mode, skool2asm.py
does not show lines inserted or
removed by the @isub
, @rsub
, @ofix
, @bfix
and @rfix
block
directives.
4. This documentation does not describe the sections in the ref
files.