diff --git a/README.md b/README.md index 12aea79..68934d7 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | PYC | `application/x-bytecode.python` | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files | | QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file | | QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files | +| Quake 3 engine demo | | [`patterns/q3demo.hexpat`](patterns/q3demo.hexpat) | Demos/replays of most Quake 3 engine games | | quantized-mesh | | [`patterns/quantized-mesh.hexpat`](patterns/quantized-mesh.hexpat) | Cesium quantized-mesh terrain | | RAR | `application/x-rar` | [`patterns/rar.hexpat`](patterns/rar.hexpat) | RAR archive file format | | RAS | `image/x-sun-raster` | [`patterns/ras.hexpat`](patterns/ras.hexpat) | RAS image files | diff --git a/patterns/q3demo.hexpat b/patterns/q3demo.hexpat new file mode 100644 index 0000000..4d013f2 --- /dev/null +++ b/patterns/q3demo.hexpat @@ -0,0 +1,196 @@ +#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; \ No newline at end of file diff --git a/tests/patterns/test_data/q3demo.hexpat.dm_16 b/tests/patterns/test_data/q3demo.hexpat.dm_16 new file mode 100644 index 0000000..f56af27 Binary files /dev/null and b/tests/patterns/test_data/q3demo.hexpat.dm_16 differ