\chapter{\thedos}

\thedos\ is a Disk Operating System (usually) bundled with the distribution of the \thismachine.

All \thedos-related features requires the DOS to be fully loaded.


\chapter{Bootstrapping}

\index{boot process}\thedos\ goes through follwing progress to deliver the \code{A:\rs} prompt:

\section{Probing Bootable Devices}
The BIOS will probe serial devices to find first bootable drive. If found, port number of the driver is written to the \code{\_BIOS} object, then attempts to load and run the bootloader.

\section{The Bootloader}
The Bootloader is a short program that loads the \code{TVDOS.SYS} file.

\section{TVDOS.SYS}
\thedos.SYS will load system libraries and variables and then will try to run the boot script by executing \code{A:\rs{}AUTOEXEC.BAT}

Boot Procedure:

\begin{enumerate}
 \item define \code{\_TVDOS} objects
 \item probe filesystem devices
 \item initialise DOS variables
 \item install filesystem drivers
 \item install input device drivers
 \item install GL using the external file
 \item execute \code{AUTOEXEC.BAT}
 \begin{enumerate}
  \item execute \code{command.js} with proper arguments
  \item \code{command.js} to initialise \code{shell.*} functions (this includes coreutils and patched version of \code{require})
  \item \code{command.js} to parse and run \code{AUTOEXEC.BAT}
 \end{enumerate}
\end{enumerate}

\section{AUTOEXEC.BAT}

AUTOEXEC can setup user-specific variables (e.g. keyboard layout) and launch the command shell of your choice, \code{COMMAND} is the most common shell.

Variables can be set or changed using \textbf{SET} commands.



\chapter{Coreutils}

\index{coreutils (DOS)}Coreutils are the core ``commands'' of \thedos.

\begin{outline}
\1\dossynopsis{cat}[file]{Reads a file and pipes its contents to the pipe, or to the console if no pipes are specified.}
\1\dossynopsis{cd}[dir]{Change the current working directory. Alias: chdir}
\1\dossynopsis{cls}{Clears the text buffer and the framebuffer if available.}
\1\dossynopsis{cp}[from to]{Make copies of the specified file. The source file must not be a directory. Alias: copy}
\1\dossynopsis{date}{Prints the system date. Alias: time}
\1\dossynopsis{dir}[path]{Lists the contents of the specifed path, or the current working directory if no arguments were given. Alias: ls}
\1\dossynopsis{del}[file]{Deletes the file. Aliases: erase, rm}
\1\dossynopsis{echo}[text]{Print the given text or a variable.}
\1\dossynopsis{exit}{Exits the current command processor.}
\1\dossynopsis{mkdir}[path]{Creates a directory. Aliase: md}
\1\dossynopsis{mv}[from to]{Moves or renames the file. Aliase: move}
\1\dossynopsis{rem}{Comment-out the line.}
\1\dossynopsis{set}[key=value]{Sets the global variable \code{key} to \code{value}, or displays the list of global variables if no arguments were given.}
\1\dossynopsis{ver}{Prints the version of \thedos.}
\end{outline}



\chapter{Built-in Apps}

\index{built-in apps (DOS)}Built-in Applications are the programs shipped with the standard distribution of \thedos\ that is written for users' convenience.

This chapter will only briefly list and describe the applications.

\begin{outline}
\1\dossynopsis{basica}{Invokes a BASIC interpreter stored in the ROM. If no BASIC rom is present, nothing will be done.}
\1\dossynopsis{basic}{If your system is bundled with a software-based BASIC, this command will invoke the BASIC interpreter stored in the disk.}
\1\dossynopsis{color}{Changes the background and the foreground of the active session.}
\1\dossynopsis{command}{The default text-based DOS shell. Call with \code{command -fancy} for more \ae sthetically pleasing looks.}
\1\dossynopsis{decodeipf}[file]{Decodes the IPF-formatted image to the framebuffer using the graphics processor.}
\1\dossynopsis{drives}{Shows the list of the connected and mounted disk drives.}
\1\dossynopsis{edit}[file]{The interactive full-screen text editor.}
\1\dossynopsis{encodeipf}[1/2 imagefile ipffile]{Encodes the given image file (.jpg, .png, .bmp, .tga) to the IPF format using the graphics hardware.}
\1\dossynopsis{false}{Returns errorlevel 1 upon execution.}
\1\dossynopsis{geturl}[url]{Reads contents on the web address and store it to the disk. Requires Internet adapter.}
\1\dossynopsis{hexdump}[file]{Prints out the contents of a file in hexadecimal view. Supports pipe.}
\1\dossynopsis{less}[file]{Allows user to read the long text, even if they are wider and/or taller than the screen. Supports pipe.}
\1\dossynopsis{playmov}[file]{Plays tsvmmov-formatted video. Use -i flag for playback control.}
\1\dossynopsis{playmp2}[file]{Plays MP2 (MPEG-1 Audio Layer II) formatted audio. Use -i flag for playback control.}
\1\dossynopsis{playpcm}[file]{Plays raw PCM audio. Use -i flag for playback control.}
\1\dossynopsis{playwav}[file]{Plays linear PCM/ADPCM audio. Use -i flag for playback control.}
\1\dossynopsis{printfile}[file]{Prints out the contents of a textfile with line numbers. Useful for making descriptive screenshots.}
\1\dossynopsis{touch}[file]{Updates a file's modification date. New file will be created if the specified file does not exist.}
\1\dossynopsis{true}{Returns errorlevel 0 upon execution.}
\1\dossynopsis{zfm}{Z File Manager. A two-panel graphical user interface to navigate the system using arrow keys. Hit Z to switch panels.}
\end{outline}



\chapter{Writing Your Own Apps}

\index{user apps (DOS)}User-made Applications are basically a standard Javascript program, but \thedos\ provides DOS extensions for convenience.

User apps are invoked through \thedos\ to inject the command-line arguments and some necessary functionalities.

\section{Command-line Arguments}

The command line arguments are given via the array of strings named `exec\_args`.

Index zero holds the name used to invoke the app, and the rest hold the actual arguments.


\section{Invoking Coreutils on the user Apps}

DOS coreutils and some of the internal functions can be used on Javascript program.

To invoke the coreutils, use \code{\_G.shell.coreutils.*}

\begin{outline}
\1\inlinesynopsis[\_G.shell]{resolvePathInput}[path]{Returns path object for the input path, relative to the current working directory. Object contains:}
 \2\argsynopsis{full}{fully-qualified path}
 \2\argsynopsis{string}{fully-qualified path without the drive letter}
 \2\argsynopsis{drive}{drive letter of the path}
 \2\argsynopsis{pwd}{working directory for the path}
\1\inlinesynopsis[\_G.shell]{getPwdString}[]{Returns the current working directory as a string.}
\1\inlinesynopsis[\_G.shell]{getCurrentDrive}[]{Returns the drive letter of the current working drive.}
\1\inlinesynopsis[\_G.shell]{execute}[command]{Executes the DOS command.}
\end{outline}


\section{Termination Check Injection}

Due to the non-preemptive nature of the virtual machine, the termination\footnote{Default key combination: Shift+Ctrl+T+R} signal must be explicitly captured by the app, and taking care of it by yourself can be extremely tedious. Fortunately \thedos\ parses the user-written program and injects those checks accordingly.

While- and For-loops are always have such checks injected, but the `read()` is not checked for the termination.


\chapter{Pipes}

\index{pipe (DOS)}Pipe is a way to chain the IO of the one program/command into the different programs/commands in series.

A pipe can be either named or anonymous: named pipes are ones that are created by the user while the anonymous pipes are created by the DOS process as a result of the command pipelining.

\section{Command Pipelining}

In \thedos, a pipe can be used to route the output of a command into the other command. For example, \code{dir | less} will route the output of the \code{dir} into the text viewer called \code{less} so that the user can take their time examining the list of files in the directory, even if the list is taller that the terminal's height.

\section{User-defined Pipe}

A user program can create and interact with the pipe so long as it's \emph{named}. The contents of the pipe can be read and modified just like a Javascript variable.

Named pipes can be retrieved on \code{\_G.shell.pipes.*}

\section{Pipe-related Functions}

\begin{outline}
\1\inlinesynopsis[\_G.shell]{getPipe}[]{Returns the currently opened pipe. \code{undefined} is returned if no pipes are opened.}
\1\inlinesynopsis[\_G.shell]{appendToCurrentPipe}[text]{Appends the given text to the current pipe.}
\1\inlinesynopsis[\_G.shell]{pushAnonPipe}[contents]{Pushes an anonymous pipe to the current pipe stack.}
\1\inlinesynopsis[\_G.shell]{pushPipe}[pipeName, contents]{Pushes the pipe of given name to the current pipe stack.}
\1\inlinesynopsis[\_G.shell]{hasPipe}[]{Returns true if there is a pipe currently opened.}
\1\inlinesynopsis[\_G.shell]{removePipe}[]{Destroys the currently opened pipe and returns it. Any pipes on the pipe stack will be shifted down to become the next current pipe.}
\end{outline}


\chapter{File I/O}
\index{filesystem (DOS)}In \thedos, drives are assigned with a drive letter, and the drive currently booted on is always drive \textbf{A}.


\section{The File Descriptor}
\index{file descriptor (DOS)}A file is virtualised through the \emph{file descriptor} which provides the functions to manipulate the file. Do note that when a file descriptor is created, the file is not yet opened by the drive.

To create a file descriptor, use the provided function \code{files.open(fullPath)}. \code{fullPath} is a fully qualified path of the file that includes the drive letter.

\section{Manipulating a File}
A file has folliwing properties and can be manipulated using following functions:

Properties:

\begin{outline}
\1\propertysynopsis{size}{Int}{Returns a size of the file in bytes.}
\1\propertysynopsis{path}{String}{Returns a path (NOT including the drive letter) of the file. Paths are started with, and separated using reverse solidus.}
\1\propertysynopsis{fullPath}{String}{Returns a fully qualified path (including the drive letter) of the file. Paths are separated using reverse solidus.}
\1\propertysynopsis{driverID}{String}{Returns a filesystem driver ID associated with the file.}
\1\propertysynopsis{driver}{[Object object]}{Returns a filesystem driver (a Javascript object) for the file.}
\1\propertysynopsis{isDirectory}{Boolean}{Returns true if the path is a directory.}
\1\propertysynopsis{name}{String}{Returns the name part of the file's path.}
\1\propertysynopsis{parentPath}{String}{Returns a parent path of the file.}
\1\propertysynopsis{exists}{Boolean}{Returns true if the file exists on the device.}
\end{outline}

Functions:

\begin{outline}
\1\formalsynopsis{pread}{pointer: Int, count: Int, offset: Int}{Reads the file bytewise and puts it to the memory starting from the pointer.}
 \2\argsynopsis{count}{how many bytes to read}
 \2\argsynopsis{offset}{when reading a file, how many bytes to skip initially}
\1\formalsynopsis{bread}{}[Array]{Reads the file bytewise and returns the content in Javascript array.}
\1\formalsynopsis{sread}{}[String]{Reads the file textwise and returns the content in Javascript string.}
\1\formalsynopsis{pwrite}{pointer: Int, count: Int, offset: Int}
{Writes the bytes stored in the memory starting from the pointer to file.\\Note: due to the limitation of the protocol, the non-zero offset is not supported on the serial-connected disk drives.}
 \2\argsynopsis{count}{how many bytes to write}
 \2\argsynopsis{offset}{when writing to the file, how many bytes on the file to skip before writing a first byte.}
\1\formalsynopsis{bwrite}{bytes: Uint8Array}{Writes the bytes to the file.}
\1\formalsynopsis{swrite}{string: String}{Writes the string to the file.}
\1\formalsynopsis{pappend}{pointer: Int, count: Int}{Appends the bytes stored in the memory starting from the pointer to the end of the file.}
\2\argsynopsis{count}{how many bytes to write}
\1\formalsynopsis{bappend}{bytes: Uint8Array}{Appends the bytes to the end of the file.}
\1\formalsynopsis{sappend}{string: String}{Appends the string to the end of the file.}
\1\formalsynopsis{flush}{}{Flush the contents on the write buffer to the file immediately. Will do nothing if there is no write buffer implemented --- a write operation will always be performed imemdiately in such cases.}
\1\formalsynopsis{close}{}{Tells the underlying device (usually a disk drive) to close a file. When dealing with multiple files on a single disk drive (in which can only have a single active---or opened---file), the underlying filesystem driver will automatically swap the files around, so this function is normally unused.}
\1\formalsynopsis{list}{}[Array or undefined]{Lists files inside of the directory. If the path is indeed a directory, an array of file descriptors will be returned; \code{undefined} otherwise.}
\1\formalsynopsis{touch}{}[Boolean]{Updates the file's access time if the file exists; a new file will be created otherwise. Returns true if successful.}
\1\formalsynopsis{mkDir}{}[Boolean]{Creates a directory to the path. Returns true if successful.}
\1\formalsynopsis{mkFile}{}[Boolean]{Creates a new file to the path. Returns true if successful.}
\1\formalsynopsis{remove}{}[Boolean]{Removes a file. Returns true if successful.}
\end{outline}


\section{The Device Files}

\index{device file}Some devices are also virtualised through the file descriptor, and they are given a special drive letter of \code{\$}. (e.g. \code{\$:\rs{}RND})

\begin{outline}
\1\inlinesynopsis{RND}{returns random bytes upon reading}
 \2\argsynopsis{pread}{returns the specified number of random bytes}
\1\inlinesynopsis{NUL}{returns EOF upon reading}
 \2\argsynopsis{pread}{returns the specified number of EOFs}
 \2\argsynopsis{bread}{returns an empty array}
 \2\argsynopsis{sread}{returns an empty string}
\1\inlinesynopsis{ZERO}{returns zero upon reading}
 \2\argsynopsis{pread}{returns the specified number of zeros}
\1\inlinesynopsis{CON}{manipulates the screen text buffer, disregarding the colours}
 \2\argsynopsis{pread}{reads the texts as bytes.}
 \2\argsynopsis{bread}{reads the texts as bytes.}
 \2\argsynopsis{sread}{reads the texts as a string.}
 \2\argsynopsis{pwrite}{writes the bytes from the given pointer.}
 \2\argsynopsis{bwrite}{identical to \code{print()} except the given byte array will be casted to string.}
 \2\argsynopsis{swrite}{identical to \code{print()}.}
\1\inlinesynopsis{FBIPF}{decodes IPF-formatted image to the framebuffer. Use the bundled \code{encodeipf.js} for the encoding.}
 \2\argsynopsis{pwrite, bwrite}{decodes the given IPF binary data. Offsets and counts for \code{pwrite} are ignored.}
\end{outline}



\chapter{Input Event Handling}

\thedos\ provides the library for handling the keyboard and mouse events.

\dosnamespaceis{Input}{input}

\begin{outline}
\1\inlinesynopsis{changeKeyLayout}[layoutName]{Changes the key layout. The key layout file must be stored as \code{A:\rs{}tvdos\rs{}layoutName.key}}
\1\inlinesynopsis{withEvent}[callback]{Invokes the callback function when an input event is available.}
\end{outline}

\subsection{Input Events}

Input events are Javascript array of: $$ [\mathrm{event\ name,\ arg_1,\ arg_2 \cdots arg_n}] $$, where:

\begin{outline}
\1event name --- one of following: \textbf{key\_down}, \textbf{mouse\_down}, \textbf{mouse\_move}
\1arguments for \textbf{key\_down}:
 \2\argsynopsis{\argN{1}}{Key Symbol (string) of the head key}
 \2\argsynopsis{\argN{2}}{Repeat count of the key event}
 \2\argsynopsis{\argN{3}..\argN{10}}{The keycodes of the pressed keys}
\1arguments for \textbf{mouse\_down}:
 \2\argsynopsis{\argN{1}}{X-position of the mouse cursor}
 \2\argsynopsis{\argN{2}}{Y-position of the mouse cursor}
 \2\argsynopsis{\argN{3}}{Always the integer 1.}
\1arguments for \textbf{mouse\_move}:
 \2\argsynopsis{\argN{1}}{X-position of the mouse cursor}
 \2\argsynopsis{\argN{2}}{Y-position of the mouse cursor}
 \2\argsynopsis{\argN{3}}{1 if the mouse button is held down (i.e. dragging), 0 otherwise}
 \2\argsynopsis{\argN{4}}{X-position of the mouse cursor on the previous frame (previous V-blank of the screen)}
 \2\argsynopsis{\argN{5}}{Y-position of the mouse cursor on the previous frame}
\end{outline}



\chapter{The Graphics Library}

\thedos\ provides the library for drawing pixels to the screen.

\dosnamespaceis{Graphics}{GL}

Classes:

\begin{outline}
\1\inlinesynopsis[new GL]{Texture}[width: Int, height: Int, bytes: Uint8Array]{Creates an GL Texture.}
\1\inlinesynopsis[new GL]{MonoTex}[width: Int, height: Int, bytes: Uint8Array]{Creates an 1bpp Texture.}
\1\inlinesynopsis[new GL]{SpriteSheet}[tileWidth: Int, tileHeight: Int, texture: Texture or MonoTex]{Creates an Spritesheet backed by the given texture.}
\end{outline}

Functions:

\begin{outline}
\1\formalsynopsis{drawTexImage}{texture, x, y, framebuffer, fgcol, bgcol}{Draws the texture to the framebuffer. Transparency will be ignored.}
 \2\argsynopsis{texture}{A pattern to draw. Must be an instance of the GL.Texture or GL.MonoTex.}
 \2\argsynopsis{x, y}{Top-left position of the painting area}
 \2\argsynopsis{framebuffer}{The target framebuffer on which the patterns are to be painted}
 \2\argsynopsis{fgcol, bgcol}{Fore- and background colour for the GL.MonoTex.}
\1\formalsynopsis{drawTexImageOver}{texture, x, y, framebuffer, fgcol}{Same as the \code{drawTexImage} except the transparency will be taken into account.}
\1\formalsynopsis{drawTexPattern}{texture, x, y, width, height, framebuffer, fgcol, bgcol}{Fills the given area with the texture by tiling it. Transparency will be ignored.}
 \2\argsynopsis{texture}{A pattern to draw. Must be an instance of the GL.Texture or GL.MonoTex.}
 \2\argsynopsis{x, y}{Top-left position of the painting area}
 \2\argsynopsis{width, height}{Width and the height of the painting area}
 \2\argsynopsis{framebuffer}{The target framebuffer on which the patterns are to be painted}
 \2\argsynopsis{fgcol, bgcol}{Fore- and background colour for the GL.MonoTex.}
\1\formalsynopsis{drawTexPatternOver}{texture, x, y, width, height, framebuffer, fgcol}{Same as the \code{drawTexPattern} except the transparency will be taken into account.}
\1\formalsynopsis{drawSprite}{sheet, xi, yi, x, y, framebuffer, overrideFG, overrideBG}{Paints the sprite to the framebuffer. Transparency will be ignored.}
 \2\argsynopsis{xi, yi}{XY-index in the Spritesheet, zero-based.}
 \2\argsynopsis{x, y}{Top-left position on the framebuffer where the sprite will be drawn into.}
 \2\argsynopsis{overrideFG, overrideBG}{Optional; if specified, non-transparent pixel in the sprite will take the foreground, and the transparent ones will take the background colour instead of their original colours.}
\1\formalsynopsis{drawSpriteOver}{sheet, xi, yi, x, y, framebuffer, overrideFG}{Same as the \code{drawSprite} except the transparency will be taken into account.}

\end{outline}



\chapter{External Libraries}


External libraries are packaged codes with the intention of being re-used by other programs, and can be loaded using the \code{require()} function.

\section{Loading the Libraries}

External libraries can be stored in following locations:

\begin{enumerate}
 \item \code{A:\rs{}tvdos\rs{}include}
 \item a path relative to the user program
 \item an absolute path that can be anywhere
\end{enumerate}

and can be loaded by:

\begin{enumerate}
 \item \code{let name = require(libraryname)} // no .js extension
 \item \code{let name = require(./libraryname)} // the relative path must start with a dot-slash
 \item \code{let name = require(A:/path/to/library.js)} // full path WITH the .js extension
\end{enumerate}


\section{Writing Your Own Libraries}

Codes in the library must be exported to be made available to other programs, and \thedos\ provides \code{exports} variable for the purpose.

Functions and variables can be exported by defining the \code{exports} object; example code:

\begin{lstlisting}
function foo() {
    println("Hello, module!")
}
const BAR = 127

// following line exports the function and the variable
exports = { foo, BAR }
\end{lstlisting}