Skip to content

Instantly share code, notes, and snippets.

@iamgreaser
Last active August 29, 2015 14:02
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/29b49aba794a2d6e5491 to your computer and use it in GitHub Desktop.
Save iamgreaser/29b49aba794a2d6e5491 to your computer and use it in GitHub Desktop.
Indie Quilt non-Unity Framebuffer API
Version 1ba (1 didn't provision for input, 1a didn't provision for mouse, 1b didn't actually note what direction the image went in)
For games that use some form of framebuffer, it should be possible to send extended data.
This will be denoted by the -iqframebuffer argument which follows *directly after* all the -indiequilt parameters.
Applications which support this mode will initially print the following string EXACTLY:
printf("IQFRAMEBUFFER1\n\n");
And if I'm not mistaken, from the little C++ I know this is probably how you do it in C++:
std::cout << "IQFRAMEBUFFER1" << std::endl << std::endl;
The double-newline is to detect what line endings are used.
There are 5 supported formats:
- 8bpp (1 byte per pixel)
- 15bpp (2 bytes per pixel)
- 16bpp (2 bytes per pixel)
- 24bpp (3 bytes per pixel)
- 32bpp (4 bytes per pixel)
Alpha information will be ignored.
If you want anything smaller than 8bpp, say a 4bpp framebuffer, you will have to just suck it up and convert it to 8bpp.
All framebuffer formats here are chunky. If you use a planar format, you'll have to convert it to chunky first.
Framebuffer data is encoded in a form that packs 3 bytes into 4. This means that data will be padded to a 3-input-byte/4-output-byte boundary.
Python pseudocode:
v = ord(instr[3*i]) + (ord(instr[3*i+1])<<8) + (ord(instr[3*i+2])<<16)
outstr += chr(((v>>0)&63)+33) + chr(((v>>6)&63)+33) + chr(((v>>12)&63)+33) + chr(((v>>18)&63)+33)
Each packet of framebuffer data will be terminated with a newline.
Framebuffers have the following (encoded) header in a little-endian format:
uint16_t w, h;
uint8_t format;
uint8_t reserved; // must be 0
format is one of the following values:
- 0:*8bpp R, G, B (Allegro 4 8bpp)
- 1: 16bpp LE RGB (SDL 16bpp)
- 2: 24bpp R, G, B
- 3: 32bpp R, G, B, X (OpenGL 32bpp?)
- 4:*8bpp B, G, R (SDL 8bpp?)
- 5: 16bpp LE BGR
- 6: 24bpp B, G, R
- 7: 32bpp B, G, R, X (SDL 32bpp)
- 8: 15bpp LE XRGB
- 9: 15bpp LE RGBX
-10: 15bpp LE XBGR
-11: 15bpp LE BGRX
-12: 32bpp X, R, G, B
-13: 32bpp X, B, G, R
-14: 16bpp BE RGB
-15: 16bpp BE BGR
Other values are reserved and technically invalid.
For 8bpp framebuffers (those marked with *), a 256-entry 24bpp palette follows:
uint8_t pal[256][3];
As alpha information is stripped, there's no reason to have a 32bpp palette.
Yes, greyscale stuff has to have the palette.
Then w*h*bytes_per_pixel follows in a little-endian format. It is then padded with enough bytes for the encoding to work, then terminated with a newline.
Image data is sent left-to-right, then top-to-bottom.
bytes_per_pixel is of course 1 for 8bpp modes, 2 for 15bpp or 16bpp modes, 3 for 24bpp modes, and 4 for 32bpp modes.
--------
Input is handled with packets sent from Indie Quilt encoded like above, terminated with newlines:
uint16_t keysym; // this follows the VK_* constants from here: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
uint32_t unicode; // top bit of this is a key RELEASE
int16_t mouse_x;
int16_t mouse_y;
int8_t mouse_scroll;
uint8_t mouse_button_mask;
If the top bit of "unicode" is set, this is a key release, otherwise it's a key press.
If there is no key, both keysym and unicode will be 0.
--------
It is entirely up to the implementor to accept whatever valid framebuffer packets are sent, to convert them correctly, to upscale them appropriately (retaining a square aspect ratio), and to drop frames where necessary.
I'll be covering the acceptance, conversion, and frame dropping steps. The upscaling step from there onwards should be straightforward.
@iamgreaser
Copy link
Author

This sloppy standard has been superceded by something faster, less fiddly, and more likely to anger your antivirus.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment