-
Notifications
You must be signed in to change notification settings - Fork 0
Creating Configurations
MDAL configurations describe the relation between the user input (in form of an MDAL module) and the data output (usually in form of assembly data). More specifically, MDAL configurations do three things:
- Specify the overall structure of an MDAL module for a given sound driver, and define the MDAL commands available to the user.
- Define the structure of the data output for the target sound driver.
- Describe how the user input is converted into data output.
- General Concepts
- Syntax
- Global Settings
- Command Configuration
- Blocktype Configuration
- Data Field Configuration
- Sequence Configuration
Users provide input in form of an MDAL module through the use of commands. Any statement in an MDAL module is considered a command. MDAL itself does not provide any commands, save for a very small set of standard commands. The set of commands that is available to the user is, for the most part, defined in the configuration file. The configuration file is thus the essential puzzle piece that is needed to have an MDAL compiler do anything meaningful.
A module consists of a number of different blocks, which closely mimic the structure of a tracker module. In essence, all blocks are user-defined sets of data. The first block in an MDAL module is always the header block, which specifies the configuration to be used, and may additionally set various global commands, as defined by the configuration. This is usually followed by a sequence block, which contains an order list of data block pointers, thereby setting the general structure of the song. Furthermore, a number of data blocks may be present. Any number of different data block types can be present in an MDAL module. Block types are derived from a set of standard types, including patterns, fx tables, and other generic blocks.
Data blocks consist of one or more rows, which you can think of as single-note measures in terms of classical sheet music notation. Any command can only be used once per row. As an intermediate compilation step, the data input from commands used in data blocks is internally converted into data fields. The relation between commands and fields is again specified in the configuration.
In order to create an MDAL configuration for your sound driver, you will need to take the following steps:
- Specify some global settings
- Define one or more commands
- Define one or more block types
- Specify the data fields to be used for every block type.
- Specify how the sequence is constructed from the pattern blocks.
MDAL configurations are written in XML, and follow XML syntax rules. Most importantly, this means:
- Elements must have a closing tag.
- Tags are case-sensitive.
- Attribute values must be quoted.
- Characters
&
and<
are forbidden in statements.
By default, MDAL configurations use the the .mdconf
file extension.
Unless type checking is required, MDAL treats all value statements as strings. Where integer values are required, they can either be supplied in decimal or hexadecimal form. Hexadecimal numbers are prefixed with $
. Boolean values are indicated with true|false
.
MDAL ignores whitespace between elements, and trims leading and trailing whitespace in statements.
Each MDAL configuration must be enclosed in the <mdalconfig>
root tag, which in turn must specify the version
attribute.
A minimal MDAL configuration example, containing only the mandatory tags and attributes.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--The standard XML prolog. Not strictly required,
but may cause problems with parsers if omitted.-->
<mdalconfig version="1">
<!--The root tag and MDAL version specification.-->
<sequence tracks="1" />
<!--The sequence configuration, specifying the number of tracks
to use in the sequence.-->
<commands>
<!--The command configuration block.-->
<command id="NOTE" size="word" />
<!--A command definition. This defines a command
named "NOTE", which produces two bytes (one word) of data
output.-->
</commands>
<blocktype id="Patterns" type="pattern">
<!--A blocktype configuration. This defines a blocktype
named "Patterns", which is of base type "pattern".-->
<field size="word">
<!--A data field configuration. The data output from
this field will be two bytes (1 word).-->
<set from="NOTE" />
<!--Specify that the field's output value will be
set from input to the NOTE command.-->
</field>
</blocktype>
</mdalconfig>
The mandatory root tag. All configuration elements must be enclosed in it.
Parent: none
Children: <global>
, <commands>
, <blocktype>
, <sequence>
attribute | required | Parameter Type | Description |
---|---|---|---|
version |
yes | unsigned int | Specify the MDAL version to use. Current version is 1. |
Optional definition of global parameters. May only occur once in the configuration.
Parent: <mdalconfig>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
target |
no | string | Specify the target platform of the sound driver. This setting has no effect on data output, but may be read by applications using MDAL. |
byte_directive |
no | string | Specify which assembly directive to use for byte definitions. Defaults to db . |
word_directive |
no | string | Specify which assembly directive to use for word definitions. Defaults to dw . |
hex_prefix |
no | string | Specify which prefix to use for hexadecimal numbers. Defaults to $ . |
Mandatory tag which encloses the command definitions. This tag has no attributes, and must occur exactly once in the configuration.
Parent: <mdalconfig>
Children: <command>
Defines an MDAL module command. At least one command must be defined.
Parent: <mdalconfig>
<commands>
Children: <auto>
, <allow_modifiers>
, <default_substitute>
, <force_int>
, <force_repeat>
, <force_string>
, <global_const>
, <range>
, <reference>
, <substitute>
, <use_last_set>
, <use_note_names>
attribute | required | Parameter Type | Description |
---|---|---|---|
id |
yes | string | Specify a unique command ID. Commonly MDAL uses UPPERCASE strings for command IDs. |
size |
yes | flag | Specify the data size of the commands. Available flags: bool , byte , word
|
default |
no | string | Specify the command's default value. Defaults to false for bool commands, and 0 for byte/word commands. |
Specify that users do not need to supply a value for this command. Instead, the parameter of the value
attribute is supplied whenever the command is used.
Parent: <mdalconfig>
<commands>
<command>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
value |
yes | string | Specify the parameter to be supplied when the command is used. |
Allow common arithmetic operators to be used to modify arguments to this command. This setting has no effect on data output, but may be read by applications using MDAL. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Specify that the command's default value will be supplied from another command, usually a global constant.
Parent: <mdalconfig>
<commands>
<command>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
from |
yes | command ID | Specify which command should supply the default value. |
Configure the command to only accept unsigned integer arguments. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Configure the command to be repeated on every row of data blocks using it, even if the user does not set it. The last used value will be substituted. If no value has previously been set by the user, the default value will be substituted. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Configure the command to reject integer and bool arguments. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Configure the command to be a global constant. Global constants can only be set outside of data blocks, and can be set only once per module. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Limit the range of integer arguments to the command. Note that the range check can be bypassed by supplying a string argument to the command. To enforce strict checking, you should additionally set <force_int>
.
Parent: <mdalconfig>
<commands>
<command>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
lower_limit |
yes | unsigned int | Specify the lower limit of the range. |
upper_limit |
yes | unsigned int | Specify the upper limit of the range. |
Specify that arguments to this command are to be interpreted as a reference to another data block by the MDAL parser.
Parent: <mdalconfig>
<commands>
<command>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
to |
yes | blocktype ID | The target blocktype ID. |
Specify a key argument that will be replaced by the given value. Multiple instances of this tag can be used.
Parent: <mdalconfig>
<commands>
<command>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
key |
yes | string | The argument value to be replaced. |
value |
yes | string | The value that will replace the key argument. |
Specify that the last used argument is repeated if the data output is requested from the command and the command is not currently set. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Specify that note names may be used as argument to this command. This setting has no effect on data output, but may be read by applications using MDAL. This tag has no attributes.
Parent: <mdalconfig>
<commands>
<command>
Children: none
Standard commands are provided by MDAL iself. They are always available to the user, and cannot be customized through configurations. The standard commands are:
-
CONFIG
- used to specify which configuration to use -
:
- The block delimiter. Used to declare the start of a new block, and followed by the block name (:SEQUENCE is used to declare the sequence block). -
.
- The "no-op" command. Used to specify a data block row that does not change any values from the preceding row.
Define a data block type. Data block types can be derived from the base types pattern
, table
, and generic
. An MDAL configuration must define at least one data block of type pattern
.
Parent: <mdalconfig>
Children: <init_defaults>
, <field>
attribute | required | Parameter Type | Description |
---|---|---|---|
id |
yes | string | Specify a unique ID for this block type. |
type |
no | flag | Specify the base type that this block type will be derived from. Available flags are pattern , table , and generic . Block types with base type pattern will generate a sequence. table and generic are considered synonymous by MDAL itself, but may be read by applications using MDAL. This setting defaults to generic if not specified. |
end |
no | string | The given value will be inserted into the data output at the end of a block instance. |
label_prefix |
no | string | The given value will be prefixed to block name labels in the data output. Defaults to "mdb_blocktype_id_" if not specified. |
max_length |
no | unsigned int | Limit the number of data rows in instances of this block type to the given value. |
Specify that commands used in this block type will be reset to their default values at the beginning of each block instance. This tag has no attributes.
Parent: <mdalconfig>
<blocktype>
Children: none
Define an output data field, and describe how it is composed from command data input. The order in which you define the fields of a given data block type determines the order in which the data will be output.
Parent: <mdalconfig>
<blocktype>
Children: <required_seq_begin>
, <required_blk_begin>
, <required>
, <set>
, <set_hi>
, <set_lo>
, <set_bits>
, <set_if>
attribute | required | Parameter Type | Description |
---|---|---|---|
size |
yes | flag | Specify the size of the data output. Available flags are byte and word . |
Specify that this field is required on the first row of the first pattern block in the sequence. Has no effect if the block type's base type is not pattern
. This tag has no attributes.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
Specify that this field is required on the first row of every block instance. This tag has no attributes.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
Specify at which condition the given data field will be required to be placed in the output data.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
if |
no | flag/requirement condition | Specify the requirement condition. If not specified or specified with an empty argument, the field will be considered to be always required. See the section on requirement conditions for further information. |
Derive the data output of the field from the given command input. This operation may only be used once per field.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
from |
yes | command ID | Specify the ID of the source command. |
Derive the high byte of the data output of the field from the given command input. Using this setting is only allowed if the field's size is word
. The input command must be of size byte
. This operation may only be used once per field.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
from |
yes | command ID | Specify the ID of the source command. |
Derive the low byte of the data output of the field from the given command input. The input command must be of size byte
. This operation may only be used once per field.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
from |
yes | command ID | Specify the ID of the source command. |
Configure the current field data to be logically ORed with a given value if the given boolean command is set and evaluates to true. Multiple instances of this operation may be used on a single field, in this case they are evaluated in the order in which they are specified.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
from |
yes | command ID | Specify the ID of the boolean source command. |
value |
yes | unsigned int | Specify the value to set/OR with. |
clear |
no | flag | Specify that a the field value or a part of it should be cleared before the OR operation is performed. Available flags are all (clears the entire field), hi (clears the high byte), and lo (clears the low byte). Note that clearing the high/low byte is skipped if the current field value is not an integer. |
Configure the current field data to be logically ORed with a given value if the given requirement condition evaluates to true. Multiple instances of this operation may be used on a single field, in this case they are evaluated in the order in which they are specified.
Parent: <mdalconfig>
<blocktype>
<field>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
if |
yes | requirement condition | Specify the condition at which the operation will be triggered. See the section on requirement conditions for further information. |
value |
yes | unsigned int | Specify the value to set/OR with. |
clear |
no | flag | Specify that a the field value or a part of it should be cleared before the OR operation is performed. Available flags are all (clears the entire field), hi (clears the high byte), and lo (clears the low byte). Note that clearing the high/low byte is skipped if the current field value is not an integer. |
Requirement conditions are used as arguments to the <required>
and [<set_if>
] data field child tags. They consist of one or more command IDs, connected by conjunction or disjunction. The entire expression may additionally be negated. The pipe character (|
) is used to express disjunction, the plus character (+
) is used to express conjunction (since &
is forbidden in XML), and the exclamation mark (!
) is used to express negation. When using negation, the remaining expression must be enclosed in brackets (()
) if it consist of more than one operand.
Condition expression evaluation in existing MDAL compilers is currently very simple. Conjunction and disjunction may not be mixed, and negation can only be applied globally to the whole expression.
Conditions apply to the actual internal state of the commands. Commands will be considered set if the user has set them on the module data row being currently evaluated, or if they have been auto-triggered through another requirement setting. The no-op standard command is always ignored.
Examples;
-
NOTE1
: True if command NOTE1 is currently set. -
!NOTE1
: True if command NOTE1 is currently not set. -
NOTE1+NOTE2
: True if commands NOTE1 and NOTE2 are currently set. -
NOTE1|NOTE2
: True if either command NOTE1 or NOTE2, or both are currently set. -
!(NOTE1+NOTE2)
: True if neither command NOTE1 nor NOTE2 are currently set. -
!(NOTE1|NOTE2)
: True if either command NOTE1 or NOTE2, or both are currently not set. -
!NOTE1+NOTE2
: Error: Expression too complex. -
NOTE1+NOTE2|NOTE3
: Error: Expression too complex.
In place of an actual requirement condition, a number of flags can be used. These are:
-
all
: Evaluates as true if all commands used in the data block type are currently set. -
any
: Evaluates as true if any of the commands used in the data block type is currently set. -
none
: Evaluates as true if no command is currently set.
Mandatory configuration of options for the sequence data output. Must occur exactly once in the configuration. Sequence configuration is currently under review, and may undergo major changes in the future.
Parent: <mdalconfig>
attribute | required | Parameter Type | Description |
---|---|---|---|
end |
no | string | Construct an end marker. The given string will be appended at the end of the sequence data. |
label |
no | string | Specify a label that will be inserted before the sequence in the output data. |
max_length |
no | unsigned int | Specify the maximum length of the sequence. |
Adds a track to the sequence. Each sequence must contain at least one track.
Parent: <mdalconfig>
<sequence>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
from |
yes | blocktype ID | Specify the source block type. |
Enable the generation of a loop point in the sequence.
Parent: <mdalconfig>
<sequence>
Children: none
attribute | required | Parameter Type | Description |
---|---|---|---|
type |
yes | flag | Specify how to handle the loop point. The flag label will cause a label to be inserted into the sequence data, before the point that the player should loop to. The flag pointer will do the same, but will also cause a pointer to be appended to the sequence, after the end marker. |
label |
yes | string | Specify the loop point label. |