まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

私自身は今でも PC-DOS 環境を VM などで保管していて、当時のソフトウェアやゲームなどを楽しむことがあります。

その際、VM だけでなく DOSBox を使うこともあります。「PC/AT 互換機の DOS エミュレータ」で、比較的簡単に PC-DOS 環境を再現してくれます。後は自分のホスト PC に当時の PC-DOS で動くソフトウェアを一式そろえて、そのディレクトリを DOSBox からマウントするだけで、自分の使いたいソフト/ゲームの多くが利用できます。普通に使うだけなら非常に手軽なのですが、ただ日本語化が少し面倒だったり、ネットワーク機能を拡張したりしようとすると一気にハードルが上がる、というものだと理解しています。

この DOSBox の機能拡張版である DOSBox-X というものがあります。DOSBox-X では初めから日本語化が容易にできるよう準備されていたり、「PC98 モード」と呼ばれる、PC-9801 互換の MS-DOS で動くモードが用意されていたり、またネットワーク機能(TCP/IP スタック)についても対応済み、とされていました。ただ実際に DOSBox-X でネットワーク機能を有効にしたことはこれまでありませんでした。  先日、とある要件で「TCP/IP の使える DOS 環境」が必要になり、DOSBox-X で環境構築に挑みました。ちょっとクセのある内容だったこともあり、今後の備忘録目的でブログにまとめておきます。


【前提条件】
- ホスト OS: Windows 11(有線 LAN でインターネットに接続
- DOSBox-X: バージョン 2026.05.02
- DOSBox-X に設定する IP アドレス
  - IP: 192.168.0.123
  - ネットマスク: 255.255.255.0
  - デフォルトゲートウェイ: 192.168.0.1
  - ネームサーバー: 8.8.8.8

今の時点での私の結論はホスト OS が Windows の場合、ホスト OS は有線 LAN を使ってインターネット接続をしている、というのが DOSBox-X で TCP/IP 通信を使う前提となるようです(WiFi では NG 、という意味です)


【TCP/IP を使う上で必要なソフト】
  - 16bit DOS 用の TCP/IP スタックとなるソフトであり、ping.exe などのツールも同梱されています
  - DOSBox-X に仮想の NE2000 互換 NIC を設定するのですが、そのパケットドライバとなるソフトです
  - パケットキャプチャーライブラリ


【設定内容】
ホストコンピュータ(Windows 11)の以下のディレクトリに上述のソフトウェアをインストール/展開済みであると仮定して、以下の説明を続けます(NPCAP はデフォルトインストール先にインストールされているだけでOKです):

C:\
  |- DOSBox-X\        : DOSBox-X はこのフォルダを指定してインストール
  |- mTCP\            : mTCP はこのフォルダ内に展開
    |- packet\        : NE2000.COM はここへコピー
    :

まず C:\mTCP\mtcp.cfg というテキストファイルを以下の内容で用意します。この後設定する NE2000 互換仮想 NIC をロードして、上述の IP アドレス設定するための指定内容が記載されています。この例では 192.168.0.0/24 というネットワーク(ホスト OS が存在しているネットワーク)上で 192.168.0.123 という固定 IP アドレスを使って DOSBox-X を動かそうとしている、という例です:

PACKETINT 0x60
HOSTNAME dosbox
IPADDR 192.168.0.123
NETMASK 255.255.255.0
GATEWAY 192.168.0.1
NAMESERVER 8.8.8.8
MTU 150
TCPBUFFERSIZE 4096
UDPBUFFERSIZE 2048

また DOSBox-X 自体の設定ファイルである dosbox-x.conf(C:\DOSBox-X\ 直下にあります)を以下の内容に書き換えて保存します(書き換え対象部分だけ記載しています):

  :
  :
[ne2000]
ne2000 = true
nicbase = 300
nicirq = 3
macaddr = AC:DE:48:00:12:34
backend = pcap

[ethernet, pcap]
realnic = list
timeout = default
backend = pcap
promiscuos = true

  :
  :

[autoexec]
mount c c:\mTCP
set PATH=%PATH%;c:\;c:\packet
c:
c:\packet\NE2000.COM 0x60 3 0x300
set MTCPCFG=c:\mtcp.cfg

この内容については簡単に補足しておきます。まず [ne2000] セクションがあり、DOSBox-X 内で NE2000 互換の NIC カードを有効にしたい場合は、この中で "ne2000 = true" を宣言します。また nicbase や nicirq を指定しますが、これらはデフォルトのままで問題ありません。macaddr は仮想 NE2000 NIC の Mac アドレスです。適当な値で構いません。そして "backend = pcap" という宣言で PCAP 方式で NE2000 を利用することを宣言します。

ここでの backend で明示的に指定できる値は "auto" を除けば "pcap" か "slirp" です。簡単に言うと PCAP はホスト OS と同じネットワークにブリッジ接続する方式で、一方の SLIRP は独自ネットワークを作って、そこから NAT でホスト OS のネットワークに接続する方式です。

「その2つなら後者がいい」という人も多いと思いますが、残念ながら DOSBox-X でここを SLIRP 指定すると、DOSBox-X 起動時のログに以下のようなメッセージが現れます。これを解決する方法がわからず、SLIRP 接続はあきらめました。メッセージからして現在の Windows 版 DOSBox-X ではネットワーク接続時に SLIRP は使えないのではないかと思っていますが、知見のある方がいらっしゃったらこのあたりの事情を教えてほしいです:
2026051101


ということもあり、[ne2000] セクションには "backend = pcap" という PCAP によるブリッジ接続を指定します。

次の [ethernet, pcap] セクションではブリッジ接続の設定を記載します。まず初回は "realnic = list" という一行を追加してください(後で変更します)。この設定で DOSBox-X を起動して、メニューの ヘルプ - ネットワークインターフェースの一覧 を選択します:
2026051201


すると以下のような画面になり、現在のホスト PC が認識しているネットワークインターフェースの一覧が表示されます。有線 LAN や WiFi だけでなく docker や VM 環境の仮想インターフェースも(使っているのであれば)含まれているはずです:
2026051202


この一覧から有線 LAN のインターフェースを名前を頼りに探します。上の例であれば "12 rpcap://\Device\NPF_{xxx.xx} (Network adapter 'Intel(R) Ethernet Controller (3) I225-V #2' on local host)" と書かれたものがあり、有線 LAN は何となくこれかな? というものが見つかりました。

改めて dosbox-x.conf に戻り、先ほど [ethernet, pcap] セクションの中で "realnic = list" と書いた "list" の部分をこの見つかったインターフェースの番号(上の例であれば "12")に書き換えて保存します:

最終的には以下のような内容で dosbox-x.conf を保存します:
  :
  :
[ne2000]
ne2000 = true
nicbase = 300
nicirq = 3
macaddr = AC:DE:48:00:12:34
backend = pcap

[ethernet, pcap]
realnic = 12
timeout = default
backend = pcap
promiscuos = true

  :
  :

[autoexec]
mount c c:\mTCP
set PATH=%PATH%;c:\;c:\packet
c:
c:\packet\NE2000.COM 0x60 3 0x300
set MTCPCFG=c:\mtcp.cfg

この状態で改めて DOSBox-X を起動すると、mtcp.cfg に記載した内容に従って(上の例であれば 192.168.0.123/24 という IP アドレスで)ネットワークが有効になります。ブリッジ接続しているので、同じネットワーク上の他のサーバーやルーターとも疎通確認ができるはずです。mTCP に ping.exe が付属しているので、これらを使って同一ネットワーク上の他の機器と疎通確認してください:
2026051203


ホスト OS 側で有線 LAN が有効になっていることが前提ですが、これで DOSBox-X を使って TCP/IP ネットワーク環境が整えることができました。
無線 LAN(WiFi) でもできる方法ご存知の方がいたら教えてください。Windows でなければいけるのかな・・


この連休中に 16bit PC-DOS 向けの Java(正確には Java サブセット)コンパイラとその VM である "dosjava" を生成 AI 併用で作ってみました。まだまだ機能的には未熟ですが、今のタイミングで一度公開しておきます:
https://github.com/dotnsf/dosjava

2026050700

(↑ 細かすぎて伝わらないと思ったので書きますが、Java Duke を 16bit っぽく粗くしてみました)



【"dosjava" とは?】
16bit OS である PC-DOS(DOS/V)上で動く Java のサブセットです。Java は "Write Once, Run Anywhere!"(記述したコードはどの Java 環境でも動く)を提唱していましたが、色々な制約の事情もあり、残念ながらその理念は継承できていません(別環境の javac でコンパイルした .class ファイルを持ってきても動かない、という意味です)。ただ「ソースコードレベルではなるべく修正なしに動く」ことを開発目標の1つにしています。

PC-DOS 環境なので、例えばファイル名にも制約があります(ファイル名8文字以内、拡張子3文字以内)。コンパイラは "djc.exe" で、Java VM は "djvm.exe" ですが、ソースコードは "test.java" という名称を付けることができず "test.jav" のようなファイル名にする必要があります。これを djc.exe でコンパイルすると "test.djc" というファイルになりますが、これが "test.class" に相当するものです("djvm.exe" で実行可能です)。

ちなみに私の開発環境は 64bit の Windows11 で、クロスコンパイラには Open Watcom V2 を使っています。


【「とりあえず動かしてみたい」人向け】
PC-DOS エミュレータである DOSBox を使うことをおススメします(私自身の動作確認でも DOSBox を使っています)。2026-05-07 時点での最新バージョンは 0.74-3 で、かなり枯れて(安定して)いるものです。Windows 環境であればコマンドプロンプトから winget を使って以下のコマンドでインストールすることも可能です:
> winget install -e --id DOSBox.DOSBox

"dosjava" を DOSBox から使えるようにします。端的に言えば "djc.exe" と "djvm.exe" を PC-DOS 上のパスの通ったディレクトリに置くだけでいいのですが、DOSBox の場合はホスト PC の特定フォルダをマウントする機能があるので、以下はその方法で "dosjava" を使えるようにする手順を紹介します。

まず git clone(又は zip ダウンロード&展開など)で dosjava 一式をホスト PC にコピーします(ちなみに Windows 用の git を持っていない場合はこちらからインストールしてください):
> git clone https://github.com/dotnsf/dosjava
(ホームディレクトリ直下に git clone したものとします)

この時点でホームディレクトリ(C:\Users\myname\ とします)の直下に dosjava というフォルダが作られ、一式がコピーされているものとします(ちなみに実行バイナリは dosjava\build\bin\ 以下に djc.exe と djvm.exe があります)。

これを DOSBox から使えるようにマウントします。DOSBox の設定ファイルを編集するため、"dosbox" で検索して "DOSBox 0.74-3 Options" と書かれた箇所をクリックします(上で紹介した winget 以外の方法で DOSBox をインストールした場合はこの方法では設定ファイルを編集できない可能性があるので、インストール先ディレクトリを探すなどして dosbox.conf ファイルを探してください):
2026050701


設定ファイルをテキストエディタで開いた状態になります:
2026050702


一番下までスクロールして、[autoexec] と書かれた箇所を表示します。そしてその下に以下を記載して保存します(先ほどクローンした dosjava フォルダを DOSBox の c: ドライブとしてマウントし、かつ djc.exe や djvm.exe がある build\bin\ ディレクトリにパスを通して c: ドライブに移動する、という内容です):
mount c c:\Users\(ユーザー名)\dosjava
set PATH=%PATH%;c:\build\bin
c:

2026050703

この状態で DOSBox を起動します(dosbox のアプリを開きます):
2026050704


正しく DOSBox が起動できると以下のような画面になります(上で [autoexec] 以下に書いたコマンドが実行されていることを確認します)。ちなみに DOSBox 内では英語キーボード配列になっているので注意してください(ディレクトリ区切り記号である半角\を日本語キーボードで入力するには右上の(SHIFT キーを併用すると "|" になる)キーではなく、右下の(SHIFT キーを併用すると "_" になる)キーを入力する必要がある点に注意してください:
2026050705


いくつかの動作確認済み Java ソースコードが c:\samples\ フォルダ内に格納されています。試しにこれらをコンパイル&実行してみましょう。

まずは DOSBox 内で以下のコマンドを入力して samples\ フォルダ内のファイル一覧を確認します:
c:\>cd samples
c:\samples\>dir

2026050706


例えば "hello.jav" というファイルの内容を確認するには "type hello.jav" と入力します(関数呼び出しのテストを兼ねているので少しだけ複雑化していますが、いわゆる「ハローワールド」の Java ソースコードです):
2026050707


ではこの hello.jav をコンパイル&実行してみます。まずは djc.exe でコンパイルします。"djc hello.jav" と入力します:
c:\samples\>djc hello.jav

2026050708


コンパイルに成功すると上図のように "Compiled: hello.jav -> hello.djc" と表示されます。これは「hello.jav をコンパイルし、結果を hello.djc として保存した」という意味です。この hello.jdc は一般的な Java でいう所の "hello.class" に相当するものです。

コンパイルした "hello.djc" を実行するには Java VM である "djvm.exe" を使います:
c:\samples\>djvm hello.djc

2026050709


成功すると元のソースコードで記述されていたように "Hello World!" という文字が出力されます。

この samples\ フォルダには他にも(現在の dosjava でテスト済みの)多くのサンプル Java ソースコードがあるので、同様に色々試して(コンパイル&実行)みてください。

自分でソースコードを書きたい、という場合は Windows 環境で dosjava ディレクトリ以下にソースコードを作っていただいてもいいのですが、DOSBox 内のあくまで PC-DOS 環境内で記述したい、という場合は別途 16bit PC-DOS 用のスクリーンエディタを用意して(上述のようにそのフォルダもマウントして、パスを通すなどして)利用してください。個人的には 2024 年にオープンソース化された Vz Editor がおススメです。


【(2026-05-07 時点での)仕様】
dosjava は Java と「なるべくソースコード互換」になるよう設計/開発していますが、残念ながら Java との互換性確保の優先順位を下げて実装したものもあります。

具体的には 2026-05-07 時点のビルドでは Java の以下の機能は実装済みです:
  • 型は int, String 、および int 配列
  • 以下の算術演算: +, -, *, /, %, ++, --, +=, -=
  • 以下の比較演算: ==, !=, <, >, <=, >=
  • 以下の論理演算: &&, ||, !
  • 以下の制御構造: if~else~, for ループ, while ループ
  • System.out.println( 文字列または整数 );
  • String 変数には以下のメソッドを実装済み: length(), toUpperCase(), toLowerCase(), equals(), compareTo(), startsWith(), endsWith(), indexOf(), lastIndexOf(), substr()

以下の機能は Java との互換なしに実装済みです("import java.io.File"; は不要):
  • File 関連テキスト読み書き追加関数: File.open(), File.readLine(), File.writeLine(), File.close()

以下の機能は現時点では未実装(実装予定なし)です。16bit では厳しいことに加え、関連機能(例えば浮動小数点演算を実装すると、それらの配列処理や java.lang.Math との互換性などが必要になる)との兼ね合いで優先順位を下げざるを得なかったものとご理解ください:
  • 浮動小数点演算(float, double, Float, Double)
  • ネットワーク処理
  • 日付時刻演算
  • 外部クラスの import 機能

今後の予定では日本語文字列処理やファイル処理のバイナリファイル対応の実装、そして DOSBox ではない PC-DOS での動作確認あたりを考えています。要望などあれば issues から教えてください。プルリクは大歓迎です。


【おまけ】
この dosjava は生成 AI を併用して開発しています。普通のアプリケーションサービスであれば、今のコーディング生成 AI であればソースコード実装だけでなく、ビルド、テストなども実行させ、途中で失敗する場合は原因を考えさせた上で修正→再ビルド→再テスト・・ と一通り動くようになるまでを能動的に行わせることができます(この方法で進めていくらかかるかは別の話だけど)。とても便利なのですが、本プロジェクトのように「開発環境と実行環境が別」な場合、つまりクロスコンパイルが必要なものに対して、生成 AI をどのように使っていくべきか? というのは面白いテーマのように感じています。

今回の dosjava の場合、動作確認には Windows アプリである DOSBox を使っています。残念ながら DOSBox は生成 AI が外から手を出すことができない(毎回設定ファイルを書き換えて初期実行コマンドを変えればできないことはないんだろうけど・・・)ものです。この環境だとコーディングとビルド成功までは生成 AI に任せて、動作確認やテストは手動実行する必要があります。

つまり、
  • とりあえず開発目標を定めて(人間の役割)、
  • その目標のための開発計画を考えさせて(生成 AI の役割)、
  • 開発計画に沿って、ビルドできるようになるまで実装させて(生成 AI の役割)、
  • 動作確認する。期待通りの結果が出なかった場合はエラー内容や現在の挙動内容を使える(人間の役割)
  • 現在の挙動内容をヒントにソースコードの修正プランを考えさせて、修正を実装する(生成 AI の役割)
  • (期待通りの結果になるまで上の繰り返し)
という役割分担で作業する時間が多かったと感じています。図らずも TDD(Test Driven Development : テスト駆動開発)のスタイルで開発することが感覚的にも合っていた、と思いました。


しばらくブログをご無沙汰していました。久しぶりの投稿はスプレッドシートの開発&公開の話です。

エンジニアの皆さんの多くはターミナルや(Windows であれば)コマンドプロンプトといった、いわゆる CLI(Command Line Interface) で操作するツールを普段から使っている人は珍しくないと思います。現に git などは GUI のアプリもありますが、多種多様なオプションを指定して操作しようとすると、必要なオプションを自由に指定できる CLI 版の方が使いやすいと感じます。

私自身は普段は Windows PC を使っていて、ターミナルは WSL を導入した上で Ubuntu のターミナルを開いて操作していることが多いです。このように Linux (おそらく macOS も)を使っている間は多くのツールが CLI で提供されていることもあってあまり不便に感じることはありません。

ただ、これが Windows のコマンドプロンプト(cmd.exe)を使っていると使えるツールの少なさから困ることもあります。比較的最近まではコマンドプロンプト内で使えるテキストエディタがなかったので、テキスト編集のためにいちいちメモ帳(notepad.exe)を起動して編集し、編集し終わったらまたコマンドプロンプトに戻って・・・ といったいかにも面倒な感じで操作してました。Linux なら有名な vi を使えたり、vi が苦手でも nano エディタなどターミナル内で使える多くの選択肢があるのに・・・ ただこの問題は Microsoft が edit という謹製ツールを提供してくれたおかげで解決しました。

そこで残った問題がスプレッドシートでした。エクセルを使う程でもないちょっとした演算が可能な表計算ツールを使いたい時にコマンドプロンプト内で動作するツールの選択肢が(私の知る限り)存在していないのです。ちなみに Linux であれば sc というツールが存在していて、ターミナル内でもこのスプレッドシートを使って計算することができます。

#おまけに言うと Windows の前の DOS 時代には Lotus 1-2-3 という DOS プロンプト内で動作するスプレッドシートがあったのですが、これは 16bit 環境でしか動かないので現在の 64bit Windows では互換モードも用意されていないのでした。。


・・・という背景の中、生成 AI の力を借りつつ苦手な .NET C# プログラミングに挑戦して、64bit Windows のコマンドプロンプト内で動くスプレッドシート・アプリケーションを作ってみました。以下、そのツールを簡単に紹介します。


ツールの名前は Cli SpreadSheet の略で css としています(Cascade StyleSheet ではないです)。css はこちらでソースコード含めて公開しています:
https://github.com/dotnsf/css

ツールのダウンロードは上記ページ内の「インストール」節のリンクから css.exe をダウンロードしてください(このファイル1つだけで動きます)。シンプルなツールですが .NET Runtime を内蔵していることもあって 30MB 以上あります。そして PATH の通ったフォルダにコピーします:
2026040701


起動するにはコマンドプロンプト内で "css" を実行します。パラメータでファイル名を指定(例 "css test.csv")して読み込むことも可能です。このパラメータ例で分かるかもしれませんが、CSV ファイルから読み込んだり、CSV ファイルに出力することが可能です:
2026040703


css が起動すると下図のようにコマンドプロンプト内でスプレッドシートが起動します:
2026040702


青く背景になっている部分がアクティブセルです。矢印キーまたは hjkl キーでアクティブセルを動かすことが可能です。この状態で Enter キーまたは i キーを押すと編集モードに切り替わり、次に Enter キー(確定)または ESC キー(取消)を押すまでアクティブキーの内容を編集できます:
2026040704


SUM, AVERAGE, IF, ・・・といった代表的なエクセル互換関数をサポートしています。詳しくは「関数リファレンスガイド」を参照ください:
2026040705


":" キーを押すと画面がコマンドモードになり、":e ファイル名" で CSV ファイル読み込み、":w" で CSV ファイル書き込み(ファイル名を指定する場合は ":w test.csv")、":width 数値" でアクティブのセルのある列の列幅変更、といった操作が可能です。この辺りは vi キーバインドを参考にしています。

また vi に詳しくない人向けにコマンドモードをメニューから利用できるようにもしています。その場合は "/" キーを押すことでメニューを表示し、ここから選択することでもコマンド実行が可能です(このあたりは Lotus 1-2-3 互換です):
2026040708


終了はコマンドモードから ":q" です。編集中のファイルがある場合はすぐには終了できませんが、編集を破棄して強制終了する場合は ":q!" で終了します。終了後はコマンドプロンプトに戻ります:
2026040707


概ねの使い方は以上です。詳しくは README.md や他のドキュメントを参照ください。


自分が使うことを前提(大事)に、vi キーバインドや Lotus 1-2-3 互換メニューのような機能を実装しました。最低限の関数も実装したおかげもあって、自分的には使いやすいものができたと思ってます。同じようにコマンドプロンプト内のままスプレッドシート機能を使ってみたい人がいたら是非使ってみてください。


ちなみに、このアプリを作る上で IBM Bob という生成 AI を使いました。自分が普段不慣れな言語だったこともありますが、いやあ「すげー便利」ですね。。



このページのトップヘ