事前準備

Raspberry Pi 5 で動作する Raspberry Pi OS Bookworm を前提とする。

必要なパッケージをインストールする。

sudo apt update
sudo apt install qemu-system-x86 socat

FreeDOS の起動イメージアーカイブをダウンロードして展開する。https://www.freedos.org/ からダウンロードページまでナビゲートする。または curl で、

curl -LO https://download.freedos.org/1.4/FD14-LiveCD.zip && \
unzip FD14-LiveCD.zip

確認したバージョンは以下の通り。

$ qemu-system-i386 --version
QEMU emulator version 7.2.22 (Debian 1:7.2+dfsg-7+deb12u18+b3)
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
$ socat -V
socat by Gerhard Rieger and contributors - see www.dest-unreach.org
socat version 1.7.4.4 on 06 Nov 2022 08:15:51
   running on Linux version #1 SMP PREEMPT Debian 1:6.12.25-1+rpt1 (2025-04-30), release 6.12.25+rpt-rpi-2712, machine aarch64
features:
  #define WITH_STDIO 1
  #define WITH_FDNUM 1
  #define WITH_FILE 1
  #define WITH_CREAT 1
  #define WITH_GOPEN 1
  #define WITH_TERMIOS 1
  #define WITH_PIPE 1
  #define WITH_UNIX 1
  #define WITH_ABSTRACT_UNIXSOCKET 1
  #define WITH_IP4 1
  #define WITH_IP6 1
  #define WITH_RAWIP 1
  #define WITH_GENERICSOCKET 1
  #define WITH_INTERFACE 1
  #define WITH_TCP 1
  #define WITH_UDP 1
  #define WITH_SCTP 1
  #define WITH_LISTEN 1
  #define WITH_SOCKS4 1
  #define WITH_SOCKS4A 1
  #define WITH_VSOCK 1
  #define WITH_PROXY 1
  #define WITH_SYSTEM 1
  #define WITH_EXEC 1
  #undef WITH_READLINE
  #define WITH_TUN 1
  #define WITH_PTY 1
  #define WITH_OPENSSL 1
  #undef WITH_FIPS
  #define WITH_LIBWRAP 1
  #define WITH_SYCLS 1
  #define WITH_FILAN 1
  #define WITH_RETRY 1
  #define WITH_MSGLEVEL 0 /*debug*/

FreeDOS を virtual hard drive にインストールする。これをすることでファイルの読み書きや、後に設定する端末の接続先の自動変更ができるようになる。

qemu-img create -f qcow2 freedos.qcow2 512M  # virtual hard drive を作成
DISPLAY=:0 qemu-system-i386 \
    -machine pc \
    -m 32 \
    -drive file=freedos.qcow2,format=qcow2,if=ide \
    -cdrom FD14LIVE.iso \
    -boot order=d \

ここまでタイプするとモニターをエミュレーションするウィンドウが現れ、boot menu が表示される。“Install to harddisk” を選択する。“What is your preferred language?” と聞かれるので、“English” を選択する (日本語はない)。続いて、“Welcome to the FreeDOS 1.4 installation program. … Do you want to proceed?” と聞かれる。ここで、接続されている virtual hard disk drive file (または本物の hard disk drive) が上書きされるので、よく注意し、上書きしても問題なさそうであれば Yes を選択する。“Drive C: does not appear to be parititioned” と聞かれる。パーティションとは、記憶領域を論理的に分割したもの。パーティショニングによりストレージにいくつかの区画を設定しておけば、ある区画が故障しても他の区画は問題なく使える場合があり便利。しばしば boot 用ファイルやシステム設定ファイルと、個人ファイルのパーティションを分けて使う。DOS 用にパーティショニングをするために YES を選択する。途中で “Press a key” と要求されるので、適当にエンターキーなどを押してパーティショニングを続行する。キーボードレイアウトは好きなものを選ぶ。今回は US English を選択した。ただし、今回の目的は socket 経由で DOS を操作することなので、最後は host のキーボード設定で操作することになる。“What FreeDOS packages do you want to install?” と聞かれるので、好きなものを選ぶ。socket 経由で遊ぶだけなら Plain DOS system でいい。“We are now ready to install FreeDOS 1.4.” と聞かれるので、Yes を選択する。最後に reboot するように要求されるので、Yes を選択して reboot する。再起動するので、再度 Boot Menu が現れる。“Boot from the system harddrive” を選択すると今インストールしたシステムをブートできるが、今回はこれは終了して qemu コマンドでブートする。qemu を実行しているターミナルで CTRL-C をタイプして終了。

インストールした virtual hard disk drive から i386 エミュレータで FreeDOS を起動する。

DISPLAY=:0 qemu-system-i386 \
    -machine pc \
    -m 32 \
    -drive file=freedos.qcow2,format=qcow2,if=ide \
    -boot order=c \

起動したウィンドウで、C:\FDAUTO.BAT を編集して、起動時に自動で terminal を外付けシリアルに接続するようにする。 EDIT C:\FDAUTO.BAT し、ファイル末尾に以下を追記する。

MODE COM1:9600,N,8,1
CTTY COM1

Alt-f,x で終了する。終了前に保存するか聞かれるので、保存する。 CTRL-C 等で終了する。

FreeDOS の制御端末を ソケット経由で使う

DISPLAY=:0 qemu-system-i386 \
    -machine pc \
    -m 32 \
    -drive file=freedos.qcow2,format=qcow2,if=ide \
    -boot order=c \
    -chardev socket,id=dosserial,host=127.0.0.1,port=5000,server=on,wait=off \
    -serial chardev:dosserial \
    -monitor unix:/tmp/qemu-monitor.sock,server=on,wait=off  # FreeRTOS 1.4 の COM ドライバに対するワークアラウンド

FreeRTOS 1.4 には、仮想キーボードから何かを入力しないと COM1 の受信が開始されないバグ https://github.com/FDOS/kernel/issues/236?utm_source=chatgpt.com があるのでそれに対するワークアラウンドを起動直後毎回実施する。

printf 'sendkey ret\n' | socat - UNIX-CONNECT:/tmp/qemu-monitor.sock

これで、freedos-serial.sock から FreeDOS の制御端末を操作できるようになった。

OpenHSP 経由で遊んでみる

以下の OpenHSP スクリプトは HSP 経由で DIR コマンドを FreeDOS に送り、結果を表示するプログラム。

#include "hsp3cl.as"
#include "hspsocket.as"

sock = hsock_open("127.0.0.1", 5000)
if sock < 0 : end

txbuf = "DIR"
poke txbuf, 3, 13
sent = hsock_send(sock, txbuf, 4, 1000)

sdim rxbuf, 4097
repeat 100  ; Wait for 1 sec (await-ing 10 ms 100 times) until DIR command completes.
    n = hsock_recv(sock, rxbuf, 4096, 10)
    if n > 0 {
        poke rxbuf, n, 0
        mes rxbuf, 1
    }
    await 10
loop
hsock_close sock

ビルド定義も含めたアーカイブは /file/2026/1017/freedos_terminal_hsp.zip よりダウンロードできる。

実行すると、以下のように DIR の結果が表示される。 OpenHSP でサポートされる socket ではタイムアウトを設定できないので、代わりの外部ライブラリを作成した。

$ make run
make -C hspsocket/
make[1]: ディレクトリ '$HOME/Downloads/freedos_terminal_hsp/hspsocket' に入ります
cc  -O2 -g -std=c11 -Wall -Wextra -Wpedantic -Werror -fPIC -shared  -Wl,-z,defs -o libhspsocket.so hspsocket.c
make[1]: ディレクトリ '$HOME/Downloads/freedos_terminal_hsp/hspsocket' から出ます
hspcmp --compath=/usr/local/bin/common/ -i -u -d  -ofreedos_terminal.ax freedos_terminal.hsp
#HSP script preprocessor ver3.7 / onion software 1997-2025(c)
#Use file [hspdef.as]
#Use file [dish_enhance.as]
#HSP code generator ver3.7 / onion software 1997-2025(c)
#Code size (252) String data size (259) param size (88)
#Vars (5) Labels (2) Modules (4) Libs (16) Plugins (1)
#No error detected. (total 1308 bytes)

hsp3cl freedos_terminal.ax
DIR
 Volume in drive C is FREEDOS2025
 Volume Serial Number is 3F2A-0909

 Directory of C:\

FREEDOS              <DIR>  10-17-2026  1:36a
COMMAND  COM        87,772  02-21-2025  9:06a
FDAUTO   BAT         2,592  10-17-2026  1:54a
FDCONFIG SYS           947  10-17-2026  1:41a
KERNEL   SYS        46,256  04-02-2025  2:22p
         4 file(s)        137,567 bytes
         1 dir(s)     516,571,136 bytes free
C:\>