2

我有一个项目,我正在尝试“流式传输”一个 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,然后清除捕获文件夹,然后再进行一次屏幕截图。什么是更好的选择?

(PS:上面的代码是简化的;通常我将捕获的图像复制到多个图像;img0.png 和 img1.png,以便在写入时可以读取另一个,就像翻页一样。无论如何。 )

4

1 回答 1

1

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

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

gdb -write -silent /usr/bin/dosbox

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

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

使用 设置硬件访问观察点后awatch *0x5fa9c7,我run将程序嵌入其中(可能需要gdb几个s)。continueDOSBox 启动后,我使用 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

(我做了两次短跳以跳过更长的范围,因为这是我能记住的唯一操作码,我太困了,无法谷歌其余部分)

此后,DOSBox 总是覆盖filename_000.pngfilename即被模拟的二进制文件的名称。

于 2015-08-20T20:36:43.143 回答