2

Ubuntu の DOSBox で作業している DOS ゲームを「ストリーミング」しようとしているプロジェクトがあります。アイデアは、画面のスクリーンショットを撮り、それらをサーバーにアップロードすることです。DOSBox からスクリーンショットを撮るには、xdotool を使用して、スクリーン キャプチャをトリガーするキーの組み合わせ "Ctrl+F5" をトリガーします。スクリーンショットは /capture フォルダーに保存され、そこからファイルを読み取ることができます。

問題は、スクリーンショットの名前が progName_000.png、progName_001.png になっていることです... 1 つのファイルをオーバーライドすることをお勧めします。達成することは可能ですか?

現在、私は以下の恐ろしいbashコードを使用しています:

WID=`xdotool search --limit 1 --name "DOSBox" 2>/dev/null`
while [ 1 ]; do
    fN=`ls ./DOSBox/capture/ | head -1`
    cp ./DOSBox/capture/$fN ./img.png
    rm ./DOSBox/capture/*

    xdotool key --window $WID Ctrl+F5
    sleep 0.10;
done

100 ミリ秒ごとにキャプチャ ファイルを読み取り、最初に見つかったファイルを取得して ./img.png にコピーし、キャプチャ フォルダをクリアして、別のスクリーンショットを撮ります。より良い代替手段は何ですか?

(PS: 上記のコードは単純化されています。通常、キャプチャした画像を複数の画像 (img0.png と img1.png) にコピーして、一方が書き込まれている間、もう一方がページめくりのように読み取れるようにします。 とにかく. )

4

1 に答える 1

1

コンパイルされた DOSBox バイナリを直接改ざんすることで解決策を見つけました。ソースを編集して単純にプロジェクトをビルドすることもできましたが、それのどこが楽しいのでしょうか?

バイナリ ファイルは /usr/bin/dosbox にあります。ターミナルでルートとして開きgdb、書きました

gdb -write -silent /usr/bin/dosbox

これは、Ubuntu 14.04 用にコンパイルされた私の DOSBox 0.74 バイナリのソリューションです。

まず、スクリーンショットのファイル名には、「whatevs_000.png」などの 3 桁の数字が含まれています。ファイル名はsprintf%3dまたは%03d. での幸運な検索objdump -s /usr/bin/dosbox | grep "\%03"により、文字列"%s%c%s%03d%s"が実際に に保存されていることが明らかになりました0x5fa9c7

でハードウェア アクセス ウォッチポイントを設定した後awatch *0x5fa9c7runプログラムを実行しましたgdb(数continue秒かかる場合があります)。DOSBox が起動したら、Ctrl+F5 を使用してスクリーンショットを撮り、sprintf 関数の命令でプログラムをトラップしました。数up秒後、メイン プログラム フロー (アドレス0x4a9949) に入りました。上に行くと、ディレクトリのリストを作成するための標準ライブラリ呼び出しをdisass含むループを発見しました。forループのエントリ ポイントを検出し (ループcontinue内の 2 つのステートメントを使用して、後でソース コードをチェックして確認しました)、for ループ終了ステートメント (0x4a9854) をループの終わりへの無条件ジャンプ (0x4a9908) に置き換えました。 ) 以下のように:

set write on

set *(unsigned char*)0x4a9854 = 0xeb     Short jump to 0x4a98d4
set *(unsigned char*)0x4a9855 = 0x7e

set *(unsigned char*)0x4a9856 = 0x90     Fill the remaining
set *(unsigned char*)0x4a9857 = 0x90     bytes of the previous
set *(unsigned char*)0x4a9858 = 0x90     instruction with NOPs
set *(unsigned char*)0x4a9859 = 0x90     because why not

set *(unsigned char*)0x4a98d4 = 0xeb     Short jump to 0x4a9908
set *(unsigned char*)0x4a98d5 = 0x32

(これは私が暗記できる唯一のオペコードであり、眠すぎて残りをグーグルで調べることができないため、より長い範囲をジャンプするために2回の短いジャンプを行います)

この時点以降、DOSBox は、エミュレートされるバイナリの名前である をfilename_000.png常にオーバーライドします。filename

于 2015-08-20T20:36:43.143 に答える