| Crates.io | wasm-squeeze |
| lib.rs | wasm-squeeze |
| version | 0.1.0 |
| created_at | 2025-09-17 16:15:20.403212+00 |
| updated_at | 2025-09-17 16:15:20.403212+00 |
| description | UPX-like utility to create self-decompressable WASM-4 cartridges |
| homepage | |
| repository | https://github.com/zetanumbers/wasm-squeeze |
| max_upload_size | |
| id | 1843554 |
| size | 67,125 |
wasm-squeeze is an UPX-like tool to compress WASM-4 cartridges and embed the decompressor into the binary for it to decompress itself.
Generally speaking, this tool allows to reduce cartridge's file size, so that it can be stuffed with some more code and data before reaching 64KiB file size boundary of WASM-4! However right now it doesn't reduce RAM consumption.
Use cargo for now:
cargo install wasm-squeeze
wasm-squeeze example.wasm -o example-squeezed.wasm
Please note that this tool may introduce redundant information into the cartridge, so it's most probably desirable to use wasm-opt after the module got through wasm-squeeze.
You might find stdio support useful for this, just specify "-" as input or output filepaths (not specifying those works too).
I have compared all cartridge builds published on the official site (back then) processed by wasm-opt -Oz -uim -all and the same cartridge builds going through wasm-squeeze first and then wasm-opt with aformentioned arguments.
Negative values (size increases) were preserved, however in practice users should measure benefits and not use wasm-squeeze in such cases.
Benchmarks were done on de7e7ab commit:
| name | old_size | new_size | size_decrease% |
|---|---|---|---|
| wasm4-gbvgm-player | 43.1 KiB | 4.0 KiB | 90.67 |
| zoopzoop | 19.8 KiB | 7.3 KiB | 63.07 |
| lingword | 38.4 KiB | 14.7 KiB | 61.74 |
| nyancat | 25.0 KiB | 10.7 KiB | 57.20 |
| ur | 40.3 KiB | 17.9 KiB | 55.50 |
| the-legend-of-geml-awakening | 45.6 KiB | 21.1 KiB | 53.85 |
| lad2024 | 8.6 KiB | 4.5 KiB | 48.14 |
| trials-of-the-dark-sea | 44.2 KiB | 23.4 KiB | 46.94 |
| miku-15 | 39.3 KiB | 22.2 KiB | 43.47 |
| ioccc98flightsim | 39.1 KiB | 22.2 KiB | 43.09 |
| palette-previewer | 9.1 KiB | 5.4 KiB | 40.10 |
| formula-1 | 8.2 KiB | 4.9 KiB | 40.01 |
| strikeforce | 19.4 KiB | 11.9 KiB | 38.76 |
| future-avoid | 26.8 KiB | 16.7 KiB | 37.59 |
| fuzzy-world-cup | 38.8 KiB | 26.0 KiB | 33.19 |
| presents-to-the-metal | 15.7 KiB | 10.8 KiB | 31.01 |
| first-flight | 54.2 KiB | 39.0 KiB | 28.03 |
| rubido | 27.0 KiB | 19.5 KiB | 27.79 |
| micro-quest | 15.6 KiB | 11.3 KiB | 27.50 |
| bombfighters | 38.3 KiB | 28.6 KiB | 25.28 |
| waternet | 29.4 KiB | 22.3 KiB | 24.30 |
| escape-guldur | 27.4 KiB | 21.0 KiB | 23.55 |
| punch-em-up | 33.8 KiB | 25.9 KiB | 23.40 |
| explore-the-grotto | 50.8 KiB | 39.1 KiB | 23.09 |
| racer | 35.1 KiB | 27.1 KiB | 22.92 |
| piano | 8.2 KiB | 6.3 KiB | 22.88 |
| to-the-core | 18.3 KiB | 14.4 KiB | 21.03 |
| mind-palace | 28.8 KiB | 22.8 KiB | 20.90 |
| minicraft | 34.2 KiB | 27.2 KiB | 20.49 |
| plctfarmer | 40.0 KiB | 32.1 KiB | 19.84 |
| you-will-return | 42.8 KiB | 34.4 KiB | 19.78 |
| break-it | 4.5 KiB | 3.6 KiB | 19.63 |
| wormhole | 23.0 KiB | 18.6 KiB | 19.42 |
| tictactoe | 13.0 KiB | 10.5 KiB | 19.13 |
| sound-test | 34.7 KiB | 28.1 KiB | 18.97 |
| touhou-spirits | 53.3 KiB | 43.3 KiB | 18.62 |
| zxz | 18.2 KiB | 15.1 KiB | 17.24 |
| hills-moonlight | 18.6 KiB | 15.4 KiB | 16.99 |
| samurai-revenge | 34.7 KiB | 29.1 KiB | 16.32 |
| totally-not-sumo | 18.8 KiB | 15.8 KiB | 15.92 |
| journey-to-entorus | 54.6 KiB | 45.9 KiB | 15.91 |
| disk-0-madness | 52.8 KiB | 44.5 KiB | 15.82 |
| ninja-vs-knights | 56.6 KiB | 49.1 KiB | 13.19 |
| antcopter | 32.6 KiB | 28.4 KiB | 12.88 |
| spunky | 40.6 KiB | 35.4 KiB | 12.87 |
| wasm4nia | 20.2 KiB | 17.7 KiB | 12.57 |
| wasm4-city | 39.9 KiB | 35.0 KiB | 12.17 |
| miniciv | 63.7 KiB | 56.1 KiB | 11.97 |
| sokoban | 3.4 KiB | 3.0 KiB | 11.67 |
| lumber-night | 33.3 KiB | 29.8 KiB | 10.47 |
| wumpus-hunt | 17.9 KiB | 16.2 KiB | 9.87 |
| wired | 35.1 KiB | 31.6 KiB | 9.83 |
| train | 31.6 KiB | 28.6 KiB | 9.59 |
| hotw | 32.7 KiB | 29.7 KiB | 9.36 |
| kittygame | 51.2 KiB | 46.4 KiB | 9.32 |
| dodgeball | 23.7 KiB | 21.6 KiB | 8.64 |
| snake | 10.6 KiB | 9.8 KiB | 8.14 |
| floppy-fish | 14.6 KiB | 13.4 KiB | 7.99 |
| glowfish-chess | 55.5 KiB | 51.2 KiB | 7.84 |
| iwas | 54.0 KiB | 49.8 KiB | 7.81 |
| wasm4-rpg | 59.5 KiB | 54.9 KiB | 7.70 |
| corn | 8.5 KiB | 7.9 KiB | 7.43 |
| w4f | 35.9 KiB | 33.5 KiB | 6.77 |
| big-space-iron | 21.3 KiB | 20.0 KiB | 6.35 |
| minesweeper | 19.2 KiB | 18.1 KiB | 5.55 |
| ping | 23.6 KiB | 22.3 KiB | 5.41 |
| the-romans-are-coming | 40.5 KiB | 38.7 KiB | 4.44 |
| tail-gunner | 19.5 KiB | 18.8 KiB | 3.96 |
| space-kommand | 22.2 KiB | 21.4 KiB | 3.71 |
| tankle | 34.5 KiB | 33.2 KiB | 3.55 |
| dashy-dango | 44.2 KiB | 42.7 KiB | 3.39 |
| rolly-dango | 58.1 KiB | 56.2 KiB | 3.27 |
| phantom-shift | 9.7 KiB | 9.4 KiB | 3.16 |
| wasm-wars | 13.2 KiB | 12.8 KiB | 3.09 |
| taufl | 29.8 KiB | 29.1 KiB | 2.26 |
| starshard-scavengers | 65.5 KiB | 64.2 KiB | 1.98 |
| fools-paradise | 36.4 KiB | 35.8 KiB | 1.69 |
| tankbattle | 17.4 KiB | 17.2 KiB | 1.42 |
| starfighterarena | 22.3 KiB | 22.1 KiB | 0.84 |
| hammer-joe | 37.3 KiB | 37.0 KiB | 0.68 |
| assemblio | 31.8 KiB | 31.6 KiB | 0.51 |
| raw-assembly | 253 B | 253 B | 0 |
| plasma-cube | 4.8 KiB | 4.8 KiB | 0 |
| lime-volleyball | 3.7 KiB | 3.7 KiB | 0 |
| maze-wanderer | 9.7 KiB | 9.7 KiB | 0 |
| bubblewrap | 8.0 KiB | 8.0 KiB | 0 |
| mouse-demo | 1.4 KiB | 1.4 KiB | 0 |
| 2048 | 12.0 KiB | 12.0 KiB | 0 |
| skipahead | 529 B | 529 B | 0 |
| snakery | 17.7 KiB | 17.7 KiB | 0 |
| mazethingie | 3.3 KiB | 3.3 KiB | 0 |
| seed-creator-showcase | 3.7 KiB | 3.7 KiB | 0 |
| tinypong | 1.1 KiB | 1.1 KiB | 0 |
| watris | 2.5 KiB | 2.5 KiB | 0 |
| sound-demo | 1.5 KiB | 1.5 KiB | 0 |
| text-input | 4.7 KiB | 4.7 KiB | 0 |
| platformer-test | 1.1 KiB | 1.1 KiB | 0 |
| meteoroids | 17.6 KiB | 17.6 KiB | 0 |
| seal-adventure | 2.1 KiB | 2.1 KiB | 0 |
| match3 | 2.5 KiB | 2.5 KiB | 0 |
| one-slime-army | 12.7 KiB | 12.7 KiB | 0 |
| pong | 6.7 KiB | 6.7 KiB | 0 |
| shieldshooter | 3.1 KiB | 3.1 KiB | 0 |
| wloku | 7.0 KiB | 7.0 KiB | 0 |
| image-carousel | 60.0 KiB | 60.0 KiB | 0 |
| pocket-dust | 8.1 KiB | 8.1 KiB | 0 |
| projectron | 12.2 KiB | 12.2 KiB | 0 |
| maze | 3.5 KiB | 3.5 KiB | 0 |
| starfightercreator | 13.7 KiB | 13.7 KiB | 0 |
| endless-runner | 2.5 KiB | 2.5 KiB | 0 |
| space-delivery | 11.1 KiB | 11.1 KiB | 0 |
| pid-controller | 10.0 KiB | 10.1 KiB | -0.62 |
| simple-space-invaders | 10.2 KiB | 10.5 KiB | -3.25 |
| puyo | 12.1 KiB | 12.6 KiB | -4.03 |
| lakeshooter | 8.8 KiB | 9.2 KiB | -4.69 |
| smash-sugar-parallelepipeds | 3.9 KiB | 4.4 KiB | -12.03 |
| simple-rocket | 4.1 KiB | 4.6 KiB | -12.49 |
| game-of-life | 2.9 KiB | 3.3 KiB | -16.94 |
| dont-smash-into-obstacles | 2.6 KiB | 3.0 KiB | -17.88 |
| game-of-life-zig-edition | 2.7 KiB | 3.2 KiB | -19.60 |
To put it simply, we first compile the upkr unpacker from C to WASM and optimize it for size for it to be embedded directly into the wasm-squeeze binary.
While wasm-squeeze executes, it first analyzes the input WASM module to extract relevant information.
Then the unpacker WASM module is parsed and the input module is reencoded with functions and types from the unpacker module.
Data segments are merged into a big single segment, compressed via upkr, and is encoded at some offset from 0 address.
Then the preamble code for decompression is added to the WASM's special start function, which is created in case it doesn't exist.
This preamble code does data decompression, moves decompressed data into original position, and then does some cleanup after that.
If wasm-squeeze notices that cartridge's size haven't decreased, wasm-squeeze tries to simply passthrough the input module to the output.
Thanks to @exoticorn for implementing the upkr crate, responsible for compression and decompression, designed with WASM in mind. Please check out MicroW8, another WebAssembly based fantasy console, which upkr was created for.
Thanks to @aduros for creating WASM-4 project, a beautiful place where spanned such creative community.
Thanks to the folks from @bytecodealliance for maintaining extensive for WASM manipulation wasmparser and wasm-encoder crates.