diff --git a/assets/disk0/tvdos/TVDOS.SYS b/assets/disk0/tvdos/TVDOS.SYS index d40ebb5..bb716c9 100644 --- a/assets/disk0/tvdos/TVDOS.SYS +++ b/assets/disk0/tvdos/TVDOS.SYS @@ -248,7 +248,7 @@ _TVDOS.DRV.FS.SERIAL.flush = (fd) => { } _TVDOS.DRV.FS.SERIAL.getFileLen = (fd) => { - if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`) + if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.fullPath}`) let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter) com.sendMessage(port[0], "GETLEN") @@ -264,7 +264,7 @@ _TVDOS.DRV.FS.SERIAL.getFileLen = (fd) => { // TODO pread replaces DMA.comToRam // TODO pwrite replaces DMA.ramToCom _TVDOS.DRV.FS.SERIAL.sread = (fd) => { - if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`) + if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.fullPath}`) let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter) com.sendMessage(port[0], "READ") @@ -313,7 +313,7 @@ _TVDOS.DRV.FS.SERIAL.isDirectory = (fd) => { return (response === 0) } _TVDOS.DRV.FS.SERIAL.listFiles = (fd) => { - if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.path}`) + if (129 == _TVDOS.DRV.FS.SERIAL._openr(fd)) throw Error(`No such file: ${fd.fullPath}`) let port = _TVDOS.DRV.FS.SERIAL._toPorts(fd.driveLetter) com.sendMessage(port[0], "LISTFILES") @@ -713,15 +713,15 @@ files.reservedNames = ["AUX", // unused "ZERO"] // /dev/zero /** This function only creates a file descriptor; will not actually interact with the drives yet. */ -files.open = (fullpath) => { - if (files.reservedNames.includes(fullpath.toUpperCase())) { - return new TVDOSFileDescriptor(fullpath.toUpperCase()) +files.open = (fullPath) => { + if (files.reservedNames.includes(fullPath.toUpperCase())) { + return new TVDOSFileDescriptor(fullPath.toUpperCase()) } - if (fullpath[2] != '/' && fullpath[2] != '\\') throw Error("Expected full path with drive letter, got " + fullpath) - let driveLetter = fullpath[0].toUpperCase() + if (fullPath[2] != '/' && fullPath[2] != '\\') throw Error("Expected full path with drive letter, got " + fullPath) + let driveLetter = fullPath[0].toUpperCase() let driver = _TVDOS.DRIVEFS[driveLetter] - return new TVDOSFileDescriptor(fullpath, driver) + return new TVDOSFileDescriptor(fullPath, driver) } @@ -735,14 +735,15 @@ const inputwork = {}; inputwork.keymap = []; input.changeKeyLayout = function(name) { - let res0 = filesystem.open("A",`tvdos/${name.toLowerCase()}.key`,"R"); - if (res0 != 0 && inputwork.keymap.length == 0) throw new Error(`I/O Error ${res0} - A:\\tvdos\\${name.toLowerCase()}.key`); + let f = files.open(`A:/tvdos/${name.toLowerCase()}.key`) + let res0 = f.sread().trim() + if (res0.length == 0 && inputwork.keymap.length == 0) throw new Error(`I/O Error on ${f.fullPath}`) try { - inputwork.keymap = eval(filesystem.readAll("A")); + inputwork.keymap = eval(res0) } catch (e) { - printerrln(e); - return -1; + printerrln(e) + return -1 } } @@ -925,10 +926,10 @@ Object.freeze(unicode); /////////////////////////////////////////////////////////////////////////////// // install other stuffs -filesystem.open("A", "tvdos/gl.js", "R"); -const GL = eval(filesystem.readAll("A")); +let glfile = files.open("A:/tvdos/gl.js") +const GL = eval(glfile.sread()) -let checkTerm = `if (sys.peek(-49)&1) throw new InterruptedException();`; +let checkTerm = `if (sys.peek(-49)&1) throw new InterruptedException();` let injectIntChk = (s, n) => { // primitive way of injecting a code; will replace a JS string that matches the regex... let k = s @@ -959,6 +960,6 @@ var execApp = (cmdsrc, args, appname) => { // Boot script serial.println("TVDOS.SYS initialised, running boot script..."); var _G = {}; -filesystem.open("A", "tvdos/bin/command.js", "R"); -eval(`var _AUTOEXEC=function(exec_args){${filesystem.readAll("A")}\n};` + +let cmdfile = files.open("A:/tvdos/bin/command.js") +eval(`var _AUTOEXEC=function(exec_args){${cmdfile.sread()}\n};` + `_AUTOEXEC`)(["", "/c", "\\AUTOEXEC.BAT"]) diff --git a/doc/implementation.tex b/doc/implementation.tex index 9dcb4d4..555522f 100644 --- a/doc/implementation.tex +++ b/doc/implementation.tex @@ -153,12 +153,12 @@ Sys library allows programmers to manipulate the system in low-level. \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:$$ (\textrm{peek}(addr)\ \textrm{xor}\ xorMask)\ \textrm{and}\ andMask = 0 $$} +\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 Scratchpad 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:$$ [Malloc\ unit\ size\ ,\ allocated\ block\ counts] $$} +\1\formalsynopsis{getMallocStatus}{}[IntArray(2)]{Returns the \code{malloc} status in following order:$$ [\mathrm{Malloc\ unit\ size,\ allocated\ block\ counts}] $$} \end{outline} diff --git a/doc/tsvmman.idx b/doc/tsvmman.idx index d293c01..197d384 100644 --- a/doc/tsvmman.idx +++ b/doc/tsvmman.idx @@ -25,4 +25,4 @@ \indexentry{file descriptor (DOS)|hyperpage}{34} \indexentry{device file|hyperpage}{36} \indexentry{input (DOS)|hyperpage}{38} -\indexentry{gl (DOS)|hyperpage}{38} +\indexentry{gl (DOS)|hyperpage}{39} diff --git a/doc/tsvmman.ind b/doc/tsvmman.ind index f776bb6..f4ca683 100644 --- a/doc/tsvmman.ind +++ b/doc/tsvmman.ind @@ -25,7 +25,7 @@ \indexspace - \item gl (DOS), \hyperpage{38} + \item gl (DOS), \hyperpage{39} \item graphics (library), \hyperpage{26} \item gzip (library), \hyperpage{11} diff --git a/doc/tsvmman.tex b/doc/tsvmman.tex index e02d84d..b6ea9b7 100644 --- a/doc/tsvmman.tex +++ b/doc/tsvmman.tex @@ -203,6 +203,8 @@ \newcommand{\thepublishingdate}{0000-00-00} \newcommand{\oreallypress}{\begingroup\hspace{0.083em}\large\textbf{O'REALLY\raisebox{1ex}{\scriptsize ?}} \large Press\endgroup} +\newcommand{\argN}[1]{arg\textsubscript{#1}} + \title{\vskip56pt \includegraphics[width=0.555\textwidth]{tsvmlogo_large} \vskip3pt \titlefont\Huge\textbf{PROGRAMMING GUIDE} \\ \Large \vspace{1.2em} For Version \tsvmver\hspace{0.75em}|\hspace{0.75em}\theedition} \date{} \author{} diff --git a/doc/tvdos.tex b/doc/tvdos.tex index 63e0375..f957582 100644 --- a/doc/tvdos.tex +++ b/doc/tvdos.tex @@ -102,7 +102,7 @@ Named pipes can be retrieved on \code{\_G.shell.pipes.*} \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. +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: @@ -112,7 +112,7 @@ 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{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.} @@ -147,7 +147,7 @@ Functions: \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) +\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} @@ -167,7 +167,6 @@ Functions: \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} @@ -179,9 +178,31 @@ Functions: \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}