Turbo Markup Language (TML)

January 10, 2026 · View on GitHub

logo

Turbo Markup Language (TML)

A markup and scripting language for RetroBBS

(preliminary)


Table of contents

  1. Introduction
  2. The basics
  3. The internal registers
  4. Command reference
    1. Common control codes
    2. Register operations
    3. System/connection variables
    4. Input
    5. Block instructions
    6. Other generic instructions
    7. Turbo56k related commands
    8. RetroBBS core functions
    9. Plugin functions
  5. Platform specific commands


Introduction

Before the introduction of TML RetroBBS relied in great part on hard-coding strings, control codes and special characters to match the target client platform (just the Commodore 64 at the time of this writing). This limited and complicated adding new target platforms.

The solution would come in the form of a language capable of describing platform specific encodings and control codes in plain text.

Taking inspiration in the markup style used to describe control codes on type-in programs published in 80s magazines, we have developed a new markup and scripting language based on HTML syntax.

In addition to help describe control codes and Turbo56K commands, TML also supports a limited 'register' set which when used with some basic statements for flow control allows for the creation of loops and conditional execution.

A subset of RetroBBS internal functions are also available, as well as every installed plugin.



The basics

TML syntax is based on HTML and is in fact parsed using a child class to Python's HTMLParser

Tags are the functions or statements in this language, a basic statement can output a single or multiple copies of the corresponding character or control code. Functions can have a more complex output, or alter the state of the BBS or client. Tags are always written in UPPERCASE

Example: clear screen and output a checkmark character
<CLR><CHECKMARK>

Most tags have optional parameters, this take the format parameter=value, if a parameter is not passed the default value will be used. Parameter names are always lowercase, with a few exceptions.

Example: Output 20 white Pi characters, wait 2 seconds, output a newline and 5 yellow Pound characters
<WHITE><PI n=20>
<PAUSE n=2>
<BR>
<YELLOW><POUND n=5>

Block tags include conditional execution and loop statements, and contrary to other tags, need a matching closing tag.

Example: Clear screen, then move the cursor and sound the client's BELL only if the client understand C64 PETSCII. Then output the character code 200.
<CLR>
<MODE m=PET64>
    <AT x=5 y=20>
    <BELL>
</MODE>
<CHR c=200>

Plain text in between tags is automatically encoded to the target client, newline and tab characters are stripped out before the script is interpreted.

Example: A red 'Hello' and a green ' World!' will be printed on the same line on the client's screen
<RED>HELLO
    <GREEN>
 WORLD!

Use HTML entities &lt; and &gt; to output < and > respectively, use the break tag <BR> to insert line breaks.

If you need to escape a control code in a string parameter, instead of using the normal Python forward slash (/) use HTML entity numbers, for example: /r must be represented by &#13;.

Use the &backsim; entity if you want to depict the 'back key'



The internal registers

To make possible the execution of loops, conditional and other data manipulation, a small set of 'registers' are available:

_R Return register:

Read only register, this register will contain the result from the last function call.
When used as a parameter, indicates to which register the result will be redirected/assigned to.

Example: assign 'hello' to _S, notice the reversed notation
<LET _R=_S x='hello'>

_C Connection register:

When written to, any character or string input will be sent to the client. Reading this register returns the current connection object.

_B Binary connection register:

Write only register, this register accepts binary values or strings to be sent to the client

_A Accumulator:

General purpose register, values stored into, or read from this register will not be typecast.

_S String accumulator:

String register, any value stored into this register will be typecast to a Python str.
If the typecasting fails _S will be ''.

_I Integer accumulator:

Integer register, any value stored into this register will be typecast to a Python int.
If the typecasting fails _I will be 0.

_BACK Read only 'back key' register:

This special register contains the decoded 'back key' character for the current connection. Use this register when testing a variable for the 'back key'.

Example: Wait for either Return/Enter or the back key, and act accordinly:
<INKEY k='&backsim;&#13;'>
<IF c='_A=="&#13;"'>
    RETURN!
</IF>
<IF c='_A==_BACK'>
    <BACK> BACK!
</IF>

Registers, parameter values and expressions:

The internal registers can be passed as parameters and can be used in any expression that's accepted by Python's eval() function.

Example: Output the string '_I = 2' to the client's screen.
<LET _R=_I x=2>
<LET _R=_S x='_I = '>
<OUT x='_S+str(_I)'>

Note the use of quotes in the parameter values, sometimes it will be needed to nest single and double quotes:

<RND e=10>
<OUT x='"Random number:"+str(_I)'>


Command reference:

Common control codes

These control code commands are common to every target platform, the connection encoder makes the corresponding conversion to the actual control codes.


<BELL> BELL

Send a BELL character, cause an aural or visual chime.


<CLR> Clear screen

Clears the text screen.


<HOME> Cursor home

Move the text cursor to the top left of the screen.


<CRSRL> Cursor left

<CRSRR> Cursor right

<CRSRU> Cursor up

<CRSRD> Cursor down

Move the text cursor in the corresponding direction.
Parameter:

n: number of repeats, default 1


<DEL> Delete

Print a delete/backspace character.
Parameter:

n: number of repeats, default 1


<SPC> Space

Print a space character.
Parameter:

n: number of repeats, default 1


<NUL> Null

Send a Null character, usually '0' (zero).
Parameter:

n: number of repeats, default 1


<INK>

Change the text color to the value passed as parameter. Actual color is platform dependent.

c: Index in the palette of the desired color. Default 0.


<SPINNER>

Send the spinner character, which 'animates' depicting a waiting state.
The actual character/animation sent is platform dependent.


<BACK>

Display the character used to go back a menu/screen. for Commodore platforms, _ for other platforms.



Register operations:

Basic instructions to assign or modify the internal registers.


<LET>

Assign a value to one of the internal registers.
Parameters:

_R: Destination register, default _I
x: value to assign, default _I


<INC>

Increment the _I register.


<DEC>

Decrement the _I register.


<RND>

Return a random integer within the selected limits in _I.
Parameters:

s: lower bound of the random number range, default 0 e: upper bound of the random number range, default 10


<OUT>

Convert the input parameter to a string (if necessary) and send it to the client in the correct encoding.
Parameter:

x: value to output, default _I


<LEN>

Assign the length of the input parameter to _I
Parameter:

x: String or register, default _S


System/Connection variables:


<USER>

Return the username of the current connection in _S



Input:


<INKEYS>

Wait for the user to press a key from the list passed as parameter. Return as byte in _A
Parameter:

k: a string containing the valid key presses in the native client encoding, default '/r'



Block instructions:

These instructions need a corresponding closing tag.

<IF>

Execute the code inside the block if the condition is fulfilled.
Parameter:

c: Condition to be fulfilled, default False


<MODE>

Only parse the code inside this block if the connection encoding matches the m parameter.
Parameter:

m: Encoding for this code block, default 'PET64'

<FORMAT>

All text inside the block is formatted to fit inside the client's screen width, wordwrapping where necessary.
All code and text inside the block is parsed and send to the client once the end of the block is reached, functions/statements that return Turbo56K commands are ignored, do not use <PAUSE> and functions that require user input like <INKEYS> inside the block.


<SWITCH>...<CASE>

Test the expression passed as parameter for <SWITCH> and execute the <CASE> block matching the result.
<SWITCH> parameter:

r: expression to test, default _A

<CASE> parameter:

c: value to match, default False

Example:

Wait for the user to press either the '1' or '2' keys and then spell out which one was pressed
<INKEYS k='12'>
<SWITCH r=_A[0]>
    <CASE c=49>
        ONE
    </CASE>
    <CASE c=50>
        TWO
    </CASE>
</SWITCH>

<WHILE>

Repeat the code inside the block as long as the condition is fulfilled.
Parameter:

c: Condition to be fulfilled, default False

Example:

Output 'LOOP!' five times
<LET x=0>
<WHILE c='_I<5'>
    LOOP!
    <INC>
</WHILE>


Other generic instructions:


<END>

Complete the execution, exit the script.

<PAUSE>

Pause the execution.
Parameter:

n: Seconds to pause (float), default 0




These tags implement Turbo56K commands, but some will still work on other modes, suchs as ANSI or VT52

<AT>

Move the client's text cursor to the requested position.
Parameters:

x: Screen column. Default 0
y: Screen row. Default 0


<CURSOR>

Enable or disable the client's text cursor.
Parameter:

enable: Set to True to enable the text cursor. Default True


<GRAPHIC>

Switch the client's screen to a graphic mode. And select the screen colors.
Parameters:

mode: Graphic mode, True for multicolor, False for hires. Default False. Unused on MSX1
page: Text page number, currently unused. Default 0
border: Screen border color. Default 0
background: Screen background color. Default 0


<LFILL>

Fill a screen row with the given character code.
Parameters:

row: Screen row to fill. Default 0
code: Character code to use. Default 0. For C64 this is a screen code, not PETSCII`. For MSX extended graphic characters use the position in the character ROM. ie: character 336 (0x150) should use code = 16 (0x10)


<RESET>

Reset the client's terminal screen to the default state.


<SCROLL>

Scroll the client's text screen in the required amount and direction.
Parameter:

rows: Amount of rows to scroll. Positive number will scroll up, negative will scroll down. Default 0


<SETOUTPUT>

Select the client's output device.
Parameter:

o: Boolean, True for screen, False for voice synthesizer. Default True


<SPLIT>

Split the client's screen in a top graphic mode section, and a bottom text mode section.
Parameters:

row: Screen row at witch the split occurs. Default 0
multi: Boolean, True for multicolor graphic mode. Default False
bgtop: Background color for the top section. Default 0
bgbottom: Background color for the bottom section. Default 0


<TEXT>

Switch the client's screen to text mode. And select the screen colors.
Parameters:

page: Text page number, currently unused. Default 0
border: Screen border color. Default 0
background: Screen background color. Default 0


<WINDOW>

Define text window on the client screen.
Parameters:

top: Top most row of the window. Default 0
bottom: Bottom most row of the window. Default 24

<SCNCLR>

Clear the graphic screen.


<PENCOLOR>

Set on of the graphic pens to the specified color index.
Parameters:

pen: Graphic pen to set color: Color index


<PLOT>

Plot a point on the graphic screen.
Parameters:

pen: Graphic pen to use x: X coordinate y: y coordinate


<LINE>

Draw a line on the graphic screen.
Parameters:

pen: Graphic pen to use x1: Starting X coordinate y1: Starting Y coordinate x2: End X coordinate y2: End Y coordinate


<BOX>

Draw a (filled) rectangle on the graphics screen.
Parameters:

pen: Graphic pen to use x1: First corner X coordinate y1: First corner Y coordinate x2: Second corner X coordinate y2: Second corner Y coordinate fill: True to draw a filled rectangle. False to draw only the perimeter


<CIRCLE>

Draw a circle or ellipse on the graphics screen.
Parameters:

pen: Graphic pen to use x: Center X coordinate y: Center y coordinate rx: X radius ry: Y radius


<FILL>

Flood fill
Parameters:

pen: Graphic pen to use x: X coordinate y: Y coordinate


<POLYGON>

Draw a regular polygon on the graphics screen.
Parameters:

pen: Graphic pen to use x: Center X coordinate y: Center Y coordinate r: Radius sides: Number of sides rot: Rotation in degrees


<STAR>

Draw a star on the graphics screen.
Parameters:

pen: Graphic pen to use x: Center X coordinate y: Center Y coordinate r1: External radius r2: Internal radius sides: Number of sides/points rot: Rotation in degrees


<VECTORTXT>

Draw a string onto the graphics screen using Hershey fonts.
Parameters:

pen: Graphic pen to use x: Starting X coordinate y: Starting Y coordinate font: Font face index size: Size in pixels text: The string to draw dir: Direction (0 = 0°, 1 = 90°, 2 = 180°, 3 = 270° clockwise)



RetroBBS core functions:


<UNREAD>

Returns in _A a two-element list with the number of unread public and private messages respectively.


<MTITLE>

Render a menu title frame at the top of the client's text window.
Parameters:

t: Title string. Default ''


<KPROMPT>

Render a key prompt in the [KEY] style.
Parameter:

t: Prompt string. Default 'RETURN'


<DIALOG>

Render the file dialog background
Parameters:

h: Height of the dialog box in screen rows. Default 4
t: Title string. Default ''


<CAT>

Return a Python list in _A with the files (and subdirectories) in the directory passed as argument.
Parameters:

path: Path to the directory to list. Default '.'
d: Boolean, list subdirectories. Default False
f: Boolean, add the full path to each filename/subdirectory. Default True


<SENDRAW>

Send a file to the client, no processing done.
Parameter:

file: Path to the file to be sent. Default ''


<SENDFILE>

Send a file to the client. The corresponding action or processing needed for the file type will be taken automatically.
Parameters:

file: Path to the file to be sent. Default ''
dialog: Boolean, set to True to display the file dialog prompting user action. Default False
save: Set to True if you want the (option for the) file to be saved to disk, as long as the file type and the client's terminal supports it. Default False


<SENDBITMAP>

Send a bitmap to the client. Conversion to native format will be performed if necessary.
Parameters:

file: Path to the file to be sent. Default ''


<PCMPLAY>

Start a PCM audio stream.
Parameters:

file: Path to the audio to be streamed. Default ''


<GRABFRAME>

Grab a frame from a video file/stream and display it as a graphic screen on the client's terminal.



Style colors:


Some of the style system preset colors are accessible with TML tags, these tags only affect the text ink color, but not inverse video or other text attributes.

<TXTCOLOR>

Default text color

<HLCOLOR>

Highlight text color

<RVSCOLOR>

Reverse video text color

<OKCOLOR>

Color for text indicating a successful action

<WRNCOLOR>

Color for text indicating warning

<BADCOLOR>

Color for text indicating an error or failure


Plugin functions:


All plugins installed are available as functions inside TML, the function names and parameters remain the same used in the configuration file.
Refer to the plugin section in the main readme for more information.

Example: Play SlayRadio's Shoutcast audio stream
<WEBAUDIO url='http://relay3.slayradio.org:8000/'>

Common Semigraphic characters

Some included encoders support the use of semigraphic characters in one way or another. For Commodore computers and MSX under Retroterm the full range of semigraphics con be unlocked by using reverse video. The standard MSX encoder only supports non-reversed semigraphics. For VidTex semigraphics is a distinct 'graphic' mode, and support depends on each terminal.

<xx-QUAD>

Display the specified quadrant(s) semigraphic, where xx can be any of the following:

Common for all clients supporting semigraphics

  • UL: Upper Left
  • UR: Upper Right
  • LL: Lower Left
  • LR: Lower Right
  • UL-LR: Upper Left and Lower Right
  • L-HALF: Left Half
  • B-HALF: Bottom Half

Common for MSX and VidTex

  • BLOCK: Filled block
  • R-HALF: Right Half
  • U-HALF: Upper Half

VidTex only

  • UR-LL: Upper Right and Lower Left
  • UL-UR-LL: Upper Left and Upper Right and Lower Left
  • UL-UR-LR: Upper Left and Upper Right and Lower Right
  • UL-LL-LR: Upper Left and Lower Left and Lower Right
  • LL-LR-UR: Lower Left and Lower Right and Upper Right

Platform specific commands and tags:

Commodore 64:

Color control codes

Changes the text color to the specified color

  • <BLACK>
  • <WHITE>
  • <RED>
  • <CYAN>
  • <PURPLE>
  • <GREEN>
  • <BLUE>
  • <YELLOW>
  • <ORANGE>
  • <BROWN>
  • <PINK>
  • <GREY1> or <DGREY>
  • <GREY2> or <GREY> or <MGREY>
  • <LTGREEN>
  • <LTBLUE>
  • <GREY3> or <LT_GREY>

<RVSON>

Engage reverse video mode. Mode is automatically disengaged when a carriage return character is parsed on the terminal side


<RVSOFF>

Disengage reverse video mode.


<CBMSHIFT-D>

Disable the manual change of character sets (CBM+SHIFT key combination)


<CBMSHIFT-E>

Enable the manual change of character sets (CBM+SHIFT key combination)


<UPPER>

Change the character set to Uppercase/Graphics


<LOWER>

Change the character set to Uppercase/Lowercase


<POUND>

Displays the pound "£" character.


<PI>

Displays the pi "π" character.


<HASH>

Displays a full checkerboard character


<LEFT-HASH>

Displays a left half checkerboard character


<BOTTOM-HASH>

Displays a bottom half checkerboard character


<HLINE>

Displays a full width centered horizontal line character


<VLINE>

Displays a full height centered vertical line character


<CROSS>

Displays a full size cross character


<CHECKMARK>

Displays a checkmark "" character


<UARROW>

Displays the PETSCII upper arrow "" character, equivalent to the ASCII caret "^".


<LARROW>

Displays the PETSCII left arrow "" character.


<CBM-U>

Displays the 3/8 upper block character.


<CBM-O>

Displays the 3/8 lower block "" character.


<CBM-B>

Displays the quadrant upper left and lower right character ""


<CBM-J>

Displays the 3/8 left block character.


<CBM-L>

Displays the 3/8 right block character.



Commodore Plus/4:

In addition to the Commodore 64 tags...

<FLASHON>

Engage character flash mode. Mode is automatically disengaged when a carriage return character is parsed on the terminal side


<FLASHOFF>

Disengage character flash mode.

Commodore 128:

In addition to Commodore 64 and Plus/4 tags...

Color control codes, 80 column mode

Changes the text color to the specified color

  • <BLACK>
  • <WHITE>
  • <RED>
  • <CYAN>
  • <PURPLE>
  • <GREEN>
  • <BLUE>
  • <YELLOW>
  • <DPURPLE> or <DARK_PURPLE>
  • <BROWN>
  • <PINK>
  • <DCYAN> or <DARK_CYAN>
  • <GREY2> or <GREY> or <MGREY>
  • <LTGREEN>
  • <LTBLUE>
  • <GREY3> or <LT_GREY>

<ULINEON>

Engage character underline mode.


<ULINEOFF>

Disengage character flash mode.



MSX:

Color control codes

Changes the text ink color to the specified color

  • <BLACK>
  • <WHITE>
  • <RED>
  • <CYAN>
  • <PURPLE>
  • <GREEN>
  • <BLUE>
  • <YELLOW>
  • <PINK>
  • <GREY>
  • <LTGREEN>
  • <LTBLUE>
  • <DRED>
  • <DGREEN>
  • <LTYELLOW>

<PAPER>

Changes the text paper color to the expecified color. Paper color applies only for text printed after this tag
Parameters:

c: Palette color number, default 1 (black)


<POUND>

Displays the pound "£" character.


<PI>

Displays the pi "π" character.

<TRI-LEFT> <TRI-RIGHT> <TRI-UP> <TRI-DOWN>

Displays a triangle occupying the corresponding character quadrant (and pointing to the opposite direction)



VidTex

Color control codes

Changes the text ink color to the specified color

  • <GREEN>
  • <YELLOW>
  • <BLUE>
  • <RED>
  • <WHITE>
  • <CYAN>
  • <PURPLE>
  • <ORANGE>
  • <BLACK>

<G4>

Semigraphic mode

<GN>

Normal text mode