PixelProtocol 3 is a simple binary protocol for defining what is being sent between a GUI client and a game engine.
It's for implementing games where old-school looking pixel art can be appreciated.
- 256 indexed colors.
- A resolution of 320x200 pixels is recommended.
- Should be possible to implement both in 16-bit assembly for DOS and in a modern browser.
- Aiming to be WebSocket-friendly.
- Pixels are not sent over the network, only commands for drawing them.
- It should be possible to create a DosBox server for serving games over this protocol.
- It should be possible to create a mobile client for playing games over this protocol.
- The music is extremely simple 4-track MIDI.
Protocol Header
Name |
Type |
Description |
ver |
uint16 |
protocol version |
width |
uint16 |
width |
height |
uint16 |
height |
commands |
[]uint16 |
list of commands (uint8 cmd + uint8 argument) |
The commands can be streamed.
Cmd |
Name |
uint8 argument |
Description |
0x00 |
palsel |
color index, 0..255 |
choose palette color, prepare for filling the palette |
0x01 |
setred |
red value, 0..255 |
set red value of chosen palette color |
0x02 |
setgreen |
set green value of chosen palette color |
set blue value of chosen palette color |
0x03 |
setblue |
set blue value of chosen palette color |
set green value of chosen palette color |
Cmd |
Name |
uint8 argument |
Description |
0x04 |
setcol |
pixel color from palette, 0..255 |
set the active color |
Cmd |
Name |
uint16 argument |
Description |
0x05 |
setx |
x position, 0..65535 |
set active x position |
0x06 |
sety |
y position, 0..65535 |
set active y position |
Cmd |
Name |
uint8 argument |
Description |
0x07 |
plot |
n pixels |
plot one or more pixels from (x,y) |
Cmd |
Name |
uint8 argument |
Description |
0x08 |
clear |
fill color from palette, 0..255 |
clear everything with the selected color |
0x09 |
rfill |
fill color from palette, 0..255 |
draw linewise until nonzero color or end, for filling the pixel buffer |
0x0a |
lfill |
fill color from palette, 0..255 |
draw backwards linewise until nonzero color or end, for filling the pixel buffer |
Cmd |
Name |
no argument |
Description |
0x0b |
flip |
|
update all pixels |
0x0c |
spriteflip |
|
update pixels where sprites have been drawn since last time this command was executed |
Cmd |
Name |
uint8 argument |
Description |
0x0d |
setlcs |
color for start of line |
prepare to draw a line |
0x0e |
setlce |
color for end of line |
prepare to draw a line |
- colors are interpolated linearly, component-wise (r, g, b, a)
Cmd |
Name |
uint16 argument |
Description |
0x11 |
lisx |
x coordinate for start of line |
prepare to draw a line |
0x12 |
lisy |
y coordinate for start of line |
prepare to draw a line |
0x13 |
liex |
x coordinate for end of line |
prepare to draw a line |
0x14 |
liey |
y coordinate for end of line |
prepare to draw a line |
Cmd |
Name |
no argument |
Description |
0x15 |
ldraw |
|
draw the line |
Cmd |
Name |
uint8 argument |
Description |
0x1a |
setcp0 |
set color for p0 |
prepare to draw a triangle |
0x1b |
setcp1 |
set color for p1 |
prepare to draw a triangle |
0x1c |
setcp2 |
set color for p2 |
prepare to draw a triangle |
Cmd |
Name |
uint16 argument |
Description |
0x1d |
setxp0 |
x coordinate for p0 |
prepare to draw a triangle |
0x1e |
setyp0 |
y coordinate for p0 |
prepare to draw a triangle |
0x1f |
setxp1 |
x coordinate for p1 |
prepare to draw a triangle |
0x20 |
setyp1 |
y coordinate for p1 |
prepare to draw a triangle |
0x21 |
setxp2 |
x coordinate for p2 |
prepare to draw a triangle |
0x22 |
setyp2 |
y coordinate for p2 |
prepare to draw a triangle |
Cmd |
Name |
uint8 argument |
Description |
0x23 |
tdraw |
0 for empty, 1 for filled |
draw a filled or empty triangle |
Cmd |
Name |
uint8 argument |
Description |
0x30 |
spid |
sprite ID |
select a sprite ID to work with |
0x31 |
spw |
sprite width |
set sprite width |
0x32 |
sph |
sprite height |
set sprite height |
0x33 |
spclr |
color |
clear contents with the given color |
0x34 |
spush |
amount of pixels |
add N pixels of the active color |
0x35 |
spt |
amount of pixels |
add N transparent pixels |
0x36 |
sprot |
value from 0..255, used as float from 0..2*PI |
rotate the current sprite |
0x37 |
spscale |
value from 0..255, used as float from -20..20 |
scale the current sprite |
0x38 |
spcopy |
sprite ID |
copy to another sprite ID |
Cmd |
Name |
uint16 argument |
Description |
0x39 |
spx |
x coordinate |
set x coordinate for where to draw the sprite |
0x3a |
spy |
y coordinate |
set y coordinate for where to draw the sprite |
Cmd |
Name |
uint8 argument |
Description |
0x3b |
blit |
number of sprites to draw |
draw n instances of this sprite, following the pixel buffer direction |
0x3c |
blitinc |
number of sprites to draw |
like blit , but increases the sprite ID at every step |
- The "pixel buffer direction" is from left to right, then starting on the next y coordinate (+ sprite height) when reaching the end of the line.
- Several sprites can be placed in a row with the
blit
command. They are placed next to each other, without overlapping.
- For the
blitinc
command, increasing the value from 255 wraps around and sets to current sprite ID to 0.
- Sprites can have a resolution up to
128*128
(inclusive).
Cmd |
Name |
uint8 argument |
Description |
0x40 |
con0 |
value from 0..255, used as float from -20..20 |
set convolution filter value 0 |
0x41 |
con1 |
value from 0..255, used as float from -20..20 |
set convolution filter value 1 |
0x42 |
con2 |
value from 0..255, used as float from -20..20 |
set convolution filter value 2 |
0x43 |
con3 |
value from 0..255, used as float from -20..20 |
set convolution filter value 3 |
0x44 |
con4 |
value from 0..255, used as float from -20..20 |
set convolution filter value 4 |
0x45 |
con5 |
value from 0..255, used as float from -20..20 |
set convolution filter value 5 |
0x46 |
con6 |
value from 0..255, used as float from -20..20 |
set convolution filter value 6 |
0x47 |
con7 |
value from 0..255, used as float from -20..20 |
set convolution filter value 7 |
0x48 |
con8 |
value from 0..255, used as float from -20..20 |
set convolution filter value 8 |
0x49 |
condiv |
convolution division, 0..255, used as float from -20..20 |
set convolution division value |
0x4a |
apply |
|
apply convolution filter to all pixels |
0x4b |
consp |
|
apply convolution filter to the current sprite |
The convolution filter parameters 0..255 are treated as if they were floats between -20 and 20 (inclusive).
Example filters:
- blur is 0,1,0,1,1,1,0,1,0 div 5
- flame is 0,1,0,1,1,1,0,0,0 div 4
Cmd |
Name |
uint8 argument |
Description |
0x50 |
radd |
utf-8 byte |
add a byte to the current UTF-8 rune |
Cmd |
Name |
no argument |
Description |
0x51 |
rclear |
|
clear the current UTF-8 rune |
0x52 |
rsprite |
|
fill the current sprite with the current rune |
At a minimum, these glyphs must exist:
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,._:;"'[]{}()-\/|*#@?!☃
Implementations should supply at least a font that works at 8x8 character size.
The snowman is useful for identifying if the protocol can correctly support at least one non-ASCII character.
Use an ø
if no glyph is available for an UTF-8 rune.
Keyboard, Joystick and Mouse
For returning the state of the client.
A channel must be set up for receiving theuint16
values that are returned by these functions.
Commands that return an uint16
:
Cmd |
Name |
no argument |
Description |
0x60 |
kesc |
|
is Escape being pressed? |
0x61 |
kup |
|
is W, up or joystick up pressed? args: 0 for any, 1..4 for Player 1..4 |
0x62 |
kleft |
|
is A, left or joystick left pressed? args: 0..5 |
0x63 |
kdown |
|
is S, down or joystick down pressed? args: 0..5 |
0x64 |
kright |
|
is D, right or joystick right pressed? args: 0..5 |
0x65 |
ka |
|
is Return, comma (,) or joystick A button pressed? args: 0..5 |
0x66 |
kb |
|
is Space, dot (.) or joystick B button pressed? args: 0..5 |
- P1 means Player 1, P2 means Player 2.
- Player 1 has WASD keys, lshift, lctrl and/or Joystick 1.
- Player 2 has the arrow keys, comma (,), dot (.) and/or Joystick 2.
- Player 3 has the numpad arrows and/or Joystick 3.
- Player 4 has Joystick 4.
Cmd |
Name |
uint8 argument |
Description |
0x67 |
kshift |
0 for left, 1 for right, 2 for any |
returns 1 if Shift is held down |
0x68 |
kalt |
0 for left, 1 for right, 2 for any |
returns 1 if Alt is held down |
0x69 |
kctrl |
0 for left, 1 for right, 2 for any |
returns 1 if Ctrl is held down |
0x6a |
ksuper |
0 for left, 1 for right, 2 for any |
returns 1 if Super is held down |
Cmd |
Name |
no argument |
Description |
0x6b |
kget |
|
returns 0 if keybuffer is empty, keycode of first in keybuffer if not empty |
Cmd |
Name |
no argument |
Description |
0x6c |
mx |
|
get mouse x coordinate |
0x6d |
my |
|
get mouse y coordinate |
0x6e |
mbtn |
|
get mouse buttons, returns: 0 for none, 1 for left, 2 for right and 3 for middle |
Cmd |
Name |
uint8 argument |
Description |
0x6f |
jbtn |
joystick button ID |
check if joystick button is pressed, returns 1 for pressed |
Cmd |
Name |
uint8 argument |
Description |
0x70 |
t0prog |
MIDI program |
select a MIDI program for track 0 (there are 4 tracks) |
0x71 |
t1prog |
MIDI program |
select a MIDI program for track 1 (there are 4 tracks) |
0x72 |
t2prog |
MIDI program |
select a MIDI program for track 2 (there are 4 tracks) |
0x73 |
t3prog |
MIDI program |
select a MIDI program for track 3 (there are 4 tracks) |
Cmd |
Name |
uint8 argument |
Description |
0x80 |
t0note |
MIDI note |
play the MIDI note for track 0 for 20 ms, where note 00 is C3, 01 is D3, 02 is D3 etc (A4 is 432 Hz) |
0x81 |
t1note |
MIDI note |
play the MIDI note for track 1 for 20 ms, where note 00 is C3, 01 is D3, 02 is D3 etc (A4 is 432 Hz) |
0x82 |
t2note |
MIDI note |
play the MIDI note for track 1 for 20 ms, where note 00 is C3, 01 is D3, 02 is D3 etc (A4 is 432 Hz) |
0x83 |
t3note |
MIDI note |
play the MIDI note for track 1 for 20 ms, where note 00 is C3, 01 is D3, 02 is D3 etc (A4 is 432 Hz) |
Cmd |
Name |
no argument |
Description |
0xff |
exit |
|
end the program, disconnect |
0x90 |
esc |
|
exit if Escape has been pressed |
All state values are expected to be zeroed at the start of the program.
Description |
Type |
r, g, b, a * 256 palette info |
4 * 256 * uint8 |
x position for pixel |
uint16 |
y position for pixel |
uint16 |
color index for pixel |
uint16 |
x1 position for line |
uint16 |
y1 position for line |
uint16 |
x2 position for line |
uint16 |
y2 position for line |
uint16 |
c1 color for line start |
uint8 |
c2 color for line end |
uint8 |
x1 position for triangle |
uint16 |
y1 position for triangle |
uint16 |
x2 position for triangle |
uint16 |
y2 position for triangle |
uint16 |
x3 position for triangle |
uint16 |
y3 position for triangle |
uint16 |
c1 color for triangle point 1 |
uint8 |
c2 color for triangle point 2 |
uint8 |
c3 color for triangle point 3 |
uint8 |
convolution filter + division, 10 bytes |
10 * uint8 |
sprites |
128 * 128 * uint8 |
current sprite ID |
uint8 |
If you implement something using this protocol, please let me know. :)
- Version: 3.0.0
- Author: Alexander F. Rødseth
- License: CC0
- GitHub Project