loader: provide default arguments (zero byte) to NSOs
Certain newer unity games (Terraria, Pokemon Mystery Dungeon) require that the argument region be populated. Failure to do so results in an integer underflow in argument count, and eventually an unmapped read at 0x800000000. Providing this default fixes this. Note that the behavior of official software is as yet unverified, arguments-wise.
This commit is contained in:
parent
d8e0d839bd
commit
5a7eecc3ad
|
@ -97,7 +97,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
if (nso_header.IsSegmentCompressed(i)) {
|
if (nso_header.IsSegmentCompressed(i)) {
|
||||||
data = DecompressSegment(data, nso_header.segments[i]);
|
data = DecompressSegment(data, nso_header.segments[i]);
|
||||||
}
|
}
|
||||||
program_image.resize(nso_header.segments[i].location + data.size());
|
program_image.resize(nso_header.segments[i].location +
|
||||||
|
PageAlignSize(static_cast<u32>(data.size())));
|
||||||
std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(),
|
std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(),
|
||||||
data.size());
|
data.size());
|
||||||
codeset.segments[i].addr = nso_header.segments[i].location;
|
codeset.segments[i].addr = nso_header.segments[i].location;
|
||||||
|
@ -105,8 +106,12 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||||
codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
|
codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_pass_arguments && !Settings::values.program_args.empty()) {
|
if (should_pass_arguments) {
|
||||||
const auto arg_data = Settings::values.program_args;
|
std::vector<u8> arg_data{Settings::values.program_args.begin(),
|
||||||
|
Settings::values.program_args.end()};
|
||||||
|
if (arg_data.empty()) {
|
||||||
|
arg_data.resize(NSO_ARGUMENT_DEFAULT_SIZE);
|
||||||
|
}
|
||||||
codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
|
codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE;
|
||||||
NSOArgumentHeader args_header{
|
NSOArgumentHeader args_header{
|
||||||
NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}};
|
NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}};
|
||||||
|
|
|
@ -56,6 +56,8 @@ static_assert(sizeof(NSOHeader) == 0x100, "NSOHeader has incorrect size.");
|
||||||
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<NSOHeader>, "NSOHeader must be trivially copyable.");
|
||||||
|
|
||||||
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000;
|
||||||
|
// NOTE: Official software default argument state is unverified.
|
||||||
|
constexpr u64 NSO_ARGUMENT_DEFAULT_SIZE = 1;
|
||||||
|
|
||||||
struct NSOArgumentHeader {
|
struct NSOArgumentHeader {
|
||||||
u32_le allocated_size;
|
u32_le allocated_size;
|
||||||
|
|
Reference in New Issue