Files
tsvm/doc/tvdos.tex
minjaesong 3f521e2fb6 doc update
2022-09-17 23:48:15 +09:00

263 lines
15 KiB
TeX

\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:/} prompt:
\section{Probing Bootable Devices}
BIOS
\section{The Bootloader}
LOADBOOT
Then the Bootsector will try to read and execute \code{A:/tvdos/TVDOS.SYS}
\section{TVDOS.SYS}
\thedos.SYS will load system libraries and variables and then will try to run the boot script by executing \code{A:/AUTOEXEC.BAT}
\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{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{Applications}
\index{applications (DOS)}Applications are the programs shiped 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}{Invokens a BASIC interpreter stored in the ROM. If no BASIC rom is present, nothing will be done.}
\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{edit}{path}{The interactive full-screen text editor.}
\1\dossynopsis{false}{Returns errorlevel 1 upon execution.}
\1\dossynopsis{hexdump}{path}{Prints out the contents of a file in hexadecimal view. Supports pipe.}
\1\dossynopsis{less}{path}{Allows user to read the long text, even if they are wider and/or taller than the screen. Supports pipe.}
\1\dossynopsis{printfile}{path}{Prints out the contents of a textfile with line numbers. Useful for making descriptive screenshots.}
\1\dossynopsis{touch}{path}{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.}
\end{outline}
\chapter{Invoking Coreutils on JS}
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 fully-qualified path of the input path, relative to the current working directory.}
\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}
\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 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{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 (of 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 path. (their fullPath does not contain a drive letter)
\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 \emph{Graphics} library for the encoding.}
\2\argsynopsis{pwrite, bwrite}{decodes the given IPF binary data. Offsets and counts for \code{pwrite} are ignored.}
\end{outline}
\chapter{DOS Libraries}
\section{Input}
\dosnamespaceis{Input}{input}
\begin{outline}
\1\inlinesynopsis{changeKeyLayout}{layoutName}{Changes the key layout. The key layout file must be stored as \code{A:/tvdos/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}
\section{GL}
\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}