Skip to content

Commit a926d54

Browse files
committed
Add Heretic II M32 texture support
Implement decoding and integration for Heretic II M32 RGBA textures. Adds new decoder (src/formats/m32_image.{cpp,h}), hooks it into image loading and file handling, updates build (meson), UI previews, model skin resolution, packaging/mime/desktop metadata, docs, changelog/validation scripts, and tests/fixtures (including fuzzer). Enables 16 mip levels and ensures file associations, search hints, and model/FM skin handling recognize .m32 files.
1 parent bbad0c7 commit a926d54

26 files changed

Lines changed: 297 additions & 35 deletions

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ aligned without carrying build instructions or repository maintenance notes.
7878
- Batch conversion tool for selected assets with category tabs (images, video, archives, models, sound, maps, text, other).
7979
- Manifest-driven extension commands with capability negotiation and GUI import/write-back outputs.
8080
- An installable `pakfu_core` static library with public headers and pkg-config metadata for non-UI archive, format, search, game-profile, and extension code.
81-
- Image batch conversion supports input from all supported image preview formats, including Heretic II `m8` textures, and output to all supported image-writer formats (`png`, `jpg`, `jpeg`, `bmp`, `gif`, `tga`, `tif`, `tiff`, `pcx`, `wal`, `swl`, `mip`, `lmp`, `ftx`, `dds`) with format-aware settings (quality, compression, palette source, dithering, alpha threshold, embedded palette where applicable).
81+
- Image batch conversion supports input from all supported image preview formats, including Heretic II `m8` and `m32` textures, and output to all supported image-writer formats (`png`, `jpg`, `jpeg`, `bmp`, `gif`, `tga`, `tif`, `tiff`, `pcx`, `wal`, `swl`, `mip`, `lmp`, `ftx`, `dds`) with format-aware settings (quality, compression, palette source, dithering, alpha threshold, embedded palette where applicable).
8282
- Preview overviews surface asset context such as palette provenance, model companion files, shader texture dependency resolution, active 3D renderer state, and preview fallback notes.
8383
- Heavy previews report timing profiles, reuse cached temp exports for repeated media/model previews, and cap BSP texture resolution work for very large maps.
8484
- Modern platform-native open/save/folder dialogs with standard breadcrumbs/bookmarks and robust cross-platform behavior.
@@ -110,7 +110,7 @@ quick reference.
110110
### Preview And Inspector Support
111111
- Images:
112112
- Core: `pcx`, `wal`, `png`, `tga`, `jpg`
113-
- Also supported: `jpeg`, `bmp`, `gif`, `tif`, `tiff`, `swl`, `m8`, `mip`, `lmp`, `dds`, `ftx`
113+
- Also supported: `jpeg`, `bmp`, `gif`, `tif`, `tiff`, `swl`, `m8`, `m32`, `mip`, `lmp`, `dds`, `ftx`
114114
- Audio:
115115
- Core: `wav`, `ogg`
116116
- Also supported: `mp3`, `idwav` (Doom 3 BFG; converted to WAV for playback when payload codec is supported)
@@ -128,9 +128,9 @@ quick reference.
128128
Notes:
129129
- Multimedia playback support depends on the installed Qt Multimedia backend and codecs.
130130
- `cin` and `roq` are also handled by built-in cinematic decoders.
131-
- Some indexed formats (`wal`, `mip`, selected `lmp` cases) use game palettes when required; Heretic II `m8` textures carry an embedded palette.
131+
- Some indexed formats (`wal`, `mip`, selected `lmp` cases) use game palettes when required; Heretic II `m8` textures carry an embedded palette, while Heretic II `m32` textures store RGBA pixels.
132132
- Heretic II `bk` book sprites composite referenced `.m8` tiles, while `os` dynamic scripts are binary bytecode and open as metadata/opcode previews.
133-
- BSP inspector/preview supports Heretic II `IBSP`/converted `QBSP` maps with `.m8` texture resolution, plus Quake 3-derived families including FAKK variants used by Heavy Metal: F.A.K.K.2 and American McGee's Alice (`FAKK` v42 checksum-header BSPs).
133+
- BSP inspector/preview supports Heretic II `IBSP`/converted `QBSP` maps with `.m32`/`.m8` texture resolution, plus Quake 3-derived families including FAKK variants used by Heavy Metal: F.A.K.K.2 and American McGee's Alice (`FAKK` v42 checksum-header BSPs).
134134
- idTech4 `.map` source files and `.proc` compiled render descriptions open as text/metadata inspections. 3D map rendering is currently scoped to Quake-family `.bsp` files; idTech4 `.proc`/collision map rendering is not claimed.
135135

136136
## Build and Run

docs/CREDITS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ That compatibility is informed by public format lineage, engine behavior, and hi
1515
- id Software family engines and assets (Quake, Quake II, Quake III, Doom-family)
1616
- Related studio ecosystems that built on or extended those formats (for example Raven/Ritual/Gray Matter era pipelines)
1717
- Community-maintained references from open-source engine projects and modding documentation
18-
- [0lvin/heretic2](https://github.com/0lvin/heretic2), used as the credited Heretic II source reference for `.m8`, `.fm`, `.bk`, `.os`, and Heretic II BSP behavior
18+
- [0lvin/heretic2](https://github.com/0lvin/heretic2), checked at revision `16aaf15b66183debb4d770ea13f25b43c4dfae0b`, used as the credited Heretic II source reference for `.m8`, `.m32`, `.fm`, `.bk`, `.os`, and Heretic II BSP behavior
1919

2020
## Thanks
2121
- Modding communities who preserved format knowledge, test assets, and practical edge cases across decades of tool use

docs/DEPENDENCIES.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
- WAL: built-in decoder (Quake II; requires `pics/colormap.pcx` palette; previews all mip levels)
5656
- SWL: built-in decoder (SiN texture; embedded palette; previews mip levels)
5757
- M8: built-in decoder (Heretic II texture; embedded palette; previews up to 16 mip levels; format reference credited to [0lvin/heretic2](https://github.com/0lvin/heretic2))
58+
- M32: built-in decoder (Heretic II RGBA texture; previews up to 16 mip levels; format reference credited to [0lvin/heretic2](https://github.com/0lvin/heretic2))
5859
- DDS: built-in decoder (uncompressed masks + BC1/BC2/BC3/BC4/BC5, including DX10 headers)
5960

6061
- Archive support:
@@ -65,7 +66,7 @@
6566
- Quake Live Beta encrypted PK3: built-in decrypt/encrypt (XOR) loader/writer
6667

6768
- Model loaders:
68-
- FM: built-in loader (Heretic II mesh frames with MD2-style vertices, mesh-node surfaces, and `.m8` skin hints; format reference credited to [0lvin/heretic2](https://github.com/0lvin/heretic2))
69+
- FM: built-in loader (Heretic II mesh frames with MD2-style vertices, mesh-node surfaces, and `.m8`/`.m32` skin hints; format reference credited to [0lvin/heretic2](https://github.com/0lvin/heretic2))
6970
- MDC: built-in loader (RtCW/Enemy Territory compressed mesh)
7071
- MD4: built-in loader (RtCW/Enemy Territory skeletal mesh; frame-0 weighted reconstruction)
7172
- MDR: built-in loader (Raven skeletal mesh used by Elite Force/JK2-family games; frame-0 weighted reconstruction)
@@ -74,7 +75,7 @@
7475
- GLM: built-in loader (Ghoul2 mesh; companion `.gla` base pose when available)
7576

7677
- BSP/map preview:
77-
- Heretic II: built-in Quake II-family BSP loader support for native `IBSP` maps and converted `QBSP` maps, including Heretic II texinfo flag detection, 64-byte converted texture names, and `.m8` texture lookup priority; format reference credited to [0lvin/heretic2](https://github.com/0lvin/heretic2)
78+
- Heretic II: built-in Quake II-family BSP loader support for native `IBSP` maps and converted `QBSP` maps, including Heretic II texinfo flag detection, 64-byte converted texture names, and `.m32`/`.m8` texture lookup priority; format reference credited to [0lvin/heretic2](https://github.com/0lvin/heretic2)
7879
- idTech4: `.map` source files and `.proc` compiled render descriptions are text/metadata-inspected with explicit scope notes; PakFu does not currently claim 3D idTech4 `.proc` or collision-map rendering
7980

8081
- Cinematics (built-in decoders; used for thumbnails + playback widget):

docs/FILE_ASSOCIATION_ICONS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PakFu uses a per-extension icon set for managed archive, image, video, audio, mo
2323
| Image | `.wal` | `#1565C0` |
2424
| Image | `.swl` | `#2E7D32` |
2525
| Image | `.m8` | `#7B1FA2` |
26+
| Image | `.m32` | `#8E24AA` |
2627
| Image | `.mip` | `#6A1B9A` |
2728
| Image | `.lmp` | `#5D4037` |
2829
| Image | `.dds` | `#0277BD` |

docs/SUPPORT_MATRIX.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ repository does not need copyrighted game assets to verify the core contract.
4141
| Area | Formats | Current status | Evidence |
4242
|---|---|---|---|
4343
| Core image preview | `pcx`, `wal`, `png`, `tga`, `jpg`, `jpeg` | Supported | TGA decode and PCX encode/decode are fixture-backed; PNG/JPEG use Qt; WAL requires a 256-color Quake II palette |
44-
| Additional image preview | `bmp`, `gif`, `tif`, `tiff`, `swl`, `m8`, `mip`, `lmp`, `dds`, `ftx` | Supported | M8 is fixture-backed; other loaders are implementation-backed built-ins or Qt image readers; M8/SWL use embedded palettes and expose mip previews |
44+
| Additional image preview | `bmp`, `gif`, `tif`, `tiff`, `swl`, `m8`, `m32`, `mip`, `lmp`, `dds`, `ftx` | Supported | M8 and M32 are fixture-backed; other loaders are implementation-backed built-ins or Qt image readers; M8/SWL use embedded palettes, M32 stores RGBA, and mip-capable formats expose mip previews |
4545
| Image conversion output | `png`, `jpg`, `bmp`, `gif`, `tga`, `tiff`, `pcx`, `wal`, `swl`, `mip`, `lmp`, `ftx`, `dds` | Supported | PCX output is fixture-backed; remaining formats are implementation-backed and format-aware |
4646
| Audio playback | `wav`, `ogg`, `mp3`, `idwav` | Supported | Backend-dependent playback; IDWAV is converted to WAV for supported embedded codecs |
4747
| Built-in cinematics | `cin`, `roq` | Supported | Implementation-backed built-in decoders |
4848
| Backend video playback | `bik`, `ogv`, `mp4`, `mkv`, `avi`, `webm` | Supported when codecs are available | Backend-dependent Qt Multimedia playback |
49-
| Models | `mdl`, `md2`, `fm`, `md3`, `mdc`, `md4`, `mdr`, `skb`, `skd`, `mdm`, `glm`, `iqm`, `md5mesh`, `tan`, `obj`, `lwo` | Supported | FM is fixture-backed; other loaders are implementation-backed; FM resolves Heretic II `.m8` skins |
49+
| Models | `mdl`, `md2`, `fm`, `md3`, `mdc`, `md4`, `mdr`, `skb`, `skd`, `mdm`, `glm`, `iqm`, `md5mesh`, `tan`, `obj`, `lwo` | Supported | FM is fixture-backed; other loaders are implementation-backed; FM resolves Heretic II `.m8`/`.m32` skins |
5050
| BSP/map preview | `bsp` | Supported | Heretic II native `IBSP` and converted `QBSP` BSPs are fixture-backed; Quake/Quake II/Quake III-family loaders are implementation-backed |
5151
| idTech4 map inspection | `map`, `proc` | Text/metadata inspection supported; no 3D idTech4 renderer is claimed | Fixture-backed synthetic `.map` source and `.proc` render-description summaries |
5252
| idTech sprite/assets | `spr`, `sp2`, `spr2`, `bk`, `os` | Supported | BK/OS are fixture-backed; SPR/SP2 are implementation-backed animated previews and metadata views |

packaging/linux/io.github.themuffinator.PakFu.desktop

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ Keywords=pak;pk3;pk4;wad;idtech;quake;doom;archive;assets;
99
Terminal=false
1010
StartupNotify=true
1111
StartupWMClass=PakFu
12-
MimeType=application/x-idtech-pak;application/x-idtech-sin;application/x-idtech-pk3;application/x-idtech-pk4;application/x-idtech-pkz;application/zip;application/x-idtech-resources;application/x-doom-wad;application/x-doom-wad2;application/x-halflife-wad3;application/x-quake-bsp;text/x-idtech-map;text/x-idtech-proc;image/x-pcx;image/x-idtech-wal;image/x-idtech-swl;image/x-heretic2-m8;image/x-idtech-mip;image/x-idtech-lmp;image/x-dds;image/vnd-ms.dds;image/x-kingpin-ftx;image/png;image/jpeg;image/x-tga;image/bmp;image/gif;image/tiff;video/x-cin;video/x-roq;video/ogg;video/x-bink;video/mp4;video/x-matroska;video/x-msvideo;video/webm;audio/x-wav;audio/wav;audio/x-idwav;audio/ogg;audio/mpeg;model/x-quake-mdl;model/x-quake-md2;model/x-heretic2-fm;model/x-idtech-md3;model/x-idtech-mdc;model/x-idtech-md4;model/x-raven-mdr;model/x-idtech-skb;model/x-idtech-skd;model/x-rtcw-mdm;model/x-raven-glm;model/x-iqm;model/x-md5mesh;model/x-ritual-tan;model/x-lightwave-object;model/obj;text/x-idtech-cfg;text/x-idtech-shader;text/x-idtech-menu;text/x-idtech-def;text/x-idtech-mtr;text/plain;application/json;font/ttf;font/otf;image/x-quake-spr;image/x-quake2-sp2;image/x-quake2-spr2;image/x-heretic2-bk;application/x-heretic2-os;application/x-quake2-dm2;application/x-idtech-aas;application/x-qvm;application/x-idtech-crc;model/x-idtech-tag;model/x-raven-mdx;model/x-raven-mds;model/x-heretic2-skc;model/x-heretic2-ska;
13-
X-PakFu-Managed-Extensions=pak;sin;pk3;pk4;pkz;zip;resources;wad;wad2;wad3;bsp;map;proc;pcx;wal;swl;m8;mip;lmp;dds;ftx;png;jpg;jpeg;tga;bmp;gif;tif;tiff;cin;roq;ogv;bik;mp4;mkv;avi;webm;wav;idwav;ogg;mp3;mdl;md2;fm;md3;mdc;md4;mdr;skb;skd;mdm;glm;iqm;md5mesh;tan;lwo;obj;cfg;shader;menu;def;mtr;txt;json;ttf;otf;spr;sp2;spr2;bk;os;dm2;aas;qvm;crc;tag;mdx;mds;skc;ska;
12+
MimeType=application/x-idtech-pak;application/x-idtech-sin;application/x-idtech-pk3;application/x-idtech-pk4;application/x-idtech-pkz;application/zip;application/x-idtech-resources;application/x-doom-wad;application/x-doom-wad2;application/x-halflife-wad3;application/x-quake-bsp;text/x-idtech-map;text/x-idtech-proc;image/x-pcx;image/x-idtech-wal;image/x-idtech-swl;image/x-heretic2-m8;image/x-heretic2-m32;image/x-idtech-mip;image/x-idtech-lmp;image/x-dds;image/vnd-ms.dds;image/x-kingpin-ftx;image/png;image/jpeg;image/x-tga;image/bmp;image/gif;image/tiff;video/x-cin;video/x-roq;video/ogg;video/x-bink;video/mp4;video/x-matroska;video/x-msvideo;video/webm;audio/x-wav;audio/wav;audio/x-idwav;audio/ogg;audio/mpeg;model/x-quake-mdl;model/x-quake-md2;model/x-heretic2-fm;model/x-idtech-md3;model/x-idtech-mdc;model/x-idtech-md4;model/x-raven-mdr;model/x-idtech-skb;model/x-idtech-skd;model/x-rtcw-mdm;model/x-raven-glm;model/x-iqm;model/x-md5mesh;model/x-ritual-tan;model/x-lightwave-object;model/obj;text/x-idtech-cfg;text/x-idtech-shader;text/x-idtech-menu;text/x-idtech-def;text/x-idtech-mtr;text/plain;application/json;font/ttf;font/otf;image/x-quake-spr;image/x-quake2-sp2;image/x-quake2-spr2;image/x-heretic2-bk;application/x-heretic2-os;application/x-quake2-dm2;application/x-idtech-aas;application/x-qvm;application/x-idtech-crc;model/x-idtech-tag;model/x-raven-mdx;model/x-raven-mds;model/x-heretic2-skc;model/x-heretic2-ska;
13+
X-PakFu-Managed-Extensions=pak;sin;pk3;pk4;pkz;zip;resources;wad;wad2;wad3;bsp;map;proc;pcx;wal;swl;m8;m32;mip;lmp;dds;ftx;png;jpg;jpeg;tga;bmp;gif;tif;tiff;cin;roq;ogv;bik;mp4;mkv;avi;webm;wav;idwav;ogg;mp3;mdl;md2;fm;md3;mdc;md4;mdr;skb;skd;mdm;glm;iqm;md5mesh;tan;lwo;obj;cfg;shader;menu;def;mtr;txt;json;ttf;otf;spr;sp2;spr2;bk;os;dm2;aas;qvm;crc;tag;mdx;mds;skc;ska;

packaging/linux/io.github.themuffinator.PakFu.metainfo.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<mediatype>application/x-quake-bsp</mediatype>
1919
<mediatype>text/x-idtech-map</mediatype>
2020
<mediatype>image/x-idtech-wal</mediatype>
21+
<mediatype>image/x-heretic2-m32</mediatype>
2122
<mediatype>video/x-roq</mediatype>
2223
<mediatype>audio/x-idwav</mediatype>
2324
<mediatype>model/x-idtech-md3</mediatype>

packaging/linux/io.github.themuffinator.PakFu.mime.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<mime-type type="image/x-idtech-wal"><comment>idTech WAL texture</comment><glob pattern="*.wal"/></mime-type>
1717
<mime-type type="image/x-idtech-swl"><comment>SiN SWL texture</comment><glob pattern="*.swl"/></mime-type>
1818
<mime-type type="image/x-heretic2-m8"><comment>Heretic II M8 texture</comment><glob pattern="*.m8"/></mime-type>
19+
<mime-type type="image/x-heretic2-m32"><comment>Heretic II M32 texture</comment><glob pattern="*.m32"/></mime-type>
1920
<mime-type type="image/x-idtech-mip"><comment>idTech MIP texture</comment><glob pattern="*.mip"/></mime-type>
2021
<mime-type type="image/x-idtech-lmp"><comment>idTech LMP lump image</comment><glob pattern="*.lmp"/></mime-type>
2122
<mime-type type="image/x-kingpin-ftx"><comment>Kingpin FTX texture</comment><glob pattern="*.ftx"/></mime-type>

packaging/macos/Info.plist.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<string>wal</string>
9090
<string>swl</string>
9191
<string>m8</string>
92+
<string>m32</string>
9293
<string>mip</string>
9394
<string>lmp</string>
9495
<string>dds</string>

scripts/update_changelog.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"memory",
6666
"model",
6767
"m8",
68+
"m32",
6869
"bk",
6970
"fm",
7071
"opengl",
@@ -96,10 +97,12 @@
9697
"heretic",
9798
"heretic ii",
9899
"m8",
100+
"m32",
99101
"bk",
100102
"fm",
101103
" os ",
102104
"src/formats/m8_image",
105+
"src/formats/m32_image",
103106
"src/formats/idtech_asset_loader",
104107
"src/formats/model.cpp",
105108
"src/formats/sprite_loader.cpp",
@@ -272,7 +275,7 @@ def classify_user_change(
272275
items.append(
273276
(
274277
"Compatibility",
275-
"Heretic II filetype support has been added, including M8 textures, FM models, BK book sprites, OS script bytecode previews, and related file associations.",
278+
"Heretic II filetype support has been added, including M8/M32 textures, FM models, BK book sprites, OS script bytecode previews, and related file associations.",
276279
)
277280
)
278281
if contains_any(context, IDTECH4_MAP_KEYWORDS):

0 commit comments

Comments
 (0)