Skip to content

Commit ad1e300

Browse files
TomArrowTom
andauthored
Quake 3 Engine demo pattern & test file (#402)
* Quake 3 Engine demo pattern & test file * Quake 3 Engine demo: Increase limits (demo files can be big) and additional condition * Quake 3 demo specify little endian * Quake 3 demo format: Add message type detection * Quake 3 demo format: Read serverTime for snapshot messages * Quake 3 demo pattern: fixed bug/typo/sleepy coding * Quake 3 demo pattern: Ability to read CS_SERVERINFO * Quake 3 demo pattern: Read CS_SYSTEMINFO as well * Quake 3 demo pattern: Read first serverCommand per message * Added Quake 3 engine demo pattern to readme * Change Quake 3 engine demo entry in readme table --------- Co-authored-by: Tom <[email protected]>
1 parent e918ce5 commit ad1e300

File tree

3 files changed

+197
-0
lines changed

3 files changed

+197
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
145145
| PYC | `application/x-bytecode.python` | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files |
146146
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
147147
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
148+
| Quake 3 engine demo | | [`patterns/q3demo.hexpat`](patterns/q3demo.hexpat) | Demos/replays of most Quake 3 engine games |
148149
| quantized-mesh | | [`patterns/quantized-mesh.hexpat`](patterns/quantized-mesh.hexpat) | Cesium quantized-mesh terrain |
149150
| RAR | `application/x-rar` | [`patterns/rar.hexpat`](patterns/rar.hexpat) | RAR archive file format |
150151
| RAS | `image/x-sun-raster` | [`patterns/ras.hexpat`](patterns/ras.hexpat) | RAS image files |

patterns/q3demo.hexpat

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#pragma description Quake 3 Engine demo
2+
3+
#pragma array_limit 2147483647
4+
#pragma pattern_limit 2147483647
5+
#pragma loop_limit 16384
6+
7+
#define FINAL_DEMO_MESSAGE_NUMBER -1
8+
#define FINAL_DEMO_MESSAGE_LENGTH -1
9+
#define GETINT ((data[bitindex >> 3] | (data[(bitindex >> 3)+1]<<8) | (data[(bitindex >> 3)+2]<<16) | (data[(bitindex >> 3)+3]<<32)) >> (bitindex & 7)) & 0x7FF
10+
11+
import type.magic;
12+
import std.string;
13+
14+
u16 huffdecode[2048]={2512,2182,512,2763,1859,2808,512,2360,1918,1988,512,1803,2158,2358,512,2180,1798,2053,512,1804,2603,1288,512,2166,2285,2167,512,1281,1640,2767,512,1664,1731,2116,512,2788,1791,1808,512,1840,2153,1921,512,2708,2723,1549,512,2046,1893,2717,512,2602,1801,1288,512,1568,2480,2062,512,1281,2145,2711,512,1543,1909,2150,512,2077,2338,2762,512,2162,1794,2024,512,2168,1922,2447,512,2334,1857,2117,512,2100,2240,1288,512,2186,2321,1908,512,1281,1640,2242,512,1664,1731,2729,512,2633,1791,1919,512,2184,1917,1802,512,2710,1795,1549,512,2172,2375,2789,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2374,2446,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2751,512,2413,1798,2529,512,1804,2344,1288,512,2404,2156,2786,512,1281,1640,2641,512,1664,1731,2052,512,2170,1791,1808,512,1840,2395,1921,512,2586,2319,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2773,512,1281,2365,2410,512,1543,1909,2781,512,2097,2411,2740,512,2396,1794,2024,512,2734,1922,2733,512,2112,1857,2528,512,2593,2079,1288,512,2648,2143,1908,512,1281,1640,2770,512,1664,1731,2169,512,2714,1791,1919,512,2185,1917,1802,512,2398,1795,1549,512,2098,2801,2361,512,2400,2328,1288,512,1568,2783,2713,512,1281,1858,1923,512,1543,2816,2182,512,2497,1859,2397,512,2794,1918,1988,512,1803,2158,2772,512,2180,1798,2053,512,1804,2464,1288,512,2166,2285,2167,512,1281,1640,2764,512,1664,1731,2116,512,2620,1791,1808,512,1840,2153,1921,512,2716,2384,1549,512,2046,1893,2448,512,2722,1801,1288,512,1568,2472,2062,512,1281,2145,2376,512,1543,1909,2150,512,2077,2366,2709,512,2162,1794,2024,512,2168,1922,2735,512,2407,1857,2117,512,2100,2240,1288,512,2186,2779,1908,512,1281,1640,2242,512,1664,1731,2359,512,2705,1791,1919,512,2184,1917,1802,512,2642,1795,1549,512,2172,2394,2645,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2450,2771,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2585,512,2403,1798,2619,512,1804,2777,1288,512,2355,2156,2362,512,1281,1640,2380,512,1664,1731,2052,512,2170,1791,1808,512,1840,2811,1921,512,2402,2601,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2719,512,1281,2747,2776,512,1543,1909,2725,512,2097,2445,2765,512,2638,1794,2024,512,2444,1922,2774,512,2112,1857,2727,512,2644,2079,1288,512,2800,2143,1908,512,1281,1640,2580,512,1664,1731,2169,512,2646,1791,1919,512,2185,1917,1802,512,2588,1795,1549,512,2098,2322,2504,512,2623,2350,1288,512,1568,2323,2721,512,1281,1858,1923,512,1543,2512,2182,512,2746,1859,2798,512,2360,1918,1988,512,1803,2158,2358,512,2180,1798,2053,512,1804,2745,1288,512,2166,2285,2167,512,1281,1640,2806,512,1664,1731,2116,512,2796,1791,1808,512,1840,2153,1921,512,2582,2761,1549,512,2046,1893,2793,512,2647,1801,1288,512,1568,2480,2062,512,1281,2145,2738,512,1543,1909,2150,512,2077,2338,2715,512,2162,1794,2024,512,2168,1922,2447,512,2334,1857,2117,512,2100,2240,1288,512,2186,2321,1908,512,1281,1640,2242,512,1664,1731,2795,512,2750,1791,1919,512,2184,1917,1802,512,2732,1795,1549,512,2172,2375,2604,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2374,2446,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2813,512,2413,1798,2529,512,1804,2344,1288,512,2404,2156,2743,512,1281,1640,2748,512,1664,1731,2052,512,2170,1791,1808,512,1840,2395,1921,512,2637,2319,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2812,512,1281,2365,2410,512,1543,1909,2799,512,2097,2411,2802,512,2396,1794,2024,512,2649,1922,2595,512,2112,1857,2528,512,2790,2079,1288,512,2634,2143,1908,512,1281,1640,2724,512,1664,1731,2169,512,2730,1791,1919,512,2185,1917,1802,512,2398,1795,1549,512,2098,2605,2361,512,2400,2328,1288,512,1568,2787,2810,512,1281,1858,1923,512,1543,2803,2182,512,2497,1859,2397,512,2758,1918,1988,512,1803,2158,2598,512,2180,1798,2053,512,1804,2464,1288,512,2166,2285,2167,512,1281,1640,2726,512,1664,1731,2116,512,2583,1791,1808,512,1840,2153,1921,512,2712,2384,1549,512,2046,1893,2448,512,2639,1801,1288,512,1568,2472,2062,512,1281,2145,2376,512,1543,1909,2150,512,2077,2366,2731,512,2162,1794,2024,512,2168,1922,2766,512,2407,1857,2117,512,2100,2240,1288,512,2186,2809,1908,512,1281,1640,2242,512,1664,1731,2359,512,2587,1791,1919,512,2184,1917,1802,512,2643,1795,1549,512,2172,2394,2635,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2450,2749,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2778,512,2403,1798,2791,512,1804,2775,1288,512,2355,2156,2362,512,1281,1640,2380,512,1664,1731,2052,512,2170,1791,1808,512,1840,2805,1921,512,2402,2741,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2769,512,1281,2739,2780,512,1543,1909,2737,512,2097,2445,2596,512,2757,1794,2024,512,2444,1922,2599,512,2112,1857,2804,512,2744,2079,1288,512,2707,2143,1908,512,1281,1640,2782,512,1664,1731,2169,512,2742,1791,1919,512,2185,1917,1802,512,2718,1795,1549,512,2098,2322,2504,512,2581,2350,1288,512,1568,2323,2597,512,1281,1858,1923,512,1543,2512,2182,512,2763,1859,2808,512,2360,1918,1988,512,1803,2158,2358,512,2180,1798,2053,512,1804,2603,1288,512,2166,2285,2167,512,1281,1640,2767,512,1664,1731,2116,512,2788,1791,1808,512,1840,2153,1921,512,2708,2723,1549,512,2046,1893,2717,512,2602,1801,1288,512,1568,2480,2062,512,1281,2145,2711,512,1543,1909,2150,512,2077,2338,2762,512,2162,1794,2024,512,2168,1922,2447,512,2334,1857,2117,512,2100,2240,1288,512,2186,2321,1908,512,1281,1640,2242,512,1664,1731,2729,512,2633,1791,1919,512,2184,1917,1802,512,2710,1795,1549,512,2172,2375,2789,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2374,2446,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2751,512,2413,1798,2529,512,1804,2344,1288,512,2404,2156,2786,512,1281,1640,2641,512,1664,1731,2052,512,2170,1791,1808,512,1840,2395,1921,512,2586,2319,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2773,512,1281,2365,2410,512,1543,1909,2781,512,2097,2411,2740,512,2396,1794,2024,512,2734,1922,2733,512,2112,1857,2528,512,2593,2079,1288,512,2648,2143,1908,512,1281,1640,2770,512,1664,1731,2169,512,2714,1791,1919,512,2185,1917,1802,512,2398,1795,1549,512,2098,2801,2361,512,2400,2328,1288,512,1568,2783,2713,512,1281,1858,1923,512,1543,3063,2182,512,2497,1859,2397,512,2794,1918,1988,512,1803,2158,2772,512,2180,1798,2053,512,1804,2464,1288,512,2166,2285,2167,512,1281,1640,2764,512,1664,1731,2116,512,2620,1791,1808,512,1840,2153,1921,512,2716,2384,1549,512,2046,1893,2448,512,2722,1801,1288,512,1568,2472,2062,512,1281,2145,2376,512,1543,1909,2150,512,2077,2366,2709,512,2162,1794,2024,512,2168,1922,2735,512,2407,1857,2117,512,2100,2240,1288,512,2186,2779,1908,512,1281,1640,2242,512,1664,1731,2359,512,2705,1791,1919,512,2184,1917,1802,512,2642,1795,1549,512,2172,2394,2645,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2450,2771,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2585,512,2403,1798,2619,512,1804,2777,1288,512,2355,2156,2362,512,1281,1640,2380,512,1664,1731,2052,512,2170,1791,1808,512,1840,2811,1921,512,2402,2601,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2719,512,1281,2747,2776,512,1543,1909,2725,512,2097,2445,2765,512,2638,1794,2024,512,2444,1922,2774,512,2112,1857,2727,512,2644,2079,1288,512,2800,2143,1908,512,1281,1640,2580,512,1664,1731,2169,512,2646,1791,1919,512,2185,1917,1802,512,2588,1795,1549,512,2098,2322,2504,512,2623,2350,1288,512,1568,2323,2721,512,1281,1858,1923,512,1543,2512,2182,512,2746,1859,2798,512,2360,1918,1988,512,1803,2158,2358,512,2180,1798,2053,512,1804,2745,1288,512,2166,2285,2167,512,1281,1640,2806,512,1664,1731,2116,512,2796,1791,1808,512,1840,2153,1921,512,2582,2761,1549,512,2046,1893,2793,512,2647,1801,1288,512,1568,2480,2062,512,1281,2145,2738,512,1543,1909,2150,512,2077,2338,2715,512,2162,1794,2024,512,2168,1922,2447,512,2334,1857,2117,512,2100,2240,1288,512,2186,2321,1908,512,1281,1640,2242,512,1664,1731,2795,512,2750,1791,1919,512,2184,1917,1802,512,2732,1795,1549,512,2172,2375,2604,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2374,2446,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2813,512,2413,1798,2529,512,1804,2344,1288,512,2404,2156,2743,512,1281,1640,2748,512,1664,1731,2052,512,2170,1791,1808,512,1840,2395,1921,512,2637,2319,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2812,512,1281,2365,2410,512,1543,1909,2799,512,2097,2411,2802,512,2396,1794,2024,512,2649,1922,2595,512,2112,1857,2528,512,2790,2079,1288,512,2634,2143,1908,512,1281,1640,2724,512,1664,1731,2169,512,2730,1791,1919,512,2185,1917,1802,512,2398,1795,1549,512,2098,2605,2361,512,2400,2328,1288,512,1568,2787,2810,512,1281,1858,1923,512,1543,2803,2182,512,2497,1859,2397,512,2758,1918,1988,512,1803,2158,2598,512,2180,1798,2053,512,1804,2464,1288,512,2166,2285,2167,512,1281,1640,2726,512,1664,1731,2116,512,2583,1791,1808,512,1840,2153,1921,512,2712,2384,1549,512,2046,1893,2448,512,2639,1801,1288,512,1568,2472,2062,512,1281,2145,2376,512,1543,1909,2150,512,2077,2366,2731,512,2162,1794,2024,512,2168,1922,2766,512,2407,1857,2117,512,2100,2240,1288,512,2186,2809,1908,512,1281,1640,2242,512,1664,1731,2359,512,2587,1791,1919,512,2184,1917,1802,512,2643,1795,1549,512,2172,2394,2635,512,2171,2187,1288,512,1568,2095,2163,512,1281,1858,1923,512,1543,2450,2749,512,2181,1859,2160,512,2183,1918,1988,512,1803,2161,2778,512,2403,1798,2791,512,1804,2775,1288,512,2355,2156,2362,512,1281,1640,2380,512,1664,1731,2052,512,2170,1791,1808,512,1840,2805,1921,512,2402,2741,1549,512,2046,1893,2101,512,2159,1801,1288,512,1568,2247,2769,512,1281,2739,2780,512,1543,1909,2737,512,2097,2445,2596,512,2757,1794,2024,512,2444,1922,2599,512,2112,1857,2804,512,2744,2079,1288,512,2707,2143,1908,512,1281,1640,2782,512,1664,1731,2169,512,2742,1791,1919,512,2185,1917,1802,512,2718,1795,1549,512,2098,2322,2504,512,2581,2350,1288,512,1568,2323,2597,512,1281,1858,1923,512,1543};
15+
16+
using Message;
17+
18+
struct returnValue {
19+
s32 value;
20+
s32 bitindex;
21+
};
22+
23+
fn readbits( ref auto data, s32 len,s32 bits, s32 bitindex){
24+
u16 huffy;
25+
u64 ret= 0;
26+
s32 value = 0;
27+
s32 tmpVal = 0;
28+
value = 0;
29+
if(len-(bitindex >> 3)<4){ // for safety so we don't have to do checks everywhere else
30+
return -1;
31+
}
32+
33+
for (u32 i = 0, i < bits, i = i +8) {
34+
tmpVal = GETINT;
35+
huffy =huffdecode[tmpVal];
36+
bitindex += (huffy>>8);
37+
value |= (huffy & 0xFF) << i;
38+
}
39+
u32 valueU = value;
40+
u32 bitindexU = bitindex;
41+
ret = valueU | (bitindexU << 32);
42+
return ret;
43+
};
44+
45+
#define DECODERET value = ret & 2147483647;bitindex = ret >> 32;
46+
fn readCsString(ref auto data, s32 len, s32 bitindex){
47+
s32 value = 0;
48+
u64 ret = 0;
49+
str test = "";
50+
51+
while(true){
52+
ret = readbits(data,len,8,bitindex);DECODERET
53+
if(value != 3){
54+
break;
55+
}
56+
// configstring
57+
ret = readbits(data,len,16,bitindex);DECODERET
58+
u16 csNum = value;
59+
60+
while(true){
61+
ret = readbits(data,len,8,bitindex);DECODERET
62+
s8 val = value;
63+
if(val <= 0){
64+
break;
65+
}
66+
char c = val;
67+
test+=std::string::to_string(c);
68+
}
69+
return test;
70+
}
71+
return test;
72+
};
73+
74+
fn measureCsString(ref auto data, s32 len, s32 bitindex){
75+
s32 value = 0;
76+
u64 ret = 0;
77+
78+
while(true){
79+
ret = readbits(data,len,8,bitindex);DECODERET
80+
if(value != 3){
81+
break;
82+
}
83+
// configstring
84+
ret = readbits(data,len,16,bitindex);DECODERET
85+
u16 csNum = value;
86+
87+
while(true){
88+
ret = readbits(data,len,8,bitindex);DECODERET
89+
s8 val = value;
90+
if(val <= 0){
91+
break;
92+
}
93+
}
94+
return bitindex;
95+
}
96+
return bitindex;
97+
};
98+
99+
100+
fn readString(ref auto data, s32 len, s32 bitindex){
101+
s32 value = 0;
102+
u64 ret = 0;
103+
str test = "";
104+
105+
while(true){
106+
107+
while(true){
108+
ret = readbits(data,len,8,bitindex);DECODERET
109+
s8 val = value;
110+
if(val <= 0){
111+
break;
112+
}
113+
char c = val;
114+
test+=std::string::to_string(c);
115+
}
116+
return test;
117+
}
118+
return test;
119+
};
120+
121+
struct Message {
122+
le s32 messageNum;
123+
le s32 len;
124+
if(len != FINAL_DEMO_MESSAGE_LENGTH || messageNum != FINAL_DEMO_MESSAGE_NUMBER) {
125+
u8 data[len];
126+
if( len>=10){ // should usually be true unless corrupted
127+
128+
s32 bitindex = 0;
129+
s32 value=0;
130+
bitindex = 0;
131+
u64 ret = readbits(data,len,32,bitindex);DECODERET
132+
s32 reliableAcknowledge = value [[export]];
133+
134+
135+
136+
ret = readbits(data,len,8,bitindex);DECODERET
137+
s32 firstCmd = value [[export]];
138+
139+
if(firstCmd == 7){ // snapshot
140+
ret = readbits(data,len,32,bitindex);DECODERET
141+
s32 serverTime = value [[export]];
142+
143+
} else if(firstCmd == 2){
144+
ret = readbits(data,len,32,bitindex);DECODERET
145+
s32 serverTime = value [[export]];
146+
147+
s32 nextBitindex = measureCsString(data,len,bitindex); // silly to do the calc twice but sadly we can't return both a string and an integer, rip
148+
str CS_SERVERINFO = readCsString(data,len,bitindex) [[export]];
149+
bitindex = nextBitindex;
150+
str CS_SYSTEMINFO = readCsString(data,len,bitindex) [[export]];
151+
152+
} else if(firstCmd == 5){
153+
154+
ret = readbits(data,len,32,bitindex);DECODERET
155+
s32 firstCommandSequence = value [[export]];
156+
str firstCommand = readString(data,len,bitindex) [[export]];
157+
158+
}
159+
160+
} else{
161+
162+
std::warning("Message length under 10");
163+
}
164+
}
165+
} [[format("format::message_name")]];
166+
167+
168+
169+
namespace format {
170+
fn message_name(ref Message value) {
171+
if(value.len == FINAL_DEMO_MESSAGE_LENGTH && value.messageNum == FINAL_DEMO_MESSAGE_NUMBER) return std::string::to_string(value.messageNum) + ": " + "Demo End Message";
172+
if(value.len < 10) return std::string::to_string(value.messageNum) + ": Len < 10";
173+
if(value.firstCmd == 7) return std::string::to_string(value.messageNum) + ": Snapshot (" +std::string::to_string(value.serverTime)+ ")";
174+
return std::string::to_string(value.messageNum) + ": " + format::cmd_name(value.firstCmd);
175+
};
176+
177+
fn firstCmd_name(s8 value) {
178+
return std::string::to_string(value) + ": " + format::cmd_name(value);
179+
};
180+
fn cmd_name(s8 value) {
181+
if(value == 0) return "Bad";
182+
if(value == 1) return "NOP";
183+
if(value == 2) return "Gamestate";
184+
if(value == 5) return "Servercommand (probably with Snapshot)";
185+
if(value == 6) return "Download";
186+
if(value == 7) return "Snapshot";
187+
return "Can't detect type ("+std::string::to_string(value)+")";
188+
};
189+
}
190+
191+
struct Q3Demo {
192+
Message messages[while(!std::mem::eof())];
193+
};
194+
195+
196+
Q3Demo q3demo @ 0x00;
19 KB
Binary file not shown.

0 commit comments

Comments
 (0)