szs

szs is a WIP crate for compressing and decompressing SZS formats used in the Nintendo GameCube and Wii games. The library provides C bindings, making it useful in both Rust and C/C++ based projects.

Warning: The library is not currently in a fully functional state. Use at your own risk. 0.1.0 will start the release series. Warning: These algorithms are currently implemented in the C programming language, and not in Rust. While they have been rigorously validated, please use at your own risk. A Rust rewrite is planned.

Algorithms

Stats

Task: Compress N64 Bowser Castle (Source filesize: 2,574,368) | Method | Time Taken | Compression Rate | |--------|------------|------------------| | worst-case-encoding | 0s | 112.50% | | ctgp | 0.31s | 71.41% | | Haroohie | 0.58s | 57.23% | | mkw-sp | 3.76s | 57.23% | | nintendo | 5.93s | 56.87% | | Comparison with other libraries: | | | | Haroohie (C#) | 0.71s | 57.23% | | wszst (fast) | 0.387s (via shell) | 65.78% | | wszst (standard) | 1.776s (via shell) | 57.23% | | wszst (ultra) | 2.727s (via shell) | 56.65% | | yaz0-rs | 11.34s (via shell) | 56.87% |

In most cases, the Haroohie algorithm gets the best compression the fastest, although wszst ultra is able to get the smallest filesizes if absolutely necessary.

Rust

The following snippet demonstrates how to compress a file as a SZS format using Rust:

```rs // Sample source bytes to be encoded. let srcdata: Vec = "Hello, World!".asbytes().to_vec();

// Calculate the upper bound for encoding. let maxlen = encodedupperbound(srcdata.len() as u32);

// Allocate a buffer based on the calculated upper bound. let mut dstdata: Vec = vec![0; maxlen as usize];

// Boyer-Moore-horspool variant let algo_number: u32 = 0;

match encodealgofast(&mut dstdata, &srcdata, algonumber) { Ok(encodedlen) => { println!("Encoded {} bytes", encodedlen); // Optionally: shrink the dstdata to the actual size. dstdata.truncate(encodedlen as usize); } Err(EncodeAlgoError::Error(errmsg)) => { println!("Encoding failed: {}", errmsg); } } ```

Example (C Bindings)

```c

include szs.h

// Calculate the upper bound for encoding. u32 maxsize = riiszsencodedupperbound(sizeof(data));

// Allocate a buffer based on the calculated upper bound. void* encodedbuf = malloc(maxsize); if (!buf) { fprintf(stderr, "Failed to allocate %u bytes.\n", max_size); return -1; }

// Boyer-Moore-horspool variant u32 algorithm = RIISZSENCODEALGONINTENDO;

u32 actuallen = 0; const char* ec = riiszsencodealgofast(encodedbuf, maxsize, data, sizeof(data), &actuallen, algorithm); if (ec != NULL) { fprintf(stderr, "Failed to compress: %s\n", ec); riiszsfreeerrormessage(ec); return -1; } printf("Encoded %u bytes.\n", actuallen); // Optionally: shrink the dstdata to the actual size. encodedbuf = realloc(encodedbuf, actual_len); ```

C++ Wrapper on top of C Bindings

```cpp

include szs.h

// Boyer-Moore-horspool variant szs::Algo algorithm = szs::Algo::Nintendo; auto encoded = szs::encodealgo(data, algorithm); if (!encoded) std::println(stderr, "Failed to compress: {}.", encoded.error()); { return -1; } std::vector szsdata = *encoded; std::println("Encoded {} bytes.", szs_data.size()); ```

License

This library is published under the MIT license.