Files
tsvm/doc/implementation.tex
2026-06-06 22:04:13 +09:00

1174 lines
59 KiB
TeX

\chapter{\thismachine}
\section{Specs}
\begin{outline}
\1 16 MB memory space with maximum 8 MB of core memory
\1 7 peripheral card slots, each can map 1 MB of memory to the memory space
\1 Standard graphics adapter on slot 1, with 256 simultaneous colours, 560\times448 pixels framebuffer and 80-column 32-row text buffer
\1 Built-in mouse input support
\1 4 serial ports to connect disk drives, modems and other computers
\end{outline}
There are three memories on the system: Hardware Memory (8 MB), Core Memory (up to 8 MB) and Program Memory (infinite!)
Your Javascript program is stored into the Program Memory, and since its capacity is limitless, you can put a large graphics directly into your Javascript source code, but the Program Memory is the slowest of all three memories. For faster graphics, you need to store them onto the Core Memory then DMA-Copy them to the graphics adapter.
\section{Javascript Extensions}
\index{js extensions}\thismachine\ provides the extra functions for your convenience.
\begin{outline}
\1\inlinesynopsis[Array]{head}[]{returns the first element of the array.}
\1\inlinesynopsis[Array]{last}[]{returns the last element of the array.}
\1\inlinesynopsis[Array]{tail}[]{returns the subarray that omits the \emph{head} element.}
\1\inlinesynopsis[Array]{init}[]{returns the subarray that omits the \emph{last} element.}
\1\inlinesynopsis[Array]{sum}[selector]{returns the sum of the elements of the array. Selector is optionally defined to indicate how the value must be transformed to obtain the sum.}
\1\inlinesynopsis[Array]{max}[selector]{returns the maximum among the elements of the array. Selector is optionally defined to indicate how the value must be transformed to obtain the max.}
\1\inlinesynopsis[String]{head}[]{returns the first character of the string.}
\1\inlinesynopsis[String]{last}[]{returns the last character of the string.}
\1\inlinesynopsis[String]{tail}[]{returns the substring that omits the \emph{head} character.}
\1\inlinesynopsis[String]{init}[]{returns the substring that omits the \emph{last} character.}
\1\inlinesynopsis[String]{trimNull}[]{trims null characters at the \emph{end} of the string.}
\end{outline}
\chapter{Libraries}
\thismachine\ runs your program on an embedded ECMAScript engine. The language is standard Javascript; what makes a \thismachine\ program a \thismachine\ program is the set of \emph{host namespaces} the engine exposes --- global objects, available without any import, through which the program talks to the hardware.
\section{Namespaces}
\index{namespaces}The following namespaces are always present, whether or not an operating system is loaded:
\begin{outline}
\1\inlinesynopsis{sys}{low-level system and memory access (\code{peek}, \code{poke}, \code{malloc}, timing, input).}
\1\inlinesynopsis{graphics}{the graphics adapter: pixels, palette, graphics modes, image decoding.}
\1\inlinesynopsis{audio}{the sound card: PCM playback and the tracker engine.}
\1\inlinesynopsis{com}{block (``serial'') communication with attached devices.}
\1\inlinesynopsis{dma}{bulk memory-to-memory and memory-to-device transfers.}
\1\inlinesynopsis{gzip}{compression and decompression (see the note on the name below).}
\1\inlinesynopsis{base64}{Base64 encoding and decoding.}
\1\inlinesynopsis{serial}{a debug text channel to the host; output appears on the host's console, not on the \thismachine\ screen.}
\1\inlinesynopsis{con}{screen text manipulation, built on top of the above.}
\end{outline}
The plain \code{print}, \code{println}, \code{printerr}, \code{printerrln} and \code{read} functions are also global.
A second set of namespaces --- \code{files}, \code{input}, \code{unicode}, \code{GL}, \code{require}, \code{exports} and the \code{\_G.shell} family --- is provided by \thedos\ and is only present once the operating system has booted. Those are documented in the \thedos\ part of this book.
\textbf{A note on \code{gzip}:} despite the name, the \code{gzip} namespace compresses and decompresses using the \emph{Zstandard} format. The decompressor recognises both Zstandard and the older gzip streams, so older files keep working. The name is historical.
\section{Standard Input and Output}
\index{stdio (library)}These are standard input/output functions:
\begin{outline}
\1\inlinesynopsis{print}[String]{prints a string without a new line.}
\1\inlinesynopsis{println}[String]{prints a string with a new line.}
\1\inlinesynopsis{printerr}[String]{prints a string to error output without a new line.}
\1\inlinesynopsis{printerrln}[String]{prints a string to error output with a new line.}
\1\inlinesynopsis{read}[]{reads a string from the keyboard. Hit the Return to finish reading.}
\end{outline}
\section{Console}
\index{console (library)}Console library contains the functions for screen text manipulation.
\namespaceis{Console}{con}
Properties:
\begin{outline}
\1\inlinesynopsis{KEY\_HOME}{A keycode for the Home key. 199}
\1\inlinesynopsis{KEY\_UP}{A keycode for the Up arrow key. 200}
\1\inlinesynopsis{KEY\_PAGE\_UP}{A keycode for the Page Up key. 201}
\1\inlinesynopsis{KEY\_LEFT}{A keycode for the Left arrow key. 203}
\1\inlinesynopsis{KEY\_RIGHT}{A keycode for the Right arrow key. 205}
\1\inlinesynopsis{KEY\_END}{A keycode for the End key. 207}
\1\inlinesynopsis{KEY\_DOWN}{A keycode for the Down arrow key. 208}
\1\inlinesynopsis{KEY\_PAGE\_DOWN}{A keycode for the Page Down key. 209}
\1\inlinesynopsis{KEY\_INSERT}{A keycode for the Insert key. 210}
\1\inlinesynopsis{KEY\_DELETE}{A keycode for the Delete key. 211}
\1\inlinesynopsis{KEY\_BACKSPACE}{A keycode for the Backspace key. 8}
\1\inlinesynopsis{KEY\_TAB}{A keycode for the Tab key. 9}
\1\inlinesynopsis{KEY\_RETURN}{A keycode for the Return key. 10}
\end{outline}
Functions:
\begin{outline}
\1\formalsynopsis{getch}{}{Returns a key code read from the keyboard.}
\1\formalsynopsis{poll\_keys}{}[IntArray(8) of Keycodes]{Poll the keyboard, then returns the captured keycodes. If less than 8 keys were held down at the moment of the polling, 0 will be substituted for the spot on the array.}
\1\formalsynopsis{move}{y: Int, x: Int}{Moves the text cursor to the given position. Note that the cursor position starts at 1.}
\1\formalsynopsis{addch}{char: Int}{Puts a character denoted by its code point to where the text cursor is. The cursor will not advance. NOTE: this function accesses the graphics device directly, which may not be desirable; use \code{prnch} when you really need to \code{print} the character.}
\1\formalsynopsis{mvaddch}{y: Int, x: Int, char: Int}{Combination of \code{move} and \code{addch}.}
\1\formalsynopsis{prnch}{char: Int}{Prints out a character denoted by its code point using the escape sequences. Unlike \code{addch} this function actually print out a character, which makes difference in certain situation.}
\1\formalsynopsis{getmaxyx}{}[IntArray(2)]{Returns the size of the terminal in row-column order.}
\1\formalsynopsis{getyx}{}[IntArray(2)]{Returns the current position of the text cursor in row-column order.}
\1\formalsynopsis{curs\_up}{}{Moves the text cursor up once.}
\1\formalsynopsis{curs\_down}{}{Moves the text cursor down once. Screen will scroll if the cursor moves out of the screen.}
\1\formalsynopsis{curs\_left}{}{Moves the text cursor left once.}
\1\formalsynopsis{curs\_right}{}{Moves the text cursor right once. Will wrap to the next line if the cursor moves out of the screen.}
\1\formalsynopsis{curs\_set}{mode: Int}{Hides or shows the text cursor. 0 to hide, nonzero to show.}
\1\formalsynopsis{hitterminate}{}[Boolean]{Polls the keyboard and returns true if the Ctrl-C combination were held down.}
\1\formalsynopsis{hiteof}{}[Boolean]{Polls the keyboard and returns true if the Ctrl-D combination were held down.}
\1\formalsynopsis{resetkeybuf}{}{Zero-fills the keyboard input buffer.}
\1\formalsynopsis{video\_reverse}{}{Swaps the foreground and background colour of the text.}
\1\formalsynopsis{color\_fore}{code: Int}{Defines the foreground colour of the text. 0 -- black, 1 -- red, 2 -- green, 3 -- yellow, 4 -- blue, 5 -- magenta, 6 -- cyan, 7 -- white, -1 -- transparent}
\1\formalsynopsis{color\_back}{code: Int}{Defines the background colour of the text.}
\1\formalsynopsis{color\_pair}{fore: Int, back: Int}{Defines the foreground and background colour of the text. Colour code for this function differs from the \code{color\_back} and \code{color\_fore}; please refer to the \ref{colourpalette}.}
\1\formalsynopsis{get\_color\_fore}{}[Int]{Returns the current text foreground colour (palette index).}
\1\formalsynopsis{get\_color\_back}{}[Int]{Returns the current text background colour (palette index).}
\1\formalsynopsis{clear}{}{Clears the text buffer. The framebuffer (if any) will not be affected.}
\1\formalsynopsis{reset\_graphics}{}{Resets foreground and background colour to defaults and makes the cursor visible if it was hidden.}
\end{outline}
\section{Gzip}
\index{gzip (library)}Gzip allows texts and bytes and compressed and decompressed using the gzip format.
\namespaceis{Gzip}{gzip}
\begin{outline}
\1\formalsynopsis{comp}{String}[Int8Array]{Compresses the given string.}
\1\formalsynopsis{comp}{Int8Array}[Int8Array]{Compresses the given bytes.}
\1\formalsynopsis{compTo}{str: String, outputptr: Int}[Int]{Compresses the given string onto the memory, then returns the size of the compressed bytes.}
\1\formalsynopsis{compTo}{bytes: Int8Array, outputptr: Int}[Int]{Compresses the given bytes onto the memory, then returns the size of the compressed bytes.}
\1\formalsynopsis{compFromTo}{inputptr: Int, length: Int, outputptr: Int}[Int]{Compresses the bytes onto the memory, then returns the size of the compressed bytes.}
\1\formalsynopsis{decomp}{String}[Int8Array]{Decompresses the given string (compressed bytes represented as series of characters)}
\1\formalsynopsis{decomp}{Int8Array}[Int8Array]{Decompresses the given bytes.}
\1\formalsynopsis{decompTo}{str: String, outputptr: Int}[Int]{Decompresses the given string onto the memory, then returns the size of the decompressed bytes.}
\1\formalsynopsis{decompTo}{bytes: Int8Array, outputptr: Int}[Int]{Decompresses the given bytes onto the memory, then returns the size of the decompressed bytes.}
\1\formalsynopsis{decompFromTo}{inputptr: Int, length: Int, outputptr: Int}[Int]{Decompresses the bytes onto the memory, then returns the size of the decompressed bytes.}
\end{outline}
\section{Base64}
\index{base64 (library)}Base64 allows encoding of the binary data into the ASCII-strings and vice-versa.
\namespaceis{Base64}{base64}
\begin{outline}
\1\formalsynopsis{atob}{String}[Int8Array]{Decodes the Base64 string to bytes.}
\1\formalsynopsis{atostr}{String}[String]{Decodes the Base64 string to string.}
\1\formalsynopsis{btoa}{Int8Array}[String]{Encodes bytes to Base64 string.}
\end{outline}
\section{Sys}
Sys library allows programmers to manipulate the system in low-level.
\namespaceis{Sys}{sys}
\begin{outline}
\1\formalsynopsis{poke}{address: Int, value: Int}{Puts a value into the memory of the specified address.}
\1\formalsynopsis{peek}{address: Int}[Int]{Reads a value from the memory of the specified address.}
\1\formalsynopsis{malloc}{size: Int}[Int]{Allocates a space of the given size on the Core memory and returns its pointer (starting address)}
\1\formalsynopsis{free}{pointer: Int}{Frees the memory space previously \code{malloc}'d}
\1\formalsynopsis{memcpy}{from: Int, to: Int, length: Int}{Copies the memory block of the given length. From and To are pointers.}
\1\formalsynopsis{mapRom}{romSlotNum: Int}{Maps the contents on the given ROM to the memory address {-\nobreak65537.\nobreak.-\nobreak131072}}
\1\formalsynopsis{romReadAll}{}[String]{Reads the mapped ROM and returns its contents as a string.}
\1\formalsynopsis{uptime}{}[Long]{Returns the uptime of the system in miliseconds.}
\1\formalsynopsis{currentTimeInMills}{}[Long]{Returns the current time in miliseconds since the epoch (exact time varies by the system)}
\1\formalsynopsis{nanoTime}{}[Long]{Returns the current time in nanoseconds since the epoch (exact time varies by the system)}
\1\formalsynopsis{print}{Anything}{Prints the given value onto the printstream.}
\1\formalsynopsis{println}{Anything}{Prints the given value plus a newline onto the printstream.}
\1\formalsynopsis{readKey}{}[Int]{Reads a key press and returns its keycode. The program execution will be paused until a key is pressed.}
\1\formalsynopsis{read}{}[String]{Reads a text the user has typed and returns is as a string. The reading will be terminated when the user hits the Return key.}
\1\formalsynopsis{readNoEcho}{}[String]{Identical to \code{read} but the text the user is typing will not be printed to the screen.}
\1\formalsynopsis{spin}{}[]{Do nothing for 4 miliseconds. Always use this function for busy-waiting as the virtual machine will hang without one.}
\1\formalsynopsis{waitForMemChg}{address: Int, andMask: Int, xorMask: Int}[]{Do nothing until a memory value is changed. More specifically, this function will \code{spin} while:$$ (\mathrm{peek}(addr)\ \mathrm{xor}\ xorMask)\ \mathrm{and}\ andMask = 0 $$}
\1\formalsynopsis{getSysRq}{}[Boolean]{Returns true if System Request key is down.}
\1\formalsynopsis{unsetSysRq}{}{After using the System Request key, call this function to `release' the key so that other programs can use it.}
\1\formalsynopsis{maxmem}{}[Int]{returns the size of the Core Memory in bytes.}
\1\formalsynopsis{getUsedMem}{}[Int]{Returns how many memories can be \code{malloc}'d.}
\1\formalsynopsis{getMallocStatus}{}[IntArray(2)]{Returns the \code{malloc} status in following order:$$ [\mathrm{Malloc\ unit\ size,\ allocated\ block\ counts}] $$}
\end{outline}
\section{DMA}
\index{dma (library)}The \thismachine\ can copy blocks of memory directly, without the program shuffling individual bytes. This is far faster than a \code{peek}/\code{poke} loop and is the usual way of moving graphics into the framebuffer.
\namespaceis{DMA}{dma}
\begin{outline}
\1\formalsynopsis{ramToRam}{from: Int, to: Int, length: Int}{Copies a block of memory from one address to another.}
\1\formalsynopsis{ramToFrame}{from: Int, to: Int, length: Int}{Copies a block of memory into the framebuffer of the first graphics adapter.}
\1\formalsynopsis{ramToFrame}{from: Int, devnum: Int, offset: Int, length: Int}{Copies a block of memory into the framebuffer of the graphics adapter in the given slot, starting at the given offset.}
\1\formalsynopsis{frameToRam}{from: Int, to: Int, length: Int}{Copies a block of framebuffer memory back into ordinary memory.}
\1\formalsynopsis{frameToRam}{from: Int, to: Int, devnum: Int, length: Int}{As above, sourcing the framebuffer of the graphics adapter in the given slot.}
\1\formalsynopsis{comToRam}{portNo: Int, srcOff: Int, destOff: Int, length: Int}{Copies bytes from a serial port's receive block into memory.}
\1\formalsynopsis{ramToCom}{srcOff: Int, portNo: Int, length: Int}{Copies bytes from memory into a serial port's send block.}
\1\formalsynopsis{strToRam}{str: String, to: Int, srcOff: Int, length: Int}{Writes the characters of a Javascript string into memory as bytes.}
\end{outline}
\section{Serial Debugger}
\index{serial (library)}The \code{serial} namespace prints to a debug channel that appears on the \emph{host} machine's console, never on the \thismachine\ screen. It is invaluable for tracing a program without disturbing what the user sees.
\namespaceis{Serial}{serial}
\begin{outline}
\1\inlinesynopsis{print}[Anything]{prints a value to the host debug console.}
\1\inlinesynopsis{println}[Anything]{prints a value followed by a new line to the host debug console.}
\end{outline}
\chapter{Serial Communication}
Some peripherals such as disk drives are connected through the ``Serial Communication''.
Unlike the name suggests, Serial Communication is not at all \emph{serial}; it's more like a \emph{block communication}.
\section{Concept of the Block Communication}
\index{block communication}As long as the Sender and the Receiver are somehow connected and being recognised, the communication channel between two devices are open and available. There are two blocks per port: the send-block and the receive-block, and the contents of the blocks are memory-mapped\footnote{Both blocks are mapped to the same port; writing to the address writes to the send-block while reading reads from the receive-block. Reading from write-block or writing to the read-block is not possible}. \emph{Write} writes the sender's send-block onto the receiver's receive-block while \emph{Read} pulls the message from the receiver's send-block and writes to the sender's receive-block.
When the read/write operation is being processed, each side emits ``busy'' flag indicating they are \emph{busy}. Sending/receiving data while one side is busy is considered as an undefined behaviour.
\section{The Com Library}
\index{com (library)}portNo is a number of the port in 0--3, 0 being the first port.
\namespaceis{Com}{com}
\begin{outline}
\1\formalsynopsis{sendMessage}{portNo: Int, message: String}{Sends message to the port and returns status code the other machine emits.}
\1\formalsynopsis{fetchResponse}{portNo: Int}[String]{Fetches the message composed by other device to this machine.}
\1\formalsynopsis{sendMessageGetBytes}{portNo: Int, message: String}[String]{Sends message, waits for responce, then returns the received message.}
\1\formalsynopsis{waitUntilReady}{portNo: Int}{Blocks the program until the other device is ready.}
\1\formalsynopsis{pullMessage}{portNo: Int}[String]{Make other device to initiate sending and returns the message receive from the other device.\\NOTE: this is not a function you're looking for it you're just getting the response after the sendMessage; use fetchResponse for that.}
\1\formalsynopsis{getStatusCode}{portNo: Int}[Int]{Returns the status code of the other device.}
\1\formalsynopsis{getDeviceStatus}{portNo: Int}[\{code: Int, message: String\}]{Returns the status message of the other device. Different types of devices may have different messages.}
\1\formalsynopsis{areYouThere}{portNo: Int}[Boolean]{Returns true if there is other device connected and is working.}
\end{outline}
\subsection{Code Example: Get a File from the Disk Drive}
\begin{lstlisting}
com.sendMessage(0, "DEVRST\x17") // resets the disk drive
com.sendMessage(0, 'OPENR"my-awesome.txt",1') // tells the disk drive to open a file named 'my-awesome.txt' from the drive number 1 for reading
let status = com.getStatusCode(0)
if (0 == status){
com.sendMessage(0, "READ") // tells the disk drive that I'm about to read the file just opened
status = com.getStatusCode(0)
if (0 == status) {
println("Reading file...")
let g = com.pullMessage(0) // will negotiate with the disk drive and read the entire file
println("Here's your file:")
println(g)
} else printerrln("I/O Error " + status)
} else printerrln("I/O Error " + status)
\end{lstlisting}
\subsection{Code Example: Write a Text to the Disk Drive}
\begin{lstlisting}
com.sendMessage(0, "DEVRST\x17") // resets the disk drive
com.sendMessage(0, 'OPENW"my-awesomer.txt",1') // tells the disk drive to open a file named 'my-awesomer.txt' from the drive number 1 for writing
let status = com.getStatusCode(0)
if (0 == status){
com.sendMessage(0, "WRITE1234") // tells the disk drive that I'm about to write to the file just opened. 1234 is a size of the text to write
status = com.getStatusCode(0)
if (0 == status) {
println("Writing file...")
com.sendMessage(0, myAwesomeText) // myAwesomeText must be in the same length as what we have told to the disk drive
com.sendMessage(0, "FLUSH") // tells the disk drive to empty out whatever is left on its internal buffer, and puts the drive to ready-mode
com.sendMessage(0, "CLOSE") // tells the disk drive to close the file
} else printerrln("I/O Error " + status)
} else printerrln("I/O Error " + status)
\end{lstlisting}
\section{Communication MMIO and How It Actually Works}
\index{MMIO-com}\label{comm-mmio}The status flags and transfer/receive blocks are memory-mapped to these address:
\footnote{RW stands for read-write status. RW means both reading and writing is posseble, RO means it's read-only}
\begin{tabulary}{\textwidth}{rcL}
Address & RW & Description \\
\hline
-4077..-4080 & RW & Status Code (-128--127) for Writing Port 1--4 \\
-4081..-4084 & RO & Status Code (-128--127) of the Receiver 1--4 \\
-4085..-4092 & RO & Transfer Status Bits for Port 1--4 (two bytes per port) \\
-4093..-4096 & RW & Transfer Control for Port 1--4 \\
-4097..-8192 & RW & Message Block for Port 1 \\
-8193..-12288 & RW & Message Block for Port 2 \\
-12289..-16384 & RW & Message Block for Port 3 \\
-16385..-20480 & RW & Message Block for Port 4
\end{tabulary}
\subsection{Transfer Status Bits and Transfer Control}
The com-port will behave differently if you're writing to or reading from the address. In other words, you cannot read what you have just wrote because the reading will put the port in a different state.
\begin{figure}[h]
\begin{center}
\setlength{\tabcolsep}{4pt}
\begin{tabular}{p{32mm}@{}p{12mm}@{}p{12mm}@{}p{16mm}@{}p{24mm}l}
\\
\instbitrange{7}{0} &
\multicolumn{1}{c}{\instbit{15}} &
\instbitrange{14}{12} &
\instbitrange{11}{8} \\
\cline{1-4}
\multicolumn{1}{|c}{size-LSB} &
\multicolumn{1}{||c|}{read} &
\multicolumn{1}{c|}{000} &
\multicolumn{1}{c|}{size-MSB} &
\ Status Bits \\
\cline{1-4}
\end{tabular}
\begin{tabular}{p{10mm}@{}p{20mm}@{}p{16mm}@{}p{16mm}@{}p{16mm}@{}p{20mm}@{}p{24mm}l}
\\
\instbitrange{7}{6} &
\instbitrange{5}{4} &
\multicolumn{1}{c}{\instbit{3}} &
\multicolumn{1}{c}{\instbit{2}} &
\multicolumn{1}{c}{\instbit{1}} &
\multicolumn{1}{c}{\instbit{0}} & \\
\cline{1-6}
\multicolumn{1}{|c|}{00} &
\multicolumn{1}{c|}{M/S} &
\multicolumn{1}{c|}{T/R} &
\multicolumn{1}{c|}{busy} &
\multicolumn{1}{c|}{ready} &
\multicolumn{1}{c|}{hello} &
\ Control Bits \\
\cline{1-6}
\end{tabular}
\end{center}
\caption{Transfer Status and Transfer Control Bits}
\label{fig:transfer-status-bits}
\end{figure}
\begin{outline}
\1\inlinesynopsis{size-LSB/MSB}{size of the data within the block}
\2\argsynopsis{read}{from the other device}
\2\argsynopsis{write}{what the device is about to send. size of zero must be interpreted as 4096}
\1\inlinesynopsis{read}{bit is set if the other device \emph{hasNext}, unset otherwise or the device is not present}
\1\inlinesynopsis{M/S}{Master/Slave setup of the other device. Typically a disk drive is slave-only (01), a computer is both (11)}
\1\inlinesynopsis{T/R}{Send-Receive mode for the port. Set the bit to send from the port, unset to read}
\1\inlinesynopsis{busy}{device busy/transfer trigger}
\2\argsynopsis{read}{the port is receiving something if the bit is set}
\2\argsynopsis{write}{setting this bit initiates transfer. If the T/R bit is set, the device will send the message out, otherwise the other device will start the transfer}
\1\inlinesynopsis{ready}{write to indicate this device is ready to receive; read to know if the other device is ready}
\1\inlinesynopsis{hello}{bit is set if the other device is connected}
\end{outline}
\chapter{Human Interface}
\section{Keyboard}
\index{keyboard}The keyboard is part of the main hardware (the slot-zero IO device) and is read through MMIO. It offers two distinct views of the same physical keyboard, and a program chooses whichever suits it.
\textbf{The input stream (TTY view).} For ordinary line- and character-oriented input, the program opens the text input stream by writing a non-zero value to MMIO \code{-39}. Keystrokes are then translated to characters and pushed onto the \emph{keyboard input buffer}; the head of that buffer is read from MMIO \code{-38}, and reading it shifts the buffer along. This is the mechanism behind \code{con.getch}, \code{read} and the \code{sys.read}/\code{sys.readKey} family. Opening the stream clears the buffer, so it must be opened exactly once.
\textbf{The raw view.} For interactive programs that need to know which keys are physically held down --- games, editors --- the program latches the current input by writing to MMIO \code{-40} and then reads the \emph{list of pressed keys} from \code{-41..-48}. This buffer holds up to eight simultaneous keys (``8-key rollover''), sorted, with zero filling the unused slots. \code{con.poll\_keys} exposes this directly. Latching freezes the values so that a multi-key read is consistent.
The codes in the raw view are the engine keycodes listed below; the codes in the stream view are character codes (with a handful of control values, e.g.\ \code{3} for Ctrl-C, \code{8} for Backspace, \code{13} for Return, and \code{19}--\code{22} for the arrow keys). \thedos\ builds its event-driven \code{input} library (see the \thedos\ part) on top of the raw view.
\subsection{Keycodes}
\index{keycodes}This is a table of keycodes recognised by the LibGDX, a framework that \thismachine\ runs on.
\begin{longtable}{*{2}{m{\textwidth}}}\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\centering
\begin{tabulary}{\textwidth}{rl}
Key & Code \\
\hline
\ttfamily{0} & 7 \\
\ttfamily{1} & 8 \\
\ttfamily{2} & 9 \\
\ttfamily{3} & 10 \\
\ttfamily{4} & 11 \\
\ttfamily{5} & 12 \\
\ttfamily{6} & 13 \\
\ttfamily{7} & 14 \\
\ttfamily{8} & 15 \\
\ttfamily{9} & 16 \\
$\hookleftarrow$ & 66 \\
\condensedfont{BkSp} & 67 \\
\condensedfont{Tab} & 61 \\
\ttfamily{`} & 68 \\
\ttfamily{'} & 75 \\
\ttfamily{;} & 43 \\
\ttfamily{,} & 55 \\
\ttfamily{.} & 56 \\
\ttfamily{/} & 76 \\
\ttfamily{[}\hspace*{0.083em} & 71 \\
\ttfamily{]}\hspace*{-0.083em} & 72 \\
\ttfamily{-} & 69 \\
\end{tabulary}
\begin{tabulary}{\textwidth}{rl}
Key & Code \\
\hline
\ttfamily{+} & 70 \\
\ttfamily{A} & 29 \\
\ttfamily{B} & 30 \\
\ttfamily{C} & 31 \\
\ttfamily{D} & 32\\
\ttfamily{E} & 33 \\
\ttfamily{F} & 34 \\
\ttfamily{G} & 35 \\
\ttfamily{H} & 36 \\
\ttfamily{I} & 37 \\
\ttfamily{J} & 38 \\
\ttfamily{K} & 39 \\
\ttfamily{L} & 40 \\
\ttfamily{M} & 41 \\
\ttfamily{N} & 42 \\
\ttfamily{O} & 43 \\
\ttfamily{P} & 44 \\
\ttfamily{Q} & 45 \\
\ttfamily{R} & 46 \\
\ttfamily{S} & 47 \\
\ttfamily{T} & 48 \\
\ttfamily{U} & 49 \\
\end{tabulary}
\begin{tabulary}{\textwidth}{rl}
Key & Code \\
\hline
\ttfamily{V} & 50 \\
\ttfamily{W} & 51 \\
\ttfamily{X} & 52 \\
\ttfamily{Y} & 53 \\
\ttfamily{Z} & 54 \\
\condensedfont{LCtrl} & 57 \\
\condensedfont{RCtrl} & 58 \\
\condensedfont{LShift} & 59 \\
\condensedfont{RShift} & 60 \\
\condensedfont{LAlt} & 129 \\
\condensedfont{RAlt} & 130 \\
$\uparrow$ & 19 \\
$\downarrow$ & 20 \\
$\leftarrow$ & 21 \\
$\rightarrow$ & 22 \\
\condensedfont{Ins} & 133 \\
\condensedfont{Del} & 112 \\
\condensedfont{PgUp} & 92 \\
\condensedfont{PgDn} & 93 \\
\condensedfont{Home} & 3 \\
\condensedfont{End} & 123 \\
F1 & 131 \\
\end{tabulary}
\begin{tabulary}{\textwidth}{rl}
Key & Code \\
\hline
F2 & 132 \\
F3 & 133 \\
F4 & 134 \\
F5 & 135 \\
F6 & 136 \\
F7 & 137 \\
F8 & 138 \\
F9 & 139 \\
F10 & 140 \\
F11 & 141 \\
F12 & 142 \\
\condensedfont{Num} \ttfamily{0} & 144 \\
\condensedfont{Num} \ttfamily{1} & 145 \\
\condensedfont{Num} \ttfamily{2} & 146 \\
\condensedfont{Num} \ttfamily{3} & 147 \\
\condensedfont{Num} \ttfamily{4} & 148 \\
\condensedfont{Num} \ttfamily{5} & 149 \\
\condensedfont{Num} \ttfamily{6} & 150 \\
\condensedfont{Num} \ttfamily{7} & 151 \\
\condensedfont{Num} \ttfamily{8} & 152 \\
\condensedfont{Num} \ttfamily{9} & 153 \\
\condensedfont{NumLk} & 78 \\
\end{tabulary}
\end{longtable}
\section{Mouse}
\index{mouse}The mouse is read through the same slot-zero IO device. Its position and button state are memory-mapped:
\begin{outline}
\1the cursor's X position is a 16-bit value at MMIO \code{-33..-34}, and the Y position at \code{-35..-36}. Like the keyboard's raw view, both are latched by a write to \code{-40} so a coordinate pair can be read consistently.
\1the button state is a single byte at \code{-37}. It is a bit-field: bit 0 is the left button, bit 1 the right, bit 2 the middle. Bits 6 and 7 report a wheel notch up and down respectively; these wheel bits latch in hardware and clear when read, so a single notch is reported exactly once.
\end{outline}
Most programs do not poke these addresses directly. Under \thedos, the \code{input} library turns mouse motion, clicks and wheel notches into the \textbf{mouse\_down}, \textbf{mouse\_up}, \textbf{mouse\_move} and \textbf{mouse\_wheel} events described in the \thedos\ part of this book.
\chapter{Peripherals and Memory Mapping}
\index{memory map}The hardware registers and memories of a peripheral is memory-mapped to the specific addresses that can be \code{peek}ed and \code{poke}d.
The memory map of \thismachine\ is illustrated as following:
\newcommand{\memend}[1]{\raisebox{1.3em}{#1}}
\newcommand{\memlabel}[1]{\raisebox{-0.1ex}{#1}}
\begin{tikzpicture}
\centering
\draw[thick] (0,0) rectangle (6, 12);
% Memory starting addr
\draw (6,12) node[anchor=north west] {8388607};
\draw[thick] (0,8) node[anchor=north east] {-1} -- (6,8);
\draw (0,7) node[anchor=north east] {-1048577} -- (6,7);
\draw (0,6) node[anchor=north east] {-2097153} -- (6,6);
\draw (0,5) node[anchor=north east] {-3145729} -- (6,5);
\draw (0,4) node[anchor=north east] {-4194305} -- (6,4);
\draw (0,3) node[anchor=north east] {-5242881} -- (6,3);
\draw (0,2) node[anchor=north east] {-6291457} -- (6,2);
\draw (0,1) node[anchor=north east] {-7340033} -- (6,1);
% Memory ending addr
\draw (0,8) node[anchor=east] {\memend{0}};
\draw (6,7) node[anchor=west] {\memend{-1048576}};
\draw (6,6) node[anchor=west] {\memend{-2097152}};
\draw (6,5) node[anchor=west] {\memend{-3145728}};
\draw (6,4) node[anchor=west] {\memend{-4194304}};
\draw (6,3) node[anchor=west] {\memend{-5242880}};
\draw (6,2) node[anchor=west] {\memend{-6291456}};
\draw (6,1) node[anchor=west] {\memend{-7340032}};
\draw (6,0) node[anchor=west] {\memend{-8388608}};
% Labels
\draw(0,12.5) node[anchor=north east] {Start};
\draw(6,12.5) node[anchor=north west] {End};
\draw(3,10) node[anchor=mid] {\memlabel{Core Memory}};
\draw(3,7.5) node[anchor=mid] {\memlabel{MMIO Area}};
\draw(3,6.5) node[anchor=mid] {\memlabel{Peripheral Memory \#1}};
\draw(3,5.5) node[anchor=mid] {\memlabel{Peripheral Memory \#2}};
\draw(3,4.5) node[anchor=mid] {\memlabel{Peripheral Memory \#3}};
\draw(3,3.5) node[anchor=mid] {\memlabel{Peripheral Memory \#4}};
\draw(3,2.5) node[anchor=mid] {\memlabel{Peripheral Memory \#5}};
\draw(3,1.5) node[anchor=mid] {\memlabel{Peripheral Memory \#6}};
\draw(3,0.5) node[anchor=mid] {\memlabel{Peripheral Memory \#7}};
\end{tikzpicture}
The MMIO Area is further divided as shown:
\begin{tikzpicture}
\centering
\draw[thick] (0,0) rectangle (6, 8);
% Memory starting addr
\draw (0,8) node[anchor=north east] {-1} -- (6,8);
\draw (0,7) node[anchor=north east] {-131073} -- (6,7);
\draw (0,6) node[anchor=north east] {-262145} -- (6,6);
\draw (0,5) node[anchor=north east] {-393217} -- (6,5);
\draw (0,4) node[anchor=north east] {-524289} -- (6,4);
\draw (0,3) node[anchor=north east] {-655361} -- (6,3);
\draw (0,2) node[anchor=north east] {-786433} -- (6,2);
\draw (0,1) node[anchor=north east] {-917505} -- (6,1);
% Memory ending addr
\draw (6,7) node[anchor=west] {\memend{-131072}};
\draw (6,6) node[anchor=west] {\memend{-262144}};
\draw (6,5) node[anchor=west] {\memend{-393216}};
\draw (6,4) node[anchor=west] {\memend{-524288}};
\draw (6,3) node[anchor=west] {\memend{-655360}};
\draw (6,2) node[anchor=west] {\memend{-786432}};
\draw (6,1) node[anchor=west] {\memend{-917504}};
\draw (6,0) node[anchor=west] {\memend{-1048576}};
% Labels
\draw(0,8.5) node[anchor=north east] {Start};
\draw(6,8.5) node[anchor=north west] {End};
\draw(3,7.5) node[anchor=mid] {\memlabel{MMIO for Main Hardwares}};
\draw(3,6.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#1}};
\draw(3,5.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#2}};
\draw(3,4.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#3}};
\draw(3,3.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#4}};
\draw(3,2.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#5}};
\draw(3,1.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#6}};
\draw(3,0.5) node[anchor=mid] {\memlabel{MMIO for Peripheral \#7}};
\end{tikzpicture}
\section{MMIO for Main Hardwares}
Some internal hardwares are memory-mapped and can be controled by poking and peeking.
Multibyte values are stored in Little Endian.
\index{main hardware memory mapping}
\begin{tabulary}{\textwidth}{rcL}
Address & RW & Description \\
\hline
-1..-32 & RO & Raw Keyboard Input Buffer (raw means the values are not shifted around) \\
-33..-34 & RO & Mouse X Pos (latched by -40) \\
-35..-36 & RO & Mouse Y Pos (latched by -40) \\
-37 & RO & Mouse Button Down (1 if True) \\
-38 & RW & The head key on the Keyboard Input Buffer \\
-39 & RW & Text Input Stream control. Write nonzero value to open it. The Keyboard Input Buffer will be cleared whenever the Input Stream is opened. \\
-40 & WO & Latch Keyboard and Mouse input \\
-41..-48 & RO & List of pressed keys (latched by -40) \\
-49 & RO & System Flags A (\code{0b r000 000t}, where r: RESET button held, t: STOP button held) \\
-50..-52 & RO & Unused System Flags \\
-65..-68 & RO & Size of the Core Memory \\
-69 & WO & Counter Latch (\code{0b01}--Uptime, \code{0b10}--RTC) \\
-73..-80 & RO & System Uptime in nanoseconds (latched by -69) \\
-81..-88 & RO & RTC in nanoseconds (latched by -69) \\
-89 & RW & ROM Mapping \\
-90 & RW & Power Management Flags (\code{0b P000 b0ca}), where P: CPU halted, b: the device is battery-operated, c: a battery is detected, a: the battery is charging \\
-91 & RO & BMS Battery Percentage \\
-92 & RO & BMS Battery Voltage multiplied by 10 \\
-1025..-2048 & RW & Reserved for the integrated peripherals \\
-4077..-20480 & $ \ast $ & See \ref{comm-mmio} \\
-65537..-131072 & RO & Contents in the mapped ROM
\end{tabulary}
\chapter{Text and Graphics Display}
\index{display model}The reference graphics adapter drives the screen from two superimposed surfaces:
\begin{outline}
\1the \textbf{framebuffer} (also called the pixel buffer), a grid of pixels whose size and colour depth depend on the current graphics mode; and
\1the \textbf{text buffer}, a grid of character cells, each with its own foreground and background colour.
\end{outline}
These are composited every frame in a fixed order: first the screen background (border) colour, then the framebuffer, then the text on top. The text is therefore always visible over whatever the framebuffer holds, and a text cell whose background uses the transparent palette entry lets the framebuffer show through. A program that wants a purely graphical display simply leaves the text buffer blank; one that wants a classic terminal leaves the framebuffer cleared.
While the graphics adapters can be plugged into any peripheral slot, it is highly recommended they occupy the 1st slot. The Memory address charts for the graphics adapter on this documentation will assume as such.
\section{Text Buffer}
\index{text buffer}The reference text buffer stores 80 columns, 32 rows of characters and 256 foreground and background colours are assigned separately for each character cell.
\subsection{Escape Sequences}
\newcommand{\csi}{{\condensedfont{CSI}}}
Printing out certain sequences of string can invoke special functions on the graphics, and such sequneces are called Escape Sequences.
For the following chart, please interpret \csi\ as \code{\rs{}x1B [}.
\begin{tabulary}{\textwidth}{lL}
Sequence & Description \\
\hline
\csi\ \emph{n} A & Moves the cursor up by \emph{n} (default \code{1}) \\
\csi\ \emph{n} B & Moves the cursor down by \emph{n} (default \code{1}) \\
\csi\ \emph{n} C & Moves the cursor right by \emph{n} (default \code{1}) \\
\csi\ \emph{n} D & Moves the cursor left by \emph{n (default \code{1})} \\
\csi\ \emph{n} E & Moves the cursor to the beginning of the line \emph{n} (default \code{1}) lines down \\
\csi\ \emph{n} F & Moves the cursor to the beginning of the line \emph{n} (default \code{1}) lines up \\
\csi\ \emph{n} G & Moves the cursor to the \emph{n}th (default \code{1}) column \\
\csi\ \emph{n} ; \emph{m} H & Moves the cursor to \emph{n}th row, \emph{m}th column \\
\csi\ 2 J & Clears the entire text buffer \\
\csi\ \emph{n} S & Scoll the entire page up by \emph{n} (default \code{1}) lines \\
\csi\ \emph{n} T & Scoll the entire page down by \emph{n} (default \code{1}) lines \\
\csi\ m & Resets the text attributes to the default status \\
\csi\ 7 m & Inverts the text by swapping the foreground and background colour \\
\csi\ 30-37 m & Changes the foreground colour. 30--Black, 31--Red, 32--Green, 33--Yellow, 34--Blue, 35--Magenta, 36--Cyan, 37--White \\
\csi\ 40-47 m & Changes the background colour. 40--Black, 41--Red, 42--Green, 43--Yellow, 44--Blue, 45--Magenta, 46--Cyan, 47--White \\
\csi\ 38 ; 5 ; \emph{col} m & Changes the foreground colour using the Colour Palette \\
\csi\ 48 ; 5 ; \emph{col} m & Changes the foreground colour using the Colour Palette \\
\csi\ ? 25 h & Shows the text cursor \\
\csi\ ? 25 l & Hides the text cursor \\
{\condensedfont{\rs{}x84} \emph{charcode}} u & Prints out the symbol corresponds to the given charcode
\end{tabulary}
\subsection{Code Page}
\label{codepage}
\index{code page}By default \thismachine\ uses slightly modified version of CP-437, this is a character map of it:
{\centering
\includegraphics[width=\linewidth]{tsvmcp.png}
\captionof{figure}{\thismachine\ Character Map}
\label{fig:codepage}
}
\newpage
\section{Frame Buffer}
\index{frame buffer}The framebuffer holds the pixel image. In the default mode it is $560\times448$ pixels, one byte per pixel, where each byte is an index into the 256-entry colour palette. Pixels are written either with the \code{graphics} library (\code{plotPixel}, \code{plotRect}, \dots), or far more quickly by \code{dma}-copying a prepared image into the framebuffer region of the adapter's memory.
\subsection{Graphics Modes}
\index{graphics mode}The adapter can be reconfigured into several modes that trade resolution, colour depth and the number of \emph{layers} (independent pixel planes that the adapter composites together). The mode is selected with \code{graphics.setGraphicsMode}, or by poking the Current Graphics Mode register. The higher modes need extra video-memory banks to be fitted; if the required banks are absent, the mode change is ignored.
\begin{center}
\begin{tabulary}{\textwidth}{clcl}
Mode & Resolution & Colours & Layers / requirement \\
\hline
0 & $560\times448$ & 256 & 1 layer (default) \\
1 & $280\times224$ & 256 & 4 layers \\
2 & $280\times224$ & 4096 & 2 layers \\
3 & $560\times448$ & 256 & 2 layers (needs bank 2) \\
4 & $560\times448$ & 4096 & 1 layer (needs bank 2) \\
5 & $560\times448$ & 15-bit & 1 layer (needs bank 2) \\
8 & $560\times448$ & 24-bit & 1 layer (needs banks 3 \& 4) \\
\end{tabulary}
\end{center}
A graphics adapter ships with one 256\,kB memory bank and can hold up to four. The number of installed banks is reported by the adapter and limits which modes are available.
\subsection{Direct Colour}
\index{direct colour}The 4096-colour (``direct colour'') modes do not use the palette. Instead two layers are paired to form one frame: the low layer carries the red and green channels (\code{0b RRRR GGGG}) and the high layer carries the blue channel and a 4-bit transparency (\code{0b BBBB AAAA}), giving 4096 colours each with 16 levels of transparency.
\subsection{Layers and Scrolling}
\index{layers}When a mode provides more than one layer, the \emph{layer arrangement} register chooses the order in which the layers are stacked, so a program can swap front and back planes without moving any pixels. The whole framebuffer can also be panned: the horizontal and vertical framebuffer-scroll registers shift the entire image, and a per-scanline horizontal offset table allows each scanline to be displaced independently --- the basis of split-screen and wavy ``raster'' effects.
\subsection{Colour Palette}
\label{colourpalette}
\index{colour palette}By default the reference graphics adapter of the \thismachine\ uses following colour palette:
{\centering
\includegraphics[width=\linewidth]{tsvmpal.png}
\captionof{figure}{\thismachine\ Colour Palette}
\label{fig:colourpalette}
}
{\centering
\fontsize{7pt}{0pt} % second argument is baselineskip but it's useless in table
\newlength{\extrarowheighttwo}
\setlength{\extrarowheighttwo}{\extrarowheight}
\setlength{\extrarowheight}{-0.4ex}
\begin{longtable}{*{2}{m{\textwidth}}}\hline
\endfirsthead
\endhead
\endfoot
\hline
\endlastfoot
\centering
\begin{tabulary}{\textwidth}{rl}
{\ttfamily 0} & {\ttfamily \#0007} \\
{\ttfamily 1} & {\ttfamily \#004F} \\
{\ttfamily 2} & {\ttfamily \#008F} \\
{\ttfamily 3} & {\ttfamily \#00BF} \\
{\ttfamily 4} & {\ttfamily \#00FF} \\
{\ttfamily 5} & {\ttfamily \#020F} \\
{\ttfamily 6} & {\ttfamily \#024F} \\
{\ttfamily 7} & {\ttfamily \#028F} \\
{\ttfamily 8} & {\ttfamily \#02BF} \\
{\ttfamily 9} & {\ttfamily \#02FF} \\
{\ttfamily 10} & {\ttfamily \#040F} \\
{\ttfamily 11} & {\ttfamily \#044F} \\
{\ttfamily 12} & {\ttfamily \#048F} \\
{\ttfamily 13} & {\ttfamily \#04BF} \\
{\ttfamily 14} & {\ttfamily \#04FF} \\
{\ttfamily 15} & {\ttfamily \#060F} \\
{\ttfamily 16} & {\ttfamily \#064F} \\
{\ttfamily 17} & {\ttfamily \#068F} \\
{\ttfamily 18} & {\ttfamily \#06BF} \\
{\ttfamily 19} & {\ttfamily \#06FF} \\
{\ttfamily 20} & {\ttfamily \#090F} \\
{\ttfamily 21} & {\ttfamily \#094F} \\
{\ttfamily 22} & {\ttfamily \#098F} \\
{\ttfamily 23} & {\ttfamily \#09BF} \\
{\ttfamily 24} & {\ttfamily \#09FF} \\
{\ttfamily 25} & {\ttfamily \#0B0F} \\
{\ttfamily 26} & {\ttfamily \#0B4F} \\
{\ttfamily 27} & {\ttfamily \#0B8F} \\
{\ttfamily 28} & {\ttfamily \#0BBF} \\
{\ttfamily 29} & {\ttfamily \#0BFF} \\
{\ttfamily 30} & {\ttfamily \#0D0F} \\
{\ttfamily 31} & {\ttfamily \#0D4F} \\
{\ttfamily 32} & {\ttfamily \#0D8F} \\
{\ttfamily 33} & {\ttfamily \#0DBF} \\
{\ttfamily 34} & {\ttfamily \#0DFF} \\
{\ttfamily 35} & {\ttfamily \#0F0F} \\
{\ttfamily 36} & {\ttfamily \#0F4F} \\
{\ttfamily 37} & {\ttfamily \#0F8F} \\
{\ttfamily 38} & {\ttfamily \#0FBF} \\
{\ttfamily 39} & {\ttfamily \#0FFF} \\
{\ttfamily 40} & {\ttfamily \#300F} \\
{\ttfamily 41} & {\ttfamily \#304F} \\
{\ttfamily 42} & {\ttfamily \#308F} \\
\end{tabulary}
\begin{tabulary}{\textwidth}{|rl}
{\ttfamily 43} & {\ttfamily \#30BF} \\
{\ttfamily 44} & {\ttfamily \#30FF} \\
{\ttfamily 45} & {\ttfamily \#320F} \\
{\ttfamily 46} & {\ttfamily \#324F} \\
{\ttfamily 47} & {\ttfamily \#328F} \\
{\ttfamily 48} & {\ttfamily \#32BF} \\
{\ttfamily 49} & {\ttfamily \#32FF} \\
{\ttfamily 50} & {\ttfamily \#340F} \\
{\ttfamily 51} & {\ttfamily \#344F} \\
{\ttfamily 52} & {\ttfamily \#348F} \\
{\ttfamily 53} & {\ttfamily \#34BF} \\
{\ttfamily 54} & {\ttfamily \#34FF} \\
{\ttfamily 55} & {\ttfamily \#360F} \\
{\ttfamily 56} & {\ttfamily \#364F} \\
{\ttfamily 57} & {\ttfamily \#368F} \\
{\ttfamily 58} & {\ttfamily \#36BF} \\
{\ttfamily 59} & {\ttfamily \#36FF} \\
{\ttfamily 60} & {\ttfamily \#390F} \\
{\ttfamily 61} & {\ttfamily \#394F} \\
{\ttfamily 62} & {\ttfamily \#398F} \\
{\ttfamily 63} & {\ttfamily \#39BF} \\
{\ttfamily 64} & {\ttfamily \#39FF} \\
{\ttfamily 65} & {\ttfamily \#3B0F} \\
{\ttfamily 66} & {\ttfamily \#3B4F} \\
{\ttfamily 67} & {\ttfamily \#3B8F} \\
{\ttfamily 68} & {\ttfamily \#3BBF} \\
{\ttfamily 69} & {\ttfamily \#3BFF} \\
{\ttfamily 70} & {\ttfamily \#3D0F} \\
{\ttfamily 71} & {\ttfamily \#3D4F} \\
{\ttfamily 72} & {\ttfamily \#3D8F} \\
{\ttfamily 73} & {\ttfamily \#3DBF} \\
{\ttfamily 74} & {\ttfamily \#3DFF} \\
{\ttfamily 75} & {\ttfamily \#3F0F} \\
{\ttfamily 76} & {\ttfamily \#3F4F} \\
{\ttfamily 77} & {\ttfamily \#3F8F} \\
{\ttfamily 78} & {\ttfamily \#3FBF} \\
{\ttfamily 79} & {\ttfamily \#3FFF} \\
{\ttfamily 80} & {\ttfamily \#600F} \\
{\ttfamily 81} & {\ttfamily \#604F} \\
{\ttfamily 82} & {\ttfamily \#608F} \\
{\ttfamily 83} & {\ttfamily \#60BF} \\
{\ttfamily 84} & {\ttfamily \#60FF} \\
{\ttfamily 85} & {\ttfamily \#620F} \\
\end{tabulary}
\begin{tabulary}{\textwidth}{|rl}
{\ttfamily 86} & {\ttfamily \#624F} \\
{\ttfamily 87} & {\ttfamily \#628F} \\
{\ttfamily 88} & {\ttfamily \#62BF} \\
{\ttfamily 89} & {\ttfamily \#62FF} \\
{\ttfamily 90} & {\ttfamily \#640F} \\
{\ttfamily 91} & {\ttfamily \#644F} \\
{\ttfamily 92} & {\ttfamily \#648F} \\
{\ttfamily 93} & {\ttfamily \#64BF} \\
{\ttfamily 94} & {\ttfamily \#64FF} \\
{\ttfamily 95} & {\ttfamily \#660F} \\
{\ttfamily 96} & {\ttfamily \#664F} \\
{\ttfamily 97} & {\ttfamily \#668F} \\
{\ttfamily 98} & {\ttfamily \#66BF} \\
{\ttfamily 99} & {\ttfamily \#66FF} \\
{\ttfamily 100} & {\ttfamily \#690F} \\
{\ttfamily 101} & {\ttfamily \#694F} \\
{\ttfamily 102} & {\ttfamily \#698F} \\
{\ttfamily 103} & {\ttfamily \#69BF} \\
{\ttfamily 104} & {\ttfamily \#69FF} \\
{\ttfamily 105} & {\ttfamily \#6B0F} \\
{\ttfamily 106} & {\ttfamily \#6B4F} \\
{\ttfamily 107} & {\ttfamily \#6B8F} \\
{\ttfamily 108} & {\ttfamily \#6BBF} \\
{\ttfamily 109} & {\ttfamily \#6BFF} \\
{\ttfamily 110} & {\ttfamily \#6D0F} \\
{\ttfamily 111} & {\ttfamily \#6D4F} \\
{\ttfamily 112} & {\ttfamily \#6D8F} \\
{\ttfamily 113} & {\ttfamily \#6DBF} \\
{\ttfamily 114} & {\ttfamily \#6DFF} \\
{\ttfamily 115} & {\ttfamily \#6F0F} \\
{\ttfamily 116} & {\ttfamily \#6F4F} \\
{\ttfamily 117} & {\ttfamily \#6F8F} \\
{\ttfamily 118} & {\ttfamily \#6FBF} \\
{\ttfamily 119} & {\ttfamily \#6FFF} \\
{\ttfamily 120} & {\ttfamily \#900F} \\
{\ttfamily 121} & {\ttfamily \#904F} \\
{\ttfamily 122} & {\ttfamily \#908F} \\
{\ttfamily 123} & {\ttfamily \#90BF} \\
{\ttfamily 124} & {\ttfamily \#90FF} \\
{\ttfamily 125} & {\ttfamily \#920F} \\
{\ttfamily 126} & {\ttfamily \#924F} \\
{\ttfamily 127} & {\ttfamily \#928F} \\
{\ttfamily 128} & {\ttfamily \#92BF} \\
\end{tabulary}
\begin{tabulary}{\textwidth}{|rl}
{\ttfamily 129} & {\ttfamily \#92FF} \\
{\ttfamily 130} & {\ttfamily \#940F} \\
{\ttfamily 131} & {\ttfamily \#944F} \\
{\ttfamily 132} & {\ttfamily \#948F} \\
{\ttfamily 133} & {\ttfamily \#94BF} \\
{\ttfamily 134} & {\ttfamily \#94FF} \\
{\ttfamily 135} & {\ttfamily \#960F} \\
{\ttfamily 136} & {\ttfamily \#964F} \\
{\ttfamily 137} & {\ttfamily \#968F} \\
{\ttfamily 138} & {\ttfamily \#96BF} \\
{\ttfamily 139} & {\ttfamily \#96FF} \\
{\ttfamily 140} & {\ttfamily \#990F} \\
{\ttfamily 141} & {\ttfamily \#994F} \\
{\ttfamily 142} & {\ttfamily \#998F} \\
{\ttfamily 143} & {\ttfamily \#99BF} \\
{\ttfamily 144} & {\ttfamily \#99FF} \\
{\ttfamily 145} & {\ttfamily \#9B0F} \\
{\ttfamily 146} & {\ttfamily \#9B4F} \\
{\ttfamily 147} & {\ttfamily \#9B8F} \\
{\ttfamily 148} & {\ttfamily \#9BBF} \\
{\ttfamily 149} & {\ttfamily \#9BFF} \\
{\ttfamily 150} & {\ttfamily \#9D0F} \\
{\ttfamily 151} & {\ttfamily \#9D4F} \\
{\ttfamily 152} & {\ttfamily \#9D8F} \\
{\ttfamily 153} & {\ttfamily \#9DBF} \\
{\ttfamily 154} & {\ttfamily \#9DFF} \\
{\ttfamily 155} & {\ttfamily \#9F0F} \\
{\ttfamily 156} & {\ttfamily \#9F4F} \\
{\ttfamily 157} & {\ttfamily \#9F8F} \\
{\ttfamily 158} & {\ttfamily \#9FBF} \\
{\ttfamily 159} & {\ttfamily \#9FFF} \\
{\ttfamily 160} & {\ttfamily \#C00F} \\
{\ttfamily 161} & {\ttfamily \#C04F} \\
{\ttfamily 162} & {\ttfamily \#C08F} \\
{\ttfamily 163} & {\ttfamily \#C0BF} \\
{\ttfamily 164} & {\ttfamily \#C0FF} \\
{\ttfamily 165} & {\ttfamily \#C20F} \\
{\ttfamily 166} & {\ttfamily \#C24F} \\
{\ttfamily 167} & {\ttfamily \#C28F} \\
{\ttfamily 168} & {\ttfamily \#C2BF} \\
{\ttfamily 169} & {\ttfamily \#C2FF} \\
{\ttfamily 170} & {\ttfamily \#C40F} \\
{\ttfamily 171} & {\ttfamily \#C44F} \\
\end{tabulary}
\begin{tabulary}{\textwidth}{|rl}
{\ttfamily 172} & {\ttfamily \#C48F} \\
{\ttfamily 173} & {\ttfamily \#C4BF} \\
{\ttfamily 174} & {\ttfamily \#C4FF} \\
{\ttfamily 175} & {\ttfamily \#C60F} \\
{\ttfamily 176} & {\ttfamily \#C64F} \\
{\ttfamily 177} & {\ttfamily \#C68F} \\
{\ttfamily 178} & {\ttfamily \#C6BF} \\
{\ttfamily 179} & {\ttfamily \#C6FF} \\
{\ttfamily 180} & {\ttfamily \#C90F} \\
{\ttfamily 181} & {\ttfamily \#C94F} \\
{\ttfamily 182} & {\ttfamily \#C98F} \\
{\ttfamily 183} & {\ttfamily \#C9BF} \\
{\ttfamily 184} & {\ttfamily \#C9FF} \\
{\ttfamily 185} & {\ttfamily \#CB0F} \\
{\ttfamily 186} & {\ttfamily \#CB4F} \\
{\ttfamily 187} & {\ttfamily \#CB8F} \\
{\ttfamily 188} & {\ttfamily \#CBBF} \\
{\ttfamily 189} & {\ttfamily \#CBFF} \\
{\ttfamily 190} & {\ttfamily \#CD0F} \\
{\ttfamily 191} & {\ttfamily \#CD4F} \\
{\ttfamily 192} & {\ttfamily \#CD8F} \\
{\ttfamily 193} & {\ttfamily \#CDBF} \\
{\ttfamily 194} & {\ttfamily \#CDFF} \\
{\ttfamily 195} & {\ttfamily \#CF0F} \\
{\ttfamily 196} & {\ttfamily \#CF4F} \\
{\ttfamily 197} & {\ttfamily \#CF8F} \\
{\ttfamily 198} & {\ttfamily \#CFBF} \\
{\ttfamily 199} & {\ttfamily \#CFFF} \\
{\ttfamily 200} & {\ttfamily \#F00F} \\
{\ttfamily 201} & {\ttfamily \#F04F} \\
{\ttfamily 202} & {\ttfamily \#F08F} \\
{\ttfamily 203} & {\ttfamily \#F0BF} \\
{\ttfamily 204} & {\ttfamily \#F0FF} \\
{\ttfamily 205} & {\ttfamily \#F20F} \\
{\ttfamily 206} & {\ttfamily \#F24F} \\
{\ttfamily 207} & {\ttfamily \#F28F} \\
{\ttfamily 208} & {\ttfamily \#F2BF} \\
{\ttfamily 209} & {\ttfamily \#F2FF} \\
{\ttfamily 210} & {\ttfamily \#F40F} \\
{\ttfamily 211} & {\ttfamily \#F44F} \\
{\ttfamily 212} & {\ttfamily \#F48F} \\
{\ttfamily 213} & {\ttfamily \#F4BF} \\
{\ttfamily 214} & {\ttfamily \#F4FF} \\
\end{tabulary}
\begin{tabulary}{\textwidth}{|rl}
{\ttfamily 215} & {\ttfamily \#F60F} \\
{\ttfamily 216} & {\ttfamily \#F64F} \\
{\ttfamily 217} & {\ttfamily \#F68F} \\
{\ttfamily 218} & {\ttfamily \#F6BF} \\
{\ttfamily 219} & {\ttfamily \#F6FF} \\
{\ttfamily 220} & {\ttfamily \#F90F} \\
{\ttfamily 221} & {\ttfamily \#F94F} \\
{\ttfamily 222} & {\ttfamily \#F98F} \\
{\ttfamily 223} & {\ttfamily \#F9BF} \\
{\ttfamily 224} & {\ttfamily \#F9FF} \\
{\ttfamily 225} & {\ttfamily \#FB0F} \\
{\ttfamily 226} & {\ttfamily \#FB4F} \\
{\ttfamily 227} & {\ttfamily \#FB8F} \\
{\ttfamily 228} & {\ttfamily \#FBBF} \\
{\ttfamily 229} & {\ttfamily \#FBFF} \\
{\ttfamily 230} & {\ttfamily \#FD0F} \\
{\ttfamily 231} & {\ttfamily \#FD4F} \\
{\ttfamily 232} & {\ttfamily \#FD8F} \\
{\ttfamily 233} & {\ttfamily \#FDBF} \\
{\ttfamily 234} & {\ttfamily \#FDFF} \\
{\ttfamily 235} & {\ttfamily \#FF0F} \\
{\ttfamily 236} & {\ttfamily \#FF4F} \\
{\ttfamily 237} & {\ttfamily \#FF8F} \\
{\ttfamily 238} & {\ttfamily \#FFBF} \\
{\ttfamily 239} & {\ttfamily \#FFFF} \\
{\ttfamily 240} & {\ttfamily \#000F} \\
{\ttfamily 241} & {\ttfamily \#111F} \\
{\ttfamily 242} & {\ttfamily \#222F} \\
{\ttfamily 243} & {\ttfamily \#333F} \\
{\ttfamily 244} & {\ttfamily \#444F} \\
{\ttfamily 245} & {\ttfamily \#555F} \\
{\ttfamily 246} & {\ttfamily \#666F} \\
{\ttfamily 247} & {\ttfamily \#777F} \\
{\ttfamily 248} & {\ttfamily \#888F} \\
{\ttfamily 249} & {\ttfamily \#999F} \\
{\ttfamily 250} & {\ttfamily \#AAAF} \\
{\ttfamily 251} & {\ttfamily \#BBBF} \\
{\ttfamily 252} & {\ttfamily \#CCCF} \\
{\ttfamily 253} & {\ttfamily \#DDDF} \\
{\ttfamily 254} & {\ttfamily \#EEEF} \\
{\ttfamily 255} & {\ttfamily \#0000} \\
\, & \, \\
\, & \, \\
\end{tabulary}
\end{longtable}
\captionof{table}{Index--RGBA Table of the Colour Palette}
}
\setlength{\extrarowheight}{\extrarowheighttwo}
\section{The Graphics Library}
\index{graphics (library)}Graphics library provides basic functions to communicate and manipulate the graphics adapter. Coordinates are in pixels with the origin at the top-left; colours are palette indices unless the adapter is in a direct-colour mode.
\namespaceis{Graphics}{graphics}
Drawing:
\begin{outline}
\1\formalsynopsis{plotPixel}{x: Int, y: Int, colour: Int}{Plots a single pixel on the first framebuffer.}
\1\formalsynopsis{plotPixel2}{x: Int, y: Int, colour: Int}{Plots a single pixel on the second framebuffer.}
\1\formalsynopsis{plotRect}{x: Int, y: Int, w: Int, h: Int, colour: Int}{Fills a rectangle on the first framebuffer. An optional sixth argument selects a blending effect.}
\1\formalsynopsis{plotRect2}{x: Int, y: Int, w: Int, h: Int, colour: Int}{As \code{plotRect}, on the second framebuffer.}
\1\formalsynopsis{clearPixels}{col: Int}{Fills the entire framebuffer with the given colour.}
\1\formalsynopsis{clearText}{}{Blanks the text buffer.}
\1\formalsynopsis{getGpuMemBase}{}[Int]{Returns the base address of the graphics adapter's memory, for direct access via \code{peek}/\code{poke} or \code{dma}.}
\end{outline}
Colour:
\begin{outline}
\1\formalsynopsis{setBackground}{r: Int, g: Int, b: Int}{Sets the screen background (border) colour, 8 bits per channel.}
\1\formalsynopsis{resetPalette}{}{Restores the default colour palette.}
\1\formalsynopsis{setPalette}{index: Int, r: Int, g: Int, b: Int, a: Int}{Sets one palette entry. Channels are 4-bit (0--15); \code{a} (alpha) defaults to 15 (opaque).}
\1\formalsynopsis{setTextFore}{b: Int}{Sets the current text foreground colour.}
\1\formalsynopsis{setTextBack}{b: Int}{Sets the current text background colour.}
\1\formalsynopsis{getTextFore}{}[Int]{Returns the current text foreground colour.}
\1\formalsynopsis{getTextBack}{}[Int]{Returns the current text background colour.}
\end{outline}
Mode and geometry:
\begin{outline}
\1\formalsynopsis{setGraphicsMode}{mode: Int}{Switches the graphics mode (see \emph{Graphics Modes}).}
\1\formalsynopsis{getGraphicsMode}{}[Int]{Returns the current graphics mode.}
\1\formalsynopsis{getPixelDimension}{}[IntArray(2)]{Returns the framebuffer size as \code{[width, height]}.}
\1\formalsynopsis{getTermDimension}{}[IntArray(2)]{Returns the text grid size as \code{[columns, rows]}.}
\1\formalsynopsis{setFramebufferScroll}{x: Int, y: Int}{Pans the whole framebuffer to the given offset.}
\1\formalsynopsis{getFramebufferScroll}{}[IntArray(2)]{Returns the current framebuffer scroll offset.}
\1\formalsynopsis{scrollFrame}{xdelta: Int, ydelta: Int}{Pans the framebuffer by a relative amount.}
\1\formalsynopsis{setLineOffset}{line: Int, offset: Int}{Sets the per-scanline horizontal offset (raster effects).}
\1\formalsynopsis{getLineOffset}{line: Int}[Int]{Returns the per-scanline horizontal offset.}
\end{outline}
Text cursor and symbols (these talk to the adapter directly; under \thedos\ prefer the \code{con} library):
\begin{outline}
\1\formalsynopsis{getCursorYX}{}[IntArray(2)]{Returns the text cursor position as \code{[row, column]}.}
\1\formalsynopsis{setCursorYX}{cy: Int, cx: Int}{Moves the text cursor.}
\1\formalsynopsis{putSymbol}{c: Int}{Writes the character of the given code at the cursor, without advancing it.}
\1\formalsynopsis{putSymbolAt}{cy: Int, cx: Int, c: Int}{Writes a character at a specific cell.}
\end{outline}
Image decoding: the adapter can decode compressed still images straight into memory. \code{decodeImage(srcFilePtr, srcFileLen)} decodes an image (JPEG, PNG, TGA, \dots) whose bytes are already in memory and returns its dimensions; \code{decodeImageTo} writes the result to a given buffer, and \code{decodeImageResample} scales it on the way. These, together with the hardware decoders for the iPF, TEV and TAV formats, are what the \thedos\ media players are built on; the formats themselves are described in the \thedos\ part.
\section{MMIO and Memory Mapping}
Multibyte values are stored in Little Endian.
\index{graphics adapter memory mapping}
\begin{tabulary}{\textwidth}{rcL}
Address & RW & Description \\
\hline
-131073..-131074 & RO & Framebuffer Width \\
-131075..-131076 & RO & Framebuffer Height \\
-131077 & RO & Text Columns \\
-131078 & RO & Text Rows \\
-131079 & RW & Text Mode Attributes \\
-131080 & RW & Graphics Mode Attributes \\
-131081 & RO & Last Used Colour for the Framebuffer \\
-131082 & RW & Text Foreground Colour \\
-131083 & RW & Text Background Colour \\
-131084 & RO & Number of Graphics Memory Banks (1--4) \\
-131085 & RW & Current Graphics Mode \\
-131086 & RW & Current Layer Arrangement Index \\
-131087..-131088 & RW & Framebuffer Horizontal Scroll \\
-131089..-131090 & RW & Framebuffer Vertical Scroll \\
-132097..-133120 & RW & Scanline Offsets \\
-133121..-135168 & RW & Font ROM Mapping Area \\
-196609..-262144 & RW & Draw Instructions Area \\
-1048577..-1299456 & RW & First Framebuffer \\
-1299457 & RW & Screen Background RED \\
-1299458 & RW & Screen Background GREEN \\
-1299459 & RW & Screen Background BLUE \\
-1299460 & RW & Command \\
-1299461..-1299472 & RW & Command Arguments \\
-1302527..-1302528 & RW & Text Cursor Position in $row \times 80 + col$ \\
-1302529..-1305088 & RW & Text Foreground Colours \\
-1305089..-1307648 & RW & Text Background Colours \\
-1307649..-1310208 & RW & Text Buffer \\
-1310209..-1310720 & RW & Palettes in This Pattern: {\ttfamily 0b RRRR GGGG; 0b BBBB AAAA} \\
-1310721..-1561600 & RW & Second Framebuffer \\
\end{tabulary}
\chapter{Audio}
\index{audio adapter}The \thismachine\ sound card is built from four independent \textbf{playheads}. Each playhead can play either a stream of PCM samples or a tracker track, and the four are mixed together to the card's native output of 32\,kHz stereo.
The playheads are not locked to one another, so timing between them is not guaranteed. A single piece of music should therefore live on a single playhead; the remaining playheads are best used for sound effects or left idle.
\section{PCM Playback}
\index{PCM playback}In PCM mode a playhead is fed a queue of raw samples, which the card plays back at the hardware rate. This is the path used by the \thedos\ players for raw PCM, WAV/ADPCM, MP2 and \thedos's own compressed audio --- a player decodes the file into samples and pushes them into a playhead's queue. The relevant format details are covered, from the listener's point of view, in the \thedos\ part.
\section{Tracker Playback}
\index{tracker engine}In tracker mode a playhead is driven by the card's built-in tracker engine. The engine keeps a pool of digitised \emph{samples}, a set of \emph{instruments} built from them, and the \emph{patterns} and cue sheet that sequence the notes; once these are loaded the playhead renders the song autonomously. This is how \thismachine\ plays its native \textbf{Taud} music.
This guide deliberately stops at that overview. The Taud file format, the instrument and envelope model, the effect commands, and the \emph{Microtone} tracker used to author Taud music are large topics with a manual of their own, and are out of scope here.
\section{The Audio Library}
\index{audio (library)}The \code{audio} namespace controls the playheads. The functions below cover everyday playback; the engine also exposes a large number of tracker-control and voice-inspection calls (pattern and cue upload, tempo, per-voice queries, \dots) that belong with the Taud documentation.
\namespaceis{Audio}{audio}
\begin{outline}
\1\formalsynopsis{setPcmMode}{playhead: Int}{Puts a playhead (0--3) into PCM mode.}
\1\formalsynopsis{setTrackerMode}{playhead: Int}{Puts a playhead into tracker mode.}
\1\formalsynopsis{play}{playhead: Int}{Starts the playhead.}
\1\formalsynopsis{stop}{playhead: Int}{Stops the playhead.}
\1\formalsynopsis{isPlaying}{playhead: Int}[Boolean]{Whether the playhead is currently playing.}
\1\formalsynopsis{getPosition}{playhead: Int}[Int]{Current playback position of the playhead.}
\1\formalsynopsis{setMasterVolume}{playhead: Int, volume: Int}{Sets the playhead's output volume.}
\1\formalsynopsis{setMasterPan}{playhead: Int, pan: Int}{Sets the playhead's stereo pan.}
\1\formalsynopsis{putPcmDataByPtr}{playhead: Int, ptr: Int, length: Int, destOffset: Int}{Copies PCM samples from memory into the playhead's buffer.}
\1\formalsynopsis{purgeQueue}{playhead: Int}{Empties the playhead's pending sample queue.}
\1\formalsynopsis{resetParams}{playhead: Int}{Resets the playhead to default parameters.}
\1\formalsynopsis{getMemAddr}{}[Int]{Returns the base address of the audio adapter's memory space.}
\1\formalsynopsis{getBaseAddr}{}[Int]{Returns the base address of the audio adapter's MMIO area.}
\end{outline}