我有一个项目,我正在尝试' 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,然后清除捕获文件夹,并拍摄另一个屏幕截图。什么是更好的选择?
(PS:上面的代码是简化的;通常我将捕获的图像复制到多个图像; img0.png和img1.png,这样当一个被写入时,另一个可以被读取,就像页面翻转一样。无论如何。)
答案 0 :(得分:0)
我通过直接篡改编译的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
设置硬件访问观察点后,我run
gdb
中的程序{可能需要多个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
(我跳了两个短跳,跳过更远的范围,因为这是我唯一能记住的操作码,我对其余的谷歌太困了)
在此之后,DOSBox始终覆盖filename_000.png
,filename
是要模拟的二进制文件的名称。