.. _controlFiles: Control files ============= A control file contains a list of start addresses of code and data blocks. This information can be used by :ref:`sna2skool.py ` to organise a `skool` file into corresponding code and data blocks. Each block address in a control file is marked with a 'control directive', which is a single letter that indicates what the block contains: * ``b`` indicates a data block * ``c`` indicates a code block * ``g`` indicates a game status buffer entry * ``i`` indicates a block that will be ignored * ``s`` indicates a block containing bytes that are all the same value (typically unused zeroes) * ``t`` indicates a block containing text * ``u`` indicates an unused block of memory * ``w`` indicates a block containing words (two-byte values) (If these letters remind you of the valid characters that may appear in the first column of each line of a :ref:`skool file `, that is no coincidence.) For example:: c 24576 Do stuff b 24832 Important data t 25088 Interesting messages u 25344 Unused This control file declares that: * Everything before 24576 will be ignored * There is a routine at 24576-24831 titled 'Do stuff' * There is data at 24832-25087 * There is text at 25088-25343 * Everything from 25344 onwards is unused (but will still be disassembled as data) Addresses may be written as hexadecimal numbers, too; the equivalent example control file using hexadecimal notation would be:: c $6000 Do stuff b $6100 Important data t $6200 Interesting messages u $6300 Unused Besides the declaration of block types, addresses and titles, the control file syntax also supports the declaration of the following things: * Block descriptions * Register values * Mid-block comments * Block end comments * Sub-block types and comments * DEFB/DEFM/DEFW/DEFS statement lengths in data, text and unused sub-blocks * ASM directives (except block directives) The syntax for declaring these things is described in the following sections. Block descriptions ------------------ To provide a description for a code block at 24576 (for example), use the ``D`` directive thus:: c 24576 This is the title of the routine at 24576 D 24576 This is the description of the routine at 24576. If the description consists of two or more paragraphs, declare each one with a separate ``D`` directive:: D 24576 This is the first paragraph of the description of the routine at 24576. D 24576 This is the second paragraph of the description of the routine at 24576. Register values --------------- To declare the values of the registers upon entry to the routine at 24576, add one line per register with the ``R`` directive thus:: R 24576 A An important value in the accumulator R 24576 DE Display file address Mid-block comments ------------------ To declare a mid-block comment that will appear above the instruction at 24592, use the ``D`` directive thus:: D 24592 The next section of code does something really important. If the mid-block comment consists of two or more paragraphs, declare each one with a separate ``D`` directive:: D 24592 This is the first paragraph of the mid-block comment. D 24592 This is the second paragraph of the mid-block comment. Block end comments ------------------ To declare a comment that will appear at the end of the routine at 24576, use the ``E`` directive thus:: E 24576 And so the work of this routine is done. If the block end comment consists of two or more paragraphs, declare each one with a separate ``E`` directive:: E 24576 This is the first paragraph of the end comment for the routine at 24576. E 24576 This is the second paragraph of the end comment for the routine at 24576. Sub-block syntax ---------------- Sometimes a block marked as one type (code, data, text, or whatever) may contain instructions or statements of another type. For example, a word (``w``) block may contain the odd non-word here and there. To declare such sub-blocks whose type does not match that of the containing block, use the following syntax:: w 32768 A block containing mostly words B 32800,3 But here's a sub-block of 3 bytes at 32800 T 32809,8 And an 8-byte text string at 32809 C 32821,10 And 10 bytes of code at 32821 S 32831,17 Followed by 17 zeroes at 32831 The directives (``B``, ``T``, ``C`` and ``S``) used here to mark the sub-blocks are the upper case equivalents of the directives used to mark top-level blocks (``b``, ``t``, ``c`` and ``s``). The comments at the end of these sub-block declarations are taken as instruction-level comments and will appear as such in the resultant `skool` file. If an instruction-level comment spans a group of two or more sub-blocks of different types, it must be declared with an ``M`` directive:: M 40000,21 This comment covers the following 3 sub-blocks B 40000,3 W 40003,10 T 40013,8 If the length parameter is omitted from an ``M`` directive, the comment is assumed to cover all sub-blocks from the given start address to the end of the top-level block. Three bits of sub-block syntax left. First, the blank sub-block directive:: c 24576 A great routine 24580,11 A great section of code at 24580 This is equivalent to:: c 24576 A great routine C 24580,11 A great section of code at 24580 That is, the the type of a blank sub-block directive is taken to be the same as that of the parent block. Next, the address range:: c 24576 A great routine 24580-24590 A great section of code at 24580 This is equivalent to:: c 24576 A great routine 24580,11 A great section of code at 24580 That is, you can specify the extent of a sub-block using either an address range, or an address and a length. Finally, the implicit sub-block extent:: c 24576 A great routine 24580 A great section of code at 24580 24588,10 Another great section of code at 24590 This is equivalent to:: c 24576 A great routine 24580,8 A great section of code at 24580 24588,10 Another great section of code at 24588 But the declaration of the length (8) of the sub-block at 24580 is redundant, because the sub-block is implicitly terminated by the declaration of the sub-block at 24588 that follows. This is exactly how top-level block declarations work: each top-level block is implicitly terminated by the declaration of the next one. Sub-block lengths ----------------- Normally, a ``B`` sub-block declared thus:: B 24580,12 Interesting data would result in something like this in the corresponding skool file:: 24580 DEFB 1,2,3,4,5,6,7,8 ; {Interesting data 24588 DEFB 9,10,11,12 ; } But what if you wanted to split the data in this sub-block into groups of 3 bytes each? That can be achieved with:: B 24580,12,3 Interesting data which would give:: 24580 DEFB 1,2,3 ; {Interesting data 24583 DEFB 4,5,6 24586 DEFB 7,8,9 24589 DEFB 10,11,12 ; } That is, in a ``B`` directive, the desired DEFB statement lengths may be given as a comma-separated list of numbers following the sub-block length parameter, and the final number in the list is used for all remaining data in the block. So, for example:: B 24580,12,1,2,3 Interesting data would give:: 24580 DEFB 1 ; {Interesting data 24581 DEFB 2,3 24583 DEFB 4,5,6 24586 DEFB 7,8,9 24589 DEFB 10,11,12 ; } If the statement length list contains sequences of two or more identical lengths, as in:: B 24580,21,2,2,2,2,2,2,1,1,1,3 then it may be abbreviated thus:: B 24580,21,2*6,1*3,3 The same syntax can be used for ``S``, ``T``, ``W`` sub-blocks too. For example:: S 32768,100,25 Four 25-byte chunks of zeroes would give:: 32768 DEFS 25 ; {Four 25-byte chunks of zeroes 32793 DEFS 25 32818 DEFS 25 32843 DEFS 25 ; } DEFB and DEFM statements may contain both bytes and strings; for example:: 40000 DEFM "Hi ",5 40004 DEFB 4,"go" Such statements can be encoded in a control file thus:: T 40000,4,3:B1 B 40004,3,1:T2 That is, the length of a string in a DEFB statement is prefixed by ``T``, the length of a sequence of bytes in a DEFM statement is prefixed by ``B``, and the lengths of all strings and byte sequences are separated by colons. This notation can also be combined with the '*' notation; for example:: T 50000,8,2:B2*2 which is equivalent to:: T 50000,8,2:B2,2:B2 DEFS statements may specify a byte value other than zero; for example:: 60000 DEFS 20,170 60020 DEFS 40,85 These statements can be encoded in a control file thus:: S 60000,60,20:170,40:85 Number bases ------------ Numeric values in DEFB, DEFM, DEFS and DEFW statements are normally rendered in either decimal or hexadecimal, depending on the options passed to :ref:`sna2skool.py`. To force a numeric value to be rendered in a specific base, attach a ``b`` (binary), ``d`` (decimal) or ``h`` (hexadecimal) prefix to the statement length. For example:: B 40000,8,b1:d2:h1,d1,b1,h2 will result in something like this in the corresponding skool file:: 40000 DEFB %10101010,23,43,$5F 40004 DEFB 56 40005 DEFB %11110000 40006 DEFB $2B,$80 ASM directives -------------- To declare an ASM directive for a block or an individual instruction, use the following syntax:: ; @directive:address[=value] where: * ``directive`` is the directive name * ``address`` is the address of the block or instruction to which the directive applies * ``value`` is the value of the directive (if it requires one) For example, to declare a :ref:`label` directive for the instruction at 32768:: ; @label:32768=LOOP Note that neither ASM block directives (such as the :ref:`bfixBlockDirectives`) nor the exact location of :ref:`org`, :ref:`writer`, :ref:`start`, :ref:`end`, :ref:`ignoreua` and :ref:`set` ASM directives can be preserved using this syntax. Instruction-level comments -------------------------- One limitation of storing instruction-level comments as shown so far is that there is no way to distinguish between a blank comment that spans two or more instructions and no comment at all. For example, both:: 30000 DEFB 0 ; { 30001 DEFB 0 ; } and:: 30000 DEFB 0 ; 30001 DEFB 0 ; would be preserved thus:: B 30000,2,1 To solve this problem, a special syntax is used to preserve blank multi-instruction comments:: B 30000,2,1 . When restored, this comment is reduced to an empty string. But how then to preserve a multi-instruction comment consisting of a single dot (``.``), or a sequence of two or more dots? In that case, another dot is prefixed to the comment. So:: 30000 DEFB 0 ; {... 30001 DEFB 0 ; } is preserved thus:: B 30000,2,1 .... Note that this scheme does not apply to multi-instruction comments that contain at least one character other than a dot; such comments are preserved verbatim (that is, without a dot prefix). Control file comments --------------------- A comment may be added to a control file by starting a line with a hash character (``#``), a per cent sign (``%``), or a semicolon (so long as the next non-whitespace character is not ``@``, because ``; @`` is used to declare ASM directives). For example:: # This is a comment % This is another comment ; This is yet another comment Limitations ----------- A control file can be useful in the early stages of developing a `skool` file for reorganising code and data blocks, but it cannot preserve the following elements: * ASM block directives * the exact locations of `@org`, `@writer`, `@start`, `@end`, `@ignoreua` and `@set` ASM directives * data definition entries ('d' blocks) and remote entries ('r' blocks) * comments that are not part of a code or data block :ref:`skoolFileTemplates`, however, can preserve all of these elements, and so may be a better choice for `skool` files that contain any of them. Revision history ---------------- +---------+-------------------------------------------------------------------+ | Version | Changes | +=========+===================================================================+ | 1.0.7 | Added support for block titles, block descriptions, register | | | values, mid-block comments, block end comments, sub-block types | | | and instruction-level comments | +---------+-------------------------------------------------------------------+ | 2.0.6 | Added support for hexadecimal numbers | +---------+-------------------------------------------------------------------+ | 2.1 | Added support for DEFB statement lengths | +---------+-------------------------------------------------------------------+ | 2.1.1 | Added the ``M`` directive | +---------+-------------------------------------------------------------------+ | 2.1.2 | Added support for DEFM, DEFS and DEFW statement lengths | +---------+-------------------------------------------------------------------+ | 2.2 | Added support for the ``*`` notation in DEFB, DEFM, DEFS and DEFW | | | statement length lists | +---------+-------------------------------------------------------------------+ | 2.4 | Added support for non-block ASM directives | +---------+-------------------------------------------------------------------+ | 3.1.4 | Added support for DEFB and DEFM statements that contain both | | | strings and bytes | +---------+-------------------------------------------------------------------+ | 3.6 | Added support for preserving blank comments that span two or more | | | instructions | +---------+-------------------------------------------------------------------+ | 3.7 | Added support for binary numbers; added support for specifying | | | the base of numeric values in DEFB, DEFM, DEFS and DEFW | | | statements; added the ``s`` and ``S`` directives and support for | | | DEFS statements with non-zero byte values | +---------+-------------------------------------------------------------------+