2

ラップトップのビデオ ディスプレイに送信された画像を処理する必要があり、C++ またはシェル プログラムを使用してキーボード入力を Linux システムに送信する必要があります。

私の目標は、FPS ゲームの一部である画像を処理し、これらの画像に基づいてそのゲーム内でアクション (したがってキーボード入力) を行うことです。何らかの API を使用して、ゲーム X または Y にインターフェイスする方法を (可能であれば) 理解しようとする代わりに、Linux の入力と出力を何らかの方法でハイジャックして、これがゲームにインターフェイスする最も簡単な方法であると考えました。

カーネルやデバイスドライバーのハッキングなしでこれを行う方法はありますか? 以前、recordmydesktop を使用してデスクトップをビデオとして記録しましたが、そのコードをハッキングして、そこから何かをリバース エンジニアリングしようとすることができると思います。他のアイデアはありますか?私はUbuntu 11を使用しています。

関連する質問

4

3 に答える 3

5

これを行うために、カーネルやデバイス ドライバーのような低レベルの操作を行う必要はありません。

たとえば、 XTest X11拡張機能を使用して、入力イベントをプログラムで偽造できます(この投稿から、キーボードの別の例があります)。

#include <X11/extensions/XTest.h>  
#include <unistd.h>  

int main ()  
{  
  Display *dpy = NULL;  
  XEvent event;  

  dpy = XOpenDisplay (NULL);  

  /* Get the current pointer position */  
  XQueryPointer (dpy, RootWindow (dpy, 0),  
        &event.xbutton.root, &event.xbutton.window,  
        &event.xbutton.x_root, &event.xbutton.y_root,  
        &event.xbutton.x, &event.xbutton.y,  
        &event.xbutton.state);  

  /* Fake the pointer movement to new relative position */  
  XTestFakeMotionEvent (dpy, 0, event.xbutton.x + 100,  
        event.xbutton.y + 50, CurrentTime);  
  XSync(dpy, 0);  
  XCloseDisplay (dpy);  
  return 0;  
}   

画像をキャプチャする最も簡単な方法は、( を介して)関数の挿入LD_PRELOADを使用して への呼び出しを「インターセプト」glXSwapBuffersすることです。これは、各フレームが描画されるたびに呼び出されます。そこから、フレームバッファの内容をコピーして、必要な操作を実行できglReadPixelsます。

たとえば、OpenGL フレームをインターセプトするためのテストされていないアウトライン:

// Function pointer to the *real* glXSwapBuffers
static void (*glx_fptr)(Display*, GLXDrawable) = NULL;

// Make sure init gets called when the shared object is loaded. GCC specific.
static void init(void)  __attribute__((constructor));

static void init(void) {
    dlerror();
    // find the real glXSwapBuffers
    glx_fptr = dlsym(RTLD_NEXT, "glXSwapBuffers");
    if (NULL == glx_fptr)
        fprintf(stderr, "[glvidcap] %s\n", dlerror());
}

void glXSwapBuffers(Display *dpy, GLXDrawable drawable) {
    unsigned int w = 0;
    unsigned int h = 0;
    static int x,y;
    static Window win;
    static unsigned int border,depth;
    // Find the window size. (You could skip this and make it all static if you
    // Trust the window not to change size
    XGetGeometry(dpy, drawable, &win, &x, &y, &w, &h, &border, &depth);

    // Assuming frame is some memory you want the frame dumped to:
    glReadPixels(0,0,w,h,GL_BGR,GL_UNSIGNED_BYTE, frame);

    // Call the real function:
    assert(glx_fptr);
    glx_fptr(dpy, drawable);
}

次に、これを共有オブジェクトとしてコンパイルし、LD_PRELOAD見ているゲームを実行する前にその共有オブジェクトをコンパイルします。

代わりに SDL アプリケーションである場合は、必要に応じてSDL_Flipまたはの呼び出しをインターセプトできSDL_UpdateRectます。

于 2011-08-28T14:40:51.473 に答える
1

Thanks to @awoodland's answer, I looked for related resources, and found this

http://bzr.sesse.net/glcapture/glcapture.c

I compile this code as

gcc -shared -fPIC -o glcapture.so glcapture.c -ldl

and load it for FPS game Urban Terror in a script as

LD_PRELOAD=`pwd`/glcapture.so [DIR]/UrbanTerror/ioUrbanTerror.i386

The moment this script is ran, the game is loaded. For some reason, the game graphics do not show, but I can improve that later. When I exit the game, I see gettimeofday messages printed on the console, which tells me the hook worked. I'll provide more details as I continue to work this code.

For sending key presses, I followed the link

http://bharathisubramanian.wordpress.com/2010/03/14/x11-fake-key-event-generation-using-xtest-ext/

After I installed the necessary package on Ubuntu with

sudo apt-get install libxtst-dev

Then fakeKey.c compiled and worked without problems.

Note: I started a project on Github for this, anyone is welcome to fork, help, etc.

于 2011-08-28T19:46:38.637 に答える
0

私は最終的に解決策を持っています。UrT は OpenGL を独自にロードするため、ウォールハックなどは不可能だと思います。残りの最良のオプションは、X 枚のスクリーンショットを撮ることです。これは、Python のようなスクリプト言語からでも非常に高速に機能しました。次のコードは、一連のスクリーンショットを取得し、OpenCV を介してアニメーションとして表示します。もちろん、UrT を最小化モードで起動する必要があります。残りの詳細は私のプロジェクトにあります。

import gtk.gdk
import PIL
from opencv.cv import *
from opencv.highgui import *
from opencv.adaptors import PIL2Ipl

w = gtk.gdk.get_default_root_window()
sz = w.get_size()
print "The size of the window is %d x %d" % sz

size_x = 600
size_y = 400
start_x = 0
start_y = 100
end_x = start_x+size_x
end_y = start_y+size_y
box = (start_x, start_y, start_x+size_x, start_y+size_y)

while True:
    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
    pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
    width,height = pb.get_width(),pb.get_height()
    im = PIL.Image.fromstring("RGB",(width,height),pb.get_pixels())
    im = im.crop(box)
    cv_img = PIL2Ipl(im)
    cvNamedWindow("fps")
    cvShowImage("fps", cv_img)
    cvWaitKey(30) 

また、ゲームにキーを送信するために、上記の方法が機能せず、フォワード ウォーク キーを UrT に送信するためにxdotoolを使用する必要がありました。

xdotool search --name ioUrbanTerror  windowactivate keydown W
于 2011-10-11T12:58:13.927 に答える