mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-27 11:19:04 +00:00
815325ccec
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- A new NSO compression method was introduced in Switch 22.0.0. This is a customized variant of zstd and is used when NSO flags have bit 7 set. Key characteristics: - ZSTD_MAGICNUMBER is set to 0x4349425A (b'ZBIC') instead of 0xFD2FB528 - ZSTD_LEGACY_SUPPORT is set to 0 - ZSTD_TRACE is set to 1, zstd version used is 1.5.7 (10507) - FSE_readNCount is replaced with a BIC (Binary Interpolative Coding) version which improves compression of entropy tables significantly Source: https://switchbrew.org/wiki/22.0.0 Implementation: - Detect ZBIC segments via NSO flag bit 7 (NsoFlags_UseZbicCompression) and/or ZBIC magic scan in nso.cpp - Fall back to LZ4 when ZBIC is not detected or returns unexpected size - Handle segment 0 alternate offset (0x100 vs 0x108) for both ZBIC and LZ4 References: - Atmosphère loader/strat zstd-zbic integration: https://github.com/Atmosphere-NX/Atmosphere/commit/082115187a0509cb6b8a757de639a4e4741b8712 - nxdumptool ZBIC segment compression support: https://github.com/DarkMatterCore/nxdumptool/commit/441e5c0904f29427987433be4eb057a2843d222a - STORM_SWITCH ZBIC implementation: https://github.com/ReiKatari/STORM_SWITCH/commit/1e09eb82b760aaf340b810031400991c0740c091 Tested with firmware 23.0.0 and ZBIC-compressed NSOs. Co-authored-by: xbzk <xbzk@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4482 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: lizzie <lizzie@eden-emu.dev> Reviewed-by: Maufeat <sahyno1996@gmail.com>
47 lines
1.1 KiB
C++
47 lines
1.1 KiB
C++
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include <cstring>
|
|
|
|
#include "common/zbic_compression.h"
|
|
|
|
#define ZSTD_ZBIC_SUPPORT 1
|
|
#define ZSTDLIB_VISIBLE static
|
|
#define ZSTDLIB_HIDDEN static
|
|
#define ZSTDERRORLIB_VISIBLE static
|
|
#define ZSTDERRORLIB_HIDDEN static
|
|
#undef ZSTD_MULTITHREAD
|
|
|
|
#if defined(__ANDROID__)
|
|
#undef _GNU_SOURCE
|
|
#endif
|
|
|
|
#include "zstd.h"
|
|
#define g_ZSTD_threading_useless_symbol g_ZSTD_zbic_threading_useless_symbol
|
|
#include "zstd.c"
|
|
#undef g_ZSTD_threading_useless_symbol
|
|
|
|
namespace Common::Compression {
|
|
|
|
bool IsZBIC(std::span<const u8> src) {
|
|
if (src.size() < sizeof(u32)) {
|
|
return false;
|
|
}
|
|
u32 magic = 0;
|
|
std::memcpy(&magic, src.data(), sizeof(u32));
|
|
return magic == ZSTD_MAGICNUMBER; // 0x4349425A ("ZBIC")
|
|
}
|
|
|
|
int DecompressDataZBIC(std::span<u8> dst, std::span<const u8> src) {
|
|
if (dst.empty() || src.empty()) {
|
|
return -1;
|
|
}
|
|
const size_t res = ZSTD_decompress(dst.data(), dst.size(), src.data(), src.size());
|
|
if (ZSTD_isError(res)) {
|
|
return -1;
|
|
}
|
|
return static_cast<int>(res);
|
|
}
|
|
|
|
} // namespace Common::Compression
|