The LZMA encoder was called with numThreads=8 at all 19 call sites,
but LZMA only supports 1 or 2 (and _7ZIP_ST forces it to 1 anyway).
Replace with LZMA_THREADS(ctx) macro that clamps ctx->num_threads
to [1, 2], making the code say what it means and honoring the
consumer's threading preference from the threads=N option.
Switch zstd encoder from simple API (ZSTD_compress) to advanced API
(ZSTD_CCtx + ZSTD_compress2) with configurable worker threads via
ZSTD_c_nbWorkers. Consumer controls threading through threads=N
option string parameter. Default is 1 (single-threaded, bit-identical
output to previous behavior).
- Enable ZSTD_MULTITHREAD compile definition and link pthreads
- Add num_threads field to options struct and context
- Parse threads=N in option string (clamped >= 1)
- Rewrite aaruf_zstd_encode_buffer() with num_threads parameter
- Update all call sites (write.c, close.c)
The spec used `2 << x` where `1 << x` (= 2^x) was intended.
`2 << x` equals 2^(x+1), which is off by factor 2. The code
unanimously uses `1 << x` across 40+ sites. Corrects the
example result from 0x6A0000 to 0x350000 accordingly.
Replace string-keyed uthash lookups with HASH_FIND/HASH_ADD on native
uint64_t keys. This eliminates per-lookup malloc/snprintf/strlen/free
overhead from the block cache hot path (2 lookups per sector read).
Before: malloc(17) + snprintf hex + HASH_FIND_STR + free per lookup
After: HASH_FIND with 8-byte integer key, zero allocations
Also removes the unused string-key API (find_in_cache/add_to_cache)
and the uint64_to_string helper — all callers use uint64 keys.
Fix off-by-one in eviction: >= caused cache to hold max_items-1
entries instead of max_items. Changed to > so the configured
capacity is honored exactly.
When reading back Mode 2 sectors with errored ECC/EDC (SectorStatusErrored),
the else branch copied 2328 bytes from bare_data. However, bare_data only
contains the user data portion (2048 bytes for Form 1, 2324 for Form 2).
The EDC/ECC suffix was stored separately in sector_suffix during write but
never read back, causing the suffix area to contain stale data from adjacent
sectors in the decompressed block.
Fix both DDT v2 and v1 code paths to check the subheader form bit and copy
user data + suffix from their respective storage locations.
Affects any Mode 2 disc image (Dreamcast, PS1, PS2 CD, Saturn, Mega CD,
PC Engine CD, Neo Geo CD) where sectors have incorrect or zeroed ECC/EDC.
Implements zstd as an alternative to LZMA for data block and
subchannel compression using the allocated compression IDs 4
(kCompressionZstd) and 5 (kCompressionZstdCst).
Adds zstd v1.5.7 as a bundled submodule with a static library
build including x86_64 assembly fast path for decompression.
Write path selects zstd or LZMA based on the zstd option.
Subchannel blocks use zstd+CST instead of LZMA+CST when enabled.
LZMA properties header is only written for LZMA-based compression
types, preventing format corruption in zstd-compressed images.
Activated via options string: "zstd=true;zstd_level=19".
Default remains LZMA for backwards compatibility.
Tested: SHA-256 verified lossless roundtrips across 9 disc systems
(Dreamcast, Saturn, Mega CD, PC Engine CD, Neo Geo CD, PS1, PS2 CD,
PS2 DVD) and PS1 SBI subchannel preservation with zstd+CST.
Replace hardcoded SHARED in add_library() with the standard CMake
BUILD_SHARED_LIBS variable. Default remains shared for backwards
compatibility.
-DBUILD_SHARED_LIBS=OFF → static library (libaaruformat.a)
-DBUILD_SHARED_LIBS=ON → shared library (libaaruformat.so, default)
Also define _POSIX_C_SOURCE=200809L on non-Windows platforms so that
POSIX functions (strdup, fseeko, ftello) are properly declared when
building with CMAKE_C_EXTENSIONS=OFF (strict C99 mode).
Tested: shared + static with GCC, static with musl cross-compiler.
When reading back Mode 2 Form 2 sectors with SectorStatusMode2Form2NoCrc,
the 4-byte EDC field at bytes 2348-2351 was left untouched. Since the
caller's buffer may contain arbitrary data, this results in non-deterministic
output for those bytes.
The NoCrc status indicates the original disc had no CRC (zeroed EDC).
The fix adds the missing else branch to zero the EDC field, matching
the behavior that Mode2Form2Ok already has via aaruf_ecc_cd_reconstruct.
Both DDT v1 and v2 code paths are fixed.