diff --git a/docs/modding/local-doors.md b/docs/modding/local-doors.md index b5c56f9c..06b80ac1 100644 --- a/docs/modding/local-doors.md +++ b/docs/modding/local-doors.md @@ -10,37 +10,48 @@ The `abracadabra` module provides a generic and flexible solution for many door ### Configuration The `abracadabra` `config` block can contain the following members: -* `name`: Used as a key for tracking number of clients using a particular door. -* `dropFileType`: Specifies the type of drop file to generate (See **Argument Variables** below). -* `cmd`: Path to executable to launch. -* `args`: Array of argument(s) to pass to `cmd`. See below for information on variables that can be used here. -* `cwd`: Set the Current Working Directory for `cmd`. Defaults to the directory of `cmd`. -* `nodeMax`: Max number of nodes that can access this door at once. Uses `name` as a mapping key -* `tooManyArt`: Art file spec to display if too many instances are already in use -* `io`: Where to process I/O. Can be `stdio` or `socket`. When using `stdio`, I/O is input/output from stdin/stdout. When using `socket` a temporary socket server is spawned that can be connected to. The server listens on localhost on `{srvPort}` (see below under Argument Variables). -* `encoding`: Specify the door's encoding. Defaults to `cp437`. Linux binaries for example, often produce `utf8`. -#### Drop File Types -Drop file types specified by `dropFileType`: -* `DOOR`: [DOOR.SYS](http://goldfndr.home.mindspring.com/dropfile/doorsys.htm) -* `DOOR32`: [DOOR32.SYS](https://raw.githubusercontent.com/NuSkooler/ansi-bbs/master/docs/dropfile_formats/door32_sys.txt) -* `DORINFO`: [DORINFOx.DEF](http://goldfndr.home.mindspring.com/dropfile/dorinfo.htm) +| Item | Required | Description | +|------|----------|-------------| +| `name` | :+1: | Used as a key for tracking number of clients using a particular door. | +| `dropFileType` | :+1: | Specifies the type of dropfile to generate (See **Dropfile Types** below). | +| `cmd` | :+1: | Path to executable to launch. | +| `args` | :-1: | Array of argument(s) to pass to `cmd`. See **Argument Variables** below for information on variables that can be used here. +| `cwd` | :-1: | Sets the Current Working Directory (CWD) for `cmd`. Defaults to the directory of `cmd`. | +| `nodeMax` | :-1: | Max number of nodes that can access this door at once. Uses `name` as a tracking key. | +| `tooManyArt` | :-1: | Art spec to display if too many instances are already in use. | +| `io` | :-1: | How to process input/output (I/O). Can be `stdio` or `socket`. When using `stdio`, I/O is handled via standard stdin/stdout. When using `socket` a temporary socket server is spawned that can be connected back to. The server listens on localhost on `{srvPort}` (See **Argument Variables** below for more information). Default value is `stdio`. | +| `encoding` | :-1: | Sets the **door's** encoding. Defaults to `cp437`. Linux binaries often produce `utf8`. | + +#### Dropfile Types +Dropfile types specified by `dropFileType`: + +| Value | Description | +|-------|-------------| +| `DOOR` | [DOOR.SYS](http://goldfndr.home.mindspring.com/dropfile/doorsys.htm) +| `DOOR32` | [DOOR32.SYS](https://raw.githubusercontent.com/NuSkooler/ansi-bbs/master/docs/dropfile_formats/door32_sys.txt) +| `DORINFO` | [DORINFOx.DEF](http://goldfndr.home.mindspring.com/dropfile/dorinfo.htm) #### Argument Variables The following variables may be used in `args` entries: -* `{node}`: Current node number. -* `{dropFile}`: Drop _filename_ only. -* `{dropFilePath}`: Full path to generated drop file. -* `{userId}`: Current user ID. -* `{userName}`: _Sanitized_ username. Safe for filenames, etc. -* `{userNameRaw}`: _Raw_ username. May not be safe for filenames! -* `{srvPort}`: Temporary server port when `io` is set to `socket`. -* `{cwd}`: Current Working Directory. -Example: +| Variable | Description | Example | +|----------|-------------|---------| +| `{node}` | Current node number. | `1` | +| `{dropFile}` | Dropfile _filename_ only. | `DOOR.SYS` | +| `{dropFilePath}` | Full path to generated dropfile. The system places dropfiles in the path set by `paths.dropFiles` in `config.hjson`. | `C:\enigma-bbs\drop\node1\DOOR.SYS` | +| `{userId}` | Current user ID. | `420` | +| `{userName}` | _Sanitized_ username. Safe for filenames, etc. | `izard` | +| `{userNameRaw}` | _Raw_ username. May not be safe for filenames! | `\/\/izard` | +| `{srvPort}` | Temporary server port when `io` is set to `socket`. | `1234` | +| `{cwd}` | Current Working Directory. | `/home/enigma-bbs/doors/foo/` | + +Example `args` member using some variables described above: ```hjson args: [ - "-D", "{dropFile}", "-N", "{node}" + "-D", "{dropFilePath}", + "-N", "{node}" + "-U", "{userId}" ] ``` @@ -63,7 +74,7 @@ $_com1 = "virtual" The line `$_com1 = "virtual"` tells DOSEMU to use `stdio` as a virtual serial port on COM1. -Next, we create a virtual **X** drive for Pimp Wars to live such as `/enigma-bbs/DOS/X/PW` and map it with a custom `autoexec.bat` file within DOSEMU: +Next, we create a virtual **X** drive for Pimp Wars to live such as `/enigma-bbs/DOS/X/PW` and map it with a custom `AUTOEXEC.BAT` file within DOSEMU: ``` @echo off path d:\bin;d:\gnu;d:\dosemu @@ -80,30 +91,70 @@ Note that we also have the [BNU](http://www.pcmicro.com/bnu/) FOSSIL driver inst Finally, let's create a `menu.hjson` entry to launch the game: ```hjson doorPimpWars: { - desc: Playing PimpWars - module: abracadabra - config: { - name: PimpWars - dropFileType: DORINFO - cmd: /usr/bin/dosemu - args: [ - "-quiet", + desc: Playing PimpWars + module: abracadabra + config: { + name: PimpWars + dropFileType: DORINFO + cmd: /usr/bin/dosemu + args: [ + "-quiet", "-f", "/path/to/dosemu.conf", "X:\\PW\\START.BAT {dropFile} {node}" - ], - nodeMax: 1 - tooManyArt: DOORMANY + ], + nodeMax: 1 + tooManyArt: DOORMANY io: stdio - } + } } - ``` -### QEMU with abracadabra -[QEMU](http://wiki.qemu.org/Main_Page) provides a robust, cross platform solution for launching doors under many platforms (likely anwywhere Node.js is supported and ENiGMA½ can run). Note however that there is an important and major caveat: **Multiple instances of a particular door/OS image should not be run at once!** Being more flexible means being a bit more complex. Let's look at an example for running L.O.R.D. under a UNIX like system such as Linux or FreeBSD. +### Shared Socket Descriptors +Due to Node.js limitations, ENiGMA½ does not _directly_ support `DOOR32.SYS` style socket descriptor sharing (other `DOOR32.SYS` features are fully supported). However, a separate binary called [bivrost!](https://github.com/NuSkooler/bivrost) can be used. bivrost! is available for Windows and Linux x86/i686 and x86_64/AMD64. Other platforms where [Rust](https://www.rust-lang.org/) builds are likely to work as well. -Basically we'll be creating a bootstrap shell script that generates a temporary node specific `go.bat` to launch our door. This will be called from `autoexec.bat` within our QEMU FreeDOS partition. +#### Example configuration +Below is an example `menu.hjson` entry using bivrost! to launch a door: + +```hjson +doorWithBivrost: { + desc: Bivrost Example + module: abracadabra + config: { + name: BivrostExample + dropFileType: DOOR32 + cmd: "C:\\enigma-bbs\\utils\\bivrost.exe" + args: [ + "--port", "{srvPort}", // bivrost! will connect this port on localhost + "--dropfile", "{dropFilePath}", // ...and read this DOOR32.SYS produced by ENiGMA½ + "--out", "C:\\doors\\jezebel", // ...and produce a NEW DOOR32.SYS here. + + // + // Note that the final params bivrost! will use to + // launch the door are grouped here. The {fd} variable could + // also be supplied here if needed. + // + "C:\\door\\door.exe C:\\door\\door32.sys" + ], + nodeMax: 1 + tooManyArt: DOORMANY + io: socket + } +} +``` + +Please see the [bivrost!](https://github.com/NuSkooler/bivrost) documentation for more information. + +#### Phenom Productions Releases +Pre-built binaries of bivrost! have been released under [Phenom Productions](https://www.phenomprod.com/) and can be found on various boards. + +#### Alternative Workarounds +Alternative workarounds include Telnet Bridge (`telnet_bridge` module) to hook up Telnet-accessible (including local) door servers -- It may also be possible bridge via [NET2BBS](http://pcmicro.com/netfoss/guide/net2bbs.html). + +### QEMU with abracadabra +[QEMU](http://wiki.qemu.org/Main_Page) provides a robust, cross platform solution for launching doors under many platforms (likely anywhere Node.js is supported and ENiGMA½ can run). Note however that there is an important and major caveat: **Multiple instances of a particular door/OS image should not be run at once!** Being more flexible means being a bit more complex. Let's look at an example for running L.O.R.D. under a UNIX like system such as Linux or FreeBSD. + +Basically we'll be creating a bootstrap shell script that generates a temporary node specific `GO.BAT` to launch our door. This will be called from `AUTOEXEC.BAT` within our QEMU FreeDOS partition. #### Step 1: Create a FreeDOS image [FreeDOS](http://www.freedos.org/) is a free mostly MS-DOS compatible DOS package that works well for running 16bit doors. Follow the [QEMU/FreeDOS](https://en.wikibooks.org/wiki/QEMU/FreeDOS) guide for creating an `freedos_c.img`. This will contain FreeDOS itself and installed BBS doors. @@ -114,7 +165,7 @@ qemu-system-i386 -localtime /home/enigma/dos/images/freedos_c.img -hdb fat:/path ``` With the above you can now copy files from D: to C: within FreeDOS and add the following to it's `autoexec.bat`: -```batch +```bat CALL E:\GO.BAT ``` @@ -146,7 +197,7 @@ unix2dos /home/enigma/dos/go/node$NODE/GO.BAT qemu-system-i386 -localtime /home/enigma/dos/images/freedos_c.img -chardev socket,port=$SRVPORT,nowait,host=localhost,id=s0 -device isa-serial,chardev=s0 -hdb fat:/home/enigma/xibalba/dropfiles/node$NODE -hdc fat:/home/enigma/dos/go/node$NODE -nographic ``` -Note the `qemu-system-i386` line. We're telling QEMU to launch and use localtime for the clock, create a character device that connects to our temporary server port on localhost and map that to a serial device. The `-hdb` entry will represent the D: drive where our drop file is generated, while `-hdc` is the path that `GO.BAT` is generated in (`E:\GO.BAT`). Finally we specify `-nographic` to run headless. +Note the `qemu-system-i386` line. We're telling QEMU to launch and use localtime for the clock, create a character device that connects to our temporary server port on localhost and map that to a serial device. The `-hdb` entry will represent the D: drive where our dropfile is generated, while `-hdc` is the path that `GO.BAT` is generated in (`E:\GO.BAT`). Finally we specify `-nographic` to run headless. For doors that do not *require* a FOSSIL driver, it is recommended to not load or use one unless you are having issues. @@ -154,29 +205,25 @@ For doors that do not *require* a FOSSIL driver, it is recommended to not load o Finally we can create a `menu.hjson` entry using the `abracadabra` module: ```hjson doorLORD: { - desc: Playing L.O.R.D. - module: abracadabra - config: { - name: LORD - dropFileType: DOOR - cmd: /home/enigma/dos/scripts/lord.sh - args: [ - "{node}", - "{dropFile}", - "{srvPort}", - ], - nodeMax: 1 - tooManyArt: DOORMANY - io: socket - } + desc: Playing L.O.R.D. + module: abracadabra + config: { + name: LORD + dropFileType: DOOR + cmd: /home/enigma/dos/scripts/lord.sh + args: [ + "{node}", + "{dropFile}", + "{srvPort}", + ], + nodeMax: 1 + tooManyArt: DOORMANY + io: socket + } } ``` -## Shared Socket Descriptors -As of this writing `DOOR32.SYS` style socket descriptor sharing is **not** supported. Workarounds include using the Telnet Bridge (`telnet_bridge` module) to hook up to local Telnet-accessible door servers such as [NET2BBS](http://pcmicro.com/netfoss/guide/net2bbs.html). - ## Additional Resources - ### DOSBox * [DOSBox-X](https://github.com/joncampbell123/dosbox-x)