Skip to content

Amiga Doors

ENiGMA½ can run Amiga BBS doors written for AmiExpress (the “/X” family) in an Amiga emulator that is built in: the vAmiga core, compiled to WebAssembly and shipped in the enigma-vamiga npm package. There is no external emulator to install, and no Kickstart ROM or Workbench is needed: the package bundles the AROS ROM. The amiga_door module runs the emulator in a worker thread and bridges the caller to it.

ENiGMA½ also runs CLI doors: ordinary AmigaDOS programs that read the keyboard and write the screen through their standard input and output, the way many Amiga BBS games were written. See CLI Doors. And it runs ARexx doors, the /X scripts marked TYPE=AIM, on an image that carries ARexx from your own Workbench 3.1; see ARexx Doors.


  1. A caller picks the menu entry. ENiGMA½ checks nodeMax, that no other session is using the door’s image (for a door that saves its changes), and the caller’s time left.
  2. The first session for a door image boots the emulator (at warp speed, about 0.4 seconds), waits for the shim to say it is ready, and keeps a snapshot of the booted machine in memory. Later sessions restore that snapshot in about 50 ms.
  3. ENiGMA½ hands the shim the user block (name, location, security level, time left, terminal size, and so on) and the door to run. This takes the place of a drop file.
  4. The door runs. Its output goes to the caller, and the caller’s keys go to the door.
  5. When the door ends, the shim reports how it ended. After a clean exit, ENiGMA½ writes the disk changes the session made back to the image file.

Each caller gets an emulator of their own, so one caller per emulator. The emulator is only a copy of the disk; see Persistence for what that means for a door with shared state.


  • The enigma-vamiga package. It is a dependency of ENiGMA½ and is installed with the rest.
  • A door image. A small hard-disk image holding the shim, a startup sequence and the door. See Building a Door Image.
  • Optionally, a Kickstart ROM. The bundled AROS ROM runs most /X doors. If a door needs the real thing, supply your own Kickstart 3.1 ROM with rom. ENiGMA½ does not ship Kickstart; see Licensing.

No ROM is needed. The enigma-vamiga package bundles the AROS replacement Kickstart, published under the AROS Public License 1.1, and every door type runs on it (ARexx doors too, once the ARexx files from a Workbench disk are on the image). The bundled pair is the AROS build of 2026-08-20:

FileSizeCRC32
aros-rom.bin524,288 bytesCDB1F414
aros-ext.bin524,288 bytes6F9A4AD2

This aros-rom.bin carries a fix to AROS’s FFS bitmap handling (enigma-vamiga 0.1.2 and later), which is why its CRC32 differs from the stock AROS build, 7AE94477; the package’s roms/README.md explains the fix. With the bundled ROM an image of any size is safe to write to. A stock AROS ROM, supplied through the rom option, corrupts an FFS volume of more than one bitmap block (about 2032 KB) when a door writes to it, so ENiGMA½ logs a warning at startup when rom is set and the image is bigger than that; keep the image at 2032 KB or less with such a ROM.

Kickstart 3.1, optional. If you own a Kickstart ROM you may use it instead with the rom option: a plain, unencrypted, 524,288-byte image whose file name ends in .rom or .bin (the emulator refuses other extensions before looking at the contents). Kickstart 3.1 is the tested release; the shim needs Kickstart 2.0 or newer. Known-good dumps, by CRC32:

RevisionMachineCRC32
40.63A500 / A600 / A2000FC24AE0D or 88136CA9 (the emulator’s two known dumps); FC8A3FD2 is also widely listed
40.68A12001483A091
40.69A12001D9AA278
40.68A3000EFB239CC
40.68A4000D6BAE334

The A1200 and A500-family builds are the right ones for the machine ENiGMA½ emulates; the A3000 and A4000 builds also boot but carry drivers for hardware the emulator lacks. A ROM the emulator does not recognise still loads, as “Unknown ROM”. To check a file:

Terminal window
python3 -c "import zlib,sys;print('%08X'%zlib.crc32(open(sys.argv[1],'rb').read()))" kick40068-a1200.rom
xxd -l 4 kick40068-a1200.rom # 1114 4ef9 for a plain Kickstart 2.0+ image

Amiga Forever ships its ROMs encrypted: the file is 524,299 bytes and starts with the text AMIROMTYPE1. Decrypt it once with the rom.key from the same folder, since the emulator refuses encrypted files:

Terminal window
python3 misc/amiga_door/tools/decrypt_af_rom.py amiga-os-310-a1200.rom rom.key kick40068-a1200.rom

Kickstart and Workbench are copyrighted (Amiga Corporation; Cloanto’s Amiga Forever is the usual legitimate source). Their licences cover personal systems and say nothing about public servers, which is one more reason the bundled AROS ROM is the default.

Workbench 3.1, needed only for ARexx doors. The AROS ROM has no ARexx, so make_image.sh -w reads RexxMast, rexxsyslib.library, rexxsupport.library, the IEEE math libraries, Rexxc/ and a few C: commands from your own Workbench3.1.adf. A Workbench 3.1 set is six ADF images of 901,120 bytes each: Workbench3.1, Extras3.1, Fonts, Install3.1, Locale and Storage3.1; only the first is read. Amiga Forever ships them unencrypted. For reference, one clean set of dumps has these CRC32 values; other dumps differ in date stamps, and the image builder checks contents rather than checksums:

DiskCRC32
Workbench3.1D233484C
Extras3.132F55078
Fonts63470DE4
Install3.1B631F796
LocaleE0E5DE81
Storage3.14BD38EF4

An image that contains Workbench files is licensed material: keep it on your server and out of any public repository.


A door image is a bare FFS partition (no RDB), named BBS, 4 MB unless the door needs more. Every session carries a copy of the image, so keep it small. It holds:

C/axshim the host shim
Libs/AEDoor.library the library most doors open
S/Startup-Sequence boots straight into the shim
Doors/<name>/... the door, its data files, icons and configuration

Build one with misc/amiga_door/image/make_image.sh. It uses xdftool from amitools, which you install in a Python virtual environment:

Terminal window
python3 -m venv ~/amitools-venv
~/amitools-venv/bin/pip install amitools
XDFTOOL=~/amitools-venv/bin/xdftool \
misc/amiga_door/image/make_image.sh ~/amiga/dreamsweeper.hdf ~/doors/dreamsweeper

The script takes the image to create and one or more door directories. Each directory is copied, layout kept, to Doors/<directory name>/ in the image, so the door above ends up at BBS:Doors/dreamsweeper/.... Give several directories to put several doors on one image. Options: -s SIZE (default 4M), -n VOLUME (default BBS), -x PATH for xdftool, and -f to replace an existing image. When it finishes it lists the image so you can check it.

The door setting names the door’s path inside the image, written with BBS:, for example BBS:Doors/dreamsweeper/dreamsweeper.xim.

Copy these from the door’s archive, keeping its layout under BBS::

  • Data and configuration files the door reads. Some doors will not create their data file and need an empty one to exist; make_image.sh keeps empty files.
  • Icons with tooltypes (<door>.info). /X doors often read their settings from their icon.
  • Screens and bulletins the door displays.

Doors that read files straight from an /X install’s own data (BBS:user.data, BBS:Node<n>/...) are not supported; they may not work.

/X doors are on Aminet under comm/amiex, and many are still distributed by the AmiExpress community; the Up Rough door repository collects thousands of Amiga BBS door archives. Read the AEDoor 2.8 documentation that comes with the door developer kits if a door’s own notes are thin. ENiGMA½ supports XIM doors, which are the ones that talk to a node through AEDoor.library, /X ARexx doors and CLI doors (below). It does not run doors written for the message ports of other BBS software (Paragon, CNet, including CNet’s ARexx doors).


Add an amiga_door module entry to a menu in menu.hjson. name, image and door are required.

ItemRequiredDescription
nameYesDoor name. Used as a key for tracking concurrent sessions.
imageYesPath to the door’s .hdf image.
doorYesAmiga path of the door executable inside the image, such as BBS:Doors/DreamSweeper/dreamsweeper.xim. For an ARexx door, the script’s full path (BBS:Doors/Kickboxing/KickBox.Rexx), with no blanks, quotes or shell characters. XIM and CLI door paths may have blanks but none of the shell characters " * ` $ ; < > |. At most 199 characters, Latin-1, no control characters.
doorTypeNoxim for an AmiExpress XIM door, aim for an /X ARexx door, cli for a CLI door. Default: xim.
consoleModeNoCLI doors only: cooked (line input with echo, like an Amiga Shell window) or raw (each key as typed) until the door picks a mode itself. Default: cooked.
doorDirNoThe door’s current directory. Default: the door’s own directory.
doorArgsNoXIM and ARexx doors: extra arguments after the node number. CLI doors: the door’s whole argument line. {name}, {node}, {level} and {timeleft} are filled in; see CLI Doors. The arguments may be at most 199 characters and the whole command line (door path, node number, arguments) 299, with placeholders counted at their widest; a longer setting is refused.
doorStackNoDoor stack size in bytes, 4096 to 1048576. Default: 32768.
mainlineNoThe /X command line the caller “typed”. Some doors parse it. Default: empty.
romNoPath to a Kickstart ROM. Default: the bundled AROS ROM.
extRomNoPath to an extension ROM. Default: the bundled AROS extension with the bundled ROM, none with your own rom.
cpuNo68000, 68010 or 68EC020. Default: 68EC020.
chipKbNoChip RAM: 256, 512, 1024 or 2048. Default: 512.
slowKbNoSlow RAM, 0 to 1536 in steps of 256. Default: 512.
fastKbNoFast RAM, 0 to 8192 in steps of 64. Default: 8192. The core supports at most 8 MB.
overclockNoCPU speed multiplier, 1 to 16. Default: 1.
nodeMaxNoMaximum concurrent sessions. 0 is unlimited. Default: 0, or 1 when sharedState is true and nodeMax is not set.
sharedStateNoThe door writes state all callers share (high scores, a wall): sets nodeMax to 1 when nodeMax is not set. A door that persists already runs one caller at a time per image. Default: false. See Persistence.
tooManyArtNoArt spec shown when nodeMax is reached or the door’s image is in use by another session.
minTimeLeftMinutesNoRefuse to start if the caller has less time than this left today.
notEnoughTimeArtNoArt spec shown when minTimeLeftMinutes refuses.
encodingNoEncoding of the door’s output. Default: latin1. Any encoding iconv-lite knows.
amigaConsoleNoTranslate the Amiga console’s controls for PC terminals (see Characters and Fonts). Default: true with a Latin-1 encoding, false with any other.
fontNoSyncTERM font for the door’s duration: a font name or alias, or none to leave the caller’s font alone. Default: topaz.
persistNoWrite the door’s disk changes back to the image. Default: true.
persistOnNoThe exit statuses after which to persist: any of ok, carrier, timeout, break, error. Default: ['ok', 'carrier'] for xim doors, ['ok'] for cli and aim doors; a list you give always wins. carrier, timeout and break persist only if the door ended by itself (see Persistence).
logNoXIM and ARexx doors: log every request the door makes at debug level. Default: false.
warpBootSecondsNoHow long the first boot runs flat out, 0 to 3600. Default: 30.
regTimeoutSecondsNoXIM doors: the door must register with the shim within this many seconds, 0 to 86400; 0 waits for ever. Default: 30.
disconnectGraceSecondsNoAfter a hangup, time-up or break, how long ENiGMA½ waits for the door to finish and the shim to report its exit, 1 to 3600. The shim itself gives a door 30 seconds and then reports it gone, so keep this above 30. With no report in time nothing is saved. Default: 35.
inputTimeoutSecondsNoA door waiting this long for a key gives up, 1 to 86400. Default: users.idleLogoutSeconds, or the shim’s 300 seconds.
crlfNoA line feed in the door’s output goes out as CR LF, as /X does. Default: true.
timezoneMinutesNoMinutes east of UTC for the Amiga clock, -720 to 840. Default: the server’s.

Every problem in a door’s configuration is reported at once in the log (Could not start Amiga door), and the caller sees ” could not be run. Please let the sysop know.” and is returned to the menu. A missing image, rom or extRom file is handled the same way.

The only system setting is doors.amiga.snapshotCacheEntries (default 4): how many booted-machine snapshots ENiGMA½ keeps in memory, about 1.5 MB each, one per door image and machine configuration. A door without a snapshot boots instead of restoring. 0 turns the cache off.

doorDreamSweeper: {
desc: Playing DreamSweeper
module: amiga_door
config: {
name: DreamSweeper
image: /home/enigma/amiga/dreamsweeper.hdf
door: BBS:Doors/dreamsweeper/dreamsweeper.xim
sharedState: true
tooManyArt: DOORMANY
}
}

Many Amiga BBS games, RPGs and strategy games among them, are not XIM doors but ordinary AmigaDOS programs: they read keys from standard input and write to standard output, and the BBS ran them in a raw console. Set doorType: cli for these. The shim then starts the program with its input and output connected to the caller (it acts as the program’s console), and nothing else changes: the same image, snapshot, persistence and font handling apply.

  • The caller is anonymous unless you pass them. A CLI door cannot ask the BBS anything, so it knows only what is on its command line. Put what the door’s documentation asks for in doorArgs with these placeholders:

    PlaceholderBecomes
    {name}The caller’s user name, as one quoted argument
    {node}The node number
    {level}The caller’s security level
    {timeleft}Minutes left in the caller’s session

    {name} is always one quoted argument, with characters the Amiga shell would act on (quotes, *, back-quotes, $, ;, <, >, |) replaced by _, so a user name can neither run a command nor add a keyword to the door’s command line. A name too long for the room left on the command line is cut short inside its quotes. Do not put quotes around placeholders yourself. There is no node number in front of a CLI door’s arguments.

  • Console mode. The console starts in cooked mode: typed text is echoed, Backspace edits and Return ends a line, as in an Amiga Shell window. A door that wants single keys switches to raw mode itself. Some doors expect the BBS to have opened a raw console already (“run it through a RAW cli” in their notes) and never switch; set consoleMode: raw for those.

  • Hangups. When the caller hangs up or runs out of time, the door’s input ends (end of file), its output is refused, and it gets a Ctrl-C, which is what Amiga BBSes did. A door that ignores all of that is given up on after 30 seconds, as for XIM doors, and its exit is reported as carrier (or timeout). Nothing it wrote is saved in that case, because the door was still running (see Persistence).

  • Libraries. A door may need libraries that are not in the AROS ROM. Doors compiled with DICE C (Battle Grounds, for one) quit at once, without a word, unless mathieeedoubbas.library, mathieeedoubtrans.library and mathieeesingtrans.library are in BBS:Libs. Copy them from the AROS m68k distribution (Libs/ on the boot ISO), or from your own Workbench disks when you use a Kickstart ROM.

  • Character set. Many CLI doors draw with the PC (CP437) character set rather than the Amiga’s. For those set encoding: cp437 and font: none.

A CLI door’s image needs axshim 1.1 or later (the shim in this repository); an image made with axshim 1.0 runs it as an XIM door, which fails.

Battle Grounds 0.9e is a hack-and-slash RPG with persistent characters. It takes the caller’s name on its command line, reads S:BattleG.config (whose first line is its data directory, here doors:rpgs/battleg/, which needs a Users directory) and expects a raw console. Global War 2.19 is a multi-player strategy game that takes AmigaDOS keyword arguments and keeps its world in DOORS:GlobalWar/GW.dat. Both are in the Up Rough door repository.

doorBattleGrounds: {
desc: Playing Battle Grounds
module: amiga_door
config: {
name: BattleGrounds
image: /home/enigma/amiga/cli-doors.hdf
door: BBS:Doors/rpgs/battleg/bg
doorType: cli
consoleMode: raw
doorArgs: "{name}"
encoding: cp437
font: none
sharedState: true
}
}
doorGlobalWar: {
desc: Playing Global War
module: amiga_door
config: {
name: GlobalWar
image: /home/enigma/amiga/cli-doors.hdf
door: BBS:Doors/GlobalWar/GlobalWar
doorType: cli
doorArgs: "{name} ACCESS {level} PAGELENGTH 24 TIMELEFT {timeleft}"
encoding: cp437
font: none
sharedState: true
}
}

Global War 2.19 cannot save on a fresh install: it deletes GW.dat before renaming its new save over it, and gives up when there is no GW.dat to delete. Give it the empty world it would have written, the text GLOBAL WAR v2.19 (with the trailing space) padded with zero bytes to 68 bytes: printf 'GLOBAL WAR v2.19 ' > GW.dat && truncate -s 68 GW.dat, then copy it to Doors/GlobalWar/GW.dat in the image.

Many /X doors were written as ARexx scripts. Their command icon says TYPE=AIM, and the script starts with parse arg NODE, options results and address value "AERexxControl"NODE. AmiExpress ran them through its REXXDOOR utility; the shim takes REXXDOOR’s place: it opens the AERexxControl<node> port, runs the script with RX, and answers its commands (GETUSER, PUTUSTR/PUTUSER, TRANSMIT, SENDSTRING, GETCHAR, QUERY, SHOWFILE, REMOVERESERVED, SHUTDOWN and the rest) from the same user information XIM doors get. Set doorType: aim and name the script in door.

Terminal window
XDFTOOL=~/amitools-venv/bin/xdftool misc/amiga_door/image/make_image.sh \
-w ~/amiga/Workbench3.1.adf -s 4M ~/amiga/kickboxing.hdf ~/doors/Kickboxing
  • Where the script goes. Anywhere on the image: a script finds its data through its own paths (KickBoxing uses doors:Kickboxing/...; DOORS: is BBS:Doors), and door names the script.
  • Hangups and time. When the caller hangs up, runs out of time or leaves the door waiting for a key longer than inputTimeoutSeconds, every command the script sends fails with return code 10, as under AmiExpress. Scripts written for /X take that as the cue to save and stop (many set SIGNAL ON ERROR); one that carries on gets a Ctrl-C, which stops an ARexx script.
  • Libraries. A script that ADDLIBs a library not on the Workbench disk needs it, and whatever that library opens, in the image’s Libs/. The Death Game plays without rexxarplib.library until its once-a-day reset, which needs rexxarplib together with screenshare.library, diskfont.library and ARP’s arp.library.
  • What a script changes in the user record (PUTUSER, for example The Death Game’s upload credits) lasts for the session only; ENiGMA½’s user record is not changed.
  • Errors. An ARexx error in the script (+++ Error 41 in line 51: Invalid expression) is logged with the door’s exit. Without ARexx on the image, the session ends at once and the log says no rexxsyslib.

KickBoxing 1.0 (187 FAC, 1994; Demozoo) is a boxing and training game with Amiga-scene art; Hacker 5.2c (Up Rough door repository) is a hacker-wars game. Hacker draws with PC characters. For KickBoxing, move KickBox.Rexx into the archive’s Kickboxing directory and give that directory to make_image.sh (as above); for Hacker, give it the archive’s hacker directory.

doorKickBoxing: {
desc: Playing KickBoxing
module: amiga_door
config: {
name: KickBoxing
image: /home/enigma/amiga/arexx-doors.hdf
door: BBS:Doors/Kickboxing/KickBox.Rexx
doorType: aim
doorStack: 40000
sharedState: true
}
}
doorHacker: {
desc: Playing Hacker
module: amiga_door
config: {
name: Hacker
image: /home/enigma/amiga/arexx-doors.hdf
door: BBS:Doors/hacker/hacker.rexx
doorType: aim
doorStack: 50000
encoding: cp437
font: none
sharedState: true
}
}

Hacker runs avail flush after every command and stops with an error if the image has no C:Avail, so build its image with -w. Its archive ships the author’s own players: leave out hackerdata/users/* and hackerdata/userlist for a fresh game.


The door’s disk is the image file, and each session works on a copy of it. A door that saves something (a high score, a message on a wall) writes it to that copy. What happens next:

  • After a clean exit (the door ended normally, status ok), ENiGMA½ writes the disk blocks the session changed back into the image file. The next session starts from the saved disk.
  • After a hangup the door is told the carrier is gone and gets the shim’s 30 seconds to save and quit; its exit is reported as carrier. ENiGMA½ waits for that report for disconnectGraceSeconds (35 by default). If the door ended by itself within that time, it is treated as a clean exit and what it saved is written back, for an XIM door (carrier is in the default persistOn for xim only). If the shim had to give up on a door that was still running, nothing is written, because its disk is in an unknown state; the log says why.
  • After anything else (the time ran out, an error), nothing is written, so a door that crashed or was cut off halfway leaves the image as it was. persistOn widens this if you want, for example ['ok', 'carrier', 'timeout']. carrier, timeout and break always require that the door ended by itself (the shim reports its return code; -1 means it was still running when the shim gave up). Remove carrier from persistOn for a door that does not save cleanly on a hangup: what is written is whatever the door left on its disk.
  • Why CLI and ARexx doors differ. On a hangup a CLI door is sent end-of-file and a break, and an ARexx door a break, so a return code does not prove the door finished its writes: it may simply have been interrupted. Their default persistOn is therefore ['ok'], and a hangup mid-game leaves the image as it was. An XIM door is not interrupted; it only sees carrier-lost replies to its input requests and normally saves and quits, so carrier stays in its default. Add carrier to persistOn for a CLI or ARexx door you know saves safely on a break.
  • How it is written. The changed blocks go into a copy of the image in the same directory, which is synced to disk and then renamed over the image. A server crash, a full disk or a stopped ENiGMA½ at any moment leaves either the old image or the new one, never a mix of the two. If the write takes longer than 30 seconds the caller is returned to the menu, but the write is left to finish (for up to five minutes) rather than being cut off. Persisting needs the image’s directory to be writable by ENiGMA½ with free space for a second copy of the image, and the image must be a plain file, not a single-file bind mount (the rename fails); the log says so when it does. What gets saved is whatever the door left on its disk: a door that exits cleanly with its own files in a bad state is saved that way.
  • When the disk changed, the cached snapshots of that image are dropped, since they hold the old disk. The next session boots and caches a fresh one.
  • persist: false makes every session start from the image as it is, whatever the door writes.

Because sessions are independent copies, two callers on one image could not see each other’s writes, and each would write back the disk blocks it changed over the other’s (directory and allocation blocks among them). So a door that persists (the default) holds its image for the whole session: while one caller is in it, anyone who picks a door on the same image, this door or another, is told it is busy (tooManyArt, or “Too many active instances”), just as nodeMax refuses. The image is released once the door has exited and its changes are written. ENiGMA½ also checks, before writing, that the image file is still the one the session started from; if something else changed it meanwhile (a sysop’s xdftool, a copy put in place), the session’s changes are not written and the log says NOT persisted.

Sharing an image therefore serialises callers: all the persisting doors on one image run one caller at a time between them. Give doors their own images when you want them to run side by side; separate images run in parallel. A door that keeps nothing between sessions (a single-player game with no saved files) can set persist: false: it then never holds its image and runs on as many nodes as nodeMax allows, every session starting from the image as it is.


Amiga doors write ISO 8859-1 (Latin-1) text and draw with the Amiga’s Topaz font. Two things follow:

  • Amiga console controls that PC terminals do not share are translated for the caller: the single-byte control sequence introducer 0x9B becomes ESC [, a form feed (the Amiga’s clear screen, which also drops the font on a SyncTERM-style terminal) becomes ESC[2J ESC[H, the cursor on/off sequences ESC[ p and ESC[0 p become ESC[?25h and ESC[?25l, a console reset keeps the font, and a cursor position below the screen is moved onto it (see below). Everything else in the door’s output is passed through. This is done for doors with a Latin-1 encoding (the default) only: a door that writes CP437 is a PC-style door, where 0x9B is a cent sign, and its output is left as written. amigaConsole: true or false overrides that either way.
  • With a Latin-1 encoding and the Topaz font, door bytes reach the caller as they are, and the caller’s terminal shows them through the font. With another encoding, the output is converted to the caller’s character set first (a character split across two writes is kept whole).
  • When the font is not none, ENiGMA½ switches a SyncTERM-compatible terminal to the font (topaz by default) before the door starts and back afterwards (ESC[0;42 D before, ESC[0;0 D after, for Topaz). Callers whose terminals do not support SyncTERM fonts see the door in their own font: the text is readable, and the Amiga’s box-drawing and graphic characters show as whatever Latin-1 gives them. If most of your callers are in that position, set font: none.

The terminal size is the caller’s, polled once a second, so a resize reaches the door. Many /X doors were written on PAL Amigas with 32-line screens and place text on rows 26 and 27 without asking; with the Amiga console translation on, a cursor position below the caller’s last row is moved onto the last row, which is what the Amiga console itself does, so an 80x25 caller sees the bottom of the layout overwritten rather than the screen scrolling. Callers with taller terminals (SyncTERM’s 80x50 modes, for example) see the full layout, and a door that asks the BBS for the screen length is told the real one. Time left is polled every five seconds, so a door sees the caller’s budget shrink as it does everywhere else on the board.


  • CPU: the 68000, 68010 and 68EC020 only. There is no 68030, 68040 or 68060, and no FPU.
  • Memory: at most 8 MB of fast RAM. The AROS ROM needs at least 1 MB in total (chip plus slow plus fast).
  • One caller per emulator. Every session is its own emulated machine, with the memory and CPU that costs. Use nodeMax to bound it.
  • ARexx needs your Workbench. AROS does not have ARexx; ARexx doors run only on an image built with your own Workbench 3.1 (make_image.sh -w).
  • No transfers from doors. A door cannot start a ZMODEM (or any other) file transfer to the caller.
  • No sysop break. There is no way for the sysop to break into a running door’s session from the door.
  • No JH_EF editor. A door that asks the BBS for its full-screen editor is refused, and the door carries on without it.
  • XIM, ARexx and CLI doors only. Doors written for other BBS software’s message ports (Paragon, CNet, CNet’s ARexx doors) are not supported.
  • CLI doors have no window. A CLI door that asks its console for the window size gets no answer; it should take the screen length from its command line.

The door never registers. The shim waited regTimeoutSeconds for the door to announce itself and gave up, and the caller was returned to the menu. Turn on log: true and read the debug log. Usual causes: the door path is wrong (it must be a path inside the image, written with BBS:), the door needs a file or library that is not on the image (it will fail quietly before it reaches the shim), or the door is not an XIM door.

A CLI door ends at once, with no output. It could not start or quit before printing anything, usually for want of a library. The exit is logged with the door’s return code (rc). Check the libraries the door needs (see CLI Doors) and that its configuration files are where its documentation says.

An ARexx door ends at once. The log line for the exit says why. error=no rexxsyslib: the image has no ARexx; build it with make_image.sh -w. ARexx is not running: RexxMast is not on the image or did not start. script ended without a host command with an out= text: the script stopped before it said anything, usually an ARexx error (shown) or a missing ADDLIB library.

A CLI door waits for Return after every key. It expects a raw console and never asks for one; set consoleMode: raw.

Unknown ROM. The ROM given as rom is not one vAmiga knows. Use the bundled ROM, or a Kickstart ROM from a supported release (Kickstart 3.1 is the target).

“File does not match its type” for a ROM. vAmiga picks how to read a ROM from its file extension. A ROM file with no .rom or .bin extension is rejected with this message. Rename the file, for example kick31.rom.

The image is not bootable. The emulator booted but the shim never said hello. Check that the image is an FFS partition made by make_image.sh (or the recipe in misc/amiga_door/image/README.md), that C/axshim and S/Startup-Sequence are on it, and that the first session logs “Amiga door snapshot cached”. A raw floppy .adf is not a hard-disk image.

The first caller waits a moment, later ones do not. The first session boots the machine; the others restore a snapshot. A restart of ENiGMA½ empties the cache.

A door’s changes vanish. The session did not end cleanly (see persistOn), persist is false, or the image file was changed by something else while the door ran (the log says NOT persisted).

“Too many active instances” with nobody in the door. Another door on the same image is in use: a door that persists holds its image for the whole session. Give the doors separate images to run them at the same time.

The door’s screen looks wrong. Try font: none for callers without SyncTERM fonts, or set encoding if the door writes something other than Latin-1.


  • AROS is distributed under the AROS Public License (APL 1.1). The ROM in enigma-vamiga is unchanged AROS, and its source is available from aros.org.
  • Kickstart and Workbench belong to their owners. ENiGMA½ does not ship them, and you do not need them. If you use rom, it is your own copy.
  • vAmiga is under the Mozilla Public License 2.0. The patches ENiGMA½ makes to it are published in the enigma-vamiga package.
  • axshim and the image tools are BSD-2-Clause. AEDoor.library is NilBBS’s MIT-licensed library, with a small patch. Doors are their authors’ own, under whatever terms they chose.