← Back
arcanebyte

arcanebyte/lisa-doom

View on GitHub ↗
Stars
3
Forks
0
Watchers
3
Open issues
0
Contributors
1
Language
C++
License
GNU General Public License v2.0
Default branch
main
Created Oct 1, 2026Updated Oct 1, 2026

Star growth

Today—
This week—
This month—

Star history will appear here once this repo has been tracked for a couple of days.

README

Doom on the Apple Lisa

Doom on an Apple Lisa 2: a 68000 at 5 MHz, 1.5 MB of RAM, a 720 × 364 one-bit screen and a ProFile hard disk. It's a port of Frenkel Smeijers' Doom8088: Motorola 68000 Edition, whose AT&T UNIX PC target is nearly the same machine.

There are two builds from one source tree:

  • Standalone. The Lisa boots Doom straight off the ProFile with no operating system. This is the one to run: it has twice the memory and sixteen greys.
  • UniPlus+. Doom as an ordinary program under UniSoft's UniPlus+ System V, a UNIX port from 1984. This came first and still works.

We did the work under the LisaEm emulator, and the standalone build boots and plays on a real Lisa. It is slow: the best-looking build runs at about 1.1 frames per second.

Build Columns Shades Heap (bytes) fps
UniPlus+ 60 2 612,352 1.732
Standalone 60 2 1,204,240 1.944
Standalone 120 16 greys, dithered 1,182,720 1.112

These are 200 frames of -timedemo demo3, which renders every tic with no frame skipping, so they're worst-case figures. PORT.md says how they were measured and why the two 2-colour figures should be re-run.

What you need

  • A Mac with Python 3 and the m68k cross toolchain. The Makefile hasn't been tried on Linux. The Lisa's own C compiler is never used.

    brew install m68k-elf-gcc m68k-elf-binutils
    
  • A WAD. None is in the repository. The game uses Episode 1 WADs preprocessed for Doom8088: DOOMST2.WAD for 2 colours and DOOMST16.WAD for 16 greys. doom/VENDOR.md says where they come from. Put the one you want in the top of the repo, or pass its path with WAD=.

The standalone boot disk

make bootimage COLORS=16

This writes build/profile.image, a 10 MB ProFile image: the boot block, then Doom, then the WAD as raw sectors from sector 1024. There's no filesystem on it.

If you only want to play it, the releases page has this image already built: 16 greys at 120 columns, with DOOMST16.WAD in it.

Options:

COLORS=16 16 greys with DOOMST16.WAD. The default is 2 colours with DOOMST2.WAD, matching upstream's black-and-white builds
WAD=/path/to/DOOMST16.WAD where the WAD is
BOOTIMAGE=/path/to/out.image where to write the image
VWW=120 renderer columns: 30, 60 or 120. Only with COLORS=16
BENCH=1 build the benchmark instead of the game: play demo3 for BOOTFRAMES frames and print the result
ZONECAP=612352 cap the heap, for comparing against the UniPlus+ build at equal memory

On a real Lisa

Copy build/profile.image to an ESProFile card as profile.image, connect it to the built-in parallel port, and start the Lisa from the ProFile. The boot block draws a progress bar beside the ROM's hourglass while it loads, then Doom draws its face while the level loads, then the title screen. The machine needs 1.5 MB or more.

In LisaEm

Point the ProFile on the built-in parallel port at the image, set the memory to 1536 KB or more, set the speed to 5 MHz before powering on, and leave the speed alone during a run. The standalone clock only keeps time if the speed is constant. LisaEm must not have the image open while make bootimage rewrites it.

Keys

Action Key
Walk keypad 8 2 4 6
Strafe , .
Fire /
Use Return or Space
Weapon [ ]
Automap Tab
Menu Clear or Backspace
Quit ⌘Q, back to the boot ROM

The number row types, so IDDQD works.

The UniPlus+ version

make                    # build/doom and build/vidtest
make check              # host-side tests, no Lisa needed
make put IMAGE=/path/to/uniplus.image
make wad IMAGE=/path/to/uniplus.image

put copies the programs into /doom on the image and wad copies the WAD there. FSBASE is the block where the image's root filesystem starts; tools/extract_profile_image.py --list prints it, and the default is a 20 MB image with the root on the second half. LisaEm must not have the image open, and back it up first. tools/README.md has the rules.

Then, on the Lisa, as root (mapping the screen with phys() needs it):

cd /doom
./rundoom

rundoom runs the game and puts the terminal and the bottom four raster lines back afterwards. ./doom -frames 200 -timedemo demo3 runs the two-minute benchmark.

The keys are the same, with three differences: the arrows or the number row walk, because the console can't tell the keypad apart; the menu is Clear or control-Z E; and quit is control-Z Q.

What's in the repo

doom/ upstream Doom8088ST, unmodified
port/i_lisav.c, port/i_lisav16.c video, 2-colour and 16-grey, from upstream's i_3b1v.c
port/i_lisa.c system, keyboard and clock under UniPlus+, from upstream's i_3b1.c
port/i_boot.c the same for the standalone build
port/vidtest.c, port/rundoom the UniPlus+ screen test, and the wrapper script
lib/ crt0, system call stubs, a 4 KB libc, nlist, and the Lisa screen code
boot/ boot block, startup, interrupt handlers and machine layer for the standalone build
tools/ mkaout.py (ELF to UniPlus+ a.out), mkboot.py (boot disk layout), disk image tools
test/ the host-side tests

Documentation

  • PORT.md: how the port was done and what went wrong.
  • TOOLCHAIN.md: cross-compiling C for UniPlus+. The executable format, system calls, memory limits and writing a libc. Nothing in it is specific to Doom, so if you're here for the Lisa and not for Doom, start there.

Licence

Everything in this repository is GPL v2 or later; LICENSE has the text. Doom8088ST is GPL v2 or later, and port/ derives from it. The toolchain in lib/, boot/ and tools/ is original to this repository and under the same licence. Doom and its WADs belong to id Software. There's no WAD in the repository. The boot image on the releases page has upstream's in it, as upstream's own release does.