MS-DOS Player for Win32-x64
This is MS-DOS emulator running on Win32-x64 command prompt.
16bit MS-DOS compatible commands can be executed on Win32-x64 envrionment.
Download
MS-DOS Player for Win32-x64 謎WIPページ
私が開発するネタとしては、珍しく実用的かもしれませんね。
まあ、自分が必要で作っただけなんですが(苦笑)
2024/10/31
CGA/MDAのテキストモードのVRAM、または仮想テキストバッファを読むことで、
コンソール画面の表示内容を取得できるようにしました。
VZエディタで[ESC]Eでプロンプトに降りた時、DOS画面が復帰するようになっています。
INT 21h, AH=13h/17hで、ワイルドカードを含むファイル名をサポートしました。
FCBを使ったファイルの削除およびリネームのサービスです。
MS-DOS V6.22のCOMMAND.COMのDEL/RENコマンドで使われていました。
2024/10/24-2
先の更新で、エラーテーブルをIRETテーブルと同じメモリ領域にいれたときに、
後続のMCBのセグメントをエラーテーブル分だけずらすのを忘れてました。
取り急ぎバイナリを更新しておきます。
2024/10/24
INT 21h, AH=0Fh/10h/11h/12h/13h/16h/17h/23h/29hを修正しました。
FCBを使ったサービスで失敗したときに、拡張エラーコードを設定するようにしました。
V6.22のCOMMAND.COMで、DIR実行時にエラーが表示されなくなっています。
INT 21h, AH=4Eh/AX=714Ehを修正しました。
最初のエントリが見つからないときに、適切なエラーコードを返すようにしました。
INT 2Fh, AX=0502hで拡張エラーメッセージを返すようにしました。
パラメータエラーの筈なのですが、COMMAND.COMは拡張エラーを期待しているようです。
INT 2Fh, AX=122Eh, DL=00h/02h/04h/06hで取得するエラーテーブルを追加しました。
ただし全種類共通で、中身の空っぽな単一のテーブルを参照しています。
またDL=01h/03h/05h/07hでエラーテーブルのアドレスを変更できるようにしました。
プロセス起動時のメモリ確保のコードを整理しました。
コンベンショナルメモリが不足の場合、常に自動的にUMBを使用するようにしました。
COMモデルの起動時に、64KBのメモリの空きがないときに失敗するようにしました。
プロセス終了時に、開放するメモリのMCBが壊れている場合に修復するようにしました。
INT 2Fh,AX=4810hのサポートを廃止しました。
DOSKEYの1行入力ですが、従来よりDOSKEYは未インストール扱いとなっています。
Windows 98のCOMMAND.COMがインストールチェック無しに使っていたため、
一応サポートしてましたが、VZの常駐の妨げになっていたため廃止することにしました。
Windows 98のCOMMAND.COM上で、VZを常駐した状態でバッチファイルを実行すると、
バッチファイルから子プロセスを起動するとき、コンベンショナルメモリの空きが
0になってしまう問題が発生しています。
常駐時は、VZ.BAT経由ではなくVZIBMJ.COMを直に起動するようにしてください。
(V6.22のCOMMAND.COMだとそのような問題は発生しないのですが…)
MS-DOS Playerの起動時に、スペース入りのargvを渡された場合、仮想マシンに渡す
コマンドラインにダブルクォーテーションで括って追加するようにしました。
2024/10/20
NP21/WのI386コアを、ver0.86 rev92相当に更新しました。
SSSE3, SSE4, SSE4aのサポートが追加されています。
DOSアプリでこれらのCPU拡張命令を使うことはないと思いますが(苦笑)
2024/10/18
-pオプションでコードページを指定した場合に、実際に指定したコードページに
変更する処理が抜けていたのを修正しました。
仮想マシン上でカーソルを非表示にしても、実際の表示には反映されませんが、
(理由については2017/8/25の項目をご参照ください)
-hオプションを指定することで、カーソルの非表示を反映するようにしました。
切断されたリモートドライブに対して、GetDriveTypeA()を実行すると、
長時間固まってしまう場合がある問題の対策を入れました。
先にWNetGetConnectionA()を実行して、リモートドライブである場合は、
GetDriveTypeA()を実行しないようにしています。
WNetGetConnectionA()は共有の設定を見るだけで、実際のドライブに対しては
何もアクセスしないのではないか、という期待をしています。
2024/10/7
INT DChとINT DDhの割込みベクタが同じ値になるように修正しました。
これが違う値の場合はPC-98x1であると判定する手法があるそうです。
J-3100用のATOK割込みが機能しなくなっていたのを修正しました。
先日内部処理で使用する割込み番号を変更した際にミスしてました。
2024/10/6-2
INT 2Fh, AX=1703h,1709hを修正しました。
データ長の指定が、何故かSI:DIになっていたのを、SI:CXに修正しました。
INT 2Fh, AX=1705hを修正しました。
クリップボード内のデータ長の取得に失敗したとき、AX,DXをクリアするようにしました。
INT 2Fh, AX=1704h,1705hを改良しました。
データ長の取得を、GlobalSize()でなくstrlen()で行うようにしました。
2024/10/6
INT 2Fh, AX=1700h-1705h,1708h-1709hをサポートしました。
古いバージョンのWindowsの、クリップボードを読み書きするサービスです。
VZエディタで使用できるらしいので、ひとまず実装してみました。
私の方では未確認のため、よろしければテストお願いいたします。>金野様
2024/9/23
INT 2Fh, AX=1689hをサポートしました。
Windows 3.xで、処理をアイドル状態にするAPIになります。
もしかしたら、DOS窓用のコンソールアプリで使っているかもしれません。
内部処理で使用している割込み番号を、6xhから4xhに変更しました。
ユーザが使用する可能性のある番号を、システム用の予約番号に変更した形です。
2024/9/22
高橋版VZエディタ向けの修正を行いました。
INT 21h, AH=3Dhで、$IBMAIASをオープンすることで存在チェックをしていますが、
デバイス名がnull terminatedになっていませんでした。
$IBMAIASから始まるパスは、強制的に8文字までで切るように補正します。
INT 21h, AX=4400hで、$IBMAIASのデバイス情報にDX=8080hを返すようにしました。
高橋版VZエディタは、DL=80hになっているかチェックしているようです。
2024/9/21
DOSVAXJ3の実装を参考に、INT 16h, AH=13hと、INT 6Fhの実装を整理しました。
IMEのオンオフやモードの取得・変更をする処理です。
また、$IBMAFNT/$IBMADSP/$IBMAIASが存在しているふりをするようにしました。
(ダミードライバの追加と、INT 21h, AH=3Dhでオープンできるようにした)
DOSVAXJ3だとVZでIMEの制御がうまくできるらしいので、これで様子をみてみます。
システムポートのbit4, bit5で、タイマーのCh.1/2の出力の読めるようにしました。
それぞれ、RAMのリフレッシュ信号と、ビープ音の信号に使用されています。
前者は15us間隔でトグルしますが、そこまで高精度に時間を管理できないので、
連続して読む度に、1msの間に最大66回までトグルするようにしました。
…こんなところをチェックするCLIなツールがあるとも思えませんが(苦笑)
2024/9/19
INT 21h, AH=49hの処理を修正しました。
メモリブロックの開放後、後続の空きメモリとの結合をしないようにしました。
INT 21h, AH=4Ahの処理を修正しました。
指定したメモリブロックのサイズの変更に成功した場合、そのメモリブロックのオーナを
呼び出し元のプロセスに変更するようにしました。
サイズの変更に失敗した場合も、可能な限り最大のサイズに変更するようにしました。
DOS 4.0のソースを見る限りでは、以下のような挙動になっているようです。
後続の空きメモリブロックと結合することで、可能な限りサイズを大きくする。
指定のサイズ以上になった場合は、指定のサイズまでメモリブロックを分割して、
(元オーナが他のプロセスだろうが、空きメモリブロックだろうが、お構いなしに)
そのメモリブロックのオーナを自プロセスにする。
サイズが足りない場合は、どこまでサイズを大きくできたかをBXに返す。
このとき、メモリブロックを元のサイズに戻したりはしない。
VZエディタで、開放したメモリブロックのサイズを変更するような処理があるらしく、
これで動作が改善しているのではないかと思います。
2024/9/10
INT 13h, AH=15hを修正しました。
ハードディスクとフロッピーディスクのディスクタイプを逆に返していたのを
修正するのにあわせて、2Dと2DD/2HDの識別もするようにしました。
また、ディスクのブロック数をCX:DXに返すようにしました。
2024/9/8
COMMAND.COMがない状態で「COOMAND.COM /C」で内部コマンドを実行する件で、
TRUENAMEとVERについてもMS-DOS Playerの内部処理で実行するようにしました。
TRUENAMEについては、そもそもWindows NTのcmd.exeでサポートされていない、
VERについては、WindowsでなくMS-DOSのバージョンを表示したい、という理由です。
INT 13h, AH=08hについて、DLに接続されているフロッピードライブ数を、
BHに0をセットするように修正しました。
ただし、フロッピードライブの接続は、A:とB:しかチェックしていません。
2024/9/7
プロセスの起動周りのコードを整理しました。
影響の大きそうな変更も入っていますので、テストにご協力お願いいたします。
「COMMAND.COM /C TYPE (file)」のように、子プロセスで内部コマンドを実行する場合、
A-Z:/CHDIR/PATH/SETは、MS-DOS Playerの内部処理で実行するようにしました。
子プロセスでこれらのコマンドを実行しても、呼び出し元に反映されないためです。
その他のコマンドは、COMMAND.COMを子プロセスとして起動して実行をします。
COMMAND.COMがない場合、system()でcmd.exeに渡してWindows側で処理しますが、
TYPEコマンドについては、INT 29hを通るように、MS-DOS Playerの内部処理で実行します。
「COMMAND.COM /C 実行ファイル」を起動しようとして、COMMAND.COMがない場合は、
実行ファイルを直接起動しますが、このとき新しいプロセスの第1・第2のFCBを更新して、
実行ファイルに指定された引数が入るように修正しました。
INT 10hやINT 21hで文字を画面に表示する際、INT 29hを経由して表示した場合に、
(INT 29hをフックしている場合のみ、INT 29hを経由するようになっています)
INT 29hを直に呼んだように、制御コードがシンボルとして表示される問題を修正しました。
起動時にCOMMAND.COMを探す際に、PATHおよびMSDOS_PATHに指定されたパスを
探索していなかった問題を修正しました。
過去にコードを整理していたときに、処理の順番を誤って変更してしまったようです。
2024/9/4-2
子プロセスとして「COMMAND.COM /C 実行ファイル 引数」を起動しようとして、
COMMAND.COMが見つからない場合、/Cで指定した実行ファイルを直に起動します。
この際、「引数」の部分だけ新しいプロセスのPSPにセットすることになりますが、
引数の先頭にスペースを入れるようにしました。
小林様が移植されたGREPは、引数の先頭がスペースであることを期待しているようです。
INT 21h, AH=49hの処理が成功した場合、AXにES-1をセットするように修正しました。
Undocumentedな仕様ですが、DOS 4.0のソースを見ると、確かにそのようです。
2024/9/4
^G(ベル)がコンソールに出力された場合、INT 29hを呼ばないようにしました。
子プロセスを起動するとき、コマンド引数の末端に0x0dをセットするようにしました。
鈴木様からご指摘のあった、古いバージョンのVZからGREPを呼んだ際の問題の対策です。
2024/8/31
実行ファイルを読み込む処理を改良しました。
プログラム名だけ指定した場合、.COM / .EXE / .BATを付けてファイルを読み込みますが、
拡張子なしでプログラム名と同じ名前のファイル(JGAWK.EXEとJGAWKなど)があると、
そちらが優先して読み込まれてしまっていました。
拡張子がないファイルが、実行ファイルとして読み込まれないように修正しています。
2024/7/31
Visual C++ 6.0 SP6でビルドできるよう手直ししてみました。
ただしMAMEコアのみで、NP21/Wコアは未対応です。
ビルドしたバイナリが、Windows NT 4.0上で動作することを確認しています。
今回から、x86版はVC++2008で、x64版はVC++2017でビルドするようにしました。
VC++2008でビルドしたx86版は、Windows 2000上で動作します。
2024/7/17
結局、本国ポルトガル語のエラーメッセージも追加しました。
ブラジル以外のポルトガル語の場合は本国ポルトガル語になります。
2024/7/16
ブラジルポルトガル語のエラーメッセージを追加しました。
コードページ850または860で、言語設定がポルトガル語系の場合に有効となります。
ただし、本国ポルトガル語の設定の場合もブラジルポルトガル語となります。
話者の人口比を鑑みて、ということでご了承ください。
2024/7/15
INT 2Fh, AX=0502hを修正しました。
拡張エラーコードではなく、パラメータエラーのメッセージを取得するようにしました。
日本語メッセージをSJISでハードコードしていたのを、BYTEのConstな配列に変更しました。
ソースのエンコードを変更すると文字化けする問題が解決しています。
このついでに、フランス語、ドイツ語、スペイン語、韓国語のエラーメッセージを追加しました。
アクティブなコードページが932のときは日本語、949のときは韓国語、
850のときはWindowsの言語設定がフランス語、ドイツ語、スペイン語のときはその言語、
それ以外のときは英語のエラーメッセージが取得されます。
中国語、台湾語版のWindows 98のCOMMAND.COMはローカライズされていないみたいですね。
2024/7/6
INT 16h, AH=F0hを修正しました。
ビープ音の周波数を、PITに設定されたカウント値から決定するようにしています。
2024/7/3
IMEを操作する処理周りのコードを整理しました。
ImmGetDefaultIMEWndの返り値がNULLでないかチェックしていなかったので、
非アジア圏のWindows環境で、IMEがない場合に問題があったかもしれません。
2024/7/1
INT 10h, AX=8200hを修正しました。
BLがFFh以外のとき、変更前のスクロールモードの値をALに返すように修正しています。
INT 16h, AH=02h/12h/51hを修正しました。
トグルするキーの状態を正しく取得できるようになっています。
ただしVK_KANAの状態は、Windows10ではIME絡み?でうまく取得できないようです。
INT 10h, AX=5000h/5001h, AH=85hをサポートしました。
J-3100のカーソルモードの取得・変更、カーソル位置の文字のアトリビュートを取得します。
INT 16h, AH=F0h/F1h/F5h/F6hをサポートしました。
J-3100のビープ鳴動、キーのロック状態の変更、キーバッファへの追加や状態の取得をします。
INT 6Fh, AH=01h/02h/03h/04h/05h/0Bh/66hをサポートしました。
J-3100で使用しているATOK5/6のオン・オフや状態の変更・取得をします。
またATOK5/6のダミードライバーを組み込みました。
主に、J31BASICで使用されているっぽいサービス類を中心にサポートしています。
INT 10h/16h, AX=5000h/5001hをサポートしました。
AXのビデオ・キーボードBIOSのカントリーコードの取得・変更をします。
ただし、値の変更をしても、BIOSの動作には影響しません。
INT 16h, AX=1300h/1301hをサポートしました。
DOS/VのIMEのオン・オフや状態の変更・取得をします。
Windows10の新しいIMEは、コンソールアプリ上の挙動が色々と怪しくなっているようで、
ローマ字・カナ入力の状態を正しく取得できません。
このため、ローマ字・カナ入力を切り替える処理は、現状では無効にしています。
従来のIMEを使っているか否かの判定はできそうなのですが、
Microsoft IME以外を使っているかの判定をどうすればいいか調査中です。
2024/6/27
MAMEとNP21/WのI386コアにおいて、消費クロックの積算を無効にしました。
RDTSC命令は、ホストCPUのTSCの値を返すようにしています。
Nmlgc様のプルリクエストの変更を、更に推し進めてみた感じですね。
処理速度が大きく向上しているのではないかと思います。
x64版のビルドにおいて、ホストの環境変数からパスを読み込む際に、
C:\Windows\System32をC:\WINDOWS\SYSWOW64に置換するようにしました。
2021/12/30に、x64版でtesti386を実行すると例外が発生すると書きましたが、
パスの通っているディレクトリからpsapi.dllをロードしようとして、
x64版ではC:\Windows\System32\psapi.dllがロードされていました。
これが64bitのバイナリのため、例外を起こしてしまったようです。
(x86版では、C:\Windows\SysWOW64\psapi.dllが代わりにロードされます)
2024/6/24
cracyc様のforkに来てた、Nmlgc様のプルリクエストを一部取り込みました。
主にNP21/WのI386コア絡みの高速化のハックと、不要なグローバル変数の初期化の省略です。
(ただし、I386コアの変更はバイナリには反映されていません)
ついでに、テキストVRAMへのWORD/DWORD書込みを微妙に(if文1回)高速化しました。
2024/6/23
cracyc様のforkから、更に修正を取り込ませていただきました。
Nmlgc様のプルリクエストも多々含まれています。
(コンソールの処理の全般的な修正は、変更が巨大なので、まだ様子見させてください)
メモリのアロケーションの処理を改良しました。
プロセス開始時のメモリ確保で、メモリチェーンの最後のブロックを使用する処理を廃止して、
一般にアロケーションストラテジに従うように変更しています。
INT 17h, AX=5000hにおいて、BXの値の判定処理が間違っていたのを修正しました。
INT 21h, AH=1Bh/1Chにおいて、取得したメディアタイプをDS:BXにコピーするのではなく、
DS, BXの値を、ドライブパラメータブロック上のアドレスに変更するように修正しました。
INT 33hのマウスサービスを、INT 15h, AH=C2hを呼び出す実装に修正しました。
DESQview向けに、BIOSワークエリアの50h-58hの初期化処理を修正しました。
マウスホイールをPageUp/Downとして処理するようにしました。
その他、マルチスレッド周りの処理のコード整理などをしています。
2024/3/2
INT 21h, AH=43h, BL=08hが、BL=06hと同じ動作になっていた問題を修正しました。
内蔵デバッガを改良しました。
Rコマンドでレジスタ以外にフラグの値の変更もできるようにしました。
また、V30のディスアセンブラを、i386用のディスアセンブラと統合しました。
V30専用命令以外で正しく認識されない命令があったのが解決しています。
レジスタ名も標準的な名前で表示されるようになっています。
(この辺りはCommon Source Code Projectでも同様の対応を行う予定です)
roytam様のforkから、更に修正を取り込ませていただきました。
conhost-v2のクラッシュ対策の改良と、WindowsNT 3.51/4向けの修正をしています。
…流石にNT 3.51は使ったことないなー(苦笑)
2024/2/28
INT 21h, AX=4404h/4405h/440Ahを修正しました。
BXでハンドルを指定するか、BLでドライブを指定するか、間違えて処理していました。
AX=440Ahはハンドル指定、AX=4404h/4405hはドライブ指定に修正しています。
内蔵デバッガを改良しました。
プロテクトモード時のコードページの処理を修正しました。
また実行トレースに、各命令を16bit/32bitのどちらで実行したか記録するようにしました。
(V30の場合は8080モードか否かを記録)
Uコマンド、UTコマンドで正しく命令を表示できるようになっているかと思います。
roytam様のforkを参考に、conhost-v2のクラッシュ対策を入れました。
カーソルが最後の行にあるときにウィンドウサイズを変更するとクラッシュし易いようです。
また未確認ですが、Windows NT4.0 / 2000で動作するための修正も取り込んでいます。
2024/2/19
strcpy_s()で、指定したバッファ長よりも長い文字列をコピー元として指定したときに、
例外0xc0000417が発生することがあるようです。
そのようなケースでも安全に文字列をコピーするための関数のはずなので釈然としませんが、
ひとまずstrncpyで処理をするように対策をいれました。
strcpy_sの仕様を長年勘違いしてました、これはお恥ずかしい。
strlcpyのような動作をするんだと勘違いしてました(苦笑)
2024/2/18
cracyc様のforkから、更に修正を取り込ませていただきました。
INT 67h, AX=5B00h/5B01h/5B04hについて、BHに00h以外を指定したときにエラーを返すようにしました。
MDA(Monochrome Display Adopter)をサポートしました。
その代わりに、コンベンショナルメモリの上限がB8000hからB0000hとなり、32KBだけ減少しています。
(それでも、VGAのVRAMがない分だけ、通常の環境より64KB大きいのですが)
CRTC, Status Registerも、MDAのアドレスでアクセス出来るようにしたのと、同期信号を50Hzにしました。
2024/2/15
cracyc様とroytam様のforkから、修正を取り込ませていただきました。
FCBを使ったファイルアクセスと、MAME版i386コアのFPU周りの例外の修正などです。
また、MAME版i386コアのDAA/DAS/AAA/AAS/AAM/AAD命令を、DOSBoxの実装を基に修正しました。
Pentium4版で、testi386.exeが実機と同じ結果が得られるようになっています。
NP21/WのI386コアを、ver0.86 rev92 beta2相当に更新しました。
また、ビルド時のワーニングが出ないように修正しました。
環境変数のアクセス時に、正しくない環境テーブルを参照したときのチェックを強化しました。
最近のビルドでtesti386.exeが動かなくなっていた問題が解決しています。
メモリアクセスの処理を効率化しました。
基本メモリ、拡張メモリ、予約領域(VRAMなど)の順に、少ない条件分岐でアクセスできるようにしています。
微妙に処理速度が上がっているかもしれません。
2023/12/14
INT 10h AH=08hについて、漢字の文字コードを取得できるよう修正しました。
こちらの不具合は、金野様にご指摘いただきました。
いつもお世話になっております。
ReadConsoleOutputCharacterAで漢字を1文字だけ取得すると、20hが返るようです。
行全体を取得することで、漢字の第1・2バイトのどちらも読めるようになっているかと思います。
2022/12/30
NP21/WのI386コアを、ver0.86 rev88 beta4相当に更新しました。
ただし、fpemul_softfloat.cについては、testi386.exeで例外が発生するようになったため、
今回はまだ取り込んでいません。
2022/9/20
通常、MS-DOS Player上で動作するアプリがCOMMAND.COMにアクセスしようとすると、
2015/12/28に記載の通りのパスにあるCOMMAND.COMにリダイレクトされますが、
仮想マシン上でCOMSPECの値が変更された場合は、そのパスを参照するようにしました。
2022/8/31
プロセス起動時のPSPについて、第1および第2のFCBの内容をセットするようにしました。
最初のプロセス起動時と、INT 2Eh, INT 2Fh AX=AE01hについて対応しています。
2022/8/15
BEEP音を連続して発声したとき、再生が止まらないように修正しました。
waveOut系APIでダブルバッファで再生するようにしています。
ウインドウプロシージャでなく、関数指定でコールバックを受け取れたんですね(苦笑)
NP21/WのI386コアについて、FPUタイプをSOFTFLOATからDOSBOX2に変更しました。
またDOSBOXのFPU_ST80()について、NaN/INFのケースを考慮して修正しました。
2022/7/21
BEEP音の再生をサポートしました。
システムポートのbit0,1がオンのとき、PITのCh.3のカウント値に応じた周波数で再生します。
再生中にカウント値を変更することも可能です。
PITのカウント値を下位・上位とも設定したときに、再生する周波数が更新されます。
waveOut系APIで実装していますが、生成したサウンドバッファをループ再生するのに、
コールバック関数を使わずにループ回数を指定しているため、BEEP音を再生し続けると、
2分間で再生が止まります。
コンソールでコールバック関数を使うのが面倒そうなので、手抜き実装です(苦笑)
2022/7/1
古いROMライタを動かす必要がありまして、シリアル通信周りの改良を行いました。
INT 14h AH=01hにおいて、DTRとRTSをオンにして、DSRとCTSがオンになるまで待って、
送信バッファに空きが出来るまで待機してから、送信データを書き込むように修正しました。
INT 14h AH=02hにおいて、DTRをオン、RTSをオフにして、DSRがオンになるまで待って、
受信バッファにデータが入るまで待機してから、受信データを読み込むように修正しました。
このとき、タイムアウト時間が経過したら、AHのbit7を立てて失敗するよう修正しました。
また、タイムアウト時間の初期値をBIOSのワークエリアに入れるようにしました。
DTR/DSRフロー制御およびRTS/CTSフロー制御をサポートしました。
それぞれ、-sd, -scオプションで有効になります。
フロー制御が有効のとき、シリアルポートのDTR/RTSの状態を実際に操作します。
また、DSR/CTSの状態を実際に読み取ってフロー制御を行います。
フロー制御が無効のとき、シリアルポートのDTR/RTSはオンにしたままとなります。
仮想マシンからは、DTR/RTSに設定した値(実際のシリアルポートには反映されません)が、
そのままDSR/CTSの値として読み取られます。
送信から受信に移行するため、DTR,RTSがオンの状態から、RTSだけオフにするとき、
送信バッファに未送信のデータが残っていたら、全部送信するまで待機するようにしました。
送信バッファのデータをWriteFile()で送信する際、実際に送信されたバイト数だけ、
送信バッファからデータを消すように修正しました。
2021/12/30
QEMUのtesti386.exeを参考に、NP21/WのI386コアを修正しました。
ia32_x86版のバイナリで、実機と同じ結果が得られるようになっています。
具体的な変更点は以下の通りです。
- DAA/DAS/AAA/AAS/AAM/AAD命令を、DOSBoxの実装を基に修正しました。
- SHLD/SHRD命令で、16bit以上シフトしたときの処理を修正しました。
- FCOM/FCOMI/FXAM命令で、NaNやINFのときのC1,C2,C3フラグの値を修正しました。
- FDECSTP/FINCSTP命令で、C1をクリアするよう修正しました。
- FLD系命令で、スタックオーバフローの有無でC1をセットまたクリアするよう修正しました。
- FSTENV/FLDENV/FSAVE/FLDENV命令で、data16プリフィックスを反映するよう修正しました。
なお、ia32_x64版だと、浮動小数点のテストで例外が発生してしまいます。
x86ビルドとx64ビルドで、何かしら処理が等価になっていないようですね、要調査。
2021/5/2
-a, -lオプションを追加しました。
-aでANSI.SYSを無効にできます。
ESCをシンボルとして表示したいときに指定してください。
-lで半角の罫線を半角の+,−,|で表示します。
2020/4/18の暫定対応を復活させる形です。
外字をSetPixelで対応しようかなーとか妄想中です。
2021/1/2
標準入出力のハンドルを正しく閉じられない問題を修正しました。
例えば、SYMDEBの>コマンドで出力をファイルに吐き出せない問題が解決しています。
ファイルのリダイレクトは、通常はファイルディスクリプタを複製することで実現しますが、
SYMDEBでは、標準出力をクローズして、直後にリダイレクト先のファイルをオープンすることで、
リダイレクト先のファイルがFD=1になることを期待していました。
Microsoft純正にしては、ちょっと実装が雑なんじゃないかなーと思わなくもないです(苦笑)
2020/12/25
INT10h, INT 21h AH=02h/06h/40h, INT 29hのそれぞれについて、制御文字をシンボルとして表示するか、
制御文字として扱うか、処理を分けるようにしました。
また、CtrlやAltを押しながら文字以外のキーを押したときのスキャンコードを修正しました。
2020/12/24
終了時にコードページを元に戻す処理が正しく動作していなかったのを修正しました。
また、コマンドプロンプトやPower Shellから起動したことを判定する処理を修正しました。
INT 16h, AH=51hをサポートしました。
AXのキーボードのシフト状態を取得するサービスで、Windows 3.1のインストーラから呼ばれていました。
2020/12/6
前回の修正で自動的にフォントを切り替える処理を入れましたが、これを修正しました。
GetCurrentConsoleFontEx()でフォント情報を取得するとき、FaceNameがUnicodeになっていました。
SetCurrentConsoleFontEx()でフォントを変更するとき、PowerShellではそのままでいいのですが、
コマンドプロンプトの場合は普通のワイド文字に変換しないと失敗するようです。
制御文字は^Zのように表示していたのですが、コードページが932でない場合はそのまま表示するようにしました。
英語モードのフォントでは、この領域にも文字パターンがあるみたいです。
Mr. Daniel Zingaroからご報告いただいていた、Usurperというソフトが動かない問題が解決しました。
このソフトのバグだと思いますが、開いているファイルをINT 21h, AH=41hで削除しようとしていました。
従来はエラーを返していたのですが、MS-DOSではファイルの削除に成功してしまうようです。
ただファイルハンドルを開いたままファイルだけ削除してしまうので、ファイルシステムの破壊の恐れがあるとか。
取り敢えず、ファイルの削除はしないけど、エラーは返さないように修正しておきました。
NP21/WのI386コアを、ver0.86 rev79 beta4に更新しました。
2020/5/10
Windows10のコマンドプロンプトで半角の罫線が正しく表示できない問題について、再修正しました。
ラスターフォントの場合は問題ないようですので、INT 10hを使用した際に自動的にフォントを変更するようにしました。
MS-DOS Playerが終了したときに、元のフォントに戻されます。
2020/4/18
Windows10のコマンドプロンプトで半角の罫線が正しく表示できない問題について、暫定的に対策しました。
本来はこのように表示される筈が(これはWindows7で表示したときの画面です)、
Windows10のコマンドプロンプトではこんな感じになってしまっていました。
どうもフォントの問題らしいです。
暫定的に、半角の+,−,|で代替して、それっぽく表示するようにしました。
Windows10で、コードページが932の場合のみ有効になります。
将来的に、状況が改善するようでしたら元に戻す予定です。
2020/4/16
XMSが有効な状態でも、BorlandのTLinkが動くようになりました。
INT 15h, AH=88hで100000H以降のメモリ容量を取得する際に、XMSが有効な場合は0を返すように修正しています。
DOSBoxの実装を見て気が付きました、多謝多謝です。
INT 15h, AH=89hの実装も、最新版のDOSBoxに合わせる形で修正しました。
こちらは効果は不明です。
2020/4/15
BorlandのTLinkが動くようになりました。
INT 2Fh, AX=FB42h/FB43h(Borland C++ DPMILOAD.EXEの存在チェック)に何も返さないように修正しています。
INT 2FHの未実装ファンクションは、何を返すのが正しいんでしょうか…
ちなみに-xオプションでXMSを有効にするとエラーになってしまいます。
EMBかHMA周りで何か問題が残っているっぽいです。
その他、Neko Project 21/WのCPUコアで、A20マスクがPC-98x1仕様のままになっていたのを修正したり、
内蔵デバッガのU, BPコマンド周りでCSのアドレス変換を修正したりしています。
2020/4/11
昨日の版で、Windows98のCOMMAND.COMが動かなくなっていたのを修正しました。
文字列入力など時間がかかるサービスの実行中に、タイマ割り込みが発生できるようにするため、
サービスは別スレッドで回して、その間に本スレッドでCPUにダミーループを実行させています。
このとき、別スレッドで回しているサービスの処理が、CPUのレジスタを破壊してしまわないように、
ダミーのレジスタを用意して、サービスが終了したらCPU側のレジスタに書き戻すようにしました。
この書き戻すタイミングが悪かったようです。
そこで、サービスが終了後、CPUが実行しているダミーループを抜けたことを確認してから、
サービスが変更したダミーレジスタの値をCPU側に書き戻すように修正しました。
2020/4/10
cracyc様のforkから、多数の修正を取り込ませていただきました。
随分と細かいところまでチェックしていただいて、多謝多謝です。
EMS周りの修正と、サービスの呼び出し方の変更の取り込みは保留します。
グラフィック周りは当面は取り込まない予定です。
2020/4/9
内蔵デバッガを改良しました。
UT, N, L, Wコマンドをサポートした他、プロテクトモード時のアドレス表示および指定を改良しています。
アーカイブ内の実行ファイルではデバッガは無効になっていますので、必要な方はビルドをお願いします。
2020/4/6
Neko Project 21/Wのi386コアを組み込んでみました。(多謝多謝です>NP2関係各位)
ia32_x86, ia32_x64の2つのバイナリです。
何か新たに動くようになっているかは分かりませんが、プロテクトモードの再現性は向上しているかと思います。
従来のMAMEベースのi386/i486のバイナリもも残しています。
V30コアに8080エミュレーション機能を組み込んでみました。
酔狂にもMS-DOS Player上であえてCP/M80エミュレータを動かしたい場合にお試しください。
2019/10/22
INT 21h, AH=2Chにおいて、1/100秒の値が正しくない問題を修正しました。
藤田望様から頂いたパッチを取り込んでいます、対応が遅くなってしまい申し訳ございません。
2018/12/18
i386コアを、MAME 0.204相当に更新しました。
特に何か動作が改善したということはないかと思いますが(苦笑)
INT 21h, AH=0Ahを実行したときに、CRを表示するよう修正しました。
Mr.Mark Ogdenから頂いたパッチを取り込んだものです。
対応が遅くなってしまい申し訳ございません。
2018/5/5
i386コアを、MAME 0.197相当に更新しました。
2017/10/26
INT 21h, AH=0Fh/14h/15h/16h/17h/21h/22h/23h/24h/27h/28hを修正しました。
FCBを使用したファイル操作関係のサービスです。
◆N2583ZYOB6様から頂いたパッチを取り込んでいます、多謝多謝です。
FCB関連のサービスを使っているソフトがなくて、テスト出来てなかったんですよね(苦笑)
2017/9/3
INT 15h, AX=E820h/E881hをサポートしました。
メモリマップやメモリ容量を取得するBIOSサービスです。
INT 15h, AH=89hを、最新のDOSBoxのソースを元に修正しました。
プロテクトモードに移行するサービスですが、VirtualBoxのNotes on BIOS usageによると、
AIX 1.3くらいしか使ってないようで(苦笑)
2017/8/28
INT 67h, AX=DE00h-DE0Chをサポートしました。
VCPI関係のサービスですが、取り敢えずMSTATでは認識したようです。
メモリ調査関係のソフトはともかく、VCPIを有効に使用するソフトがあるものかどうか(苦笑)
INT 21h, AH=56hを修正しました。
ファイルのリネームのサービスですが、リネーム後のファイル名が既に存在する場合、
エラーコードとしてAX=05h(Access Denied)を返すようにしました。
こちらの不具合は、金野様にご指摘いただきました。
2017/8/27
Windows 2000において、フォントサイズの変更を正しく動作するようにしました。
GetConsoleFontIfo()で取得した、コンソールでサポートされているフォントサイズ一覧のうち、
実際には変更できない(多分コードページ依存でダメっぽい?)ものが含まれているため、
SetConsoleFont()の実行後に、本当にそのフォントサイズに変更できたのか確認しています。
Windows 2000では、GetCurrentConsoleFont()がサポートされていないため、
GetClientRect()でコンソールのクライアント領域の大きさを取得して、行桁数で割ることで、
フォントサイズを取得するようにしました。
2017/8/26
Windows 10の拡張されたコマンドプロンプト上で動作するように修正しました。
マウスイベントを受け取るために、マウスによる編集などの新機能を自動的に無効にしたり、
ウィンドウサイズやフォントサイズの変更に失敗する問題の対策を入れています。
2017/8/25
INT 16h, AH=09h/0Ahをサポートしました。
キーボードBIOSの拡張機能のサポートの有無や、キーボードIDの取得をします。
また、INT 16h, AH=11hを修正しました。
キー入力を取得しますが、キーバッファからは削除されないようにしています。
CRTCのI/Oで、R10とR11の値を操作することで、カーソルのサイズや表示・非表示を
変更できるようにしました。
なお、コントロールパネルのキーボードのプロパティで、カーソルの点滅が
有効になっている場合、カーソルを非表示にしないようになっています。
カーソルを表示・非表示することで、自前でカーソルの点滅を行うソフトがありますが、
Windows側で行われるカーソルの点滅が重なって、殆どカーソルが表示されなくなる、
ということを避けるためです。
ソースを整理しました。
現在、文字セットはマルチバイト文字を指定してビルドをしていますが、
ユニコード、または指定なしにしても、正しくビルド、動作するようにしました。
関数や型宣言について、明示的にANSI版を指定するように修正しています。
(例えば、CreateFile()を、CreateFileA()にするなど)
_WIN32_WINNTに0x400(Windows NT 4.0)を指定して、ビルドが通るようにしました。
Windows 2000以降でサポートされた関数は、LoadLibrary()するようにしています。
VC++2003辺りでビルドすれば、Windows NT 4.0で動かせるかもしれません。
2017/8/24
一段落と言いつつ、もうちょっとだけSO1関係です(苦笑)
INT 15h, AH=C2hで設定する、PS/2マウスのハンドラの呼び出し方を修正しました。
SO1のMOUSE.BINで、マウスの移動やボタンのクリックを検出できるようになっています。
CRTCのI/Oを操作して、BIOSが管理しているカーソル位置とは別の位置に、
コンソール上のカーソルの表示位置を変更した際、INT 21hなどで文字を表示すると、
正しい位置に表示されない可能性がある問題を修正しました。
2017/8/23
CRTCのI/Oを一部実装しました。
R14とR15の値を変更した場合は、BIOSが管理しているカーソル位置とは別に、
コンソール上のカーソルの表示位置を変更するようになっています。
MS-DOS Playerでは、各割り込みの割り込み先として、256個のIRET命令が並んだ
テーブル上のアドレスを指しています。
CPUコアのIRET命令内で、プログラムカウンタがこのテーブル上のアドレスの場合、
MS-DOS Player上のシステムコールのルーチンを呼び出すようになっています。
しかし、SO1では、INT 21hの割り込み先がIRET命令の場合、MS-DOS環境上で
動作していないと判定するようになっており、DIRコマンドなどが正常に動作しない
問題がありました。
そこで、CPUの例外、ハードウェア割り込み、PC BIOS、MS-DOSの各サービスなどに
予約されている割り込み番号については、テーブル上のIRET命令にJMP FARする
ダミールーチンを、割り込み先として指すように修正しました。
また、INT 21h, AH=4Ehを修正しました。
これはファイルやディレクトリを検索するサービスで、SO1ではDIRコマンドの実装で
使用していますが、検索対象のアトリビュートマスクに3Fhを指定していました。
マスクのbit3は、ボリュームラベルを対象とするフラグで、これが指定されていると、
ディレクトリとボリュームラベルのみ検索されるようになっています。
そのため、DIRコマンドで、ディレクトリしか表示されない問題がありました。
この問題に対するHackとして、アトリビュートマスクに3Fhが指定された場合は、
自動的にbit3をクリアするように修正しました。
INT 10h, AX=1100h/1110hをサポートしました。
ユーザが指定したサイズのフォントをロードするサービスとなります。
またこれに伴い、コンソールのフォントサイズを変更する処理において、指定された
高さの±2、幅の±3の範囲で、自動的に近いサイズを選択するよう改良しています。
ところで、INT 10hの各種サービスの実装では、コンソール関係のWin32 APIを
多用していますが、Windows 10の拡張されたコマンドプロンプトで、これらのAPIが
うまく動作しない場合があるようです。
コマンドプロンプトのプロパティ画面において、「従来のコンソールを使う」という
チェックボックスをチェックすると、正しく動作するようになります。
Pedro Pablo Lopez Rodriguez様に、何度かテストにご協力いただきましたが、
MS-DOS Player上でSO1が正しく動作するようになった、との評価をいただきました。
PS/2マウス周りのBIOSの修正とか、まだまだ細かい残項目は残っていますが、
ここ1か月ほど行ってきたSO1の対応作業も、これで一段落ですね。
内蔵デバッガの細かい不具合を修正しました。
なお、リリースしているバイナリでは、内蔵デバッガは無効となっています。
2017/8/21
キーボード周りを更に修正しました。これで一段落かなと思います。
コンソールに対してキーイベントが一気にやってきた場合、最後に受け取った
キーコードのみがキーボードコントローラから読み取れるようになっていました。
これを、キーボードコントローラのデータレジスタが空でない場合は、
コンソールから読み込んだキーコードをFIFOバッファにキャッシュしておいて、
キーボードコントローラのデータレジスタが読み込まれて空になったら、
32msec周期で、FIFOバッファにキャッシュされたキーコードを、データレジスタに
セットしてやることで、全てのキーコードを読み込めるようにしました。
また、キーボードコントローラのデータレジスタを読み込んだときに、
ステータスのbit0だけでなく、データレジスタもクリアするようにしました。
BIOSのキーボードバッファを使用せずに、キーボードコントローラのみを
直接参照するようなソフトにおいて、
キーバッファが空でない場合に発生するダミーのIRQ1のハンドラ内で、
ステータスのbit0を参照して、データレジスタが空でないことを確認せず、
いきなりデータレジスタを読み込んでしまうような処理の場合、
一度のキー入力が何度も読み込まれてしまう不具合が修正されています。
INT 10h, AH=11hを修正しました。
フォントサイズが変更されたときに、BIOSデータエリア内の+85hにある、
フォントの高さの値を更新するようにしています。
2017/8/20
INT 10h, AX=1101h/1102h/1104h/1111h/1112h/1114hを修正しました。
動作がよく分らないため一時的に無効にしていましたが、
コンソールの行桁を変更するのにあわせて、フォントサイズも変更するようにしました。
ただし、8x8, 8x14, 8x16に一致するフォントサイズがサポートされていない場合は、
ラスターフォントが選択されている前提で、近いサイズに変更するようにしています。
SO1では、8x8フォントを読み込むようになっています。
英語モードだと、ラスターフォントでちょうどこのサイズがサポートされているのですが、
日本語モードだと、一番近いサイズが5x8なので、画面サイズがかなり小さくなりますね。
まあ、日本語モードで動かすようなソフトでもないのですが(苦笑)
また先の更新で、キーバッファが空でない場合に、IRQ1を発生するように修正した件について、
キーバッファに入らないキー入力の場合に、割り込みが発生しなくなっていたのを修正しました。
SO1で、ALT+Funtionキーを受け付けるようになっています。
今回の修正項目について、Pedro Pablo Lopez Rodriguez様から詳細なレポートを頂きました。
まことに多謝多謝です。
2017/8/12
キーバッファの処理を改良しました。
SO1において、キー入力が安定するようになりました。
従来は、MS-DOS Playerのコード上のFIFOバッファで管理していたのですが、
これを、BIOSデータエリア上のキーバッファで管理するようにしました。
キーバッファの内容を直接参照するソフトの動作が改善しているかと思います。
また、BIOSデータエリア上のキーバッファが空でない場合は、32msecおきに
IRQ1(キーボード割り込み)を発生するようにしました。
キーバッファにまだデータが残っているのに読みに来なくて、次にキーが押されて
割り込みが発生したときに、その前に押されてキーバッファに残っていたキーが
遅れて取り込まれて、今押されたキーは取り込まれないままバッファに残る、
みたいな状況が改善しています。
ただし、BIOSデータエリア上のキーバッファはたった16文字分しかありません。
これに収まりきらない分は、従来のFIFOバッファの方に入れておいて、
BIOSデータエリア上のキーバッファに空きができたら、従来のFIFOバッファから
順次移していくようにしています。
IME上で長い文章を入力して、一気に変換して確定すると、コンソールに対して
一気に入力が反映されるので、このような仕組みが必要になります。
2017/8/11
MS-DOS Playerでは、最初に起動したプログラムが終了すると、FFFF:0000に
リターンするようになっています。
ここにはHALT命令が置かれており、これが実行されるとMS-DOS Playerが終了します。
このため、CPUコア内のm_haltedフラグを、MS-DOS Playerの終了フラグとしても
流用していたのですが、実行中のプログラム内でHALT命令が実行された場合でも、
MS-DOS Playerが終了してしまいます。
この辺は、まだ純粋なMS-DOSの仮想環境として実装していて、PC/ATの周辺回路を
サポートしていなかった(周辺回路からの割り込みで、HALT状態から抜けることを
期待できなかった)頃からの仕様を引きずってしまっていました。
(CPUが1命令実行する毎に、m_haltedのチェックをするのを辞めることで、
処理速度の向上を期待した、というのもあった気がします)
そこで、MS-DOS Playerの終了フラグは別途用意して、CPUコア内のHALT命令で、
実行したPCがFFFF:0000だった場合に、この終了フラグを立てるようにしました。
これで、実行中のプログラム内でHALT命令を実行できるようになりました。
INT 10h, AH=0Ehを修正しました。
画面に1文字表示する機能ですが、AH=09h/0Ahと同様に、BHに出力先の画面番号が
入っているものと勘違いしていました。
現在選択されている画面への出力、ということでいいみたいですね。
INT 15h, AX=C200h-C209hをサポートしました。
PS/2マウス関係のサービスです。
INT 15h, AX=C207hで指定する、マウスの状態が変化したときに呼ばれるハンドラは、
INT 33hのMS MOUSEのハンドラより優先されるようになっています。
以上の修正で、マドリード工科大学(Polytechnic University of Madrid)の
Operating Systemの教授である、Pedro Pablo Lopez Rodriguez様が開発された、
教育用のOS、「SO1」がブートするようになりました。
デフォルトのログオンアカウントが分らないので、ちゃんと動作するかは未確認です。
MEU.COM対策で、キー入力をチェックをしながらスピンロックしている場合に、
Sleep(10)のかわりに、_mm_pause()を実行するよう修正した件について、
もう少し修正をおこないました。
_mm_pause()は、SSE2のPAUSE命令としてビルドされます。
SSE2をサポートしないCPUでは、この命令はREP NOPと解釈されますので、
不正なニーモニックを実行したとして例外が発生するということはありませんが、
この場合、ビジーループの解決にはなりません。
そこで、SSE2がサポートされている場合はPAUSE命令を実行、そうでない場合は、
Windows Server 2003 / Windows XP 64bit Edition以降の場合はSleep(0)を、
それ以前の場合は、Sleep(1)を実行するようにしました。
Windows Server 2003 / XP 64bit Edition以降では、Sleep(0)を実行した場合、
スレッドのプライオリティに関わらず、他の実行準備が出来ているスレッドに
スイッチしてくれるようです。
それ以前のWindowsでは、Sleep(0)を実行しても、自分と同じプライオリティの
実行準備ができているスレッドがいないと、そのまま処理が続行してしまうため、
ビジーループの解消にはならないということのようですね。
SSE2命令はPentium4からサポートなので、対応していないCPUで実行している方が
今更いらっしゃるとも思えないのですが(苦笑)、まあ念のためということで。
ついでに、MS-DOS Playerのプロセスのプライオリティを、通常よりは高い
(ABOVE_NORMAL_PRIORITY_CLASS)に設定するようにしてみました。
心なしか、処理が速くなっているような気がする、かもしれません。
2017/8/9
メモリユーティリティのMEU.COMの表示が遅い問題を修正しました。
キー入力の有無のチェックの処理を、短期間に繰り返し実行している場合には、
スピンロックをしていると見做して、キーチェック毎にSleep(10)してやることで、
キー入力をスムーズにする処理が入っています。
こちらのソフトでは、1文字表示する毎に、何故かINT 21h, AH=06h, DL=FFhで
キー入力のチェックをしており、上記の条件に当てはまっていたため、
1文字表示する毎にSleep(10)してしまっていました。
Sleep(10)の代わりに、_mm_pause()を実行するように修正しています。
2017/8/4
子プロセスとして32bit/64bitのプログラムを実行できるようになった件ですが、
子プロセスとして起動した32bit/64bitのプログラムが終了するまで、
MS-DOS Playerに処理が戻らないことを意識していただく必要があります。
特に子プロセスとパイプを繋ぐときはご注意ください。
例題として、TYPEコマンドとMOREをパイプで繋ぐケースを考えてみます。
以下、話を単純化するため、64bit Windows上の話とします。
COMMAND.COM, MORE.COMは16bit、CMD.EXT, MORE.EXEは64bitのプログラムとします。
使用するMS-DOS Player(MSDOS.EXE)も64bit版とします。
>MSDOS.EXE COMMAND.COM
>TYPE HOGE.TXT | MORE.COM
MS-DOS Player上で動いている、16bitのCOMMAND.COMと、16bitのMORE.COMを
パイプで繋いでいますが、これは問題なく動作します。
このパイプは、MS-DOS Playerの仮想DOS環境上で繋がれたパイプとなります。
>MSDOS.EXE COMMAND.COM
>TYPE HOGE.TXT | MORE.EXE
子プロセスとして起動した64bitのMORE.EXEが終了するまで、MS-DOS Playerに
処理が戻りませんので、TYPE HOGE.TXTの出力はMORE.EXEに繋がりません。
つまり、MS-DOS Playerの仮想DOS環境上では、32bit/64bitの子プロセスと
パイプを繋ぐことはできません。
>MSDOS.EXE COMMAND.COM
>CMD.EXE
>TYPE HOGE.TXT | MORE.COM
MS-DOS Playerから子プロセスとして起動された64bitのCMD.EXE上では、
16bitのMORE.COMは動作しません。
また、CMD.EXE上でEXITして終了するまで、MS-DOS Playerには処理は戻りません。
>MSDOS.EXE COMMAND.COM
>CMD.EXE
>TYPE HOGE.TXT | MORE.EXE
MS-DOS Playerから子プロセスとして起動された64bitのCMD.EXEと、64bitのMORE.EXEを
パイプで繋いでいますが、これは問題なく動作します。
MS-DOS Playerとは関係なく、普通にコマンドプロンプト(CMD.EXE)を起動して、
普通にTYPE HOGE.TXT | MORE.EXEを実行したときと同じ状況です。
このパイプは、64bit Windows上で繋がれたパイプだということにご注意ください。
>MSDOS.EXE COMMAND.COM
>CMD.EXE
>TYPE HOGE.TXT | MSDOS.EXE MORE.COM
MS-DOS Playerから子プロセスとして起動された64bitのCMD.EXEと、別に起動された
MS-DOS Playerとパイプを繋いでいますが、これは問題なく動作します。
このパイプは、64bit Windows上で繋がれたパイプだということにご注意ください。
またこのとき、MORE.COMは、最初に起動したCOMMAND.COMとは別のDOS仮想環境上で
動作していることにご注意ください。
>MSDOS.EXE COMMAND.COM /C TYPE.HOGE.TXT | MORE.EXE
64bitのMS-DOS Playerと、64bitのMORE.EXEをパイプで繋いでいますが、
これは問題なく動作します。
このパイプは、64bit Windows上で繋がれたパイプだということにご注意ください。
またこのとき、MORE.EXEは、MS-DOS Player上の子プロセスとしてではなく、
MS-DOS Playerとは別のプロセスとして起動していることにご注意ください。
>MSDOS.EXE COMMAND.COM /C TYPE.HOGE.TXT | MORE.COM
MORE.COMは、MS-DOS Player上の子プロセスとしてではなく、MS-DOS Playerとは
別のプロセスとして起動することになりますが、勿論、64bit Windows上では
16bitのMORE.COMは動作しません。
>MSDOS.EXE COMMAND.COM /C TYPE.HOGE.TXT | MSDOS.EXE MORE.COM
MS-DOS Playerと、別に起動されたMS-DOS Playerとパイプを繋いでいますが、
これは問題なく動作します。
このパイプは、64bit Windows上で繋がれたパイプだということにご注意ください。
また、COMMAND.COMとMORE.COMは、別のDOS仮想環境上で動作していることに
ご注意ください。
>MSDOS.EXE -cMORE32.EXE MORE.COM
>MSDOS.EXE COMMAND.COM /C TYPE.HOGE.TXT | MORE32.EXE
>MSDOS.EXE COMMAND.COM
>CMD.EXE
>TYPE HOGE.TXT | MORE32.EXE
16bitのMORE.COMを、MS-DOS Playerに埋め込んで、64bitのプログラムに変換すれば、
64bitのプログラムとパイプを繋ぐことが可能です。
2017/7/27
通常のMS-DOS環境上で、Win32/64のプログラムを実行すると、
This program cannot be run in DOS mode.
と表示されて、そのままプログラムが終了するようになっています。
これは、Win32の実行ファイルのヘッダ内に、このようなメッセージを表示して
そのまま終了するようなMS-DOS用スタブプログラムが埋め込まれて、
MS-DOS環境ではそちらが実行されるようになっているからです。
MS-DOS Player上でWin32のプログラムを実行した場合も同様の動作でしたが、
INT 21h, AX=4B00h, INT 2Eh, またはINT 2Fh, AX=AE01hなどのサービスで、
Win32のプログラムを子プロセスとして起動しようとした場合は、
system() Win32 APIを使って、Win32の子プロセスとして実行するようにしました。
このとき、子プロセスが終了するまで、MS-DOS Playerは待機します。
ただし、INT 21h, AX=4B01h/4B03hなど、プログラムファイルをロードするだけで、
実際には実行しない場合は、プログラムファイルがそのままロードされます。
その後に、メモリ上にロードしたプログラムに処理が移った場合は、従来通り、
This program cannot be run in DOS mode.が表示されて終わりです。
なお、指定されたコマンドラインをそのまま丸ごと、system()に投げています。
16bitのプログラムとパイプで繋ぐようなケースは考慮していません。
また、子プロセスがコンソールに文字を表示する際、MS-DOS Player側のINT 29hは
経由されませんのでご注意ください。
こちらの処理は、あくまで子プロセスの起動時のみとなります。
「msdos (プログラム名)」で起動時に指定したプログラムがWin32の場合は、
This program cannot be run in DOS mode.が表示されますが、
この場合は素直に対象のプログラムを直接起動してください、ということで(を
MS-DOS PlayerでCOMMAND.COMを実行して、その上でWin32のコンソールアプリを
シームレスに使用できるようになっているかと思います。
Windows上でVZエディタを使用する際、CLPPST.EXEというWin32のプログラムを使って、
Windows側のクリップボードと連携しているそうです。
今回の修正で、この仕組みが動くようになっているといいのですが…。
素直にINT 21h, AX=4B00h辺りを使っててくれれば大丈夫だと思うんですけどね。
# DOS時代はSEDIT派でしたので、VZエディタの使い方をよく知らなかったり(苦笑)
# 検証ご協力お願いいたします>今野様
2017/7/24
キーの押し離し、キーの読み込みがあった際に、BIOSデータエリア内にある、
キーバッファの内容や、キーバッファの書き込み・読み込み位置の情報を、
然るべく更新するように修正しました。
キーバッファの内容を直接参照するソフトが動作するようになったかと思われます。
こちらの不具合は、Pedro Pablo Lopez Rodriguez様にご指摘いただきました。
スペインのマドリード工科大学(Polytechnic University of Madrid)で、
Operating Systemの教授をされているそうです。
もし拙作が、教育や研究のお役に立てているようでしたら光栄ですね。
Shift+F8〜F10、Ctrl+F1を入力できない不具合を修正しました。
WindowsキーおよびMenuキーを無視するために、スキャンコードが5Bh〜5Ehの場合は
キーバッファに入れないようにしていたのですが、
ShiftまたはCtrlキーとファンクションキーを同時に押したときのスキャンコードで、
5Bh〜5Ehになるものがあり、これらも無視されてしまっていたようです。
また、-nオプションが機能していなかった不具合を修正しました。
これらの不具合は、前回に引き続き、金野様にご指摘いただきました。
INT 29hの処理中、TSCが正しく更新されない不具合を修正しました。
RDTSC命令はPentium以降ですので、リリースしているバイナリでは無関係です。
また、INT 29h、またはINT 21h/2Fhでキー入力待ちなど時間が掛かるサービスの実行中に、
タイマ割り込みによって更にINT 21h/2Fhで時間が掛かるサービスを呼び出した場合は、
サービスの処理待ちの為に更に別スレッドを立ち上げないようにしました。
普通はそのようなことはないかと思いますが、念のための安全対策です。
2017/7/14
INT 21h, AX=440Ch, CL=5Fhをサポートしました。
INT 2Fh, AX=1A01h, CL=5Fhをサポートしました。
いずれもディスプレイの情報を設定するサービスですが、画面サイズのみ設定可能です。
MODE CON COLS=40 LINES=25とか出来るようになっているかと思います。
INT 21h/2Fhのサービスによって、コンソールに文字を表示する際に、
INT 29hの処理がフックされている場合は、INT 29hを経由するように修正しました。
制限として、INT 29hの処理がフックされている場合、STDINからの入力を待って、
更に入力に対してエコーを返すサービス(INT 21h, AH=01h/0Ah/3Fh)を実行中は、
仮想マシンのCPUの動作が停止して、タイマ割り込みが発生しなくなります。
これらのサービスの入力待ちの処理は、仮想マシンのCPU上でループするのではなく、
MS-DOS Playerのサービスの処理上でループすることで待機しています。
この待機中も、タイマ割り込みが発生できるように、CPUを回し続けるために、
別スレッドでサービスの処理を実行して、そちらで入力待ちをしてやって、
メインスレッドでは、CPUでダミールーチンを実行し続けるようになっています。
(この辺りについては、2017/2/22の記事をご参照ください。)
この別スレッドで実行しているサービスの処理内で、コンソールにエコーを返す際に、
INT 29hを実行するために、メインスレッドで回っているCPUに茶々を入れることが
構造的にとても難しかったため、INT 29hの処理がフックされている場合は、
サービスの処理をそのままメインスレッドで実行するようにしました。
このとき、メインスレッドで入力待ちをしている間、CPUの動作が停止してしまうため、
タイマ割り込みは発生できなくなります。
また、INT 29hの処理内で、再度コンソールに文字を表示するINT 21h/2Fhのサービスが
呼び出された場合、無限ループに入らないように、INT 29hは再発生しません。
今回の実装で、CPUコアからDOSのシステムコールのエミュレーションが呼ばれて、
その中で、INT 29hを実行してIRETするまでCPUコアを回してやって、
その中で、またDOSのシステムコールのエミュレーションが呼ばれて、といった感じで、
再入することを想定していなかった色々な処理を再入しまくってます。
何かしら処理に矛盾を来たしていないか、安定性に問題ないか、色々と苛めテストに
ご協力いただけますと幸いです。
本件は、VZエディタの私家版を開発されている、金野様よりご指摘いただきました。
VZエディタからDOSコマンドを実行する際に、INT 29hをフックすることで、
DOSコマンドの実行結果を取り込む、みたいなことをしているそうです。
Windows NTやOS/2上のコマンドプロンプトでも、コンソールに文字を表示する際に、
INT 29hを経由しないそうですが、意外と互換性が微妙なんですかね?
(この問題を補うために、toint29というソフトが公開されています)
2017/7/12
INT 2Fh, AX=1205hを修正しました。
DOS 3.0以降の内部サービスで、スタック上のWORDの文字コードを表示しますが、
下位BYTEしか表示できていませんでした。
INT 2Fh, AX=1217h/121Fhをサポートしました。
こちらもDOS 3.0以降の内部サービスで、CDSを取得したり作成したりします。
INT 2Fh, AX=1222hをサポートしました。
こちらもDOS 3.0以降の内部サービスで、拡張エラーコードを設定します。
普通はINT 21h, AX=5D0Ahを使用するかと思います。
INT 2Fh, AX=1A01h, CL=7Fhをサポートしました。
ANSI.SYSの内部サービスで、ディスプレイの情報を取得します。
やっぱり普通はINT 21h, AX=440Ch, CL=7Fhを使用するかと思います。
INT 33h, AX=000Ah/0025h/0027h/0028h/0029h/004Dh/006Dhをサポートしました。
マウスカーソルの形状や移動量、画面モード、ドライバの情報を取得、設定します。
AX=0028h/0029hの、画面モードの設定および列挙が、何故マウスBIOSにあるのか、
いまいちそうなった経緯が分かりません(苦笑)
INT 67h, AH=55h/56hをサポートしました。
INT 67h, AX=5900h/5B00h/5B01h/5B02hをサポートしました。
LIM EMS 4.0のサービスで、PDMI.COM/PDMS.COMで使用されていました。
と言っても、EMSの情報を取得・表示するために使っているだけです。
実用的な意味でちゃんと使用しているソフトは、今のところ確認できていません。
INT 67h, AX=7000h/7001hをサポートしました。
こちらもEMSのサービスで、やっぱりPDMI.COM/PDMS.COMで使用されていました。
EMSのページフレームとVRAMを切り替えるサービスですが、
常にEMSのページフレームとして使用すると返すようにしています。
手持ちの資料だと、1989年出版の「MS-DOS プログラマーズ・バイブル」でしか
言及されていないのですが、その後廃止されてしまったのでしょうか。
2017/7/7
INT 21h, AH=33h/37h/6dh/6Eh/6Fh/70h/71h/72hを修正しました。
ファンクションまたはサブファンクションがサポートされていなかった場合に返る、
エラーコードおよびCFの状態を修正しています。
INT 21h, AH=43hおよびAX=7143Hを修正しました。
処理を共通化していますが、それぞれサポートしていないサブファンクションに対して
エラーを返すように修正しました。
INT 21h, AH=43hにおいて、DR-DOSが使用していたサブファンクション番号が、
INT 21h, AX=7143hにおいては、Windows95が別の用途に使用しているようですね。
INT 21h, AX=4410h/4411hを修正しました。
指定されたファンクションがサポートされていると返す条件を修正しています。
2017/7/4
INT 21h, AH=59hを修正しました。
BXの値が0000hであることをチェックするようにしました。
INT 21h, AX=5D0Ahを実行していない場合は、AX, BH, BL, CHの値のみ更新するようにしました。
GW-BASIC 3.23で、FILESでクラッシュしたり、SAVE/LOADに失敗する問題が修正されています。
どうも、CL, DX, SI, DI, DS, ESの値が変わらないことを期待しているようです。
なお、PC DOS 7 Technical Updateでは、これらのレジスタの値は破壊されるとされていました。
sava様の翻訳された、DR-DOS System and Programmer's Guideでも同様です。
…まあ、破壊しなくてはいけない訳でもないですし、ね(苦笑)
2017/7/1
COMモデルのプログラムで、CALL 5でファンクションコールする仕組みをサポートしました。
CLの値をファンクション番号として、INT 21hと同じファンクションコールしているだけです。
補足ですが、これはCP/M 80風のシステムコールの方法になります。
COMモデルのプログラムの場合、CS:0000hにPSPが、CS:0100hにプログラムがロードされます。
PSPの5バイト目、つまりCS:0005hには、MSDOS.SYS内のルーチンへのFAR CALLの命令が存在しまして、
このアドレスをNEAR CALL、つまりCALL 5すると、CLで指定されたファンクションがコールされます。
ファンクションの内容も、ファンクション番号00h〜24hは、ほぼCP/M 80との互換性がありました。
実際、CP/M 80用のアセンブラのソースで、8080のニーモニックを8086に機械的に置き換えるだけで、
大体はMS-DOS上で動作できるようになったそうです。
# ここで言っているCOMモデルというのは、WindowsのCOMのことではなくて、
# MS-DOSの実行プログラムのメモリモデルのEXEモデル、COMモデルの方です、念のため。
2017/6/16
INT 10h, AX=1312h/1313hをサポートしました。
INT 10h, AX=1320h/1321hと同じです。
sava様のDOS/V INT 10h 私的 REFERENCEではAX=1320h/1321hとなっていますが、
Ralf Brown氏のInterrupt ListではAX=1312h/1313hとなっていたため、
一応どちらでも呼べるようにしておきました。
INT 21h, AH=17hを修正しました。
FCBを使用したリネームですが、実装ミスで正しく動作していませんでした。
今まで誰からも指摘がなかった辺り、FCBを使ったファイル操作系のサービスは
殆ど使用されていないみたいですね。
INT 21h, AX=4302hを修正しました。
圧縮ボリューム上のファイルの実サイズを取得するサービスですが、
GetFileSize()の使い方が間違っていました。
直前で使っているGetCompressedFileSize()に引きずられたみたいです。
(GetFileSizeはハンドル渡し、GetCompressedFileSizeはパス渡し)
INT 21h, AX=4402hをサポートしました。
キャラクターデバイスの情報を取得するサービスです。
ただし、現状で情報が正しく取得できるデバイスは、EMMXXXX0のみです。
CONFIG$の場合は、00h 00h 00h 00h 00hが返ります。
それ以外のデバイスの場合は、Access Deniedが返るようになっています。
なお、EMMXXXX0については、DOSBoxの実装を参考にさせていただきました。
$IBMADSPについても実装したいのですが、まったく情報がありません(苦笑)
INT 21h, AX=440Ahをサポートしました。
開いているファイルが、ネットワークドライブ上かどうかを判定します。
従来は、常にローカルドライブであると返すようになっていました。
INT 21h, AX=5D00hをサポートしました。
ネットワーク上のコンピュータでINT 21hサービスを実行するものですが、
対象のコンピュータとして、現在のシステムが指定されている場合のみ、
そのまま指定されたINT 21hサービスを実行するようになっています。
それ以外は、ネットワーク機能がインストールされていないエラーを返します。
INT 21h, AX=6523hを修正しました。
指定の文字コードがYかNかを判定するサービスです。
マルチバイト文字が指定された場合に、YyとNnを逆に判定していました。
INT 21h, AX=71A9hをサポートしました。
ネットワークドライブ上のファイルをオープンするサービスですが、
そのままローカルドライブ用のAX=716Chで処理するようにしました。
XMS call AH=06h/08h/0Ah/0Chを修正しました。
DOSBoxの実装に準じた処理に変更しています。
COMMAND.COMがないときに、COMMAND /Cを実行したときの処理において、
リダイレクト先にファイル以外のデバイスを指定できるようにしました。
INT 21h, AH=3DhなどでCONを開く際に、読み書きモードが指定されている場合、
自動的に読み込みモードで開くようにしました。
WindowsのCONデバイスは、読み込みモードでしか開けないようですが、
MODE.COMが読み書きモードで開こうとして失敗していた問題の対処のためです。
書き込みモードで開こうとした場合は、そのまま失敗するようになっています。
また、COM/LPT/EMMXXXX0のデバイスインフォメーションの値を変更しました。
ファイル/デバイスのオープン関係、パスなどの文字列処理関係を中心に、
一部ソースコードの整理をしました。
エンバグして、今まで動いていたコードが動かなくなっているかもしれません。
何かお気づきの点がありましたらお知らせください。
2017/6/9
CDS(Current Directory Structure)を修正しました。
26ドライブ分のCDSの領域を確保するようにしました。
Drive Attributeについて、リモートドライブか、SUBSTされたドライブか、
普通の物理ドライブかに応じた値を入れるようにしました。
また、そのドライブのDPBへのポインタを設定するようにしました。
INT 21h, AH=3Bhを修正しました。
カレントディレクトリ変更時に、該ドライブのCDSを更新するようにしました。
INT 21h, AX=4409hを修正しました。
指定されたドライブがネットワークドライブでない場合に、SUBSTされたドライブか
判定をするようにしました。
INT 21h, AX=440Ch, CL=4Ch/4Dh/6Bhをサポートしました。
437(US English)と、システムコードページと、アクティブなコードページを、
重複しないで列挙するようにしています。
MODE.COMで、サポートしているコードページ一覧を取得するのに使用していました。
INT 21h, AX=5F07h/5F08hをサポートしました。
指定されたドライブを有効・無効にするものですが、指定されたドライブのCDS中の、
Drive Attributeの値を弄っているだけのようです。
FORMAT.COMが使用していました。
INT 21h, AX=71AAhを修正しました。
SUBSTを設定または解除する前に、指定されたドライブが存在しているかどうかを
確認するようにしました。
INT 2Fh, AX=4308hをサポートしました。
HIMEM.SYSのサービスで、/MACHINEで指定された値を取得します。
現状では、/MACHINE:ATが指定されており、A20マスクの切り替えは高速であるとの
値を返すようにしています。
2017/6/7
INT 15h, AH=84hをサポートしました。
ジョイスティックの読み込みですが、GW-BASICが使用しているため一応実装しました。
現状の実装では、実際にジョイスティックの状態を読みに行くのではなく、
常にジョイスティックが繋がっていない状態を返すようになっています。
なお、DOSBoxの実装を参考にさせて頂きました、ありがとうございます。
INT 21H, AH=53hをサポートしました。
BIOSパラメータブロックをディスクパラメータブロックに変換するサービスです。
FreeDOSに同梱されているRDISKで使用されていました。
INT 21H, AX=43FFh, BP=5503h, CL=39h/56hをサポートしました。
Windows98(DOS 7.2)のサービスで、長いパスのディレクトリ作成、リネームをします。
INT 21H, AX=5D0Ahをサポートしました。
次に実行されるINT 21H, AH=59hで取得される、拡張エラーコードを設定します。
INT 21H, AX=6500h/7002hをサポートしました。
Windows95のサービスで、日付フォーマットや通貨記号など、国別情報を設定します。
いずれのサービスも、実際に使用しているソフトは未確認です。
INT 2FH, AX=150Bh/150Dhをサポートしました。
MSCDEX絡みのサービスで、ドライブがCD-ROMかどうかの判定をします。
MSCDEXのインストールチェックでは、インストールされていないと返していますが、
DOSSHELLが、MSCDEXのインストールチェック無しでAX=150Bhを使用していました。
AX=150Dhも同じようなサービスなので、ついでに実装しています。
INT 33H, AX=0018h/0019hをサポートしました。
マウスBIOSで、AX=000Chとは別のイベントハンドラを登録するサービスです。
やっぱり、実際に使用しているソフトは未確認です。
2017/5/31
INT 13h, AH=00h/01h/02h/03h/04h/08h/0Ah/0Bh/0Dh/10h/15hをサポートしました。
DISK BIOSで、ドライブの情報取得や、セクタの読み書きなどのサービスです。
但し、セクタの書き込みについては、安全のためフロッピードライブのみとなります。
INT 21h, AX=5E00h/5F05hをサポートしました。
MS-Networkで、コンピュータ名やネットワークドライブの割り当て情報を取得します。
INT 67h, AX=5901hをサポートしました。
LIM EMS 4.0で、EMSの総ページ数や空きページ数を取得するサービスです。
なお、AX=5900hについては、常にOSによるアクセス拒否を返すようにしています。
INT 21h, AH=38hおよびINT 2Fh, AX=1404hを改良しました。
指定された国コードの国情報を取得できるようになっています。
INT 2Fhの諸サービスで、ソフトウェアのインストールチェックを追加しました。
未定義サービスの確認用で、具体的な動作には影響ありません。
i86/i286コアに、MAME 0.150〜0.185の変更を反映しました。
i86の未定義命令関係や、i286のLAR/LSLのゲートチェックなどが修正されています。
2017/5/28
i386コアの修正漏れがありました。
これで最新のMAME 0.185相当になっているかと思います。
2017/5/26
Drive Parameter Block関係の処理を修正しました。
従来は、INT 21h, AH=1Bhなどで、Drive Parameterを参照するときに、
はじめてDrive Parameter Blockを初期化していましたが、
INT 21h, AH=52hでDOS Info Tableを取得して、そこから辿っていって
Drive Parameter Blockを直接参照するような場合を考慮して、
全26ドライブ分のDrive Parameter Blockについて、ドライブ番号や、
次のDrive Parameterへのリンクなど、一部のデータについては、
起動時に初期化しておくようにしました。
また、Drive Parameter Blockに割り当てたデータサイズが不足していて、
その後ろに割り当てていたSystem File Tableと破壊し合う可能性がある
不具合を修正しました。
INT 67h, AH=4Fhを修正しました。
AL=00hで保存したEMSのマップ状態を、AL=01hで復元する際に、
マップされていない状態を復元できない不具合を修正しています。
これらの修正の結果、PDMS/PDMIが動作するようになりました。
従来は、未初期化のDrive Parameter Blockを走査した結果、
内部テーブルが溢れた旨のエラーが発生していました。
キーバッファの処理を改良しました。
BIOSデータエリア上のキーバッファに、これから読み込まれるキーコード、
および最後に読み込まれたキーコードを格納するようにしました。
直接キーバッファの中の値を参照するような、行儀の悪いソフトがありましたら、
これで動作が改善するかもしれません。
i386コアを、MAME 0.184相当にアップデートしました。
2017/5/24
前回、不正な命令を無視する処理を弄った際に、i386の一部命令がおかしくなっていたのを修正しました。
また、キーボードコントローラでCPUをリセットしたり、i286/i386でトリプルフォールトが発生したときに、
BIOSデータエリアの0040:0067に指定されたアドレスにジャンプするように修正しました。
INT 10h, AH=0Ch/0Dhをサポートしました。
グラフィック画面のピクセルを読み書きするサービスです。
コンソールアプリでこれらを使用するものがあるとは思えないのですが、まあ何となく(苦笑)
コンソールウィンドウのデバイスコンテキストを取得して、SetPixel/GetPixelしているだけです。
2017/3/1
昨日の、子プロセスとしてCOMMAND.COMを起動するときのパイプの処理について、
"<", ">"だけでなく、"0<", "1>", "2>"もチェックするように修正しました。
CPUが不正な命令を実行してINT 06hが発生した場合、通常は実行中のプロセスを停止しますが、
-iオプションが指定されていると、不正な命令を無視して実行を続けます。
このとき、INT 06hから復帰するアドレスは、先に実行した不正な命令の先頭となるため、
不正な命令をもう1度実行してしまわないように、アドレスを+1するようになっています。
例えば、i386がリアルモードで動いているときに、プロテクトモード用の命令を実行したときも、
不正な命令と見做されます。
このような場合も想定して、単純にアドレスを+1するのではなく、不正な命令なりの命令長を取得して、
その分だけ加算したアドレスに復帰するように修正しました。
2017/2/28
INT 21h, AH=4Bhで子プロセスを実行する際に、COMMAND.COM /C (program)のように、
COMMAND.COM経由で実行する場合は、COMMAND.COM /Cを除いて、直接対象のプログラムを
実行するようになっています。
これは、COMMAND.COMが存在しない場合を想定した仕様ですが、パイプが指定されていた場合
(COMMAND.COM /C (program) > (filename)など)に、パイプの部分まで、対象のプログラムの
引数として渡されてしまう問題がありました。
これを、COMMAND.COMが存在する場合は、そのまま素直にCOMMAND.COM経由で実行する、
そうでない場合は、パイプの処理をMS-DOS Player側のコードで処理するよう修正しました。
LIST.COMで、FV.COMを使ってアーカイブの内容を表示するコマンドが動作するようになっています。
なお、FVを起動するときに、パイプを使ってテンポラリファイルに結果を出力するのですが、
TEMPのパスが長い場合、正しくテンポラリファイルのパスが生成できないようです。
MSDOS_TEMPを指定するなどして、TEMP/TMPが短いパスになるようにしてください。
プリンタポートにおいて、新しいファイルを出力する際に、漢字オンの状態になっている場合、
古いファイルに漢字オフを出力してから閉じるように修正しました。
また、漢字オンの際に制御コードを透過する処理において、チェック対象の制御コードを、
「AXテクニカルリファレンスマニュアル 1989」に記載されているものに限定しました。
各社のプリンタのマニュアルを見ていたのですが、どうにも拡張部分がきりがなさそうで(苦笑)
TYPE (filename) > "COM1:9600,N,8,1"のように、シリアルポートをファイルとして開いた場合、
READ/WRITEの際にバッファの状態をチェックするように修正しました。
バッファが空または満杯で、送受信ができない場合、最大1秒まで待機するようになっています。
2017/2/26
プリンタポートをサポートしました。
プリンタI/O直叩き、プリンタBIOS経由、TYPE file > PRNのようにファイルとして開いた場合の
いずれにも対応しています。
出力されたデータは、TEMP以下に"年-月-日_時-分-秒.PRN"というファイル名で保存されます。
プリンタBIOSは、INT 17h, AH=00h/01h/02h以外に、AH=03h/50h/51h/52h/84h/85hもサポートしました。
これらはAX仕様の拡張プリンタBIOSで、主にシフトJISを自動的にJISに変換するようになっています。
本来のAXの仕様では、ANK文字についてもJISコードに変換して、半角モードで出力するのですが、
これは流石にオミットして、1バイト文字のまま出力するようにしています。
あわせて、シリアルポートについても、ファイルとして開く機能をサポートしました。
"COM1:9600,N,8,1"のような書式で開いた場合は、パラメータも反映されるようになっています。
2017/2/23
キー入力を検出した際、BIOSデータエリア中のカーソル位置を更新するようにしました。
従来は、基本的には文字を表示した際に更新するようにしていましたが、
カーソルが画面の一番下にあるときに、IMEがオンになって、画面の一番下にIMEの情報
(IMEの変換モードとか変換候補とか)を表示するために、画面が上にスクロールして、
カーソル位置が1行上に移動する、というケースが考慮されていませんでした。
sava様からご指摘いただきました、多謝多謝。
ただ、FreeCOMのコマンド入力の処理では、最初にカーソル位置を記録しておいて、
エスケープキーが押された場合は記録した位置にカーソルを移動するみたいでして。
文字の入力によって画面がスクロールすることは考慮されているみたいなんですが、
IMEがオンになって画面がスクロールした場合はうまくいかないみたいです。
これはまあ仕方ないかなあと思います。
INT 21h, AX=0Ah/3Fhの行入力の処理において、バックスペースキーを押した際に、
漢字などマルチバイト文字をチェックするように修正しました。
Windows 98 Second EditionのCOMMAND.COMのコマンド入力では正しく動作しましたが、
FreeCOMでは、INT 21h, AX=07hの1文字入力を使っているので、やっぱり駄目です。
2017/2/22
INT 21h, AH=00h/07h/08h/0Ah/3Fhなどでは、文字または文字列の入力があるまで
DOSサービス内で待機します。
従来の実装では、MS-DOS PlayerのDOSサービスのコード上で、文字または文字列の
入力があるまで待機しており、その間はCPUは停止していました。
そのため、入力待機中はタイマ割り込みを発生させることが出来ませんでした。
これを改良して、これらのサービスの処理を別スレッドで動かすようにして、
スレッドが終了するまでは、CPUでダミーループを回転させてやることで、
文字または文字列の入力の待機中も、タイマー割り込みを発生させることが
できるようになりました。
例えば、Clock386というTSRを常駐してやって、COMMAND.COMのコマンド待ち受け中も
(これはINT 21h, AH=0Ahを使用しています)、右上の時計の表示が更新される
ようになりました。
コンソール系の処理の彼方此方にCritical Sectionを仕込みましたので、
動作に問題はないと思いますが、何か問題がございましたらお知らせください。
DR-DOSのCOMMAND.COMが起動するようになりました。
一番元のPSP(最初のプロセス起動時に親として指定するPSP)のParent PSPとして、
そのPSP自身のセグメントを指定するように修正しています。
起動だけはするのですが、色々なDR-DOS専用のサービスは実装されていませんので、
ちゃんと動作するかは未検証です。
こちらの修正で、18:00にアーカイブを更新しています。
ダウンロード済みの方は、必要に応じて再ダウンロードをお願いいたします。
2017/2/21
INT 21h, AX=0Ah/3Fhにおいて、エスケープキーを押したときに、それまでに
入力した内容を消去して、最初のカーソル位置に戻るように修正しました。
また、複数行にまたがってバックスペースキーが機能するように修正しました。
マウスBIOSにおいて、カーソルの位置を8の倍数で返すようにしました。
これは、テキストモードでの動作を想定しています。
また、カーソルが非表示のときも、ボタンの状態は更新するようにしました。
INT 33h, AX=0004h/001Fh/0020hをサポートしました。
このうち、AX=001Fh/0020hについては、DOSBoxの実装を参照しています。
2017/2/18
INT 21h, AH=02h/06h/09hにおいて、最後に出力したキャラクターの値を
ALにセットするよう修正しました。
藤田望様から頂いたパッチを取り込んでいます、多謝多謝。
-eが指定されている場合に、ホスト側から最低限読み込まれる環境変数について、
INCLUDEとLIBを抜いて、LASTDRIVEを追加しました。
ホスト側の環境変数にMSDOS_LASTDRIVEやMSDOS_TZが定義されていた場合に、
仮想環境側のLASTDRIVEやTZの値に反映されるようにしました。
ホスト側と異なる値(特にTZ)を指定する必要がある場合にお使いください。
ホスト側で、MSDOS_LASTDRIVEもLASTDRIVEも定義されていない場合は、
仮想環境側にLASTDRIVE=Zが自動的に追加されます。
また、ホスト側で、MSDOS_TZもTZも定義されていない場合、ロケール情報を基に、
仮想環境側にTZの値を自動的に設定するようにしました。
一部のロケールでは、標準時間、夏/冬時間のコードが地域相応のものとなります。
未対応のロケールでは、GMT???またはGMT???GSTとなります。
なお、標準時間、夏/冬時間のコードは、古式ゆかしい3文字のものにしています。
例えばシドニーでは、今風のAEST-10AEDTではなく、EAS-10EADとなります。
元ネタは、検索していて見つけた、NASAのサイトにあるWinVNのマニュアルです。
具体的な対応ロケールは、アーカイブ中のreadme.txtをご参照いただくとして、
カナダ、アメリカ、メキシコ、ブラジル、ヨーロッパ、日本、中国、韓国、台湾、香港、
シンガポール、インド、オーストラリア、ニュージーランドなど、
需要のありそうな地域については、概ねカバーできているかと思います。
この辺は、敢えて設定していない場合もあるでしょうし、余計なお世話かなとは
思いましたが、試験的に実装してみました。
何か問題がございましたら、ご意見をいただけますと幸いです。
Ctrl-BreakおよびCtrl-Cの処理を改良しました。
GW-BASICで、AUTOコマンドをCtrl-Cで抜けたり、プログラムの実行をCtrl-Breakで
停止できるようになっています。
I/Oから読まれるキーボードの値やキーバッファに入れる値を修正したり、
Ctrl-Breakが押された場合に、INT 9hからINT 1Bhを呼ぶようにしたり、
INT 21hのキー入力中にCtrl-Break/Cが押された場合に03 CR LFを表示したり、
何故か未実装だった、INT 21h, AX=3302hをサポートしたりています。
コンベンショナルメモリとUMBの結合、分離の処理を整理しました。
コンベンショナルメモリのおケツに、UMBと結合するためにVRAMをスキップする
ダミーのメモリコントロールブロックを置いているのですが、
MZの値をMに、パラグラフ数をVRAMのサイズ分だけ指定することでUMBと結合、
MZの値をZに、パラグラフ数を0にすることでUMBと分離するようにしました。
なお、従来は、ダミーのメモリコントロールブロックのMZは常にMを指定して、
その1つ前のメモリコントロールブロックのMZの値を変更していました。
また、システムが確保したメモリブロックのコントロールブロックのPSPの値に、
従来は根拠レスに-1を指定していたのを、8に変更しました。
この結果、ようやくFreeDOSのMEM.EXEがちゃんと動くようになりました。
自分用に、内蔵デバッガーを実装してみました。
素直にDEBUGとかSYMDEBとか使えばいいのですが、どうしても画面が崩れてしまって
不便な場合もありますので。
リリースしているバイナリでは無効になっていますので、msdos.hで宣言されている
#define USE_DEBUGGERのコメントアウトを外して、自前でビルドしてください。
Common Source Code Projectの内蔵デバッガーと大体同じような感じですが、
INTの番号とAH/ALの値を指定して、ブレークを掛けられるようになっています。
なお、メモリの読み書きでブレークを掛ける処理については、CPUからのアクセスに
対してのみブレークするようになっています。
BIOSやDOSサービスの実装において、メモリを読み書きする関数を使わずに、
直接メモリを読み書きしている箇所が余りに多いので、完全な対応は難しいです。
1プロセスで複数のコンソールを持てないので、telnetクライアントを起動して、
そちらで操作する仕様にしました。
ポートは23番、使用されていれば9000番以降を開くようになっています。
Tera Term PRO、PuTTY、Windows標準のtelnet.exeの何れかが、標準的なパスに
インストールされていれば、起動時に自動的に起動するようになっています。
Tera Term PROやPuTTYでは、デフォルトで行単位送信モード(Line at Tiem)が
有効になっているかと思われますが、バックスペースの処理の関係上、
1文字単位で送信(Character at Time)にした方が操作しやすいかと思います。
2017/2/2
エラーコードからエラーメッセージを取得するサービスを実装しました。
拡張エラーはINT 2Fh, AH=05hで、パラメータエラーはINT 2Fh, AX=122Eh, DL=08hで
取得されるアドレスをCALL FARすることで取得します。
コードページが932の場合は日本語のメッセージを、それ以外の場合は英語のメッセージを
返すようにしています。
また、MS-DOS Playerを起動する前に、chcpで437などにコードページを変更した場合は、
MS-DOS Player上でも、chcpで指定したコードページがアクティブになるようにしました。
MS-DOS Player上でコードページを変更すると、コンソールの入出力のコードページも、
それに合わせて変更されます。
_getmbcp()/_setmbcp()と、GetConsoleCP()/SetConsoleCP()/SetConsoleOutputCP()とで、
カバーしているコードページが違いそうですが、少なくとも932と437の間での変更であれば、
期待した通りに動作しているようです。
INT 67h, AH=57hにおいて、EMSの転送の最大サイズを、1ページのサイズの4000hに
制限していましたが、これを割り当てられたページ数分だけ転送できるようにした他、
成功時でもリザルトとして80h(インターナルエラー)が返っていたのを修正しました。
INT 24Hの処理を修正しました。
従来は、問答無用で実行中のプログラムを終了するような実装になっていましたが、
中止 (A), 再試行(R), 無視 (I), 失敗 (F)から選択できるようにしています。
環境変数をホストから読み込む際に、APPENDの値をショートパスに変換するようにしました。
また、MSDOS_APPENDが定義されていた場合、その値をAPPENDの前に追加するようにしました。
PATHとMSDOS_PATHと同じような扱いですが、MSDOS_APPENDは仮想環境には追加されません。
また、通常はありえないですが、COMSPEC/PATH/TEMP/TMPがホスト環境で定義されてなくても、
仮想環境には追加されるように修正しました。
この場合、COMSPECの値はC:\COMMAND.COM、PATHの値は空、TEMP/TMPの値は
GetTempPath()で取得されたパスが指定されます。
コンソールウィンドウが閉じられた、またはエミュレータ内部で致命的なエラーが発生したなど、
正常に終了できない場合に、newやmallocで確保したリソースを開放する処理について、
XMSの管理テーブルや、ホストと接続したシリアルI/Oのバッファを開放できるようにした他、
終了するまでに、既に開放されたリソースがアクセスされないように改良しました。
2017/1/31
綾川鞠乃介様のATVが動作するようになりました。
ATVではEMSを使用しているのですが、取得したEMSのハンドルの値が0番から
始まっていたのが良くなかったようです。
また、!コマンドでシェルに降りるとき、一旦ATV.EXEを終了してしまって、
シェルを終了したときに、ATV.EXEを再起動するようになっています。
このとき、INT 21h, AX=4B00hにおいて、ES:BXで指定されるパラメータブロックは、
最初にATV.EXEを起動したときのものを、そのまま使いまわしています。
しかし、INT 21h, AH=4Chでシェルを終了する際に、元のESの値が復元されて
いなかったため、再起動時のINT 21h, AX=4B00hにおいて、パラメータブロックが
正しい位置を指していませんでした。
ESの値を復元するようにしたところ、!コマンドが正常に動作するようになりました。
また、INT 21h, AX=4B01hで子プログラムをロードした際に、子プログラムの
スタックの先頭にAXの値を積むように修正しました。
INT 67h, AH=52hにおいて、DXの値の範囲をチェックしないようにしました。
EMS関係のサービスでは、DXにEMSのハンドルを指定するものが多いのですが、
INT 67h, AH=52hではEMSハンドルを参照していませんでした。
I-OデータのMSTATで、EMSの情報が取得できるようになっています。
ビルド環境をVC++2013からVC++2008に戻しました。
まだWindows 2000でお使いいただいている方がいらっしゃるようなのですが、
VC++2013でビルドしたバイナリはWindows 2000で動作しないようです。
2017/1/1
Windows XP向けにリビルドしました。
前回から、ビルド環境をVC++2013に変更したのですが、プラットフォームを変更し忘れてました。
2016/12/31
ここ半年ほど、ちょこちょこ進めていた作業を一旦リリースしておきます。
将来的に、Win16のエミュレーションを出来ないかなということで、
日本語版Windows 3.1のインストーラが使用するサービスを実装してみました。
$IBMADSPの存在と、フォントパターンが取得できるかで日本語環境かどうか確認したり、
NetWareのサービスを実行してネットワークドライブをスキャンしたりと、
なかなかどうして意外とカオスなことをしているみたいです。
構成を指定して、一通りファイルをコピーして、WIN.COMに処理が移ったところ?で
エラーになってしまいます。
その後に、win3muが話題になってきまして、この件はここまでで打ち切りです(苦笑)
2016/7/30
プログラム起動時のメモリ確保では、メモリチェーンの最後のブロックを使用するようにしています。
これは、後から確保したメモリサイズを変更することを想定しているためですが、
コンベンショナルメモリとUMBのメモリチェーンが結合している場合、容量の小さいUMB側から
メモリを確保してしまうという問題がありました。
これを、UMBの結合如何にかかわらず、先にコンベンショナルメモリからメモリ確保を試みて、
失敗した場合のみ、UMBから確保するように修正しました。
常駐プログラムが、INT 21h, AH=31hやINT 27hで、メモリ上に自分を残したまま終了する際に、
メモリチェーンが壊れていることを検出した場合、コンベンショナルメモリまたはUMBの末端まで
そのプログラムがメモリを確保していたと仮定して、MCBを修復するようにしました。
INT 2Fh, AH=12hの、DOS内部で使用されているサービス群をサポートしました。
(AL=02h/04h/05h/0Dh/11h/12h/13h/14h/1Ah/1Bh/1Eh/21h/25h/26h/28h/29h/2Bh/2Ch/2Dh/2Fh)
DOSカーネルだけでなく、COMMAND.COMやMEM.EXEなどでも使用されているようです。
これによって、やっとMEM.EXEでダミーデバイスが認識されるようになりました。
i386以降限定で、XMSのAH=88h/89h/8Eh/8Fhをサポートしました。
XMS Ver 3.0系のサービスになります。
これにともない、XMSのバージョンおよびドライバのリビジョンを変更しました。
ついでにEMSのバージョンも上げています。
試験的に、HMA関係の実装をしてみました。
INT 2Fh, AH=4Ah, AL=01h/02h/03h/04h、XMSのAH=01h/02hが実装されています。
従来は、DOSがHMAに常駐している扱いにして、HMAは使用できないようにしていましたが、
任意のプログラムがHMAを確保できるようにしました。
また、Win95のHMA管理を取り入れて、複数のプログラムがHMAを共有できるようにしました。
といっても、通常はDOSがHMAに常駐していますから、自前でHMAの確保を試みるような
プログラムがあるのか、というと微妙なところです。
却って不具合の原因になりかねませんので、現状では無効にしてあります。
msdos.hの#define SUPPORT_HMAのコメントアウトを外すと有効にできますので、
必要に応じて修正、ビルドしてください。
今後のリリースで有効にするかどうかは、フィードバックを見て追々判断したいと思います。
COM3/4を使用できるようにしました。
実用的な意味は多分ないですが、COM3/4がCOM1/2とそれぞれIRQを共有しているということを
最近知りましたので、まあ折角だからということで。
9600bpsのモデムを4つ繋いで、草の根BBSのホストを立ち上げるとかの検証をしてくださる
酔狂な方がいらっしゃいましたら、是非結果をご報告ください(を
2016/6/24
16bitのコマンドファイルをmsdos.exeに埋め込む処理を改良しました。
PEフォーマットに従って、実行ファイルに新たなセクションを追加して、そこにコマンドファイルを
格納するようにしました。
従来よりも、ウイルスとして誤検出される危険が減っているといいなあと思います(苦笑)
実行時に、埋め込まれたコマンドファイルを展開する際、できるだけ元と同じファイル名で
カレントディレクトリに展開するようにしました。
例えば、VZエディタでは、コマンドファイルと同じファイル名の定義ファイルを読みに行くように
なっていますので、そのようなケースを考慮した修正です。
ただし、カレントディレクトリに、同じファイル名のファイルがある場合は、上書きしないように、
テンポラリなファイル名で展開されます。
なお、展開したコマンドファイルは、終了時に自動的に削除されるようになっています。
また、実行時のコードページを記録するかどうかを、-pオプションで指定できるようにしました。
メモリ管理系のサービスの実行時に、Memory Control Blockが壊れているのを検出した場合、
また、プロセスの終了時に、PSPが書き換わってしまったなどの理由で、プロセス管理データを
取得できなかった場合、従来は、問答無用でMS-DOS Playerを終了するようになっていましたが、
しかるべきエラーコードを返して、処理を続行するように修正しました。
(どのみち致命的な状況なので、素直に強制終了しておいた方がいいかもしれませんが…)
コンソールウィンドウが閉じられた、またはエミュレータ内部で致命的なエラーが発生したなど、
正常に終了できない場合に、newやmallocで確保したリソースを、出来る限り開放するようにしました。
INT 2Ehで起動したプロセスが終了したときに、または、プロセスの起動に失敗した場合に、
AXにステータスを格納するように修正しました。
BIOSデータエリアの0040:0010や、INT 11hで取得される、Equipment List Flagsの値を修正しました。
フロッピードライブ数の情報を追加するようにしました。(A:およびB:のみチェック)
16bitのコマンドファイルが格納されているディレクトリがあったとして、ホスト環境のPATHでは
参照したくないけど、MS-DOS PlayerのPATHでは参照したい場合があるかと思います。
このような場合のために、MSDOS_PATHという環境変数にディレクトリを登録しておくと、
ホスト環境のMSDOS_PATH;PATHが、MS-DOS PlayerのPATHにコピーされるようにしました。
このため、MS-DOS Player上では、MSDOS_PATH内のファイルが先に検索されるようになります。
2016/6/22
16bitのコマンドファイルをmsdos.exeに埋め込んで、単体で動作する32bit/64bitの実行ファイルを
生成する仕組みをサポートしました。
例えば、msdos.exe -cMARS32.EXE MARS.EXEのように実行すると、MARS.EXEを埋め込んだ、
MARS32.EXEという実行ファイルが生成されます。
このとき、MARS32.EXEは、msdos.exeなしで単体動作することができます。
-c以外のオプションを指定すると、実行時に、それらのオプションが指定された状態になります。
例えば、msdos.exe -ccommand32.exe -v6.22 -x command.comのように指定すると、
バージョンが6.22、XMS/EMSが有効な状態で、command.comが起動する実行ファイルになります。
EXDEB起動時に、Machineの表示が乱れる問題を修正しました。
INT 21h, AH=30hにおいて、BHだけでなく、BLおよびCXを更新するようにしました。
EXDEBでは、BL=00hだとPC-98、BL=01hだとPC-AT、BL=02hだとFMRと表示します。
Windows 98 SEで確認したところ、BL=00hが返るようなので、それに合わせました。
INT 15h, AX=5000h/5001hを修正しました。
INT 15h, AX=5000hを実行して、エラーが返らないと、DOS/Vと判定しているようです。
2016/6/21
CTRL-Cを押したときの処理を修正しました。
INT 21hの、一部コンソール系のサービスを実行中に押した場合、INT 23hが実行されます。
CTRL-Breakについては、従来通り、即エミュレータが終了するようになっています。
シリアルポートの改良を行いました。
指定されたボーレートが、Windows側でサポートしているかチェックするようにしました。
ブレーク信号を、最低限200msecはオンにしたままにするようにしました。
また、フロー制御を、Windows側に任せるようにしました。
DSR/CTS信号については、I/Oポートに出力したDTR/RTS信号がそのまま読み込まれます。
タイマーの改良を行いました。
タイマーをtimeGetTime()で駆動しているため、従来は、カウント中の値を取得すると、
1msecはずっとそのままの値が返ってきていました。
これを、1msec後のカウント値を下回らない範囲で、値を取得する毎に-1するようにしました。
IO.SYSの空間(0070:0000)に、更にダミードライバを追加しました。
また、各ドライバのStrategy/Interruptに、ダミーのルーチンを指定しました。
余り意味はないですが、わざわざドライバヘッダを検索して、Strategy/Interruptルーチンを
直接呼び出すようなソフトがあれば、いきなり暴走はしなくなっているかと思います。
BIOSデータエリアの0040:0010や、INT 11hで取得される、Equipment List Flagsの値を修正しました。
ポインティングデバイスの有無や、シリアル・パラレルポート数の情報を追加しています。
フロッピードライブ数の情報はどうしましょうか?
GetDriveType()はリムーバブルか否かしか判断できないし、DeviceIoControl()は大げさですし。
A:/B:ドライブ限定でGetDriveType()が無難かな、とは思うのですが。
実際、わざわざ設定するほど重要な情報でもないような気がするんですよね(苦笑)
2016/6/17
シリアルポートの実装を行いました。
安定性にはまだ難があるかもしれません、テストにご協力お願いいたします。
仮想マシンのCOM1, COM2を、ホスト側の任意のCOMポートに接続することができます。
ホスト側のCOMポートは、USB接続のシリアルポートを使用可能です。
(今回のテストでは、I/OデータのUSB-RSAQ5を使用しました)
-sオプションで、ホスト側で見つかったCOMポートの順に、COM1, COM2に割り付けられます。
-s3,4のように、オプションで、ホスト側のCOMポートの番号を指定することも可能です。
なお、通信速度は、9600bpsまでに制限しています。
3F88h, 2F8h辺りのI/Oポートを直叩きすることも、INT 14h経由で操作することも可能です。
スクリーンショットは、株式会社エイテックのSmart-Writer SW-1のコントロールソフトです。
シリアルポートのテスト用に、ヤフオクで調達しました(を
スーパーカセットビジョンの、ドラゴン大秘境のROMを吸い出しています。
INT 21h, AH=65h, AL=23h/A0h/A1h/A2hをサポートしました。
INT 2Fh, AH=14h, AL=00h/01h/02h/03h/04hをサポートしました。
主に、NLSFUNC.COM関係のサービスです。
その他、ダミーのDMAコントローラやパラレルI/Oを実装したり、IO.SYSの空間(0070:0000)に、
ダミーのCON/CLOCK$ドライバのヘッダを置いたりしています。
ダミードライバを追加してみたものの、まだMEM.EXEが認識してくれないんですよねえ。
2016/6/10
マウスの実装を行いました。
MS-DOS Playerはコンソールアプリのみサポートしていますが、DOSSHELLやEDITなど、
DOS標準のツールの中にも、マウスを使用するものもあるようです。
DOSSHELLでは、選択したプログラムの実行のため、TEMP以下にバッチファイルを作ります。
Windowsでは、TEMPは"C:\User\(User Name)\AppData\Local\Temp"のようなパスになりますが、
バッチファイルのパスが長くなり過ぎて、正しく動作しない場合があります。
この対処として、ホスト側でMSDOS_TEMPという環境変数(例えば、"C:\TEMP")があれば、
その値が、仮想環境のTEMP/TMPの値として使われるようにしました。
COMMAND.COM上で、"COPY (file) (directory)"の実行に失敗する不具合を修正しました。
COMMAND.COMは、コピー先のパスを、INT 21h, AH=6Chでファイルとして開いてみて、
失敗したら、コピー先のパスがディレクトリであるか判断しているようです。
このとき、INT 21h, AH=6Chで、ファイルを開くのに失敗したときに返るエラーコードは、
ファイルはあるけど何故か開くのに失敗した場合と、ファイルがないから失敗した場合とで、
ことなる値になるべきです。
従来の実装では、_access()関数を使って、ファイルの存在チェックをしていましたが、
この関数は、ファイルだけでなくディレクトリの存在もチェックしてしまいます。
このため、FindFirstFile()関数を使って、アトリビュートをチェックしてやることで、
ファイルかディレクトリかをチェックするように修正しました。
まだこんなバグが残っていたのかと、個人的にちょっとショックだったりします(苦笑)
その他、INT 21h, AH=29hにおいて、ドライブ付のファイルパスのパースに失敗するように
エンバグしてしまっていたのを修正したり、雑多なサービスの実装をしたりしました。
2016/6/8
FreeDOS関係の動作確認中です。
COMMAND.COMでCOPYに失敗する問題、MORE.EXEでキーを受け付けない問題を修正しました。
COPYの方は、INT 21h, AH=40hで、CX=0000hを指定したときのAXの返り値の問題でした。
CX=0000hの場合、現在のシーク位置にファイルサイズを変更します。
現在のシーク位置が、現在のファイルサイズより先にある場合、00hを付け足すことで、
シーク位置までファイルを大きくしますが、このとき付け足したバイト数をAXに返していました。
この場合、AX=0000hを返すのが正しかったようです。
MOREの方ですが、例えばTYPE (file) | MOREを実行すると、MORE.EXE上では、
ファイルハンドル複製/多重化の果てに、ファイルハンドル0番にstderrが割り当てられいて、
コンソール系のAPIが正しく動作しなくなっていたみたいです。
ファイルハンドル0番がattyで入力なデバイスでない場合は、コンソール系のAPIではなく、
_kbhit()や_getch()などの関数を使用するように修正しました。
これらの関数だと、ファイルハンドルの状態によらず、キーボードを読んでくれるようです。
また、コンソール系のAPIで使用するハンドルは、起動時にGetStdHandle()で取得したものを
ずっと使いまわしていましたが、ファイルハンドル複製/多重化の影響を受けて、
ハンドルが無効になってしまう場合があるようです。
そのため、コンソール系のAPIを使うたびに、GetStdHandle()で取得するように修正しました。
その他、DOS Swappable Data Areaやその中のInDOSフラグの取得(INT 21h, AH=34h/AX=5D06h)、
拡張国別情報の小文字テーブルの取得(INT 21h, AX=6503h)をサポートしました。
2016/6/7
PITの動作タイミングの精度向上を図りました。
CPUBENCHなどで、結果のバラつきが減っているかと思います。
INT 21h, AH=44h(IOCTRL関係)やINT 21h, AX=71AAh(SUBST)をサポートしました。
SUBSTが動くようになっていますが…余り意味はないですかね(苦笑)
デバッグ用のコード整理を行いました。
その結果見つかった、これまで未実装だったサービスを幾つか実装しています。
但し、大半は、単に該機能が未サポートだとのエラーを返すだけです。
2016/6/3
更にEMS/XMSの実装を進めました。
INT 67h, AH=4Fhを新規にサポートしました。
また、XMS call AH=04h/05/06hの、A20マスク周り(主にローカル関係)を改良しました。
動作検証は出来ていないけど、実装としてはこれで一段落?
INT 67hには、VCPI周りの機能も入っているのですが、流石にこれは要らないですよね?
起動時、ファイルハンドルの3番(AUX)と4番(PRN)用に、NULをオープンするようにしました。
COMMAND.COM上で、TYPEで内容を表示したファイルが、DEL出来なくなる不具合が修正されています。
TYPEコマンドでは、自分で開いたファイルハンドルを覚えておいて、終了時にそれを閉じるなんて
まどろっこしい事はせずに、5〜19番を片っ端からクローズするという豪快なことをしていまして。
そのため、3〜4番で開かれたファイルがクローズされませんでした。
システムファイルテーブル周りの実装を進めました。
INT 2Fh, AX=1216h/1220hを新規にサポートしました。
また、ファイルのオープン時と、INT 2Fh, AX=1216h時に、テーブルを更新するようにしました。
その他、INT 15h, AH=89hの処理の改良や、INT 15h, AH=8Ah, INT 21h, AX=440Ahをサポートするなど、
引き続き細々とした修正をしています。
2016/6/2
EMSの実装を進めました。
INT 67h, AH=4Eh/50h/52h/57h/58h/5Ahを新規にサポートしています。
また、EMMXXXX0をファイルオープンすることで、EMSの存在判定をする場合に対応しました。
EMS/XMSで通常使用しそうなサービス類は、これで大体サポートできたかと思います。
引き続き、テストにご協力お願いいたします。
ファイルI/Oにおいて、指定されたファイルハンドルをそのまま使うのではなく、
PSP内のファイルテーブルから、実際のファイルハンドルを取得するように修正しました。
また、子プロセス起動時に、親プロセスのPSPのファイルテーブルを引き継ぐように修正しました。
COMMAND.COM上で、リダイレクトやパイプが動作するようになりました。
INT 21h, AH=45h/46hの、ファイルハンドル複製/多重化を使っていると思っていたのですが、
PSPのファイルテーブルの0〜1番(標準入出力)に、リダイレクト先のファイルのハンドルを
入れてやることで、リダイレクトを実現していたみたいです。
上記の例では、stdin.txtに記載したコマンドをSYMDEBで実行して、結果をstdout.txtに出力します。
そして、TYPEコマンドでstdout.txtを表示して、パイプでMOREに渡しています。
こちらの修正で、ファイルI/O周りをもりっと書き換えています。
影響範囲が広いので、こちらもテストにご協力いただけますと幸いです。
ところで上記の例、地味に、制御コードを^Zみたいに表示できるように修正しています。
行入力時に、バックスペースで^Zを削除するのも大丈夫です。
従来は記号が表示されてしまっていたのですが、スクリーンショットを撮ってて気になりまして(苦笑)
その他、DOS INFOのundocumentedなパラメータの処理をDOSBoxから取り込んだり、
INT 21h, AH=29hの改良や、INT 2Fh, AX=168Fhのサポートなど、細々とした修正をしています。
2016/5/29
EMSとXMSをサポートしました。
-xオプションを付けて起動すると、EMS,XMSが有効となります。
ただし、XMSはi286以降でのみサポートします。
また、コンベンショナルメモリとUMBのメモリチェインの接続をサポートしました。
十分な検証ができていませんので、テストにご協力お願いいたします。
一応、VZエディタでEMSを認識したり、X8MAPでEMS/XMSの領域を参照できるようです。
INT 21h, AH=38hで取得する国別情報で参照されている、大文字変換ルーチンをサポートしました。
こちらに含まれるzip.exeを起動したとき、クラッシュせずにオプション一覧が表示されるようになりました。
システムコールのフック用のIRETテーブルを、MCBで管理されたメモリブロック内に配置するようにしました。
INT 2Ehの割り込みベクタのセグメントから、MCBを取得する場合のための修正です。
内蔵のi386の逆アセンブラを修正しました。
これは開発用であり、配布しているバイナリには含まれません。
2016/5/24
タイマー値を、INT 1AHを使わず、直接BIOSデータエリアから取得する場合の処理を改良しました。
Turbo Pascalで作成したツールが動作するようになっているかと思います。
また、タイマー値の更新処理を高速化しました。
INT 24h/25hで、32MB以上のボリュームにアクセスできるように修正しました。
2015/12/28
Windows 2000で起動しなくなっていた問題を修正しました。
コマンドプロンプトから起動したか、実行ファイルをダブルクリックして起動したかの判定に、
GetConsoleProcessList()を使用するように、2015/10/17の更新で変更していましたが、
これはWindows 2000ではサポートされないようです。
今回、LoadLibrary()でGetConsoleProcessList()をロードして使用するようにしました。
ロードできない場合は、別の方法で判定するようになっています。
現在、環境変数COMSPECの指すパスはC:\COMMAND.COMに固定されています。
その上で、MS-DOS Player上で動作するアプリがC:\COMMAND.COMにアクセスしようとしたら、
実際のCOMMAND.COMのパスにリダイレクトされるようになっています。
この実際のCOMMAND.COMのパスを、環境変数MSDOS_COMSPECで指定できるようにしました。
MSDOS_COMSPEC自体は、MS-DOS Player上で動作するアプリからは認識されません。
MSDOS_COMSPECが存在しない場合は、従来通り、COMMAND.COMを
- 実行対象のアプリのあるディレクトリ
- MS-DOS Playerの実行ファイルのあるディレクトリ
- パスの通っているディレクトリ
の順に検索して、最初に見つかったパスにリダイレクトされます。
2015/11/7
sava様にご提供頂いたパッチを取り込みました。
主な修正点は以下になります。
- -vオプションの読み取りの修正
- INT 21h, AX=6501h〜6507hを実装(FreeCOM)
- Vista以降で管理者権限のない状態でのINT 21h, AH=1Chなどの動作改善(Turbo C++のインストーラ)
- INT 21h, AH=3Bh(chdir)のエラーコードを3に変更(command.comのdelコマンド)
- INT 21h, AX=7141h(LFN remove)のワイルドカード処理を実装(win9x command.comのdelコマンド)
- INT 15h, AH=88h, AX=E801h(16MB超メモリ)を実装(CWSDPMI+gccなど)
- DOS INFO内にダミーのNULデバイスヘッダ作成(zmap, mrepなど一部のメモリ表示系プログラム)
- i386/i486版のメモリサイズを32MBに変更
いつもお世話になっております、多謝多謝です。
2015/10/20-2
DJGPPの動作確認をしてみました。
最新のバイナリだとクラッシュしてしまいました。
.SファイルはDJGPP/TMPに生成されていましたので、アセンブラの問題でしょうか?
ちょっと古い目のバイナリだとうまくいきました。
ダウンロードしたのは以下のファイルです。
環境構築は、こちらのサイトを参考にさせていただきました。
2015/10/20
INT 21h, AH=14h/15h/17h/23h/24h/27h/28hを実装しました。
FCBを用いたファイル操作関係になりますが、使っているソフトがあるのかどうか(苦笑)
INT 10h, AX=1118hを実装しました。
V-TEXTの縦長モードですが、コンソールを80x50に変更する形で実装しています。
CPUモデルにNEC V30を追加しました。
あわせて、msdos.vcprojに80186, V30, Pentium/PRO/MMX/2/3/4, MediaGXのConfigurationを追加しました。
こちらではバイナリのリリースはしませんので、必要に応じてmsdos.vcprojをビルドしてください。
2015/10/18
一部コードを整理しました。
機能的な変更はありません。
2015/10/17
今回はかなり大規模な変更が入っています。
今まで動いていたソフトが動かなくなっているかもしれません。
動作確認ご協力お願いいたします。
Jason Hood様から頂いた、大規模なパッチを取り込みました。
(DOS界隈では、ANSICONとかDOSLFNで著名な方です。突然メールを頂いてびっくり)
こちらでは未確認ですが、DJGPPやDOS4GWなども動くようになっているみたいです。
DOSエクステンダが動くようになると、色々と夢が膨らみますね。
主だった修正点は以下の通りです。
- コンソール周りの改良(エスケープシーケンス、テキストVRAM、キー入力など)
- INT 10h(ビデオBIOS)の改良
- INT 16h(キーボードBIOS)の改良
- INT 21hの改良(主にFCB、LFNの処理など)
- メモリ上のBIOS領域の改良
- MCBやPSPの処理の改良
- システムドライブのルートに新規ファイルを書き込めない場合、%TEMP%にリダイレクトする
- 各種オプションの追加
コンソール周りやINT 10h/16hの改良の成果として、Konno版のVZエディタが動くようになりました。
従来、V-TEXT使用時は画面サイズが80桁x25行固定でしたが、起動時のコンソールのサイズにあわせて、
任意の画面サイズで動作するようになっています。
オプションで画面サイズを指定することもできるようになりましたので、
msdos -n64,160 vzibmj
とやって、SXGAサイズ(160桁x64行)で起動することも可能です。
なお、BIOS領域内のキーバッファを直接参照しているソフト向けに、該メモリを読んだときに、
適宜Sleep()を入れるようになっています。
この影響で、CPUBENCHの結果がやや遅くなってしまっていますのでご注意ください。
FILMTNやFMで、プログラムの実行やファイルの閲覧ができない問題を修正しました。
子プロセスとしてCOMMAND.COMを起動するとき、コマンドラインが指定されていない場合は、
呼び出し元プロセスのDTAにあるコマンドラインを使うようにしています。
バッチファイルの実行に仮対応しました。
参照可能なところにあるCOMMAND.COMを起動して、そちらでバッチファイルを実行します。
なお、VZエディタに入っているVZ.BATでは、nulデバイスに出力をリダイレクトしています。
これを削除しないと、途中で止まってしまうようです。
2015/6/25
えむけい様にご提供頂いたパッチを取り込みました。
- 読み出し専用属性のついたファイルが開けない問題を修正
- command.com経由でプログラムを起動したときPSPのコマンドライン末尾にCRが付かない問題を修正
- find first/nextがカレントディレクトリ以外のパスを正しく検索できない問題を修正
- 複数DTAに対応
- 8.3名の生成が無効になっているなどの理由で短いファイル名が存在しないとき、find first/nextでバッファオーバーランが起きる問題を修正
- 空きクラスタ数が65536の倍数のときに誤ってディスクがいっぱいと判定される問題を修正
取り込みが遅くなってしまい申し訳ありません、多謝多謝です。
2015/4/24
i386コアに、MAME 0.160までの変更を適用しました。
SSE命令などの対応が中心なので、MS-DOS Playerでは余り意味はなさそうです。
2015/1/28
8086版のバイナリを追加しました。
i286版より更に高速に動作するかと思います。
2015/1/21
INT 21h, AH=40hを修正しました。
書き込むバイト数に0を指定した際に、現在のファイルポインタの位置に切り詰める処理をサポートしました。
また、INT 10h関係を実行した際、強制的にウィンドウサイズを80x25に変更するようになっていますが、
MS-DOS Playerの終了後に、元のサイズに戻すようにしました。
今回の更新は、sava様にご提供頂いたパッチが基になっております。
日頃より、DR-DOS System and Programmers Guide(日本語訳)を大いに参考にさせて頂いております。
まことに多謝多謝です。
2015/1/15
INT 10h, AH=1Bhにエラーを返さないようにしました。
INT 10h, AH=EFhをサポートしました。
Hercules互換ボードではないと返すようになっています。
INT 2ih, AH=3Ch/3Dh/6Chについて、CONデバイスを開く処理を改良しました。
C:\HOGE\CONのようなパスを、CONデバイスと認識するようになっています。
i286/i386コアにおいて、割り込み発生時にm_irq_stateをクリアするようにしました。
Mr. Daniel Zingaroの開発された、DroneというテキストRPGが動作するようになりました。
QBASICで開発されたソフトとのことです。
2015/1/14
i386コアに、MAME 0.157までの変更を再適用しました。
これで完全に0.157相当の動作になっている筈です。
2015/1/8
i386コアに、MAME 0.157までの変更を適用しました。
従来はオミットしていたTLB周りも、Generic virtual TLBを使用した実装になっています。
ただし、処理速度が少々低下しています。
msdos.exeをダブルクリックして起動したときに、コマンドプロンプトから起動するように、
警告メッセージを表示するようにしました。
キーを押すまで、コンソールウィンドウが閉じないようになっています。
2014/12/6
VZエディタ付属のGAME.DEFマクロが動作するようになりました。
CRTCのステータスレジスタの垂直同期信号をチェックしていたようです。
3DAHと、念のため3BAhから、ステータスレジスタを読み込めるようにしました。
垂直同期信号は、仮に60Hzで変化するようにしています。
-vオプションで、INT 21h, AH=30hが返す、MS-DOSのバージョンの値を指定できるようにしました。
また、COMMAND.COMを検索して、環境変数COMSPECの値にファイルパスを入れるようにしました。
実行対象のプログラムファイルと同じディレクトリ、msdos.exeと同じディレクトリ、カレントディレクトリ、
またはパスの通っているディレクトリにあるCOMMAND.COMを検索します。
見つからなかった場合は、ホスト環境のCOMSPECの値が使われます。
i386/i486版の高速化を図りました。
従来、RDTSC命令のために、各命令を実行するごとにサイクル数を計算していたのですが、
i386/i486ではRDTSC命令をサポートしていないため、サイクル数の計算をしないようにしました。
CPUBENCHで確認した限りでは、26%程度は高速化されているようです。
2014/12/4
「はじめて読む486」のサンプルプログラムのうち、TESTTASK, HARDINT, INTMONが動作するようになりました。
TESTTASKでは、データを表示するために、テキストVRAMに直接データを書き込んでいますが、
このとき、テキストVRAMのアドレスをビデオBIOSで取得せず、B8000hを決め打ちしています。
このため、B8000h-BFFFFhをテキストVRAMとして、データを書き込むとすぐ画面に反映するようにしました。
ただし、V-TEXTの仮想バッファは従来通り、F80000hにあるものとしています。
VZエディタなどにおいて、仮想バッファとテキストVRAMのアドレスが同じ場合、VRAMに書きっ放しで、
ビデオBIOSでバッファを画面に反映する動作を行わなくなるためです。
なお、テキストVRAMを追加したことで、コンベンショナルメモリが992KBから736KBに減少しました。
その分、アッパーメモリの空き部分の224KBをUMBに割り当てるようにしています。
Windows98 SE付属のCOMMAND.COMで、UMBからのメモリ確保が動作することを確認しました。
HARDINTは、ハードウェア割り込みのモニタを行うものです。
このため、キーを押した場合に、キー割り込みを発生するようにしました。
また、I/Oを操作しなくてもタイマを常に駆動して、定期的にタイマ割り込みを発生するようにしました。
あわせて、タイマの実装を整理、単純化しています。
ログを取って確認した限りでは、期待した周期でタイマ割り込みが発生することを確認できました。
INTMONでは、環境変数のCOMSPECからCOMMAND.COMのパスを取得して実行します。
このため、実行するプログラムと同じ、またはパスが通っているディレクトリにCOMMAND.COMがある場合、
そのパスをCOMSPECに指定するように修正しました。
なお、最近のWindows上では、環境変数が多すぎてメモリ不足でCOMMAND.COMの起動に失敗するため、
msdos -e INTMONのように、-eオプションをつけて起動するようにご注意ください。
タイマの実装を見直したついでに、CPUBENCHの動作確認を行いました。
私の開発環境では、i286版で80486DXの257MHz相当、i386版で102MHz相当の速度が出ているようです。
2014/11/30
キーボードコントローラによるA20ラインの操作をサポートしました。
「はじめて読む486」のサンプルプログラムが幾つか動作するようになっています。
これに合わせて、折角なので80486のバイナリもビルドするようにしました。
INT 21h, AX=5800h/5801h/5802h/5803hを一応サポートしました。
ただし、UMBはサポートしていません。
アロケーションストラテジに40h/41h/42hが選択されていると、常にメモリの確保に失敗します。
実際のところ、これらのサービスでエラーを返さなくしただけです。
そもそも、F8000hまでコンベンショナルメモリ扱いなので、UMBを確保する隙間がないんですよね(苦笑)
2014/11/19
BUPDATEでファイルを更新した際に、タイムスタンプが正しく更新されない不具合を修正しました。
SetFileTime()でタイムスタンプを変更するには、Writeモードでファイルを開く必要があるのですが、
BUPDATEではReadモードでファイルを開いていたのが原因です。
ファイルを開く際に、Readモードが指定されていても、Read/Writeモードで開くように修正しています。
あわせて、INT 21h, AX=5704h/5705h/5706h/5707hもサポートしました。
Windows95でサポートされた機能で、ファイルの作成日時や最終アクセス日時を取得、変更します。
2014/11/7
ヤフオクでVZエディタを入手できましたので、一先ず文章を編集できる程度まで対応してみました。
VTDOSで動かす方が快適かと思いますが、まあ折角ですので。
IMEから漢字を正しく入力できない不具合を修正しました。
INT 16h, AH=11hでキー入力を検出して、INT 16h, AH=10hでキーコードを取得しているのですが、
マルチバイト文字の場合、2バイト目を何故かINT 21h, AH=07hで取得していました。
また、カーソルキーのリピートがうまく処理できない不具合を修正しました。
INT 16h, AH=11hでキー入力を検出する際、リピート時は入力なしを挟むようにしています。
2014/8/28
i386コアについて、メモリリークが発生していたのを修正しました。
また、x87のFPREM/FPREM命令について、MAME 0.154にあわせてフラグの処理を修正しました。
2014/7/10
ビルドオプションを変更して、もう少しほんのりと高速化しました。
i286版のx64バイナリで、前回の変更とあわせて30%程度は速くなっているかと思います。
2014/7/8
i286版を、ほんのり高速化しました。
また、PSP用に確保したメモリのMCBに、プロセス名をコピーするようにしました。
2014/4/15
i286版とi386版のソースを統合しました。
また、i286版において、INT 10h/16hのサポートを追加しました。
i286コアをMAME 0.149相当に、i386コアをMAME 0.152相当に差し替えました。
ただし、i386コアについては、TLB周りをオミットしています。
2014/4/8
i286版もまだ需要があるようですので、久しぶりに更新しました。
i386版の最近の変更を反映していますが、速度優先ということで、INT 10h/16h周りは未実装のままです。
2014/4/7
COMMAND.COMを起動する場合、環境変数のCOMSPECに、そのCOMMAND.COMのパスを指定するようにしました。
また、PATH/TMP/TEMPに指定されているパスを、すべてショートパスに変換するようにしました。
先日公開された、MS-DOS V2.0のCOMMAND.COMが起動するようになっています。
こいつは、COMSPECに登録されているパスを頼りに、自分自身をメモリにロードしているみたいです。
まあ起動するというだけで、実用的価値は皆無なんですが(苦笑)
2014/3/27
BLOGの方でご指摘いただいていた、EXDEBでカーソルキーが正しく効かない不具合を修正しました。
このソフトでは、INT 16h, AH=11hでキー入力を検出して、INT 21h, AH=08hでキーコードを取得しています。
従来は、INT 16h, AH=11hでキー入力を検出すると、INT 16h, AH=10hでキーコードを取得することを前提に、
INT 16h用のキーバッファにキーコードを移していました。
そのため、INT 16h, AH=11h実行後、INT 21h, AH=08hでキーコードを正しく取得できなかったようです。
その他、INT 21h, AH=52hで取得するDOS内部情報を、従来より正確に設定するようにした他、
ここから参照される、システムファイルテーブル、CDS、FCBテーブルを初期化するようにしました。
この修正で、何か動くようになったかは不明です。
2014/3/13
Windows 98 Second Edition用のCOMMAND.COMが動作するようになりました。
INT 21h, AH=59h(拡張エラーコード取得)、INT 2Fh, AH=AEh(プログラム起動)などを実装しています。
2014/3/12
JR運賃計算システム MARS for MS-DOSが動作するようになりました。
従来動かなかったのは、INT 21h, AH=3Chで、CONデバイスを開くのに失敗していたのが原因です。
失敗していたのは、Turbo Paacalのランタイム内部の処理ですので、Turbo Pascalで開発された、
他のソフトも動くようになっているかもしれません。
2014/3/7
INT 10h(ビデオ)、INT 16h(キーボード)など、PC/ATのBIOSの実装を進めました。
FDやDoDiaryなど、PC/AT用のソフトが色々動くようになっているかと思います。
FDは一応ちゃんと動いてる感じです。
開発中、ファイルのリネームに失敗する問題がありましたが、これは解決済みです。
あまり使い込んでないので、どこかしらで未実装のサービスを叩いてしまって、
落ちてしまう箇所があるかもしれません。
FILMTNは一見動いてるっぽいのですが、プログラムを実行しようとすると、
そこで正常終了してしまいます。
なおFILMTNでは、ファイル一覧の取得に、FCBを使ったファイル検索を実行しています。
FCB絡みの処理は未実装だったので、ファイル検索とファイル削除だけ実装しました。
DoDiaryは、環境変数テーブルが1KB以下である必要があります。
最近のWindowsでは環境変数が大幅に増えていて、環境変数テーブルも大きくなりがちです。
そのため、msdos -e dd.comのように、-eオプションを付けることで、必要最低限の環境変数のみ
ホスト環境から読み込む仕組みを追加しました。
LIST.COMも、今回の更新で動くようになっています。
このソフトは、INT 10h, AH=FFhで仮想テキストVRAMを画面に反映する処理をしていません。
そのため、仮想テキストVRAMにデータが書き込むと、すぐ画面に反映する仕組みを入れました。
2012/12/23
INT 21h(ディスクのRAWライト)をサポートしました。
marucopyでのディスクへの書き込みがちゃんと動作するようになっています。
ただし、安全のためフロッピーディスクのみライト可としています。
この関係で、DPB中のメディアの種類を正しく取得できるように修正しました。
USBメモリなどはハードディスク扱いとしています。
また、INT 21h, AH=1Bh/1Ch(FAT情報の取得)をサポートしました。
INT 21h, AH=0Ehで、不正なドライブが指定されるとクラッシュする問題を修正しました。
LIST.COMで起動時にクラッシュする問題が解決しています。
(LIST.COM自体はPC/ATの画面モードを前提にしているみたいで、現状では動作はしません)
その他、INT 21h, AH=66h(コードページの取得、変更)をサポートしたり、
INT 21h, AH=67h(最大ファイル数の指定)をサポートしたり、
使うかどうか分からないようなサービスやPC BIOSを幾つかサポートしたり、
色々修正していますが、細かいことは忘れちゃいました(苦笑)
2012/8/23
CPUコアを、MAME 0.146u3ベースのi386に差し替えました。
また、INT 21h AH=52h(DOSの内部ワークエリアアドレスの取得)をサポートしました。
これによって、要i386だったDDEBが動作するようになっています。
DOS-EXTENDER対応については、今のところ未定です。
2010/11/13
今回は色々と修正を行っています。
従来動いていたソフトが動かなくなってましたら、ご報告お願いいたします。
ロングファイルネームに対応しました。
Windows95で追加された、INT 21h AH=71hのシステムコールが大体サポートされています。
(ただし、SUBSTとネットワーク関係は未実装です)
これにより、MGやFMのロングファイルネーム対応版が動作するようになりました。
また、ディレクトリの検索時に、ボリュームラベルも列挙するように修正しました。
FMでボリュームラベルが正しく表示されるようになっています。
ついでに、ファイルの時間がUTCのままだったのを、ローカル時間に変換するように修正しています。
その他、細かい修正を色々と行っています。
従来は日本語環境を決めうちにしていましたが、ホスト環境のコードページを参照して、
DBCSテーブルを初期化するようにしました。
漢字などマルチバイト文字の判定も、こちらのテーブルを参照して行います。
INT 21h AH=5Ch(ファイルロック)、AH=6Ch(拡張ファイルオープン)に対応しました。
また、隠しシステムコールであるINT 2Fhも部分的にサポートしています。
こちらは、主にデバイスドライバやWindowsのインストールチェック用です。
PITエミュレーションを、PITにアクセスがあったときのみ行うようにしました。
これで、PITを直接操作するソフト以外で、多少高速化しているかと思います。
また、カウントを16bitで読み込む際に、常に下位8bitが読み込まれる不具合を修正しています。
2010/11/10
blogの方でa様からご指摘を頂きました、INT 21h AH=3Fhの不具合の件について、
今回も佐川様よりご提供頂きましたパッチを取り込みました。
どうもありがとうございます>お二方
INT 21h AH=1Fh/32h(DPBの取得)およびINT 25h(ドライブの物理リード)をサポートした結果、
ディスクのイメージ化ツールであるMARUCOPYが動作するようになりました。
INT 26h(物理ライト)については、危険防止のため常にエラーを返すようにしています。
処理の実装はしてあるのですが、Windows Vista/7では管理者権限がないと動作しないようです。
ようやくISH.COMが動作するようになりました。
ISH.COMには不正な命令が含まれているようで、従来はエラー終了するようになっていたのを、
そのまま次の命令に進むように修正しました。
その他、INT 21h AH=4Eh/4Fh(ファイルの検索)の属性チェックの厳密化やエラーコードの修正、
スペースが含まれるファイル名の補正処理などを追加しています。
2010/7/1
佐川様よりご提供頂きました、INT 21h AH=29hの修正およびmingw32対応のパッチを取り込みました。
また、blogの方でdosanko様よりご指摘頂きました、環境変数が大きい場合の不具合修正を行いました。
どうもありがとうございます>お二方
先日新たにご指摘いただいた、symdebのrコマンドの件はまた後日にでも。
2009/12/18
標準入出力のリダイレクトをサポートしました。
SYMDEBの<コマンドや>コマンドが動作するようになっています。
パイプを使って、TYPEコマンドから受け取ったコマンドをSYMDEBに渡して、
更にSYMDEBの出力をMOREコマンドに渡す、なんてことも可能です。
WEXが動作するようになりました。
FMをサポートした際に、INT 21h AX=4B00hをエンバグしてしまっていたのを修正しています。
(肝心のLSI C-86まで動かなくなっていたのも直っています)
コマンドのファイルが存在しなかったとき、そのままsystem()コマンドに渡していましたが、
これだと*.COMをまず起動しようとして、失敗したら*.EXEとして実行する、というように
コマンド起動が失敗し得ることを想定した処理でうまくいかなくなっていました。
このため、COMMAND.COM /C付きで起動しようとしたときのみ、system()コマンドに渡すように
修正しました。
また、INT 21h, AX=4406hの処理も修正しています。
渡されたファイルが入力モードか出力モードかの判定をするものだと解釈していたのですが、
更に入力モード時に、読み込み可能なデータがあるかかどうかも判定しているんですね。
(例えば、kbhit()もこのコマンドを使って実行されるのかな?)
2009/12/10
今更ながらLHAが動作するようになりました。
Windows用のツールが幾らでもありますが、これが動かないとみっともない気がして。
これが今まで動いていなかったのは、INT 21h AH=4Eh/4Fhのファイル検索において、
検索結果を格納する際にアトリビュートをコピーし忘れていたという、これまたみっともない。
その他、解凍時に使用している、INT 21h AH=60h(真のパスを取得)を追加しています。
DOS汎用のファイルマネージャであるFMが動作するようになりました。
INT 21h AH=47hで現在のパス取得する際、ドライブ文字と最初の\を削除するように修正したり、
INT 21h AX=4B00hで、直接プログラムを起動するのではなく、"COMMAND.COM /C (program)"と
わざわざCOMMAND.COMやCMD.EXEを経由して起動するような場合に対応したり、
コンソール出力において、Console系APIを使って自前でエスケープシーケンスに対応したり、
その他にも色々と修正しています。
ドライブのボリューム名や空き容量が正しく取得できてないのは、また後日にでも。
2009/12/08
ハードウェアのエミュレーションは行わないという方針で今まで実装してきましたが、
CPUBENCHが動かないのもなあ、ということで、PICとPITを実装してみました。
PITは、カウント値を周波数で割ってmsecの値にして、CPUコアが1024ステップ実行する毎に、
timeGetTime()の値と比較する、といった感じで駆動しています。
精度もまあそれなりなので、CPUBENCHの結果をどう評価するか難しいところですね(苦笑)
で、ついでにCPUコアを80286にしてみました。
あわせてプロテクトモード用にメモリを16MBにしたり、A20ラインの制御をサポートしたり、
リアルモード復帰に必要なRTCのCMOSメモリとか、キーボードコマンドのCPUリセットとか、
その辺のI/Oも追加しています。
その他、PC BIOS(INT 15h)のうち、プロテクトメモリ絡みの87h, 88h, 89hにも対応しました。
全然確認はできていないのですが、80286のプロテクトモードを使うアプリも動くかもしれません。
また、オプションを指定せずに起動した場合に、PSPの後半のコマンド列の領域の初期化が
ちゃんとされていなかったのを修正しました。
+80hの文字列長が0になっていればいいかと思ったのですが、文字列長をまったく参照せず、
いきなり+81hから文字列の解析をはじめるアプリケーションもあるようです。
この場合、最悪PSPを突き抜けて、ロードしたプログラムの内容を破壊する場合もあり得ます。
この修正で、従来動かなかったソフトで改善されたものがあるかもしれません。
2009/12/06
SYMDEBにおいて、EXEファイルのステップ実行がうまくいかない不具合を修正しました。
従来の実装だと、JMP命令を実行しても、そのまますぐ次の命令に進んでいました。
これが、ちゃんとジャンプ先の命令に進むようになっています。
どうも、INT 21h AX=4B01hでパラメータブロックに返るSPの初期値の問題だったようです。
(SPの値の表示が0102から0100に変わっていることに注目)
その他、従来はファイル操作関係の処理にファイルストリームを使用していましたが、
これを下位入出力関数で処理するように修正しました。
機能的には変わりないですが、ソースがすっきりしてバイナリサイズも小さくなっています。
2009/12/05
BLOGのコメントで、動作しないと報告して頂いたプログラムの対応を図りました。
VTDOSという強力なライバル出現にかなり刺激されてたりします(苦笑)
画像コンバータMGが動作するようになりました。
CPUのエミュレーションを、8086からV30に変更しました。
また、INT 21h AH=02h/06hで漢字を1バイトずつ出力する際、文字化けしないよう修正しました。
SYMDEBが動作するようになりました。
Lコマンドの実行で使用している、INT 21h AX=4B01h(ファイルを読み込むけど起動しない)、
INT 21h AH=26h/50h/51h(現在のPSPのコピー作成、PSPアドレスの設定、取得)をサポートしています。
作成したコマンドのデバッグも可能です。
!コマンドで、DOSコマンドを呼び出すことも可能です。
INT 21h AX=4B00hで、COMMAND.COMまたはCMD.EXEを/Cオプションを付けて起動しようとしたとき、
system()関数でコマンドを実行するようにしています。
またSYMDEBでは、!コマンド実行時に、COMSPECからインタプリタ名を取得しているようですが、
このとき環境変数名がComSpecと小文字混じりになっていると正しく認識できないようです。
このため、ホスト環境から環境変数をコピーする際、変数名を大文字にするように修正しました。
#SYMDEB.EXEの入手に困って、HANDY98のROMドライブから吸い出したものを使ってたり(を
2009/11/20
環境をWindows VistaかWindows 7のx64環境に移行しようかと思っているのですが、
16bitプログラムが使用できなくなってしまうのが悩みの種だったりします。
実機のROM吸出しや解析ツールの開発に、いまだにLSI C-86試食版を使っているので、
中々踏み切れないんですよね。
Virtual PCなりQEMUなり、仮想環境を使うのも一つの手段ではあるのですが、
ホスト-ゲスト間でいちいちファイルの受け渡しするのが面倒くさくって。
ホストのファイルパスや環境変数をダイレクトに操作できる、コマンドプロンプトから
シームレスに使える、お手軽な方法が欲しいなと。
で、自分で作ってみたと(苦笑)
どういった機能なのかは、上記画面を見れば大体判るかと思いますが。
msdos (コマンド) [オプション]とすると、MS-DOSアプリがx64上で動作します。
エミュレーション対象は、CPU(8086)とメモリと一部のMS-DOSのシステムコールだけで、
ハードウェアを直接操作するようなアプリケーションは実行できません。
純粋なMS-DOS汎用のアプリケーションのみが動作対象となります。
現状ではLSI C-86試食版のみの対応です。
他のアプリケーションの対応は反響次第ということで。