Skip to content
RetrogamingHow-To Published Updated 7 min readViews unavailable

DOSBox-X Directserial: Bridge a Guest COM Port to a Host UART

Configure DOSBox-X directserial for a host UART, map guest COM settings carefully, and diagnose device access without confusing it with nullmodem networking.

DOSBox-X directserial connects one emulated DOS COM port to a serial device opened by the host. That makes it useful for a legacy terminal, a serial diagnostic tool, or a carefully isolated hardware experiment. The boundary is important: DOSBox-X emulates the guest-side serial interface and forwards its traffic to a host port, but it does not turn a USB serial adapter into an automatically configured device or guarantee that every guest baud and modem-control setting is supported by the host.

This is different from DOSBox-X nullmodem, which connects emulated serial endpoints through a host transport such as TCP, ENet, or a local socket/pipe. It is also different from the emulator’s NE2000 network card and from configuring the guest’s UART registers directly. Use directserial only when a real host port is the intended endpoint, and use a loopback adapter or noncritical test device before attaching equipment that can be affected by transmitted data or control-line changes.

Configure the guest COM port and host endpoint

The DOSBox-X full reference configuration lists directserial as a serial-port type and requires a realport parameter. Its examples use COM1 and ttyS0; optional parameters use the name:value form. A minimal Linux-host profile could look like this:

[serial]
serial1 = directserial realport:ttyUSB0

Here serial1 is the emulator’s first guest serial port, conventionally COM1. The host-side port name is an example only. In the inspected DOSBox-X implementation, the POSIX serial layer prepends /dev/ to the configured name, so use ttyUSB0, not /dev/ttyUSB0. Device names vary by host, adapter, and boot order. Resolve the current device from the operating system and do not assume that a stable name like /dev/ttyUSB0 identifies the same physical adapter after a change.

On Windows, the same implementation prefixes the provided port name with the Windows device-namespace prefix (two leading backslashes, a dot, and one trailing backslash) before opening it, so a name such as COM3 is the intended shape, not a Unix path. On macOS, determine the adapter’s actual device node and provide the corresponding bare name expected by the POSIX implementation. The exact node can differ by adapter and driver. Do not copy another machine’s port name and conclude that the emulator should discover hardware by itself.

DOSBox-X documents optional guest base-address and IRQ configuration for serial ports. Most applications expect a conventional COM mapping, but legacy software can be sensitive to resources. Confirm the guest’s expected COM port, I/O base, and interrupt from its documentation or a known working profile; do not change host realport to fix a guest-side IRQ conflict. Keep guest mapping and host device selection as separate settings in the troubleshooting notes.

Know what the emulator does to host serial settings

The implementation opens the selected host serial device, saves the existing port settings, configures it for byte-oriented I/O, and attempts to restore the saved settings when the handle closes. The Windows branch opens the port with exclusive access. The POSIX branch opens the /dev/-prefixed path with O_RDWR, O_NOCTTY, and O_NONBLOCK, then changes termios settings; the initial tcsetattr() return value is not checked in the inspected implementation, so a successful open alone does not establish that every requested host setting took effect. This means another terminal program or device tool can interfere with the same adapter even when DOSBox-X’s configuration is correct. Close other programs that may own or configure the port before testing.

The guest can program the emulated UART’s baud divisor, parity, data bits, and stop bits. DOSBox-X translates these settings and attempts to apply them to the host serial device. The current implementation reports a failure when a requested mode is rejected, but a successful call does not prove that every guest framing distinction survives the host API. In the inspected revision, Windows maps SERIAL_15STOP and SERIAL_2STOP to distinct ONE5STOPBITS and TWOSTOPBITS values. The POSIX branch maps both to the same CSTOPB flag, which POSIX defines as sending two stop bits. A guest request for the five-data-bit/1.5-stop-bit mode is therefore represented as two stop bits on that path, and tcsetattr() can succeed without reporting that distinction was lost. Verify the effective wire framing with a compatible peer or serial analyzer rather than relying only on the return value or a tcgetattr() readback. The Windows setup also disables CTS/DSR hardware flow control and both XON/XOFF software directions; the POSIX setup clears CRTSCTS and IXON, but leaves IXOFF untouched. Do not assume that POSIX directserial disables every software-flow-control behavior, or that it can honor a peer requiring hardware flow control. A guest program that writes the divisor therefore does not prove that the physical device accepted the exact mode. Record both the DOS-side setting and the host adapter/driver behavior, and validate with a known loopback or compatible peer.

Host permissions and policy remain in force. On Linux, inspect the device’s owner/group and the account running DOSBox-X; do not solve an access error by running the entire emulator as root. On Windows, check the COM number in Device Manager and whether another application has the port open. In both cases, the emulator’s startup log reports when it cannot open the requested serial port. Resolve the exact path, permission, and ownership cause before changing guest software.

Test one direction at a time

Begin with an isolated loopback or a second adapter configured with known, matching settings. Boot the guest with a small terminal program or diagnostic utility and test transmit, receive, and full duplex separately. Confirm baud, parity, data bits, and stop bits at both ends, and ensure the peer can operate without CTS/DSR or XON/XOFF flow control. On the POSIX path, specifically test the guest’s five-data-bit/1.5-stop-bit request: the inspected implementation sets the two-stop-bit CSTOPB mode instead, so test the actual framing rather than assuming the requested value was preserved. A successful open or tcsetattr() only establishes that the respective call did not report an error; it does not establish that the cable is wired for the peer, that the peer uses the same framing, or that application-level data is valid.

For reproducible tests, keep a per-game configuration with the DOSBox-X version or commit, guest COM number, host adapter identity, resolved device node, effective serial mode, and test output. Because the inspected CDirectSerial constructor performs SERIAL_open(), remove the adapter and restart DOSBox-X (or recreate the serial instance) before probing for the expected open error; repeating only the guest-side probe after unplugging an already-open adapter does not rerun that startup path. Reconnect it and re-resolve the host node rather than retaining a stale device name. Never run a write test against industrial, medical, financial, or other safety-relevant equipment unless the test is authorized and the protocol is known to be harmless.

Separate serial passthrough from networked serial

nullmodem is the DOSBox-X option for linking guest serial ports across an emulator-to-emulator transport. Its documented parameters include server/client and transport choices; that path does not open the same kind of host UART device as directserial. Conversely, directserial does not create a network tunnel or provide network authentication. If the goal is two game instances communicating, configure and firewall a supported nullmodem transport. If the goal is a real adapter, configure the host device and access policy. If the guest needs Ethernet, the NE2000 article covers a different emulated device and packet-driver path.

The directserial implementation schedules receive polling at a one-millisecond emulator event tick. That is an implementation detail, not a hard end-to-end latency guarantee or a promise of hardware-level timing. Host scheduling, adapter buffering, cable quality, the peer protocol, and DOSBox-X build differences all matter. For timing-sensitive uses, measure the real exchange under the exact host and adapter configuration rather than extrapolating from an emulator setting.

When a port will not open, check the device name format for the host platform, current device enumeration, permissions, and competing processes first. When it opens but communication is unreliable, verify guest COM resources, line framing, flow control, cable wiring, and peer behavior independently. This turns directserial from a mysterious “COM1 passthrough” into a testable chain with a guest UART contract, an emulator bridge, a host serial driver, and a physical or virtual endpoint.

Related:

Sources:

Comments