OPL2LPT: an AdLib sound card for the parallel port

Vincent Bernat

The AdLib sound card was the first pop­u­lar sound card for IBM PC—be­fore that, we were pam­pered by the sound of the PC speaker. Con­nected to an 8-bit ISA slot, it is pow­ered by a Yamaha YM3812 chip, also known as OPL2. This chip can drive 9 sound chan­nels whose char­ac­ter­is­tics can be fine-tuned through 244 write-only registers.

AdLib sound card
A copy of an AdLib sound card from Monotech. The OPL2 chip is in the lower right part. Notable differences with the original include the volume potentiometer and the metal film resistors—instead of carbon film resistors.

I had one but I am un­able to lo­cate it any­more. Mod­els on eBay are quite rare and ex­pen­sive. It is pos­si­ble to build one your­self (ei­ther Sergey’s one or this faith­ful re­pro­duc­tion). How­ever, you still need an ISA port. The lim­it­less imag­i­na­tion of some hack­ers can still help here. For ex­am­ple, you can com­bine Sergey’s Xi 8088 pro­ces­sor board, with his ISA 8-bit back­plane, his Su­per VGA card, and his XT-CF-Lite card to get your very own mod­ernish IBM PC com­pat­i­ble. Al­ter­na­tively, you can look at the AdLib sound card on a par­al­lel port from Raphaël Assénat.

The OPL2LPT sound card#

Re­cently, the 8-Bit Guy re­leased a video about an AdLib sound card for the par­al­lel port, the OPL2LPT. While cur­rent moth­er­boards don’t have a par­al­lel port any­more, it’s easy to add a PCI-Ex­press one. I bought a pre-sol­dered OPL2LPT and a few days later, it was in my milk box:

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

Up­date (2018-03)

You can also buy a 3D-printed en­clo­sure for the OPL2LPT. Af­ter writ­ing this ar­ti­cle, I have been of­fered one:

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

Up­date (2018-07)

The OPL3LPT is now avail­able. It fea­tures a sim­i­lar de­sign but with an OPL3 chip.

The ex­pected mode of op­er­a­tion for such a de­vice is to plug it into an ISA par­al­lel port (ac­ces­si­ble through I/O port 0x378), load a DOS driver to in­ter­cept calls to AdLib’s ad­dress, and run some AdLib-com­pat­i­ble game. While cor­rectly sup­ported by Linux, the PCI-Ex­press par­al­lel port doesn’t op­er­ate like an ISA one. QEMU comes with a par­al­lel port em­u­la­tion but, due to tim­ing is­sues, can­not cor­rectly drive the OPL2LPT. How­ever, VirtualBox em­u­la­tion is good enough.1

On Linux, the OPL2LPT can be pro­grammed al­most like an ac­tual AdLib. The fol­low­ing 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 “na­tively” use the OPL2LPT, I have mod­i­fied the fol­low­ing ap­pli­cations:

  • ScummVM, an em­u­la­tor for clas­sic point-and-click ad­ven­ture games, in­clud­ing many Lu­cas­Arts games—patch2
  • QEMU, a quick generic em­u­la­tor—patch with a min­i­mal em­u­la­tion for timers and hard-coded sleep delays 🙄
  • DOSBox, an x86 em­u­la­tor bun­dled with DOS—patch with a com­plete em­u­la­tion for timers and a ded­i­cated work­ing thread3

You can com­pare the re­sults in the fol­low­ing video, with the in­tro­duc­tion of In­di­ana Jones and the Last Cru­sade, re­leased in 1989:4

  • 0:00, DOSBox with an em­u­lated PC speaker
  • 0:58, DOSBox with an em­u­lated AdLib
  • 1:51, VirtualBox with the OPL2LPT (on an em­u­lated par­al­lel 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 im­proved OPL3 em­u­la­tor (Nuked OPL3)
  • 6:10, ScummVM with the CD track (FM Towns version)

I let you judge how good each op­tion is! There are two ways to buy an OPL2LPT OPL3LPT: in Eu­rope, from Ser­dashop or in North Amer­ica, from The 8-Bit Guy.

Addendum#

Indiana Jones and the Fate of Atlantis#

Here is an­other video fea­tur­ing In­di­ana Jones and the Fate of At­lantis, re­leased in 1992, run­ning in DOSBox with the OPL2LPT. It’s the sec­ond game us­ing the iMUSE sound sys­tem: mu­sic is syn­chro­nized with ac­tions and tran­si­tions are done seam­lessly. Quite a feat at the time!

Monkey Island 2#

The first game fea­tur­ing iMUSE is Mon­key Is­land 2, re­leased in 1991. The video be­low dis­plays the first min­utes of the game, run­ning in DOSBox with the OPL2LPT.

No­tably, at 5:33, when Guy­brush is in Woodtick, a small town on Scabb Is­land, the mu­sic plays around a vari­a­tion of a ba­sic theme with a dif­fer­ent in­stru­ment for each place with­out any in­ter­ruption.

How the videos were recorded#

With a VGA adapter, many games use Mode 13h, a 256-color mode with a 320×200 res­o­lu­tion. On a 4:3 dis­play, this mode doesn’t fea­ture square pix­els: they are stretched ver­ti­cally by a fac­tor of 1.2.

The above videos were recorded with FFmpeg (and edited with Blender). It packs a lot of use­ful fil­ters mak­ing it easy to au­to­mate video cap­ture. 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:flags=neighbor[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 in­ter­est­ing part is the filter_complex ar­gu­ment. The in­put video is padded from 640×400 to 854×400 as a first step to a 16:9 as­pect ra­tio.5 Us­ing The Se­cret Font of Mon­key Is­land, some text is added to the right of the video. The re­sult is then scaled to 854×480 to get the fi­nal as­pect ra­tio while stretch­ing pix­els to the ex­pected 1.2 fac­tor. The video up to this point is sent to a stream named game. As a sec­ond step, from the in­put au­dio, we build two vi­su­al­iza­tions: a wave­form and a spec­trum. They are stacked ver­ti­cally and the re­sult is a stream named vis. The last step is to over­lay the vi­su­al­iza­tion stream over the game­play stream.