mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-27 19:26:52 +00:00
[loader] add ZBIC (zstd variant) NSO decompression support for Switch 22.0+
This commit is contained in:
+32
-4
@@ -13,6 +13,7 @@
|
||||
#include "common/hex_util.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/lz4_compression.h"
|
||||
#include "common/zbic_compression.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
@@ -104,11 +105,38 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||
for (std::size_t i = 0; i < nso_header.segments.size(); ++i) {
|
||||
nso_file.Read(compressed_data.data(), nso_header.segments_compressed_size[i], nso_header.segments[i].offset);
|
||||
if (nso_header.IsSegmentCompressed(i)) {
|
||||
int r = Common::Compression::DecompressDataLZ4(decompressed_size.data(), nso_header.segments[i].size, compressed_data.data(), nso_header.segments_compressed_size[i]);
|
||||
ASSERT(r == int(nso_header.segments[i].size));
|
||||
std::memcpy(codeset.memory.data() + module_start + nso_header.segments[i].location, decompressed_size.data(), nso_header.segments[i].size);
|
||||
if (nso_header.IsZBICCompressed()) {
|
||||
// ZBIC compression
|
||||
const int r = Common::Compression::DecompressDataZBIC(
|
||||
decompressed_size.data(),
|
||||
nso_header.segments[i].size,
|
||||
compressed_data.data(),
|
||||
nso_header.segments_compressed_size[i]
|
||||
);
|
||||
ASSERT(r > 0);
|
||||
} else {
|
||||
// LZ4 compression
|
||||
int r = Common::Compression::DecompressDataLZ4(
|
||||
decompressed_size.data(),
|
||||
nso_header.segments[i].size,
|
||||
compressed_data.data(),
|
||||
nso_header.segments_compressed_size[i]
|
||||
);
|
||||
ASSERT(r == int(nso_header.segments[i].size));
|
||||
}
|
||||
|
||||
std::memcpy(
|
||||
codeset.memory.data() + module_start + nso_header.segments[i].location,
|
||||
decompressed_size.data(),
|
||||
nso_header.segments[i].size
|
||||
);
|
||||
} else {
|
||||
std::memcpy(codeset.memory.data() + module_start + nso_header.segments[i].location, compressed_data.data(), nso_header.segments[i].size);
|
||||
// Not compressed
|
||||
std::memcpy(
|
||||
codeset.memory.data() + module_start + nso_header.segments[i].location,
|
||||
compressed_data.data(),
|
||||
nso_header.segments[i].size
|
||||
);
|
||||
}
|
||||
codeset.segments[i].addr = module_start + nso_header.segments[i].location;
|
||||
codeset.segments[i].offset = module_start + nso_header.segments[i].location;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -58,6 +61,9 @@ struct NSOHeader {
|
||||
std::array<SHA256Hash, 3> segment_hashes;
|
||||
|
||||
bool IsSegmentCompressed(size_t segment_num) const;
|
||||
bool IsZBICCompressed() const {
|
||||
return ((flags >> 7) & 1) != 0;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
|
||||
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
||||
|
||||
Reference in New Issue
Block a user