Skip to content

Instantly share code, notes, and snippets.

@iamgreaser
Created June 26, 2014 05:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamgreaser/d22314847781681524b5 to your computer and use it in GitHub Desktop.
Save iamgreaser/d22314847781681524b5 to your computer and use it in GitHub Desktop.
Indie Quilt Hacked Framebuffer API
The other framebuffer API is deprecated. Use this one instead. It's way better.
Firstly, here's iqhack.h:
--------
#define IQHACK_BUTTON_W 0x01
#define IQHACK_BUTTON_S 0x02
#define IQHACK_BUTTON_A 0x04
#define IQHACK_BUTTON_D 0x08
#define IQHACK_BUTTON_SPACE 0x10
typedef struct iqhack_bstate
{
int buttons; // bit mask of IQHACK_BUTTON_* values
int mousex;
int mousey;
int mouseb; // bit mask of currently-down buttons (in order: left, mid, right)
} iqhack_bstate_t;
typedef struct iqhack_screen
{
int w, h;
char data[];
} iqhack_screen_t;
--------
data[] is a 32bpp raw B,G,R,A image going from left to right, top to bottom. int is 32 bits wide.
It's crucial that you have these declarations:
--------
#define DLLEXPORT __declspec(dllexport)
DLLEXPORT volatile iqhack_bstate_t iqhack_bstate;
DLLEXPORT volatile iqhack_screen_t *iqhack_screen = NULL;
--------
It's *also* crucial that you set up your screen with its width and height BEFORE you set the iqhack_screen pointer to prevent a race condition. Sample code:
--------
iqhack_screen_t *volatile iqs = malloc(sizeof(iqhack_screen_t) + 4*iq_width*iq_height);
iqs->w = iq_width;
iqs->h = iq_height;
iqhack_screen = iqs;
--------
You are allowed to read the button state and write to the screen at any time.
If you don't like tearing, stop being such a spoilt brat and harden up. (Or alternatively, make a simple proposal on how to prevent tearing.)
Now, this is activated if the "-iqfbhack" argument follows immediately AFTER the "-indiequilt diff width height" arguments.
OK, so that's pretty much how to do it from the game side.
========
How to do it from the not-game side:
- CreateProcess() with the "-indiequilt diff width height -iqfbhack" arguments.
- Do LoadLibraryEx() on the executable so we can get an HMODULE.
- Use GetProcAddress() to get the locations of iqhack_bstate and iqhack_screen.
- Use CreateRemoteThread() on the process HANDLE (obtained by CreateProcess) to call GetModuleHandle(NULL) - this is the second HMODULE.
- Use GetExitCodeThread() to get the return code of the thread made with GetRemoteThread.
- Use the two HMODULES, take the second minus the first, and add that to the iqhack_bstate and iqhack_screen pointers.
- Use WriteProcessMemory() to write the input states.
- Use ReadProcessMemory() to read the screen buffer pointer, then if not NULL, the screen width and height, and then the actual screen data, and shove it onto the actual screen somehow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment