💾 Archived View for going-flying.com › ~mernisse › 17.gmi captured on 2021-12-04 at 18:04:22. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
Every so often a wave of boredom and nostalgia crash over me in a manner that causes a reaction that pushes me towards one abandoned project or another. For years I have been trying to build an infrastructure that would allow me to re-create the BBS I used to run without having to drag out a bunch of old computers, install DOS and some archaic network stack, and hang a pile of TCP/IP to serial converters about the place. Not that I wouldn't enjoy that, I just don't want to maintain it after I have it built.
A while back I started the process by trying to put the whole BBS into DOSBox in a Docker container. I had built a DOSBox Docker container¹ years ago so I figured I'd be able to build on that. It turns out that the BBS software wants the old DOS file locking semantics and that doesn't seem to be emulated by DOSBox.
[1] Necrocomputing in Docker Containers
So that went on the shelf for a few years and after a few more projects popped on and off the stack I came back to this idea. Part of me wondered if it was important to have the whole BBS or if I really just wanted to play the old games I remembered. With this thought in mind I set out to see if I could get the venerable L.O.R.D. running in a container. Now for anyone who missed the BBS era L.O.R.D. is a text-based RPG (more of a menu based RPG, honestly) called Legend of the Red Dragon, written by a guy named Seth Robinson. It was probably the best known BBS game in the mid 1990's and was certainly the big one in my area. It turns out I still have a copy of the game in a backup archive from the early 2000's so I set about seeing if it would behave.
After a day of fighting I was looking at the familiar loading screen via a telnet session but I couldn't help but be annoyed at one small bug. You see the way games worked on the old DOS BBS systems was pretty simple. DOS could only run one program at a time so your BBS (which answered the phone and did all the hard work getting a user connected to your computer's serial port) would mostly exit, usually leaving a stub in memory that would cause the BBS to load back in when the game exited, and then execute the game. The game could therefore assume that the user was already there and most of them would just start talking to the serial port without any prompting. In my case that meant that if I started the container and didn't connect to the telnet port (which DOSBox was connecting to an emulated serial port in DOS) within a second or two, I'd miss all the intro text of the game and it would appear that nothing was happening. This was obviously not acceptable. The thought occurred to me to see if there was a way to get DOSBox to tell DOS that someone was connected. It turns out that the answer is... sort of? DOSBox does emulate some of the control lines present in a serial port, though not the released version, so I had to update my Dockerfile to build DOSBox from source instead of using a packaged version. Armed with the proper version of DOSBox I can interrogate the CD signal (Carrier Detect, used to tell the host that the connected modem has someone connected to it) and wait for it before letting the game start. But... how? I looked around a bit but couldn't find any good way to report on the status of the CD signal, or any way to check for it in a batch file (the rudimentary DOS scripting language), so I decided to see if I could dust off my very first programming language and commit a bit of computational necromancy.
I dusted off a copy of Turbo Pascal 7.0 from a backup that probably originated on floppy disks and started trying to re-learn just enough Pascal to get a bit out of a piece of hardware. I write a fair bit of C these days for various microcontrollers, usually to drive LEDs in ways that amuse me so I'm comfortable with talking to hardware at a low level. DOSBox emulates a 16550 UART chip for the serial port well enough that I was able to find the registers I needed easily enough, it was just... remembering Pascal. After about 20 minutes I came up with the program below.
{* COMTEST.PAS (C) 2020 Matthew J. Ernisse <matt@going-flying.com> * All Rights Reserved. * * Licensed under the Simplified BSD 2-Clause license. *} program COMStatus; uses Crt; const { UART Registers } DLL = 0; DLM = 1; RBR = 0; THR = 0; IER = 1; IIR = 2; FCR = 2; LCR = 3; MCR = 4; LSR = 5; MSR = 6; SCR = 7; { MSR Bits } CD = 7; RI = 6; DSR = 5; CTS = 4; { MCR Bits } RTS = 1; DTR = 0; { LSR Bits } DA = 0; var {* The DOS holds the address of the COM ports at $0040:$0000 -> :$0006, so lean on an abolutely located array as a way to access the IO port location without hard coding things like $03F8 in here. *} ComPort: array[1..4] of Word absolute $0040:$0000; begin Writeln('COMTEST (c) 2020 Matthew J. Ernisse <matt@going-flying.com>'); Writeln('All Rights Reserved.'); { Enable DTR / RTS so the modem knows we are here } Port[ComPort[1] + MCR] := $0B; Writeln('Waiting for CD on COM1'); { Watch the Modem Status Register on the UART } while (Port[ComPort[1] + MSR] and (1 shl CD)) = 0 do begin if KeyPressed then if ReadKey = ^C then Break; end; if (Port[ComPort[1] + MSR] and (1 shl CD)) > 0 then Halt(1); end.
The program is simple, it pokes some bits on the Modem Control Register (MCR) to tell DOSBox that it is ready and then waits for the Carrier Detect (CD) bit in the Modem Status Register (MSR) which DOSBox will use to tell it that someone has connected to the telnet port. Once CD turns on the program exits and the game starts.
I have to admit that this scratched a huge nostalgia itch. Not only did I get to play one of my favorite BBS games again, but I got to write some DOS batch files and even some Turbo Pascal. It made me remember late nights in front of an amber monitor, typing odd screed into a text editor to make the computer do new things. It's funny that one of the last things that I got my DOS computer to do was to blink LEDs and now I use microcontrollers that are slightly less sophisticated to do the same thing.
If you are interested in the rest of the bits that make this work, you can find it in my git repository².
[2] LORD Container Git Repository
🚀 © MMXX-MMXXI matt@going-flying.com