###

# DOjS

## A DOS JavaScript Canvas with sound.

DOjS is a JavaScript programming environment for systems running MS-DOS, FreeDOS or any DOS based Windows (like 95, 98, ME). It features an integrated editor, graphics & sound output, mouse/keyboard/joystick input and more (see below). It was inspired by Processing which is described on Wikipedia as:

> Processing is an open-source graphical library and integrated development environment (IDE) / playground built for the electronic arts, new media art, and visual design communities with the purpose of teaching non-programmers the fundamentals of computer programming in a visual context.

It also has a p5js compatibility mode where some of the functions of p5js are available and scripts can have a similar structure to Processing sketches.

You can type in a script with the builtin or your favorite text editor and then run it on a DOS command prompt.

DOjS is pronounces like doge, but ending with an "s".

DOjS was only possible due to the work of these people/projects:

- MuJS JavaScript interpreter
- The Allegro library
- DJGPP from DJ Delorie and the Linux compile scripts by Andrew Wu.
- The people that contributed to p5js.
- The Glide source cleanup of Ozkan Sezer.

You can find me on Twitter if you want...

# Download and quick start

You can find binary releases on the GitHub release page. Just extract the contents of the archive and run `DOjS.exe`.

DOjS runs in Dosbox and on real hardware or a virtual machine with MS-DOS, FreeDOS or any DOS based Windows like Windows 95/98/ME. To use 3Dfx/Glide support you need a Voodoo card or DOSBox-X (see below).

If you run it on real hardware you need at least a 80386 with 4MB. I recommend a Pentium class machine (>= 100MHz) with at least 32MB RAM. The example files run fine on an Athlon 1GHz and with 256MB RAM.

The following hardware/functions are available:

- 8/16/24 and 32 bit 2D graphics. On 24/32bit display modes alpha channel transparency is available.
- BMP, PCX, TGA and PNG image reading and writing
- GRX font loading and rendering
- Keyboard input
- Mouse input
- Joystick/Joyport input
- File IO
- MIDI output
- WAV output
- Audio input/sampling
- Allegro 3D rendering (software)
- 3dfx/Glide3 3D rendering output (hardware)
- p5js compatibility
- direct io-port access (inb, outb, etc)
- LPT or parallel port access (bi-directional)
- COM or serial port access
- IPX and TCP/IP networking
- ZIP file access

## A minimal script

You can find the following example in `examples/exampl.js`:

    /*
    ** This function is called once when the script is started.
    */
    function Setup() {
        pink = new Color(241, 66, 244, 255); // define the color pink
    }

    /*
    ** This function is repeatedly until ESC is pressed or Stop() is called.
    */
    function Loop() {
        ClearScreen(EGA.BLACK);
        TextXY(SizeX() / 2, SizeY() / 2, "Hello World!", pink, NO_COLOR);

        TextXY(10, 10, "rate=" + GetFramerate(), EGA.BLACK, EGA.LIGHT_BLUE);
    }

    /*
    ** This function is called on any input.
    */
    function Input(event) {
        str = JSON.stringify(event);
    }

Open this script with `DOjS.EXE examples\exampl.js` or use `DOjS.EXE -r examples\exampl.js` to run it without starting the integrated editor first. If the script does not exist the editor loads the template for a new script.

## p5js compatibility

If you want to write scripts using the syntax of p5js you need to use `Include('p5');` as first line of your script. You can find the following example in `examples/examplp5.js`:

    Include('p5');

    /*
    ** This function is called once when the script is started.
    */
    function setup() {
        pink = color(241, 66, 244); // define the color pink
    }

    /*
    ** This function is repeatedly until ESC is pressed or Stop() is called.
    */
    function draw() {
        background(EGA.BLACK);
        stroke(pink);
        fill(pink);
        text("Hello p5js World!", width / 2, height / 2);

        stroke(EGA.LIGHT_BLUE);
        fill(EGA.LIGHT_BLUE);
        text("rate=" + getFrameRate(), 10, 10);
    }

More info can be found at the end of this README in the section Usage and in the API documentation. Take a look at the `examples/` as well.

## 3dfx/Glide support

DOjS supports most of the Glide3 API that was used with 3dfx accelerator cards. The following hardware is supported:

- Voodoo 1 [tested]
- Voodoo 2 [tested]
- Voodoo 3 [tested]
- Voodoo 4 [tested by tunguska]
- Voodoo 5 [tested by tunguska]
- Voodoo Rush (all versions) [tested]
- Voodoo Banshee (PCI and AGP) [tested]

Additionally you can use DOSBox-X which emulates a Voodoo 1 card. Glide functions can be found in the 3dfx-module in the documentation, Javascript support functions have a "FX" prefix, all native functions are prefixed with "fx". Detailed Glide3-API documentation can be found on the internet, e.g. on FalconFly Central. Make sure you grab the Glide3 SDK and not Glide2!

You can use the included DOS version of `TEXUS.EXE` to convert bitmaps to `3df` texture files that can be loaded as textures.

!!! Attention !!! 3dfx/Glide3 support ONLY works in plain DOS, NOT in the DOS/command window of Windows 9x! Be sure to always boot into a pure DOS prompt before trying to use any of the fx-functions! Before using 3dfx/Glide3 support you need to copy the appropriate `GLIDE3X.DXE` into the same directory as `DOJS.EXE`. You can do so by using the `V_XXX.BAT` scripts in the distribution ZIP archive.

# Compilation

You can compile DOjS on any modern Linux (the instructions below are for Debian based distributions) or on Windows 10 using Windows Subsystem for Linux (WSL). Setup Windows Subsystem for Linux (WSL) according to this guide (I used Ubuntu 18.04 LTS).

## Preparation

Build and install DJGPP 7.2.0 according to this guide. I used the following command lines to update/install my dependencies:

    sudo apt-get update
    sudo apt-get dist-upgrade
    sudo apt-get install bison flex curl gcc g++ make texinfo zlib1g-dev g++ unzip htop screen git bash-completion build-essential npm zip dos2unix
    sudo npm install -g jsdoc
    sudo npm install -g better-docs

And the following commands to build and install DJGPP to `/home/ilu/djgpp`.:

    git clone https://github.com/andrewwutw/build-djgpp.git
    cd build-djgpp
    export DJGPP_PREFIX=/home/ilu/djgpp
    ./build-djgpp.sh 7.2.0

## Getting & Compiling DOjS

Open a shell/command line in the directory where you want the source to reside.

Checkout DOjS from Github:

    git clone https://github.com/SuperIlu/DOjS.git

Open the `Makefile` and `3dfx/texus/Makefile` in a text editor and change the path to DJGPP according to your installation. If you used Windows-Tools to check out DOjS from git you may need to fix the newlines of the shell scripts by using `make fixnewlines`.

Now you are ready to compile DOjS with `make clean all`. This might take some time as the dependencies are quite a large. `make distclean` will clean dependencies as well. `make zip` will create the distribution ZIP and `make doc` will re-create the HTML help.

## 3dfx/Glide3

In order to compile DOjS you need Glide3 includes and binaries. The ones included with the DOjS sources were created using my glide repository on GitHub.

# History

See the changelog for the projects history.

# Planed work

- Error popup in the editor.
- TCP/IP remote logging/debugging.
- Add ZIP file functions (e.g. https://libzip.org/users/ or https://github.com/kuba--/zip).
  - Implement 3df file loading from ZIP
- Make FreeDOS package.
- Replace PNG loading with http://alpng.sourceforge.net/ to reduce DOjS size
- Implement HTTP client by using cURL or similar (https://www.watt-32.net/misc/)
  - look into HTTPS
- add/implement some more math functions
  - https://mathjs.org/
  - https://github.com/evanw/lightgl.js
- Try to speed up `ReadBytes()` and `WriteBytes()` by not using JS arrays
- Fix bugs!
- Anything fun...

# Licenses

## DOjS

All code from me is released under MIT license.

## MuJS

MuJS is released under ISC license. See COPYING in the MuJS folder for details.

## Allegro

Allegro 4 is released under the Giftware license (https://liballeg.org/license.html).

## GRX fonts

The GRX fonts are under MIT and other licenses. See copying.grx in `LICENSE` for details. The converted fonts from the Linux Font Project are in the public domain.

## IPX and dosbuffer sub-system

This code is taken from the game Cylindrix by Hotwarez LLC, Goldtree Enterprises. It was released under GPLv2.

## CWSDPMI.EXE

CWSDPMI DPMI host is licensed under GPL. The documentation states:

> The files in this binary distribution may be redistributed under the GPL (with source) or without the source code provided.

## 3dfx/Glide3

The code is licensed under "3DFX GLIDE Source Code General Public License". Source code is available at https://github.com/SuperIlu/glide

## DZComm

DZComm serial library is release as gift-ware. See readme.txt in the dzcomm folder for details.

## Logo

The DOjS logo dog was downloaded from Pexels and kindly provided by Iago Garcia Garcia.

The logo font is Comic relief by Jeff Davis provided under SIL OPEN FONT LICENSE Version 1.1.

## WAVs

All WAV files were downloaded from BigSoundBank and are licensed under WTFPL

- https://bigsoundbank.com/detail-0283-song-of-rooster.html
- https://bigsoundbank.com/detail-1102-bell-bike-5.html
- https://bigsoundbank.com/detail-1023-explosion-far-away.html

## MIDs

The MIDI files were downloaded from the FreeDOOM project and are licensed under this license.

## p5js and examples

p5js is is released under LGPL.

The examples are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

## libpng

libpng is released under PNG Reference Library License version 2

## zlib

zlib is released under zlib license.

## loadpng

loadpng is placed in the public domain.

## zip code

zip is licensed by UNLICENSE

## WATTCP

WATTCP - TCP/IP library routines

Copyright (c) 1990, 1991, 1992, 1993 Erick Engelke

Portions Copyright (c) 1993 Quentin Smart Portions Copyright (c) 1991 University of Waterloo Portions Copyright (c) 1990 National Center for Supercomputer Applications Portions Copyright (c) 1990 Clarkson University Portions Copyright (c) 1983, 1986, Imagen Corporation

    This software is distributed in the hope that it will be useful,
    but without any warranty; without even the implied warranty of
    merchantability or fitness for a particular purpose.

RESTRICTIONS You may freely use this library to produce programs which you may give away or sell in source format, or as compiled executables, or both.

You may not sell this library or a portion thereof or distribute modified versions the library code in either source or OBJect or LIBrary format without written permission from the author. The author still maintains copyright privileges and will assert the privileges of ownership for purposes of royalties such distributions.

Portions of this code were written or enhanced by others and offerred to me for distribution in WATTCP under my copyright. To my knowledge, all copyrights exercised are listed at the top of this file. If this is incorrect, please contact me so I can rectify the situation.

# Usage

## Command line

    Usage: DOjS.EXE [-r] [-l] [-s] [-f] [-a] <script> [script parameters]
        -r             : Do not invoke the editor, just run the script.
        -l             : Use 50-line mode in the editor.
        -w <width>     : Screen width: 320 or 640, Default: 640.
        -b <bpp>       : Bit per pixel:8, 16, 24, 32. Default: 32.
        -s             : No wave sound.
        -f             : No FM sound.
        -a             : Disable alpha (speeds up rendering).
        -x             : Allow raw disk write (CAUTION!)

## Editor keys

        F1        : Open/Close help
        SHIFT-F1  : Function context help
        F3        : Save script
        F4        : Run script
        F7        : Find text
        F9        : Show/Close logfile
        F10       : Quit

        Shift-F4       : Truncate logfile and run script
        Shift-F7       : Find again
        CTRL-D         : Delete current line
        SHIFT+Movement : Select text, releasing SHIFT deselects
        CTRL-C         : Copy selection
        CTRL-X         : Cut selection
        CTRL-V         : Paste
        CTRL-LEFT      : Previous word
        CTRL-RIGHT     : Next word
        CTRL/PAGE-UP   : One page up
        CTRL/PAGE-DOWN : One page down
        HOME           : Go to start of line
        END            : Go to end of line
        CTRL-HOME      : Go to start of line
        CTRL-END       : Go to end of line
        TAB            : Insert spaces until next TAB-stop at cursor
        SHIFT-TAB      : Reduce indentation of line

        TAB size is 4.
        The help viewer will remember the current position.

        The logfile can be truncated by pressing DEL in the log viewer.

## Scripts and resources

Scripts, as well as resources can either be stored in the file system or in ZIP files. To load data from a zip file the format is `<ZIP filename>=<ZIP entry name>` (e.g. `data.zip=mypic.bmp`). DOjS can be started with a script, a script in a ZIP file or no parameters. If the script was loaded from a ZIP file the running script can obtain resources from the same ZIP file by using `ZipPrefix()` to obtain paths refering to that ZIP. If the script was not started from a ZIP `ZipPrefix()` just passes through the file name (thus loading the file from HDD). If no arameters are supplied DOjS will first try to load `<name of the EXE>.ZIP=MAIN.JS` and then `JSBOOT.ZIP=MAIN.JS`. Examples:

- `DOJS.EXE -r script.js` will start `script.js` from the HDD, `ZipPrefix("pic.bmp")` will yield `pic.bmp`.
- `DOJS.EXE -r data.zip=script.js` will start `script.js` from the ZIP file `data.zip`, `ZipPrefix("pic.bmp")` will yield `data.zip=pic.bmp`.
- `HURTZ.EXE` DOjS was renamed to `HURTZ.EXE`. It will start `MAIN.JS` from the ZIP file `HURTZ.ZIP`, `ZipPrefix("pic.bmp")` will yield `HURTZ.ZIP=pic.bmp`.
- `DOJS.EXE` The script was added to `JSBOOT.ZIP`. DOjS will start `MAIN.JS` from the ZIP file `JSBOOT.ZIP`, `ZipPrefix("pic.bmp")` will yield `JSBOOT.ZIP=pic.bmp`.

## API documentation

You can find the full API doc in the doc/html/ directory. Go to the p5.js hompage for p5.js reference.

## Script format

Scripts need to provide three functions: `Setup()`, `Loop()` and `Input()`. Scripts are loaded and executed top-own. After that `Setup()` is called once and then `Loop()` repeatedly. `Input()` is called whenever mouse of keyboard input happens.

### Setup()

This function is called once at startup. It can initialize variables, setup hardware, etc.

### Loop()

This function is called after setup repeatedly until `Stop()` is called. After calling `Stop()` the program ends when `Loop()` exits.

### Input(event)

This function is called whenever mouse/keyboard input happens.

## IPX networking

DOjS supports IPX networking. Node addresses are arrays of 6 numbers between 0-255. Default socket number and broadcast address definitions can be found in `jsboot/ipx.js`.

## Drawing functions

See API doc for details.

## Processing/p5js compatibility layer

Add `Include('p5');` as first line to your script. After that you have (limited) p5.js compatibility. Things that don't work:

- Anything 3D (objects, lights camera, etc)
- Key release events work different for Allegro and are simulated for p5js.
- Only simple vertices are supported.
- no DOM

## Logfile

All output via `Print()` and `Println()` is sent to the file `JSLOG.TXT`. You can use `Debug()` instead and output is only generated when you set the global variable `DEBUG=true`.

## Remote logging/debugging

This feature allows you to debug a running script via IPX networking and a second machine. To use remote logging do the following:

- Put both machines on the same network.
- Run `DOJS.EXE -r JSBOOT\LOGVIEW.JS` on one machine.
- Enable debugging by setting `DEBUG=true` and enable remote debugging by `REMOTE_DEBUG=true`. You can either modify `JSBOOT\FUNC.JS` or change the variables at the very beginning of your script.

This works fine with two instances of DOSBox as well. Please note that if the log messages are transmitted to fast the receiving instance of DOJS might skip some of these when displaying.