DOSBox 屏幕捕获到特定文件

DOSBox screen capture to specific file

我有一个项目,我正在尝试 'stream' DOS 游戏,在 Ubuntu 上的 DOSBox 中工作。这个想法是截取屏幕截图,然后将它们上传到服务器。要从 DOSBox 截取屏幕截图,我使用 xdotool 触发组合键 "Ctrl+F5",这会触发屏幕捕获。然后屏幕截图保存到 /capture 文件夹中,我可以从中读取文件。

问题是屏幕截图被命名为 progName_000.png、progName_001.png,...我希望覆盖单个文件。有没有可能实现?

目前我正在使用下面可怕的 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,然后清除捕获文件夹,然后再截取一张屏幕截图。什么是更好的选择?

(P.S:上面的代码是简化了的,一般我都是把抓拍的图片复制到一张以上的;img0.png和img1.png,这样while一个正在写,另一个可以读,就像翻页一样。反正。)

我通过直接篡改编译后的 DOSBox 二进制文件找到了解决方案。我本可以编辑源代码并简单地构建项目,但这样做的乐趣在哪里?

二进制文件在/usr/bin/dosbox中。我以 root 身份在终端中打开 gdb 并写入

gdb -write -silent /usr/bin/dosbox

这是我的 DOSBox 0.74 二进制文件的解决方案,为 Ubuntu 14.04 编译。

首先,截图文件名包含一个3位数字,如'whatevs_000.png'。文件名很可能是使用 sprintf 函数调用构造为字符串,使用包含 %3d%03d 的格式字符串。使用 objdump -s /usr/bin/dosbox | grep "\%03" 的幸运搜索显示字符串 "%s%c%s%03d%s" 确实存储在 0x5fa9c7.

在使用 awatch *0x5fa9c7 设置硬件访问观察点后,我 rungdb 中嵌入了程序(可能需要几个 continue)。 DOSBox 启动后,我使用 Ctrl+F5 截屏并将程序捕获到 sprintf 函数中的指令处。几个up之后,我进入了主程序流程(地址0x4a9949)。 disass向上,我发现了一个 for 循环,它有标准库调用来实现目录列表。我检测了循环的入口点(在循环中使用了两条continue语句,后面通过查看源码验证),将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

(我跳了两次短距离以跳越更长的距离,因为这是我唯一能记住的操作码,我太困了 Google 剩下的)

在这一点之后,DOSBox 始终覆盖 filename_000.pngfilename 是被模拟的二进制文件的名称。