Learn code by playing games like Warcraft 1,2,3 and World of Warcraft 😁.
Also a bit of 10 Second Ninja.
You will need python, and those module for Window:
pip install pyperclip psutil pygetwindow websockets pywin32 PyAutoGUI pynput
Envie de vous essayer à l'atelier ?
Discord: https://discord.gg/xytnYKRpzA
Dans le cadre d'un atelier Example Scratch : https://scratch.mit.edu/projects/1061213031/ https://scratch.mit.edu/projects/1018462085 Tamper Monkey code: https://github.com/EloiStree/2024_08_29_ScratchToWarcraft/blob/main/PythonBridge/ScratchVarToLocalWebsocket.js
- Version C# UDP: https://github.com/EloiStree/2024_10_23_WowIntegerWorkshopCSharp
- Version Unity3D UDP: https://github.com/EloiStree/2024_11_16_WowIntegerWorkshopUnity3D
- Version Pico W: https://github.com/EloiStree/2024_11_16_WowIntWorkshopPicoW
- Version Python: https://github.com/EloiStree/2024_06_12_WowIntegerWorkshopPython
- Version Godot: https://github.com/EloiStree/2025_11_11_WowIntegerWorkshopGodotScript
Opera GX:

https://www.opera.com/fr/gx
Tamper Monkey:

https://www.tampermonkey.net/
Installer Python:

https://www.python.org/
Installer les modules:
pip install pyperclip psutil pygetwindow websockets pywin32

Example of code in C# for Visual Studio:

https://github.com/EloiStree/2025_02_05_WarcraftClientQA
- No code to Moving with C# https://youtu.be/qxmC8YoRqHY?t=16421
- Move with Trigono https://youtu.be/QKGy2C7bsUI?t=7
Source: https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
| Key | Decimal | Hexadecimal | Press | Release |
|---|---|---|---|---|
| Release All | 0 | 0x00 | 1000 | 2000 |
| Clear Timed Command | 256 | 0xFF | 1256 | 2256 |
| Backspace | 8 | 0x08 | 1008 | 2008 |
| Tab | 9 | 0x09 | 1009 | 2009 |
| Clear | 12 | 0x0C | 1012 | 2012 |
| Enter | 13 | 0x0D | 1013 | 2013 |
| Shift | 16 | 0x10 | 1016 | 2016 |
| Ctrl | 17 | 0x11 | 1017 | 2017 |
| Alt | 18 | 0x12 | 1018 | 2018 |
| Pause | 19 | 0x13 | 1019 | 2019 |
| CapsLock | 20 | 0x14 | 1020 | 2020 |
| Esc | 27 | 0x1B | 1027 | 2027 |
| Escape | 27 | 0x1B | 1027 | 2027 |
| Space | 32 | 0x20 | 1032 | 2032 |
| PageUp | 33 | 0x21 | 1033 | 2033 |
| PageDown | 34 | 0x22 | 1034 | 2034 |
| End | 35 | 0x23 | 1035 | 2035 |
| Home | 36 | 0x24 | 1036 | 2036 |
| LeftArrow | 37 | 0x25 | 1037 | 2037 |
| Left | 37 | 0x25 | 1037 | 2037 |
| UpArrow | 38 | 0x26 | 1038 | 2038 |
| Up | 38 | 0x26 | 1038 | 2038 |
| RightArrow | 39 | 0x27 | 1039 | 2039 |
| Right | 39 | 0x27 | 1039 | 2039 |
| DownArrow | 40 | 0x28 | 1040 | 2040 |
| Down | 40 | 0x28 | 1040 | 2040 |
| Select | 41 | 0x29 | 1041 | 2041 |
| 42 | 0x2A | 1042 | 2042 | |
| Execute | 43 | 0x2B | 1043 | 2043 |
| PrintScreen | 44 | 0x2C | 1044 | 2044 |
| Insert | 45 | 0x2D | 1045 | 2045 |
| Delete | 46 | 0x2E | 1046 | 2046 |
| 0 | 48 | 0x30 | 1048 | 2048 |
| 1 | 49 | 0x31 | 1049 | 2049 |
| 2 | 50 | 0x32 | 1050 | 2050 |
| 3 | 51 | 0x33 | 1051 | 2051 |
| 4 | 52 | 0x34 | 1052 | 2052 |
| 5 | 53 | 0x35 | 1053 | 2053 |
| 6 | 54 | 0x36 | 1054 | 2054 |
| 7 | 55 | 0x37 | 1055 | 2055 |
| 8 | 56 | 0x38 | 1056 | 2056 |
| 9 | 57 | 0x39 | 1057 | 2057 |
| A | 65 | 0x41 | 1065 | 2065 |
| B | 66 | 0x42 | 1066 | 2066 |
| C | 67 | 0x43 | 1067 | 2067 |
| D | 68 | 0x44 | 1068 | 2068 |
| E | 69 | 0x45 | 1069 | 2069 |
| F | 70 | 0x46 | 1070 | 2070 |
| G | 71 | 0x47 | 1071 | 2071 |
| H | 72 | 0x48 | 1072 | 2072 |
| I | 73 | 0x49 | 1073 | 2073 |
| J | 74 | 0x4A | 1074 | 2074 |
| K | 75 | 0x4B | 1075 | 2075 |
| L | 76 | 0x4C | 1076 | 2076 |
| M | 77 | 0x4D | 1077 | 2077 |
| N | 78 | 0x4E | 1078 | 2078 |
| O | 79 | 0x4F | 1079 | 2079 |
| P | 80 | 0x50 | 1080 | 2080 |
| Q | 81 | 0x51 | 1081 | 2081 |
| R | 82 | 0x52 | 1082 | 2082 |
| S | 83 | 0x53 | 1083 | 2083 |
| T | 84 | 0x54 | 1084 | 2084 |
| U | 85 | 0x55 | 1085 | 2085 |
| V | 86 | 0x56 | 1086 | 2086 |
| W | 87 | 0x57 | 1087 | 2087 |
| X | 88 | 0x58 | 1088 | 2088 |
| Y | 89 | 0x59 | 1089 | 2089 |
| Z | 90 | 0x5A | 1090 | 2090 |
| LeftWindows | 91 | 0x5B | 1091 | 2091 |
| RightWindows | 92 | 0x5C | 1092 | 2092 |
| Applications | 93 | 0x5D | 1093 | 2093 |
| Sleep | 95 | 0x5F | 1095 | 2095 |
| Numpad0 | 96 | 0x60 | 1096 | 2096 |
| Numpad1 | 97 | 0x61 | 1097 | 2097 |
| Numpad2 | 98 | 0x62 | 1098 | 2098 |
| Numpad3 | 99 | 0x63 | 1099 | 2099 |
| Numpad4 | 100 | 0x64 | 1100 | 2100 |
| Numpad5 | 101 | 0x65 | 1101 | 2101 |
| Numpad6 | 102 | 0x66 | 1102 | 2102 |
| Numpad7 | 103 | 0x67 | 1103 | 2103 |
| Numpad8 | 104 | 0x68 | 1104 | 2104 |
| Numpad9 | 105 | 0x69 | 1105 | 2105 |
| Multiply | 106 | 0x6A | 1106 | 2106 |
| Add | 107 | 0x6B | 1107 | 2107 |
| Separator | 108 | 0x6C | 1108 | 2108 |
| Subtract | 109 | 0x6D | 1109 | 2109 |
| Decimal | 110 | 0x6E | 1110 | 2110 |
| Divide | 111 | 0x6F | 1111 | 2111 |
| F1 | 112 | 0x70 | 1112 | 2112 |
| F2 | 113 | 0x71 | 1113 | 2113 |
| F3 | 114 | 0x72 | 1114 | 2114 |
| F4 | 115 | 0x73 | 1115 | 2115 |
| F5 | 116 | 0x74 | 1116 | 2116 |
| F6 | 117 | 0x75 | 1117 | 2117 |
| F7 | 118 | 0x76 | 1118 | 2118 |
| F8 | 119 | 0x77 | 1119 | 2119 |
| F9 | 120 | 0x78 | 1120 | 2120 |
| F10 | 121 | 0x79 | 1121 | 2121 |
| F11 | 122 | 0x7A | 1122 | 2122 |
| F12 | 123 | 0x7B | 1123 | 2123 |
| F13 | 124 | 0x7C | 1124 | 2124 |
| F14 | 125 | 0x7D | 1125 | 2125 |
| F15 | 126 | 0x7E | 1126 | 2126 |
| F16 | 127 | 0x7F | 1127 | 2127 |
| F17 | 128 | 0x80 | 1128 | 2128 |
| F18 | 129 | 0x81 | 1129 | 2129 |
| F19 | 130 | 0x82 | 1130 | 2130 |
| F20 | 131 | 0x83 | 1131 | 2131 |
| F21 | 132 | 0x84 | 1132 | 2132 |
| F22 | 133 | 0x85 | 1133 | 2133 |
| F23 | 134 | 0x86 | 1134 | 2134 |
| F24 | 135 | 0x87 | 1135 | 2135 |
| NumLock | 144 | 0x90 | 1144 | 2144 |
| ScrollLock | 145 | 0x91 | 1145 | 2145 |
| LeftShift | 160 | 0xA0 | 1160 | 2160 |
| RightShift | 161 | 0xA1 | 1161 | 2161 |
| LeftControl | 162 | 0xA2 | 1162 | 2162 |
| RightControl | 163 | 0xA3 | 1163 | 2163 |
| LeftAlt | 164 | 0xA4 | 1164 | 2164 |
| RightAlt | 165 | 0xA5 | 1165 | 2165 |
| LeftMenu | 164 | 0xA4 | 1164 | 2164 |
| RightMenu | 165 | 0xA5 | 1165 | 2165 |
| BrowserBack | 166 | 0xA6 | 1166 | 2166 |
| BrowserForward | 167 | 0xA7 | 1167 | 2167 |
| BrowserRefresh | 168 | 0xA8 | 1168 | 2168 |
| BrowserStop | 169 | 0xA9 | 1169 | 2169 |
| BrowserSearch | 170 | 0xAA | 1170 | 2170 |
| BrowserFavorites | 171 | 0xAB | 1171 | 2171 |
| BrowserHome | 172 | 0xAC | 1172 | 2172 |
| VolumeMute | 173 | 0xAD | 1173 | 2173 |
| VolumeDown | 174 | 0xAE | 1174 | 2174 |
| VolumeUp | 175 | 0xAF | 1175 | 2175 |
| MediaNextTrack | 176 | 0xB0 | 1176 | 2176 |
| MediaPreviousTrack | 177 | 0xB1 | 1177 | 2177 |
| MediaStop | 178 | 0xB2 | 1178 | 2178 |
| MediaPlay | 179 | 0xB3 | 1179 | 2179 |
| LaunchMail | 180 | 0xB4 | 1180 | 2180 |
| LaunchMediaSelect | 181 | 0xB5 | 1181 | 2181 |
| LaunchApp1 | 182 | 0xB6 | 1182 | 2182 |
| LaunchApp2 | 183 | 0xB7 | 1183 | 2183 |
| OEM1 | 186 | 0xBA | 1186 | 2186 |
| OEMPlus | 187 | 0xBB | 1187 | 2187 |
| OEMComma | 188 | 0xBC | 1188 | 2188 |
| OEMMinus | 189 | 0xBD | 1189 | 2189 |
| OEMPeriod | 190 | 0xBE | 1190 | 2190 |
| OEM2 | 191 | 0xBF | 1191 | 2191 |
| OEM3 | 192 | 0xC0 | 1192 | 2192 |
| OEM4 | 219 | 0xDB | 1219 | 2219 |
| OEM5 | 220 | 0xDC | 1220 | 2220 |
| OEM6 | 221 | 0xDD | 1221 | 2221 |
| OEM7 | 222 | 0xDE | 1222 | 2222 |
| OEM8 | 223 | 0xDF | 1223 | 2223 |
| OEM102 | 226 | 0xE2 | 1226 | 2226 |
| ProcessKey | 229 | 0xE5 | 1229 | 2229 |
| Packet | 231 | 0xE7 | 1231 | 2231 |
| Attn | 246 | 0xF6 | 1246 | 2246 |
| CrSel | 247 | 0xF7 | 1247 | 2247 |
| ExSel | 248 | 0xF8 | 1248 | 2248 |
| EraseEOF | 249 | 0xF9 | 1249 | 2249 |
| Play | 250 | 0xFA | 1250 | 2250 |
| Zoom | 251 | 0xFB | 1251 | 2251 |
| PA1 | 253 | 0xFD | 1253 | 2253 |
If you want to do some round robin with the Xbox, you need switch the Window Focus.
1260 Set the focus on the window
2260 Set the focus on the OS
If in OS context
1599998888
- 15 Mouse Move in application focus screen
- 14 Mouse Move on OS screen
- 16 Move Relatively to last position
- 9999: percent width screen 0-9999 Left Right
- 8888: percent height screen 0-9999 Down Top
| Label | Press | Release |
|---|---|---|
| Mouse Left | 1260 | 2260 |
| Mouse Middle | 1261 | 2261 |
| Mouse Right | 1262 | 2262 |
| Mouse Button 4 | 1263 | 2263 |
| Mouse Button 5 | 1264 | 2264 |
| Mouse Double Click Left | 1265 | 2265 |
| Mouse Double Click Middle | 1266 | 2266 |
| Mouse Double Click Right | 1267 | 2267 |
| Scroll Up | 1268 | 2268 |
| Scroll Down | 1269 | 2269 |
| Scroll Left | 1270 | 2270 |
| Scroll Right | 1271 | 2271 |
// ########## RECEIVED INTEGER AS BYTES
/// CONVERT FOUR BYTE IN LITTLE ENDIAN FORMAT TO SIGNED INTEGER 32 BITS
// USE: byte bytes[4] = {0xC0, 0x1D, 0xFE, 0xFF}; // Little-endian encoding of -123456
// USE: int32_t result = parseLittleEndian(bytes[0], bytes[1], bytes[2], bytes[3]);
int32_t parseLittleEndian(byte b0, byte b1, byte b2, byte b3) {
// Combine bytes in little-endian order
return ((int32_t)b0) | ((int32_t)b1 << 8) | ((int32_t)b2 << 16) | ((int32_t)b3 << 24);
}
// ########## SEND INTEGER TO BYTES
// CONVERT SIGNE INTEGER INTO FOUR BYTES IN LITTLE ENDIAN
// USE: int32_t value = -123456;
// USE: byte bytes[4];
// USE: intToBytes(value, bytes);
void intToBytes(int32_t value, uint8_t bytes[4]) {
bytes[0] = value & 0xFF; // Extract the lowest 8 bits
bytes[1] = (value >> 8) & 0xFF; // Shift right by 8 bits and extract the next 8 bits
bytes[2] = (value >> 16) & 0xFF; // Shift right by 16 bits and extract the next 8 bits
bytes[3] = (value >> 24) & 0xFF; // Shift right by 24 bits and extract the highest 8 bits
}
import struct
# Pack means to turn into 1 and 0 from value with type
# Unpack means to turn 1 and 0 in value with type
# i means signed integer
# Q means long unsigned value (double of an integer)
# < in little endian order
byte_integer_value = struct.pack("<i", integer)
unpacked_integer = struct.unpack("<i", byte_integer_value)[0]
byte_index_integer_value = struct.pack("<ii", integer1, integer2)
unpacked_integers = struct.unpack("<ii", byte_index_integer_value)
byte_index_integer_date_value = struct.pack("<iiQ", integer1, integer2, date_value)
unpacked_values = struct.unpack("<iiQ", byte_index_integer_date_value)XInput is finite and won't change over time. Therefore, the following code should work for most of my future tools.
Why include XInput code in a Scratch to Warcraft project?
Because:
- This project serves as the landing page for this workshop. 😋
- I plan to support a Warcraft version with split-screen gameplay using four XInput gamepads.
Preferred versions for your code:
1899887766: To manage the left and right joysticks of the gamepad using 4 bytes.1700000000: To manage all the buttons using 4 bytes.
If those aren't feasible, try the following alternative:
🤖 Code generated by GPT without thorough re-testing at this stage.
You can find the original code here: GitHub Repository
| Short Description | Integer to Press | Integer to Release |
|---|---|---|
| Random input for all gamepads, no menu | 1399 | 2399 |
| Enable hardware joystick ON/OFF | 1390 | 2390 |
| Press A button | 1300 | 2300 |
| Press X button | 1301 | 2301 |
| Press B button | 1302 | 2302 |
| Press Y button | 1303 | 2303 |
| Press left side button | 1304 | 2304 |
| Press right side button | 1305 | 2305 |
| Press left stick | 1306 | 2306 |
| Press right stick | 1307 | 2307 |
| Press menu right | 1308 | 2308 |
| Press menu left | 1309 | 2309 |
| Release D-pad | 1310 | 2310 |
| Press arrow north | 1311 | 2311 |
| Press arrow northeast | 1312 | 2312 |
| Press arrow east | 1313 | 2313 |
| Press arrow southeast | 1314 | 2314 |
| Press arrow south | 1315 | 2315 |
| Press arrow southwest | 1316 | 2316 |
| Press arrow west | 1317 | 2317 |
| Press arrow northwest | 1318 | 2318 |
| Press Xbox home button | 1319 | 2319 |
| Random axis | 1320 | 2320 |
| Start recording | 1321 | 2321 |
| Set left stick to neutral (clockwise) | 1330 | 2330 |
| Move left stick up | 1331 | 2331 |
| Move left stick up-right | 1332 | 2332 |
| Move left stick right | 1333 | 2333 |
| Move left stick down-right | 1334 | 2334 |
| Move left stick down | 1335 | 2335 |
| Move left stick down-left | 1336 | 2336 |
| Move left stick left | 1337 | 2337 |
| Move left stick up-left | 1338 | 2338 |
| Set right stick to neutral (clockwise) | 1340 | 2340 |
| Move right stick up | 1341 | 2341 |
| Move right stick up-right | 1342 | 2342 |
| Move right stick right | 1343 | 2343 |
| Move right stick down-right | 1344 | 2344 |
| Move right stick down | 1345 | 2345 |
| Move right stick down-left | 1346 | 2346 |
| Move right stick left | 1347 | 2347 |
| Move right stick up-left | 1348 | 2348 |
| Set left stick horizontal to 1.0 | 1350 | 2350 |
| Set left stick horizontal to -1.0 | 1351 | 2351 |
| Set left stick vertical to 1.0 | 1352 | 2352 |
| Set left stick vertical to -1.0 | 1353 | 2353 |
| Set right stick horizontal to 1.0 | 1354 | 2354 |
| Set right stick horizontal to -1.0 | 1355 | 2355 |
| Set right stick vertical to 1.0 | 1356 | 2356 |
| Set right stick vertical to -1.0 | 1357 | 2357 |
| Set left trigger to 100% | 1358 | 2358 |
| Set right trigger to 100% | 1359 | 2359 |
| Set left stick horizontal to 0.75 | 1360 | 2360 |
| Set left stick horizontal to -0.75 | 1361 | 2361 |
| Set left stick vertical to 0.75 | 1362 | 2362 |
| Set left stick vertical to -0.75 | 1363 | 2363 |
| Set right stick horizontal to 0.75 | 1364 | 2364 |
| Set right stick horizontal to -0.75 | 1365 | 2365 |
| Set right stick vertical to 0.75 | 1366 | 2366 |
| Set right stick vertical to -0.75 | 1367 | 2367 |
| Set left trigger to 75% | 1368 | 2368 |
| Set right trigger to 75% | 1369 | 2369 |
| Set left stick horizontal to 0.5 | 1370 | 2370 |
| Set left stick horizontal to -0.5 | 1371 | 2371 |
| Set left stick vertical to 0.5 | 1372 | 2372 |
| Set left stick vertical to -0.5 | 1373 | 2373 |
| Set right stick horizontal to 0.5 | 1374 | 2374 |
| Set right stick horizontal to -0.5 | 1375 | 2375 |
| Set right stick vertical to 0.5 | 1376 | 2376 |
| Set right stick vertical to -0.5 | 1377 | 2377 |
| Set left trigger to 50% | 1378 | 2378 |
| Set right trigger to 50% | 1379 | 2379 |
| Set left stick horizontal to 0.25 | 1380 | 2380 |
| Set left stick horizontal to -0.25 | 1381 | 2381 |
| Set left stick vertical to 0.25 | 1382 | 2382 |
| Set left stick vertical to -0.25 | 1383 | 2383 |
| Set right stick horizontal to 0.25 | 1384 | 2384 |
| Set right stick horizontal to -0.25 | 1385 | 2385 |
| Set right stick vertical to 0.25 | 1386 | 2386 |
| Set right stick vertical to -0.25 | 1387 | 2387 |
| Set left trigger to 25% | 1388 | 2388 |
| Set right trigger to 25% | 1389 | 2389 |
| Release ALL Touch | 1390 | 2390 |
| Release ALL Touch but menu | 1391 | 2391 |
| Clear Timed Command | 1398 | 2398 |
Enables setting the GPIO to HIGH or LOW, provided the developer has the necessary permissions. Dev 0-40 refers to a list defined by the developer, specifying writable pins that can be used without explicitly identifying each pin.
Write PIN
| Label | HIGH | LOW |
|---|---|---|
| GPIO1 | 1401 | 2401 |
| GPIO2 | 1402 | 2402 |
| GPIO3 | 1403 | 2403 |
| GPIO3 | 14.. | 24.. |
| GPIO40 | 1440 | 2440 |
| Allowed by dev 1 | 1441 | 2441 |
| Allowed by dev 2 | 1442 | 2442 |
| Allowed by dev 3 | 1443 | 2443 |
| Allowed by dev 3 | 144. | 24.. |
| Allowed by dev 40 | 1480 | 2480 |
Read PIN changed
| Label | HIGH | LOW |
|---|---|---|
| GPIO1 | 1501 | 2501 |
| GPIO2 | 1502 | 2502 |
| GPIO3 | 1503 | 2503 |
| GPIO3 | 15.. | 25.. |
| GPIO40 | 1540 | 2540 |
| Allowed by dev 1 | 1541 | 2541 |
| Allowed by dev 2 | 1542 | 2542 |
| Allowed by dev 3 | 1543 | 2543 |
| Allowed by dev 3 | 154. | 25.. |
| Allowed by dev 40 | 1580 | 2580 |
I need to make a typing game and some tools for developers focusing on these characters: ~!@#$%^&*()_-+={}[]|\:;"'<>,.?/.
Note that depending on the context, you can use clipboard operations or keystroke combinations to input these characters.
It is up to the developer to choose the appropriate method based on constraints.
For example:
- On Windows, you can use Alt + [numeric code] on the numpad to input characters (e.g., Alt + 96 for
`). - This works for Unicode values up to 255, but many more are available beyond that.
| Char | Decimal | Short Description |
|---|---|---|
| 4032 | SPACE | |
| Under Escape left of number | ||
| ` | 4096 | GRAVE ACCENT |
| ~ | 4126 | TILDE |
| Numerical top key | ||
| ! | 4033 | EXCLAMATION MARK |
| @ | 4064 | COMMERCIAL AT |
| # | 4035 | NUMBER SIGN |
| $ | 4036 | DOLLAR SIGN |
| % | 4037 | PERCENT SIGN |
| ^ | 4094 | CIRCUMFLEX ACCENT |
| & | 4038 | AMPERSAND |
| * | 4042 | ASTERISK |
| ( | 4040 | LEFT PARENTHESIS |
| ) | 4041 | RIGHT PARENTHESIS |
| Left of backspace char | ||
| _ | 4095 | LOW LINE |
| - | 4045 | HYPHEN-MINUS |
| + | 4043 | PLUS SIGN |
| = | 4061 | EQUALS SIGN |
| Coding char top line | ||
| [ | 4091 | LEFT SQUARE BRACKET |
| { | 4123 | LEFT CURLY BRACKET |
| ] | 4093 | RIGHT SQUARE BRACKET |
| } | 4125 | RIGHT CURLY BRACKET |
| Ponctuation middle line | ||
| ; | 4059 | SEMICOLON |
| : | 4058 | COLON |
| " | 4034 | QUOTATION MARK |
| ' | 4039 | APOSTROPHE |
| Ponctuation down line | ||
| , | 4044 | COMMA |
| < | 4060 | LESS-THAN SIGN |
| . | 4046 | FULL STOP |
| > | 4062 | GREATER-THAN SIGN |
| / | 4047 | SOLIDUS |
| ? | 4063 | QUESTION MARK |
| Pinky finger left or right button | ||
| | | 4124 | VERTICAL LINE |
| \ | 4092 | REVERSE SOLIDUS |
| Special | ||
| ¯ | 4175 | MACRON |
| ´ | 4180 | ACUTE ACCENT |
| × | 4215 | MULTIPLICATION SIGN |
| ÷ | 4247 | DIVISION SIGN |
| 4160 | NO-BREAK SPACE |
Full list of the UTF8 Char as integer.
| Char | Decimal | Short Description |
|---|---|---|
| 4032 | SPACE | |
| ! | 4033 | EXCLAMATION MARK |
| " | 4034 | QUOTATION MARK |
| # | 4035 | NUMBER SIGN |
| $ | 4036 | DOLLAR SIGN |
| % | 4037 | PERCENT SIGN |
| & | 4038 | AMPERSAND |
| ' | 4039 | APOSTROPHE |
| ( | 4040 | LEFT PARENTHESIS |
| ) | 4041 | RIGHT PARENTHESIS |
| * | 4042 | ASTERISK |
| + | 4043 | PLUS SIGN |
| , | 4044 | COMMA |
| - | 4045 | HYPHEN-MINUS |
| . | 4046 | FULL STOP |
| / | 4047 | SOLIDUS |
| 0 | 4048 | DIGIT ZERO |
| 1 | 4049 | DIGIT ONE |
| 2 | 4050 | DIGIT TWO |
| 3 | 4051 | DIGIT THREE |
| 4 | 4052 | DIGIT FOUR |
| 5 | 4053 | DIGIT FIVE |
| 6 | 4054 | DIGIT SIX |
| 7 | 4055 | DIGIT SEVEN |
| 8 | 4056 | DIGIT EIGHT |
| 9 | 4057 | DIGIT NINE |
| : | 4058 | COLON |
| ; | 4059 | SEMICOLON |
| < | 4060 | LESS-THAN SIGN |
| = | 4061 | EQUALS SIGN |
| > | 4062 | GREATER-THAN SIGN |
| ? | 4063 | QUESTION MARK |
| @ | 4064 | COMMERCIAL AT |
| A | 4065 | LATIN CAPITAL LETTER A |
| B | 4066 | LATIN CAPITAL LETTER B |
| C | 4067 | LATIN CAPITAL LETTER C |
| D | 4068 | LATIN CAPITAL LETTER D |
| E | 4069 | LATIN CAPITAL LETTER E |
| F | 4070 | LATIN CAPITAL LETTER F |
| G | 4071 | LATIN CAPITAL LETTER G |
| H | 4072 | LATIN CAPITAL LETTER H |
| I | 4073 | LATIN CAPITAL LETTER I |
| J | 4074 | LATIN CAPITAL LETTER J |
| K | 4075 | LATIN CAPITAL LETTER K |
| L | 4076 | LATIN CAPITAL LETTER L |
| M | 4077 | LATIN CAPITAL LETTER M |
| N | 4078 | LATIN CAPITAL LETTER N |
| O | 4079 | LATIN CAPITAL LETTER O |
| P | 4080 | LATIN CAPITAL LETTER P |
| Q | 4081 | LATIN CAPITAL LETTER Q |
| R | 4082 | LATIN CAPITAL LETTER R |
| S | 4083 | LATIN CAPITAL LETTER S |
| T | 4084 | LATIN CAPITAL LETTER T |
| U | 4085 | LATIN CAPITAL LETTER U |
| V | 4086 | LATIN CAPITAL LETTER V |
| W | 4087 | LATIN CAPITAL LETTER W |
| X | 4088 | LATIN CAPITAL LETTER X |
| Y | 4089 | LATIN CAPITAL LETTER Y |
| Z | 4090 | LATIN CAPITAL LETTER Z |
| [ | 4091 | LEFT SQUARE BRACKET |
| \ | 4092 | REVERSE SOLIDUS |
| ] | 4093 | RIGHT SQUARE BRACKET |
| ^ | 4094 | CIRCUMFLEX ACCENT |
| _ | 4095 | LOW LINE |
| ` | 4096 | GRAVE ACCENT |
| a | 4097 | LATIN SMALL LETTER A |
| b | 4098 | LATIN SMALL LETTER B |
| c | 4099 | LATIN SMALL LETTER C |
| d | 4100 | LATIN SMALL LETTER D |
| e | 4101 | LATIN SMALL LETTER E |
| f | 4102 | LATIN SMALL LETTER F |
| g | 4103 | LATIN SMALL LETTER G |
| h | 4104 | LATIN SMALL LETTER H |
| i | 4105 | LATIN SMALL LETTER I |
| j | 4106 | LATIN SMALL LETTER J |
| k | 4107 | LATIN SMALL LETTER K |
| l | 4108 | LATIN SMALL LETTER L |
| m | 4109 | LATIN SMALL LETTER M |
| n | 4110 | LATIN SMALL LETTER N |
| o | 4111 | LATIN SMALL LETTER O |
| p | 4112 | LATIN SMALL LETTER P |
| q | 4113 | LATIN SMALL LETTER Q |
| r | 4114 | LATIN SMALL LETTER R |
| s | 4115 | LATIN SMALL LETTER S |
| t | 4116 | LATIN SMALL LETTER T |
| u | 4117 | LATIN SMALL LETTER U |
| v | 4118 | LATIN SMALL LETTER V |
| w | 4119 | LATIN SMALL LETTER W |
| x | 4120 | LATIN SMALL LETTER X |
| y | 4121 | LATIN SMALL LETTER Y |
| z | 4122 | LATIN SMALL LETTER Z |
| { | 4123 | LEFT CURLY BRACKET |
| | | 4124 | VERTICAL LINE |
| } | 4125 | RIGHT CURLY BRACKET |
| ~ | 4126 | TILDE |
| 4160 | NO-BREAK SPACE | |
| ¡ | 4161 | INVERTED EXCLAMATION MARK |
| ¢ | 4162 | CENT SIGN |
| £ | 4163 | POUND SIGN |
| ¤ | 4164 | CURRENCY SIGN |
| ¥ | 4165 | YEN SIGN |
| ¦ | 4166 | BROKEN BAR |
| § | 4167 | SECTION SIGN |
| ¨ | 4168 | DIAERESIS |
| © | 4169 | COPYRIGHT SIGN |
| ª | 4170 | FEMININE ORDINAL INDICATOR |
| « | 4171 | LEFT-POINTING DOUBLE ANGLE QUOTATION MARK |
| ¬ | 4172 | NOT SIGN |
| 4173 | SOFT HYPHEN | |
| ® | 4174 | REGISTERED SIGN |
| ¯ | 4175 | MACRON |
| ° | 4176 | DEGREE SIGN |
| ± | 4177 | PLUS-MINUS SIGN |
| ² | 4178 | SUPERSCRIPT TWO |
| ³ | 4179 | SUPERSCRIPT THREE |
| ´ | 4180 | ACUTE ACCENT |
| µ | 4181 | MICRO SIGN |
| ¶ | 4182 | PILCROW SIGN |
| · | 4183 | MIDDLE DOT |
| ¸ | 4184 | CEDILLA |
| ¹ | 4185 | SUPERSCRIPT ONE |
| º | 4186 | MASCULINE ORDINAL INDICATOR |
| » | 4187 | RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK |
| ¼ | 4188 | VULGAR FRACTION ONE QUARTER |
| ½ | 4189 | VULGAR FRACTION ONE HALF |
| ¾ | 4190 | VULGAR FRACTION THREE QUARTERS |
| ¿ | 4191 | INVERTED QUESTION MARK |
| À | 4192 | LATIN CAPITAL LETTER A WITH GRAVE |
| Á | 4193 | LATIN CAPITAL LETTER A WITH ACUTE |
| Â | 4194 | LATIN CAPITAL LETTER A WITH CIRCUMFLEX |
| Ã | 4195 | LATIN CAPITAL LETTER A WITH TILDE |
| Ä | 4196 | LATIN CAPITAL LETTER A WITH DIAERESIS |
| Å | 4197 | LATIN CAPITAL LETTER A WITH RING ABOVE |
| Æ | 4198 | LATIN CAPITAL LETTER AE |
| Ç | 4199 | LATIN CAPITAL LETTER C WITH CEDILLA |
| È | 4200 | LATIN CAPITAL LETTER E WITH GRAVE |
| É | 4201 | LATIN CAPITAL LETTER E WITH ACUTE |
| Ê | 4202 | LATIN CAPITAL LETTER E WITH CIRCUMFLEX |
| Ë | 4203 | LATIN CAPITAL LETTER E WITH DIAERESIS |
| Ì | 4204 | LATIN CAPITAL LETTER I WITH GRAVE |
| Í | 4205 | LATIN CAPITAL LETTER I WITH ACUTE |
| Î | 4206 | LATIN CAPITAL LETTER I WITH CIRCUMFLEX |
| Ï | 4207 | LATIN CAPITAL LETTER I WITH DIAERESIS |
| Ð | 4208 | LATIN CAPITAL LETTER ETH |
| Ñ | 4209 | LATIN CAPITAL LETTER N WITH TILDE |
| Ò | 4210 | LATIN CAPITAL LETTER O WITH GRAVE |
| Ó | 4211 | LATIN CAPITAL LETTER O WITH ACUTE |
| Ô | 4212 | LATIN CAPITAL LETTER O WITH CIRCUMFLEX |
| Õ | 4213 | LATIN CAPITAL LETTER O WITH TILDE |
| Ö | 4214 | LATIN CAPITAL LETTER O WITH DIAERESIS |
| × | 4215 | MULTIPLICATION SIGN |
| Ø | 4216 | LATIN CAPITAL LETTER O WITH STROKE |
| Ù | 4217 | LATIN CAPITAL LETTER U WITH GRAVE |
| Ú | 4218 | LATIN CAPITAL LETTER U WITH ACUTE |
| Û | 4219 | LATIN CAPITAL LETTER U WITH CIRCUMFLEX |
| Ü | 4220 | LATIN CAPITAL LETTER U WITH DIAERESIS |
| Ý | 4221 | LATIN CAPITAL LETTER Y WITH ACUTE |
| Þ | 4222 | LATIN CAPITAL LETTER THORN |
| ß | 4223 | LATIN SMALL LETTER SHARP S |
| à | 4224 | LATIN SMALL LETTER A WITH GRAVE |
| á | 4225 | LATIN SMALL LETTER A WITH ACUTE |
| â | 4226 | LATIN SMALL LETTER A WITH CIRCUMFLEX |
| ã | 4227 | LATIN SMALL LETTER A WITH TILDE |
| ä | 4228 | LATIN SMALL LETTER A WITH DIAERESIS |
| å | 4229 | LATIN SMALL LETTER A WITH RING ABOVE |
| æ | 4230 | LATIN SMALL LETTER AE |
| ç | 4231 | LATIN SMALL LETTER C WITH CEDILLA |
| è | 4232 | LATIN SMALL LETTER E WITH GRAVE |
| é | 4233 | LATIN SMALL LETTER E WITH ACUTE |
| ê | 4234 | LATIN SMALL LETTER E WITH CIRCUMFLEX |
| ë | 4235 | LATIN SMALL LETTER E WITH DIAERESIS |
| ì | 4236 | LATIN SMALL LETTER I WITH GRAVE |
| í | 4237 | LATIN SMALL LETTER I WITH ACUTE |
| î | 4238 | LATIN SMALL LETTER I WITH CIRCUMFLEX |
| ï | 4239 | LATIN SMALL LETTER I WITH DIAERESIS |
| ð | 4240 | LATIN SMALL LETTER ETH |
| ñ | 4241 | LATIN SMALL LETTER N WITH TILDE |
| ò | 4242 | LATIN SMALL LETTER O WITH GRAVE |
| ó | 4243 | LATIN SMALL LETTER O WITH ACUTE |
| ô | 4244 | LATIN SMALL LETTER O WITH CIRCUMFLEX |
| õ | 4245 | LATIN SMALL LETTER O WITH TILDE |
| ö | 4246 | LATIN SMALL LETTER O WITH DIAERESIS |
| ÷ | 4247 | DIVISION SIGN |
| ø | 4248 | LATIN SMALL LETTER O WITH STROKE |
| ù | 4249 | LATIN SMALL LETTER U WITH GRAVE |
| ú | 4250 | LATIN SMALL LETTER U WITH ACUTE |
| û | 4251 | LATIN SMALL LETTER U WITH CIRCUMFLEX |
| ü | 4252 | LATIN SMALL LETTER U WITH DIAERESIS |
| ý | 4253 | LATIN SMALL LETTER Y WITH ACUTE |
| þ | 4254 | LATIN SMALL LETTER THORN |
| ÿ | 4255 | LATIN SMALL LETTER Y WITH DIAERESIS |
It depends entirely on the context. These could be any functions or actions required by the application or system in use.
In the context of Scratch to Wow, we could list action that need to be triggerable but don't need to be store on a keystroke but write in the console from /run script
Allows to export line of color for Led and Color Picking context.
02 00 99 88 77
02 00 R G B Color 0
...
02 99 R G B Color Picking 99
Explanation of MIDI Format Tags
MIDI data is stored using 3 bytes, but I use 4-byte tags to make it more recognizable.
Tagging an event with 13 indicates that the following data is in MIDI format:
1300000000
For simplicity, here’s a beginner-friendly reference using values 0–127 in the tag system:
- 1600 – Play full note 0 | 2600 – Release note 0
- 1727 – Play full note 127 | 2727 – Release note 127
- 1728 – Press all notes | 2728 – Release all notes
In tribute to Mordhau:
- 1729 – Switch to Flute | 2729 – Switch to Muse
- 1730 – Play note 0
- 1790 – Play note 60
Note: Mordhau mode does not use note releases.
To reduce bandwidth usage, you can transmit the “held state” of the gamepad instead of sending constant updates.
1800000000is used for the full gamepad data (including both joysticks).1700000000is used for all remaining button and trigger data.
Triggers usually don’t require high-precision values in games. Using discrete levels 0, 0.25, 0.5, 0.75, and 1.0 is typically sufficient, which is why I encode them using the binary tag 17.
Below is an older code snippet showing how the 1700000000 binary structure is decoded:
( !!! I change the standard and did not change yet the Generic of Unity3D !!!
https://github.com/EloiStree/OpenUPM_PushGenericIID )
Example for Godot Push (need to be verified, Draft)
static func gamepad_resource_to_1700000000_integer(gamepad: S2W_Data_Gamepad1817) -> int:
var result: int = 0
# Set button bits
if gamepad.button_y_up:
result |= (1 << 0)
if gamepad.button_b_right:
result |= (1 << 1)
if gamepad.button_a_down:
result |= (1 << 2)
if gamepad.button_x_left:
result |= (1 << 3)
if gamepad.arrow_up:
result |= (1 << 4)
if gamepad.arrow_right:
result |= (1 << 5)
if gamepad.arrow_down:
result |= (1 << 6)
if gamepad.arrow_left:
result |= (1 << 7)
if gamepad.side_button_left:
result |= (1 << 8)
if gamepad.side_button_right:
result |= (1 << 9)
if gamepad.stick_joystick_left:
result |= (1 << 10)
if gamepad.stick_joystick_right:
result |= (1 << 11)
if gamepad.menu_left:
result |= (1 << 12)
if gamepad.menu_center:
result |= (1 << 13)
if gamepad.menu_right:
result |= (1 << 14)
if gamepad.kill_switch_is_connected:
result |= (1 << 15)
#binary order
#0.10 16 20
#0.15 17 21
#0.25 18 22
#0.50 19 23
var tl = gamepad.trigger_left_axis_01_percent
if tl > 0.99:
result |= (1 << 16)
result |= (1 << 17)
result |= (1 << 18)
result |= (1 << 19)
if tl > 0.74:
result |= (1 << 18)
result |= (1 << 19)
elif tl > 0.49:
result |= (1 << 19)
elif tl > 0.24:
result |= (1 << 18)
elif tl > 0.14:
result |= (1 << 17)
elif tl > 0.9:
result |= (1 << 16)
var tr = gamepad.trigger_right_axis_01_percent
if tr > 0.99:
result |= (1 << 20)
result |= (1 << 21)
result |= (1 << 22)
result |= (1 << 23)
if tr > 0.74:
result |= (1 << 22)
result |= (1 << 23)
elif tr > 0.49:
result |= (1 << 23)
elif tr > 0.24:
result |= (1 << 22)
elif tr > 0.14:
result |= (1 << 21)
elif tr > 0.9:
result |= (1 << 20)
return result + 1700000000
Example for Arduino Receiver (need to be verified, Draft)
else if(value>=1800000000 && value<=1899999999){
//18 50 20 00 10
//1850200010
//4 bytes because integer
int left_horizontal_from_1_to_99 = (value/1000000)%100;
int left_vertical_from_1_to_99 = (value/10000)%100;
int right_horizontal_from_1_to_99 = (value/100)%100;
int right_vertical_from_1_to_99 = (value/1)%100;
float left_horizontal_percent= IntAndBinaryUtility::turn_from_1_to_99_as_percent(left_horizontal_from_1_to_99);
float left_vertical_percent= IntAndBinaryUtility::turn_from_1_to_99_as_percent(left_vertical_from_1_to_99);
float right_horizontal_percent= IntAndBinaryUtility::turn_from_1_to_99_as_percent(right_horizontal_from_1_to_99);
float right_vertical_percent= IntAndBinaryUtility::turn_from_1_to_99_as_percent(right_vertical_from_1_to_99);
gamepad()->set_left_horizontal_percent(left_horizontal_percent);
gamepad()->set_left_vertical_percent(left_vertical_percent);
gamepad()->set_right_horizontal_percent(right_horizontal_percent);
gamepad()->set_right_vertical_percent(right_vertical_percent );
}
else if(value>=1700000000 && value<=1799999999){
m_binaryBufferOfInteger[33]; // Buffer to store the binary representation (32 bits + null terminator)
//IntAndBinaryUtility::int_to_binary_buffer(value, m_binaryBufferOfInteger, 33);
//Serial.println(m_binaryBufferOfInteger);
value=value-1700000000;
IntAndBinaryUtility::int_to_binary_buffer(value,m_binaryBufferOfInteger,33);
//Serial.println(m_binaryBufferOfInteger);
float triggerLeft=0.0;
float triggerRight=0.0;
float arrowHorizontal=0;
float arrowVertical =0;
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 0)) gamepad()->press_y(true); else gamepad()->press_y(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 1)) gamepad()->press_b(true); else gamepad()->press_b(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 2)) gamepad()->press_a(true); else gamepad()->press_a(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 3)) gamepad()->press_x(true); else gamepad()->press_x(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 4)) arrowVertical+=1; // CLOCK WISE N
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 5)) arrowHorizontal+=1; // CLOCK WISE E
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 6)) arrowVertical+=-1; // CLOCK WISE S
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 7)) arrowHorizontal+=-1; //// CLOCK WISE W
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 8)) gamepad()->press_left_side_button(true); else gamepad()->press_left_side_button(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 9)) gamepad()->press_right_side_button(true); else gamepad()->press_right_side_button(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 10)) gamepad()->press_left_stick(true); else gamepad()->press_left_stick(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 11)) gamepad()->press_right_stick(true); else gamepad()->press_right_stick(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 12)) gamepad()->press_menu_left(true); else gamepad()->press_menu_left(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 13)) gamepad()->press_home_xbox_button(true); else gamepad()->press_home_xbox_button(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 14)) gamepad()->press_menu_right(true); else gamepad()->press_menu_right(false);
if(IntAndBinaryUtility::is_integer_bit_right_to_left_true (value, 15)) {/*KILL SWITCH ON*/} else /*KILL SWITCH OFF*/;
//Decode trigger values from bits
//Left trigger: bits 16-19
//Right trigger: bits 20-23
//Pattern: 0.10 (16/20), 0.15 (17/21), 0.25 (18/22), 0.50 (19/23)
//This is the decoding logic (inverse of encoding above)
// For reference when implementing the decode function:
var trigger_left = 0.0
var trigger_right = 0.0
if is_integer_bit_right_to_left_true(value, 16): trigger_left += 0.10
if is_integer_bit_right_to_left_true(value, 17): trigger_left += 0.15
if is_integer_bit_right_to_left_true(value, 18): trigger_left += 0.25
if is_integer_bit_right_to_left_true(value, 19): trigger_left += 0.50
if is_integer_bit_right_to_left_true(value, 20): trigger_right += 0.10
if is_integer_bit_right_to_left_true(value, 21): trigger_right += 0.15
if is_integer_bit_right_to_left_true(value, 22): trigger_right += 0.25
if is_integer_bit_right_to_left_true(value, 23): trigger_right += 0.50
gamepad()->set_trigger_left_percent(triggerLeft);
gamepad()->set_trigger_right_percent(triggerRight);
if(arrowVertical==1 && arrowHorizontal==0)
gamepad()->press_arrow_n();
else if(arrowVertical==1 && arrowHorizontal==1)
gamepad()->press_arrow_ne();
else if(arrowVertical==0 && arrowHorizontal==1)
gamepad()->press_arrow_e();
else if(arrowVertical==-1 && arrowHorizontal==1)
gamepad()->press_arrow_se();
else if(arrowVertical==-1 && arrowHorizontal==0)
gamepad()->press_arrow_s();
else if(arrowVertical==-1 && arrowHorizontal==-1)
gamepad()->press_arrow_sw();
else if(arrowVertical==0 && arrowHorizontal==-1)
gamepad()->press_arrow_w();
else if(arrowVertical==1 && arrowHorizontal==-1)
gamepad()->press_arrow_nw();
else
gamepad()->release_dpad();
}
}You need to find your device on the network, depending of if you use Websocket or UDP. Int 3123 Send back on port 3123 text: IPV4|DeviceName|UniqueID|AllowedMask
You can apparently do so much more with USB... But I am not sure it would be wise in the context of this project as I am focusing on gaming here.
For this project, I developed two packages to support NES-style mini-games with multiplayer features in both Unity and Godot.
Each player action is encoded as an integer value, based on input from an Xbox controller or a custom NES mapping.
Unity
- https://github.com/EloiStree/2026_01_18_upm_nes_controller_udp
- https://github.com/EloiStree/2026_01_18_upm_nes_udp_multiplayer
Godot
- https://github.com/EloiStree/2026_01_18_gdp_nes_controller_udp
- https://github.com/EloiStree/2026_01_18_gdp_nes_udp_multiplayer
In the first exercise, I reused the Xbox input mapping for NES controls. It works, but it is more appropriate to define a dedicated NES mapping, especially for remapping mini-games.
For example:
1281→ Press the button currently mapped to Up Arrow1331→ Press the button remapped behind Up Arrow1286→ Press the button mapped to NES B (can be a keyboard key, Xbox B, Xbox A, etc.)
| Action | Server Remap Press | Server Remap Release | Local Remap Press | Local Remap Release |
|---|---|---|---|---|
| Up Arrow | 1281 | 2281 | 1291 | 2291 |
| Right Arrow | 1282 | 2282 | 1292 | 2292 |
| Down Arrow | 1283 | 2283 | 1293 | 2293 |
| Left Arrow | 1284 | 2284 | 1294 | 2294 |
| A Button | 1285 | 2285 | 1295 | 2295 |
| B Button | 1286 | 2286 | 1296 | 2296 |
| Menu Left | 1287 | 2287 | 1297 | 2297 |
| Menu Right | 1288 | 2288 | 1298 | 2298 |
- Local Remap*: Listen and replace the keystroke locally.
- Server Remap*: It is up to the server to remap the keystroke.
If you want to simulate Xbox-style inputs through the NES system:
| Action | Press | Release |
|---|---|---|
| Up Arrow | 1331 | 2331 |
| Right Arrow | 1333 | 2333 |
| Down Arrow | 1335 | 2335 |
| Left Arrow | 1337 | 2337 |
| A Button | 1300 | 2300 |
| B Button (B) | 1302 | 2302 |
| B Button (X) | 1301 | 2301 |
| B Button (Y) | 1303 | 2303 |
| Menu Left | 1309 | 2309 |
| Menu Right | 1308 | 2308 |


