Files
ImHex-Patterns/patterns/q3demo.hexpat
Tom Arrow ad1e300674 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 <tomarrowtomarrow@hotmail.com>
2025-06-17 02:06:24 -07:00

196 lines
15 KiB
Rust

#pragma description Quake 3 Engine demo
#pragma array_limit 2147483647
#pragma pattern_limit 2147483647
#pragma loop_limit 16384
#define FINAL_DEMO_MESSAGE_NUMBER -1
#define FINAL_DEMO_MESSAGE_LENGTH -1
#define GETINT ((data[bitindex >> 3] | (data[(bitindex >> 3)+1]<<8) | (data[(bitindex >> 3)+2]<<16) | (data[(bitindex >> 3)+3]<<32)) >> (bitindex & 7)) & 0x7FF
import type.magic;
import std.string;
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};
using Message;
struct returnValue {
s32 value;
s32 bitindex;
};
fn readbits( ref auto data, s32 len,s32 bits, s32 bitindex){
u16 huffy;
u64 ret= 0;
s32 value = 0;
s32 tmpVal = 0;
value = 0;
if(len-(bitindex >> 3)<4){ // for safety so we don't have to do checks everywhere else
return -1;
}
for (u32 i = 0, i < bits, i = i +8) {
tmpVal = GETINT;
huffy =huffdecode[tmpVal];
bitindex += (huffy>>8);
value |= (huffy & 0xFF) << i;
}
u32 valueU = value;
u32 bitindexU = bitindex;
ret = valueU | (bitindexU << 32);
return ret;
};
#define DECODERET value = ret & 2147483647;bitindex = ret >> 32;
fn readCsString(ref auto data, s32 len, s32 bitindex){
s32 value = 0;
u64 ret = 0;
str test = "";
while(true){
ret = readbits(data,len,8,bitindex);DECODERET
if(value != 3){
break;
}
// configstring
ret = readbits(data,len,16,bitindex);DECODERET
u16 csNum = value;
while(true){
ret = readbits(data,len,8,bitindex);DECODERET
s8 val = value;
if(val <= 0){
break;
}
char c = val;
test+=std::string::to_string(c);
}
return test;
}
return test;
};
fn measureCsString(ref auto data, s32 len, s32 bitindex){
s32 value = 0;
u64 ret = 0;
while(true){
ret = readbits(data,len,8,bitindex);DECODERET
if(value != 3){
break;
}
// configstring
ret = readbits(data,len,16,bitindex);DECODERET
u16 csNum = value;
while(true){
ret = readbits(data,len,8,bitindex);DECODERET
s8 val = value;
if(val <= 0){
break;
}
}
return bitindex;
}
return bitindex;
};
fn readString(ref auto data, s32 len, s32 bitindex){
s32 value = 0;
u64 ret = 0;
str test = "";
while(true){
while(true){
ret = readbits(data,len,8,bitindex);DECODERET
s8 val = value;
if(val <= 0){
break;
}
char c = val;
test+=std::string::to_string(c);
}
return test;
}
return test;
};
struct Message {
le s32 messageNum;
le s32 len;
if(len != FINAL_DEMO_MESSAGE_LENGTH || messageNum != FINAL_DEMO_MESSAGE_NUMBER) {
u8 data[len];
if( len>=10){ // should usually be true unless corrupted
s32 bitindex = 0;
s32 value=0;
bitindex = 0;
u64 ret = readbits(data,len,32,bitindex);DECODERET
s32 reliableAcknowledge = value [[export]];
ret = readbits(data,len,8,bitindex);DECODERET
s32 firstCmd = value [[export]];
if(firstCmd == 7){ // snapshot
ret = readbits(data,len,32,bitindex);DECODERET
s32 serverTime = value [[export]];
} else if(firstCmd == 2){
ret = readbits(data,len,32,bitindex);DECODERET
s32 serverTime = value [[export]];
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
str CS_SERVERINFO = readCsString(data,len,bitindex) [[export]];
bitindex = nextBitindex;
str CS_SYSTEMINFO = readCsString(data,len,bitindex) [[export]];
} else if(firstCmd == 5){
ret = readbits(data,len,32,bitindex);DECODERET
s32 firstCommandSequence = value [[export]];
str firstCommand = readString(data,len,bitindex) [[export]];
}
} else{
std::warning("Message length under 10");
}
}
} [[format("format::message_name")]];
namespace format {
fn message_name(ref Message value) {
if(value.len == FINAL_DEMO_MESSAGE_LENGTH && value.messageNum == FINAL_DEMO_MESSAGE_NUMBER) return std::string::to_string(value.messageNum) + ": " + "Demo End Message";
if(value.len < 10) return std::string::to_string(value.messageNum) + ": Len < 10";
if(value.firstCmd == 7) return std::string::to_string(value.messageNum) + ": Snapshot (" +std::string::to_string(value.serverTime)+ ")";
return std::string::to_string(value.messageNum) + ": " + format::cmd_name(value.firstCmd);
};
fn firstCmd_name(s8 value) {
return std::string::to_string(value) + ": " + format::cmd_name(value);
};
fn cmd_name(s8 value) {
if(value == 0) return "Bad";
if(value == 1) return "NOP";
if(value == 2) return "Gamestate";
if(value == 5) return "Servercommand (probably with Snapshot)";
if(value == 6) return "Download";
if(value == 7) return "Snapshot";
return "Can't detect type ("+std::string::to_string(value)+")";
};
}
struct Q3Demo {
Message messages[while(!std::mem::eof())];
};
Q3Demo q3demo @ 0x00;