OPL2LPT: an AdLib sound card for the parallel port

Vincent Bernat

The AdLib sound card was the first popular sound card for IBM PC—prior to that, we were pampered by the sound of the PC speaker. Connected to an 8-bit ISA slot, it is powered by a Yamaha YM3812 chip, also known as OPL2. This chip can drive 9 sound channels whose characteristics can be fine tuned through 244 write-only registers.

AdLib sound card
An AdLib sound card. The OPL2 chip is in the lower right part. CC-BY-SA-2.5.

I had one but I am unable to locate it anymore. Models on eBay are quite rare and expensive. It is possible to build one yourself (either Sergey’s one or this faithful reproduction). However, you still need an ISA port. The limitless imagination of some hackers can still help here. For example, you can combine Sergey’s Xi 8088 processor board, with his ISA 8-bit backplane, his Super VGA card and his XT-CF-Lite card to get your very own modernish IBM PC compatible. Alternatively, you can look at the AdLib sound card on a parallel port from Raphaël Assénat.

The OPL2LPT sound card🔗

Recently, the 8-Bit Guy released a video about an AdLib sound card for the parallel port, the OPL2LPT. While current motherboards don’t have a parallel port anymore, it’s easy to add a PCI-Express one. I bought a pre-soldered OPL2LPT and a few days later, it was at my doorstep:

OPL2LPT sound card
The OPL2LPT sound card on an original “Day of the Tentacle” box to indicate scale.

Update (2018.03)

You can also buy a 3D-printed enclosure for the OPL2LPT. After writing this article, I have been offered one:

OPL2LPT enclosure
The OPL2LPT sound card in its 3D-printed enclosure on a “Monkey Island 4” box.

The expected mode of operation for such a device is to plug it to an ISA parallel port (accessible through I/O port 0x378), load a DOS driver to intercept calls to AdLib’s address and run some AdLib-compatible game. While correctly supported by Linux, the PCI-Express parallel port doesn’t operate like an ISA one. QEMU comes with a parallel port emulation but, due to timing issues, cannot correctly drive the OPL2LPT. However, VirtualBox emulation is good enough.1

On Linux, the OPL2LPT can be programmed almost like an actual AdLib. The following code writes a value to a register:

static void lpt_write(uint8_t data, uint8_t ctrl) {
  ieee1284_write_data(port, data);
  ieee1284_write_control(port, (ctrl | C1284_NINIT) ^ C1284_INVERTED);
  ieee1284_write_control(port,  ctrl                ^ C1284_INVERTED);
  ieee1284_write_control(port, (ctrl | C1284_NINIT) ^ C1284_INVERTED);
}

void opl_write(uint8_t reg, uint8_t value) {
  lpt_write(reg, C1284_NSELECTIN | C1284_NSTROBE);
  usleep(4); // 3.3 microseconds

  lpt_write(value, C1284_NSELECTIN);
  usleep(23);
}

To “natively” use the OPL2LPT, I have modified the following applications:

  • ScummVM, an emulator for classic point-and-click adventure games, including many Lucas­Arts games—patch2
  • QEMU, a quick generic emulator—patch with a minimal emulation for timers and hard-coded sleep delays 🙄
  • DOSBox, an x86 emulator bundled with DOSpatch with a complete emulation for timers and a dedicated working thread3

You can compare the results in the following video, with the introduction of Indiana Jones and the Last Crusade, released in 1989:4

  • 0:00, DOSBox with an emulated PC speaker
  • 0:58, DOSBox with an emulated AdLib
  • 1:51, VirtualBox with the OPL2LPT (on an emulated parallel port)
  • 2:42, patched ScummVM with the OPL2LPT (native)
  • 3:33, patched QEMU with the OPL2LPT (native)
  • 4:24, patched DOSBox with the OPL2LPT (native)
  • 5:17, patched DOSBox with an improved OPL3 emulator (Nuked OPL3)
  • 6:10, ScummVM with the CD track (FM Towns version)

I let you judge how good is each option! There are two ways to buy an OPL2LPT: in Europe, from Serdashop or in North America, from the 8-Bit Guy.

Addendum🔗

Indiana Jones and the Fate of Atlantis🔗

Here is another video featuring Indiana Jones and the Fate of Atlantis, released in 1992, running in DOSBox with the OPL2LPT. It’s the second game using the iMUSE sound system: music is synchronized with actions and transitions are done seamlessly. Quite a feat at the time!

Monkey Island 2🔗

The first game featuring iMuse is Monkey Island 2, released in 1991. The video below displays the first minutes of the game, running in DOSBox with the OPL2LPT.

Notably, at 5:33, when Guybrush is in Woodtick, a small town on Scabb Island, the music plays around a variation of a basic theme with a different instrument for each building without any interruption.

How the videos were recorded🔗

With a VGA adapter, many games use Mode 13h, a 256-color mode with a 320×200 resolution. On a 4:3 display, this mode doesn’t feature square pixels: they are stretched vertically by a factor of 1.2.

The above videos were recorded with FFmpeg (and edited with Blender). It packs a lot of useful filters making it easy to automate video capture. Here is an example:

FONT="font=Monkey Island 1991 refined:
      fontcolor=OrangeRed:
      fontsize=16:
      x=w-text_w-10"
ffmpeg -y \
  -thread_queue_size 64 \
  -f x11grab -draw_mouse 0 -r 30 -s 640x400 -i :0+844,102 \
  -thread_queue_size 64 \
  -f pulse -ac 1 -i default \
  -filter_complex "[0:v]pad=854:400:0:0,
       drawtext=${FONT}:y= 10:text=Indiana Jones 3,
       drawtext=${FONT}:y= 34:text=Intro,
       drawtext=${FONT}:y=100:text=DOSBox,
       drawtext=${FONT}:y=124:text=VGA,
       drawtext=${FONT}:y=148:text=PC speaker,
       scale=854:480[game];
       [1:a]volumedetect;
       [1:a]showwaves=s=214x100:colors=OrangeRed:scale=lin[waves];
       [1:a]showcqt=s=214x100[spectrum];
       [waves][spectrum]vstack[vis];
       [game][vis]overlay=x=640:y=280" \
  -pix_fmt yuv420p -c:v libx264 -qp 0 -preset ultrafast \
  indy3-dosbox-pcspkr.mkv

The interesting part is the filter_complex argument. The input video is padded from 640×400 to 854×400 as a first step to a 16:9 aspect ratio.5 Using The Secret Font of Monkey Island, some text is added to the right of the video. The result is then scaled to 854×480 to get the final aspect ratio while stretching pixels to the expected 1.2 factor. The video up to this point is sent to a stream named game. As a second step, from the input audio, we build two visualisations: a waveform and a spectrum. They are stacked vertically and the result is a stream named vis. The last step is to overlay the visualisation stream over the gameplay stream.


  1. There is no dialog to configure a parallel port. This needs to be done from the command-line after the instance creation:

    $ VBoxManage modifyvm "FreeDOS (games)" --lptmode1 /dev/parport0
    $ VBoxManage modifyvm "FreeDOS (games)" --lpt1 0x378 7
    
    ↩︎
  2. The patch for ScummVM has been merged. Support for the OPL2LPT should appear in the 2.1 release. At compile-time, the --enable-opl2lpt option should be specified. ↩︎

  3. With QEMU or DOSBox, it should be the responsability of the executing game to respect the required delays for the OPL2 to process the received bytes. However, QEMU doesn’t seem to try to emulate I/O delays while DOSBox seems to not be precise enough. For the later, to overcome this shortcoming, the OPL2LPT is managed from a dedicated thread receiving the writes and ensuring the required delays are met. ↩︎

  4. Indiana Jones and the Last Crusade was the first game I tried after plugging in the brand new AdLib sound card I compelled my parents to buy on a trip to Canada in 1992. At the time, no brick and mortar retailer sold this card in my French city and online purchases (through the Minitel) were limited to consumer goods (like a VHS player). Hard times. 😏

    The video is running the VGA version (320×200, 256 colors), released in 1990. However, back in the time, I was playing the CGA/EGA version (320×200, 4 fixed colors or 640×350, 16 colors from a palette of 64). ↩︎

  5. A common method to extend a 4:3 video to a 16:9 aspect ratio without adding black bars is to add a blurred background using the same video as a source. I didn’t do this here but it is also possible with FFmpeg↩︎


Share this article