jamtool is a Rust-based library and command-line utility for manipulating .JAM texture files, used by the game
Grand Prix 2. It also includes an interactive WebAssembly-based web editor for editing textures pixel-by-pixel.
Disclaimer: this is not the classic early 2000 hero-level take on reverse engineering that made Grand Prix 2 a legend, but my mid-2026 personal excuse to learn Rust with help from generative AI on something I've never dared to do before. Because of renewed interest, I hope this can be useful to someone :).
Try it out at jamtool.playlinux.net!
cargo build --releaseThe binary will be available at target/release/jamtool.
wasm-pack build --target webThis will generate the WASM and JavaScript glue code in the pkg/ directory.
./target/release/jamtool <INPUT.JAM> <OUTPUT_DIR>This extracts all textures into the specified directory as PNGs and creates a .jammeta.txt file.
Output also includes images using the haze palettes, though they are not explicitly included in the JAM file and are ignored when encoding back to JAM.
./target/release/jamtool --encode <INPUT_DIR> <OUTPUT.JAM>This takes the PNGs and the .jammeta.txt file from the directory and encodes them back into a single JAM file.
- Pixel painting — select any GP2 palette color and draw on textures click-by-click or drag
- Zoom & pan — slider, CTRL + scroll wheel, and fit-to-canvas for precise editing
- Paste images from clipboard — paste any image, position it by dragging, resize freely with corner handles, and commit with Enter — preview is quantized to GP2 colors in real time
- Load & save .JAM — open existing files and save modified ones
- Import/Export ZIP — roundtrip to indexed PNGs with metadata for external editing
- Texture browser — sidebar with thumbnails and detail panel showing all header fields
- Pixel inspector — hover any pixel to see its global palette index and RGB color
- Build the WASM package (see above).
- Serve the project root using a web server (browsers block WASM via
file://):
Python:
python3 -m http.serverNode.js:
npx serve .- Open
http://localhost:8000(or the provided port) in your browser.
I'm doing nothing new here, none of this would have been possible without the following resources:
This project is licensed under the MIT License - see the LICENSE file for details.
