Compare commits

..

No commits in common. "master" and "1.8.0-prerelease" have entirely different histories.

21 changed files with 87 additions and 466 deletions

View File

@ -49,7 +49,7 @@ Code type 0x0 allows writing a static value to a memory address.
`0TMR00AA AAAAAAAA VVVVVVVV (VVVVVVVV)` `0TMR00AA AAAAAAAA VVVVVVVV (VVVVVVVV)`
+ T: Width of memory write (1, 2, 4, or 8 bytes). + T: Width of memory write (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative). + M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
+ R: Register to use as an offset from memory region base. + R: Register to use as an offset from memory region base.
+ A: Immediate offset to use from memory region base. + A: Immediate offset to use from memory region base.
+ V: Value to write. + V: Value to write.
@ -62,13 +62,11 @@ Code type 0x1 performs a comparison of the contents of memory to a static value.
If the condition is not met, all instructions until the appropriate End or Else conditional block terminator are skipped. If the condition is not met, all instructions until the appropriate End or Else conditional block terminator are skipped.
#### Encoding #### Encoding
`1TMCXrAA AAAAAAAA VVVVVVVV (VVVVVVVV)` `1TMC00AA AAAAAAAA VVVVVVVV (VVVVVVVV)`
+ T: Width of memory read (1, 2, 4, or 8 bytes). + T: Width of memory write (1, 2, 4, or 8 bytes).
+ M: Memory region to read from (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative). + M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
+ C: Condition to use, see below. + C: Condition to use, see below.
+ X: Operand Type, see below.
+ r: Offset Register (operand types 1).
+ A: Immediate offset to use from memory region base. + A: Immediate offset to use from memory region base.
+ V: Value to compare to. + V: Value to compare to.
@ -80,9 +78,6 @@ If the condition is not met, all instructions until the appropriate End or Else
+ 5: == + 5: ==
+ 6: != + 6: !=
#### Operand Type
+ 0: Memory Base + Relative Offset
+ 1: Memory Base + Offset Register + Relative Offset
--- ---
### Code Type 0x2: End Conditional Block ### Code Type 0x2: End Conditional Block
@ -131,7 +126,7 @@ Code type 0x5 allows loading a value from memory into a register, either using a
`5TMR00AA AAAAAAAA` `5TMR00AA AAAAAAAA`
+ T: Width of memory read (1, 2, 4, or 8 bytes). + T: Width of memory read (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative). + M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr).
+ R: Register to load value into. + R: Register to load value into.
+ A: Immediate offset to use from memory region base. + A: Immediate offset to use from memory region base.
@ -142,22 +137,6 @@ Code type 0x5 allows loading a value from memory into a register, either using a
+ R: Register to load value into. (This register is also used as the base memory address). + R: Register to load value into. (This register is also used as the base memory address).
+ A: Immediate offset to use from register R. + A: Immediate offset to use from register R.
#### Load from Register Address Encoding
`5T0R2SAA AAAAAAAA`
+ T: Width of memory read (1, 2, 4, or 8 bytes).
+ R: Register to load value into.
+ S: Register to use as the base memory address.
+ A: Immediate offset to use from register R.
#### Load From Fixed Address Encoding with offset register
`5TMR3SAA AAAAAAAA`
+ T: Width of memory read (1, 2, 4, or 8 bytes).
+ M: Memory region to write to (0 = Main NSO, 1 = Heap, 2 = Alias, 3 = Aslr, 4 = non-relative).
+ R: Register to load value into.
+ S: Register to use as offset register.
+ A: Immediate offset to use from memory region base.
--- ---
### Code Type 0x6: Store Static Value to Register Memory Address ### Code Type 0x6: Store Static Value to Register Memory Address
@ -271,10 +250,7 @@ Code type 0x9 allows performing arithmetic on registers.
+ 7: Logical Not (discards right-hand operand) + 7: Logical Not (discards right-hand operand)
+ 8: Logical Xor + 8: Logical Xor
+ 9: None/Move (discards right-hand operand) + 9: None/Move (discards right-hand operand)
+ 10: Float Addition, T==4 single T==8 double
+ 11: Float Subtraction, T==4 single T==8 double
+ 12: Float Multiplication, T==4 single T==8 double
+ 13: Float Division, T==4 single T==8 double
--- ---
### Code Type 0xA: Store Register to Memory Address ### Code Type 0xA: Store Register to Memory Address
@ -404,61 +380,6 @@ Code type 0xC3 reads or writes a static register with a given register.
--- ---
### Code Type 0xC4: Begin Extended Keypress Conditional Block
Code type 0xC4 enters or skips a conditional block based on whether a key combination is pressed.
#### Encoding
`C4r00000 kkkkkkkk kkkkkkkk`
+ r: Auto-repeat, see below.
+ kkkkkkkkkk: Keypad mask to check against output of `hidKeysDown()`.
Note that for multiple button combinations, the bitmasks should be OR'd together.
#### Auto-repeat
+ 0: The conditional block executes only once when the keypad mask matches. The mask must stop matching to reset for the next trigger.
+ 1: The conditional block executes as long as the keypad mask matches.
#### Keypad Values
Note: This is the direct output of `hidKeysDown()`.
+ 000000001: A
+ 000000002: B
+ 000000004: X
+ 000000008: Y
+ 000000010: Left Stick Pressed
+ 000000020: Right Stick Pressed
+ 000000040: L
+ 000000080: R
+ 000000100: ZL
+ 000000200: ZR
+ 000000400: Plus
+ 000000800: Minus
+ 000001000: Left
+ 000002000: Up
+ 000004000: Right
+ 000008000: Down
+ 000010000: Left Stick Left
+ 000020000: Left Stick Up
+ 000040000: Left Stick Right
+ 000080000: Left Stick Down
+ 000100000: Right Stick Left
+ 000200000: Right Stick Up
+ 000400000: Right Stick Right
+ 000800000: Right Stick Down
+ 001000000: SL Left Joy-Con
+ 002000000: SR Left Joy-Con
+ 004000000: SL Right Joy-Con
+ 008000000: SR Right Joy-Con
+ 010000000: Top button on Poké Ball Plus (Palma) controller
+ 020000000: Verification
+ 040000000: B button on Left NES/HVC controller in Handheld mode
+ 080000000: Left C button in N64 controller
+ 100000000: Up C button in N64 controller
+ 200000000: Right C button in N64 controller
+ 400000000: Down C button in N64 controller
### Code Type 0xF0: Double Extended-Width Instruction ### Code Type 0xF0: Double Extended-Width Instruction
Code Type 0xF0 signals to the VM to treat the upper three nybbles of the first dword as instruction type, instead of just the upper nybble. Code Type 0xF0 signals to the VM to treat the upper three nybbles of the first dword as instruction type, instead of just the upper nybble.

View File

@ -16,7 +16,7 @@
#pragma once #pragma once
#include <vapours.hpp> #include <vapours.hpp>
#include <stratosphere/fssystem/fssystem_nca_file_system_driver.hpp> #include <stratosphere/fssystem/fssystem_nca_file_system_driver.hpp>
#include <stratosphere/ncm/ncm_content_meta_platform.hpp> #include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::fssystem { namespace ams::fssystem {
@ -26,10 +26,10 @@ namespace ams::fssystem {
void InvalidateHardwareAesKey(); void InvalidateHardwareAesKey();
bool IsValidSignatureKeyGeneration(ncm::ContentMetaPlatform platform, size_t key_generation); bool IsValidSignatureKeyGeneration(ldr::PlatformId platform, size_t key_generation);
const u8 *GetAcidSignatureKeyModulus(ncm::ContentMetaPlatform platform, bool prod, size_t key_generation, bool unk_unused); const u8 *GetAcidSignatureKeyModulus(ldr::PlatformId platform, bool prod, size_t key_generation, bool unk_unused);
size_t GetAcidSignatureKeyModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused); size_t GetAcidSignatureKeyModulusSize(ldr::PlatformId platform, bool unk_unused);
const u8 *GetAcidSignatureKeyPublicExponent(); const u8 *GetAcidSignatureKeyPublicExponent();

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
namespace ams::ldr {
/* TODO: Is this really a FS type? What namespace does this actually live inside? */
enum PlatformId {
PlatformId_Nx = 0,
};
}

View File

@ -19,7 +19,7 @@
#include <stratosphere/ncm/ncm_ids.hpp> #include <stratosphere/ncm/ncm_ids.hpp>
#include <stratosphere/ncm/ncm_program_location.hpp> #include <stratosphere/ncm/ncm_program_location.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp> #include <stratosphere/sf/sf_buffer_tags.hpp>
#include <stratosphere/ncm/ncm_content_meta_platform.hpp> #include <stratosphere/ldr/ldr_platform_id.hpp>
namespace ams::ldr { namespace ams::ldr {

View File

@ -154,14 +154,12 @@ spl_secure_monitor_api.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/l
fs_id_string_impl.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/include fs_id_string_impl.os.generic.o: CXXFLAGS += -I$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/include
ifeq ($(ATMOSPHERE_OS_NAME),windows) ifeq ($(ATMOSPHERE_OS_NAME),windows)
# Audit builds fail when these have lto disabled. # I do not remember why these had fno-lto, but it appears to
# Noting 10/29/24: # work without no-lto (2023/03/09), so I am disabling these. I may regret this later.
# In member function '__ct ': #os_%.o: CXXFLAGS += -fno-lto
# internal compiler error: in binds_to_current_def_p, at symtab.cc:2589 #fssystem_%.o: CXXFLAGS += -fno-lto
os_%.o: CXXFLAGS += -fno-lto #fssrv_%.o: CXXFLAGS += -fno-lto
fssystem_%.o: CXXFLAGS += -fno-lto #fs_%.o: CXXFLAGS += -fno-lto
fssrv_%.o: CXXFLAGS += -fno-lto
fs_%.o: CXXFLAGS += -fno-lto
endif endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View File

@ -537,8 +537,6 @@ namespace ams::erpt::srv {
/* NOTE: Nintendo ignores the result of this call. */ /* NOTE: Nintendo ignores the result of this call. */
SubmitFsInfo(); SubmitFsInfo();
} }
#else
AMS_UNUSED(flags);
#endif #endif

View File

@ -297,20 +297,20 @@ namespace ams::fssystem {
} }
} }
bool IsValidSignatureKeyGeneration(ncm::ContentMetaPlatform platform, size_t key_generation) { bool IsValidSignatureKeyGeneration(ldr::PlatformId platform, size_t key_generation) {
switch (platform) { switch (platform) {
case ncm::ContentMetaPlatform::Nx: case ldr::PlatformId_Nx:
return key_generation <= NxAcidSignatureKeyGenerationMax; return key_generation <= NxAcidSignatureKeyGenerationMax;
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }
} }
const u8 *GetAcidSignatureKeyModulus(ncm::ContentMetaPlatform platform, bool prod, size_t key_generation, bool unk_unused) { const u8 *GetAcidSignatureKeyModulus(ldr::PlatformId platform, bool prod, size_t key_generation, bool unk_unused) {
AMS_ASSERT(IsValidSignatureKeyGeneration(platform, key_generation)); AMS_ASSERT(IsValidSignatureKeyGeneration(platform, key_generation));
AMS_UNUSED(unk_unused); AMS_UNUSED(unk_unused);
switch (platform) { switch (platform) {
case ncm::ContentMetaPlatform::Nx: case ldr::PlatformId_Nx:
{ {
const size_t used_keygen = (key_generation % (NxAcidSignatureKeyGenerationMax + 1)); const size_t used_keygen = (key_generation % (NxAcidSignatureKeyGenerationMax + 1));
return prod ? NxAcidSignatureKeyModulusProd[used_keygen] : NxAcidSignatureKeyModulusDev[used_keygen]; return prod ? NxAcidSignatureKeyModulusProd[used_keygen] : NxAcidSignatureKeyModulusDev[used_keygen];
@ -319,11 +319,11 @@ namespace ams::fssystem {
} }
} }
size_t GetAcidSignatureKeyModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused) { size_t GetAcidSignatureKeyModulusSize(ldr::PlatformId platform, bool unk_unused) {
AMS_UNUSED(unk_unused); AMS_UNUSED(unk_unused);
switch (platform) { switch (platform) {
case ncm::ContentMetaPlatform::Nx: case ldr::PlatformId_Nx:
return NxAcidSignatureKeyModulusSize; return NxAcidSignatureKeyModulusSize;
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }

View File

@ -1346,7 +1346,7 @@ namespace ams::fssystem {
R_UNLESS(::GetLastError() == ERROR_ACCESS_DENIED, last_error_result); R_UNLESS(::GetLastError() == ERROR_ACCESS_DENIED, last_error_result);
/* Check if we tried to open a directory. */ /* Check if we tried to open a directory. */
fs::DirectoryEntryType type{}; fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get())); R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get()));
/* If the type is anything other than directory, perform generic result conversion. */ /* If the type is anything other than directory, perform generic result conversion. */
@ -1459,7 +1459,7 @@ namespace ams::fssystem {
R_TRY(this->ResolveFullPath(std::addressof(native_new_path), new_path, MaxFilePathLength, 0, false)); R_TRY(this->ResolveFullPath(std::addressof(native_new_path), new_path, MaxFilePathLength, 0, false));
/* Check that the old path is a file. */ /* Check that the old path is a file. */
fs::DirectoryEntryType type{}; fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_old_path.get())); R_TRY(GetEntryTypeImpl(std::addressof(type), native_old_path.get()));
R_UNLESS(type == fs::DirectoryEntryType_File, fs::ResultPathNotFound()); R_UNLESS(type == fs::DirectoryEntryType_File, fs::ResultPathNotFound());
@ -1509,7 +1509,7 @@ namespace ams::fssystem {
R_TRY(this->ResolveFullPath(std::addressof(native_new_path), new_path, MaxDirectoryPathLength, 0, false)); R_TRY(this->ResolveFullPath(std::addressof(native_new_path), new_path, MaxDirectoryPathLength, 0, false));
/* Check that the old path is a file. */ /* Check that the old path is a file. */
fs::DirectoryEntryType type{}; fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_old_path.get())); R_TRY(GetEntryTypeImpl(std::addressof(type), native_old_path.get()));
R_UNLESS(type == fs::DirectoryEntryType_Directory, fs::ResultPathNotFound()); R_UNLESS(type == fs::DirectoryEntryType_Directory, fs::ResultPathNotFound());
@ -1577,7 +1577,7 @@ namespace ams::fssystem {
R_UNLESS(::GetLastError() == ERROR_ACCESS_DENIED, last_error_result); R_UNLESS(::GetLastError() == ERROR_ACCESS_DENIED, last_error_result);
/* Check if we tried to open a directory. */ /* Check if we tried to open a directory. */
fs::DirectoryEntryType type{}; fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get())); R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get()));
/* If the type isn't file, return path not found. */ /* If the type isn't file, return path not found. */
@ -1623,7 +1623,7 @@ namespace ams::fssystem {
ON_RESULT_FAILURE { ::CloseHandle(dir_handle); }; ON_RESULT_FAILURE { ::CloseHandle(dir_handle); };
/* Check that we tried to open a directory. */ /* Check that we tried to open a directory. */
fs::DirectoryEntryType type{}; fs::DirectoryEntryType type;
R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get())); R_TRY(GetEntryTypeImpl(std::addressof(type), native_path.get()));
/* If the type isn't directory, return path not found. */ /* If the type isn't directory, return path not found. */

View File

@ -30,7 +30,6 @@
#include <vapours/crypto/crypto_aes_ctr_encryptor_decryptor.hpp> #include <vapours/crypto/crypto_aes_ctr_encryptor_decryptor.hpp>
#include <vapours/crypto/crypto_aes_xts_encryptor_decryptor.hpp> #include <vapours/crypto/crypto_aes_xts_encryptor_decryptor.hpp>
#include <vapours/crypto/crypto_aes_gcm_encryptor.hpp> #include <vapours/crypto/crypto_aes_gcm_encryptor.hpp>
#include <vapours/crypto/crypto_aes_128_cmac_generator.hpp>
#include <vapours/crypto/crypto_rsa_pkcs1_sha256_verifier.hpp> #include <vapours/crypto/crypto_rsa_pkcs1_sha256_verifier.hpp>
#include <vapours/crypto/crypto_rsa_pss_sha256_verifier.hpp> #include <vapours/crypto/crypto_rsa_pss_sha256_verifier.hpp>
#include <vapours/crypto/crypto_rsa_oaep_sha256_decoder.hpp> #include <vapours/crypto/crypto_rsa_oaep_sha256_decoder.hpp>

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/crypto_aes_encryptor.hpp>
#include <vapours/crypto/crypto_cmac_generator.hpp>
namespace ams::crypto {
class Aes128CmacGenerator {
NON_COPYABLE(Aes128CmacGenerator);
NON_MOVEABLE(Aes128CmacGenerator);
public:
static constexpr size_t MacSize = AesEncryptor128::BlockSize;
private:
AesEncryptor128 m_aes;
CmacGenerator<AesEncryptor128> m_cmac_generator;
public:
Aes128CmacGenerator() { /* ... */ }
void Initialize(const void *key, size_t key_size) {
AMS_ASSERT(key_size == AesEncryptor128::KeySize);
m_aes.Initialize(key, key_size);
m_cmac_generator.Initialize(std::addressof(m_aes));
}
void Update(const void *data, size_t size) {
m_cmac_generator.Update(data, size);
}
void GetMac(void *dst, size_t size) {
m_cmac_generator.GetMac(dst, size);
}
};
ALWAYS_INLINE void GenerateAes128Cmac(void *dst, size_t dst_size, const void *data, size_t data_size, const void *key, size_t key_size) {
Aes128CmacGenerator cmac_generator;
cmac_generator.Initialize(key, key_size);
cmac_generator.Update(data, data_size);
cmac_generator.GetMac(dst, dst_size);
}
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_cmac_impl.hpp>
namespace ams::crypto {
template<typename BlockCipher>
class CmacGenerator {
NON_COPYABLE(CmacGenerator);
NON_MOVEABLE(CmacGenerator);
private:
using Impl = impl::CmacImpl<BlockCipher>;
public:
static constexpr size_t MacSize = BlockCipher::BlockSize;
private:
Impl m_impl;
public:
CmacGenerator() { /* ... */ }
void Initialize(const BlockCipher *cipher) {
return m_impl.Initialize(cipher);
}
void Update(const void *data, size_t size) {
return m_impl.Update(data, size);
}
void GetMac(void *dst, size_t dst_size) {
return m_impl.GetMac(dst, dst_size);
}
};
}

View File

@ -1,128 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
#include <vapours/util.hpp>
#include <vapours/crypto/impl/crypto_hash_function.hpp>
#include <vapours/crypto/impl/crypto_cbc_mac_impl.hpp>
#include <vapours/crypto/crypto_memory_clear.hpp>
namespace ams::crypto::impl {
template<typename BlockCipher>
class CmacImpl {
NON_COPYABLE(CmacImpl);
NON_MOVEABLE(CmacImpl);
public:
static constexpr size_t BlockSize = BlockCipher::BlockSize;
static constexpr size_t MacSize = BlockSize;
static_assert(BlockSize == 0x10); /* TODO: Should this be supported? */
private:
enum State {
State_None = 0,
State_Initialized = 1,
State_Done = 2,
};
private:
CbcMacImpl m_cbc_mac_impl;
u8 m_sub_key[BlockSize];
State m_state;
public:
CmacImpl() : m_state(State_None) { /* ... */ }
~CmacImpl() {
/* Clear everything. */
ClearMemory(this, sizeof(*this));
}
void Initialize(const BlockCipher *cipher);
void Update(const void *data, size_t data_size);
void GetMac(void *dst, size_t dst_size);
private:
static void MultiplyOneOverGF128(u8 *data) {
/* Determine the carry bit. */
const u8 carry = data[0] & 0x80;
/* Shift all bytes by one bit. */
for (size_t i = 0; i < BlockSize - 1; ++i) {
data[i] = (data[i] << 1) | (data[i + 1] >> 7);
}
data[BlockSize - 1] <<= 1;
/* Adjust based on carry. */
if (carry) {
data[BlockSize - 1] ^= 0x87;
}
}
};
template<typename BlockCipher>
inline void CmacImpl<BlockCipher>::Initialize(const BlockCipher *cipher) {
/* Clear the key storage. */
std::memset(m_sub_key, 0, sizeof(m_sub_key));
/* Set the key storage. */
cipher->EncryptBlock(m_sub_key, BlockSize, m_sub_key, BlockSize);
MultiplyOneOverGF128(m_sub_key);
/* Initialize the cbc-mac impl. */
m_cbc_mac_impl.Initialize(cipher);
/* Mark initialized. */
m_state = State_Initialized;
}
template<typename BlockCipher>
inline void CmacImpl<BlockCipher>::Update(const void *data, size_t data_size) {
AMS_ASSERT(m_state == State_Initialized);
m_cbc_mac_impl.template Update<BlockCipher>(data, data_size);
}
template<typename BlockCipher>
inline void CmacImpl<BlockCipher>::GetMac(void *dst, size_t dst_size) {
AMS_ASSERT(m_state == State_Initialized || m_state == State_Done);
AMS_ASSERT(dst_size >= MacSize);
AMS_UNUSED(dst_size);
/* If we're not already finalized, get the final mac. */
if (m_state == State_Initialized) {
/* Process padding as needed. */
if (m_cbc_mac_impl.GetBufferedDataSize() != BlockSize) {
/* Determine the remaining size. */
const size_t remaining = BlockSize - m_cbc_mac_impl.GetBufferedDataSize();
/* Update with padding. */
static constexpr u8 s_padding[BlockSize] = { 0x80, /* ... */ };
m_cbc_mac_impl.template Update<BlockCipher>(s_padding, remaining);
/* Update our subkey. */
MultiplyOneOverGF128(m_sub_key);
}
/* Mask the subkey. */
m_cbc_mac_impl.MaskBufferedData(m_sub_key, BlockSize);
/* Set our state as done. */
m_state = State_Done;
}
/* Get the mac. */
m_cbc_mac_impl.GetMac(dst, dst_size);
}
}

View File

@ -108,8 +108,6 @@ namespace ams::dmnt::cheat::impl {
this->LogToDebugFile("Bit Width: %x\n", opcode->begin_cond.bit_width); this->LogToDebugFile("Bit Width: %x\n", opcode->begin_cond.bit_width);
this->LogToDebugFile("Mem Type: %x\n", opcode->begin_cond.mem_type); this->LogToDebugFile("Mem Type: %x\n", opcode->begin_cond.mem_type);
this->LogToDebugFile("Cond Type: %x\n", opcode->begin_cond.cond_type); this->LogToDebugFile("Cond Type: %x\n", opcode->begin_cond.cond_type);
this->LogToDebugFile("Inc Ofs reg: %d\n", opcode->begin_cond.include_ofs_reg);
this->LogToDebugFile("Ofs Reg Idx: %x\n", opcode->begin_cond.ofs_reg_index);
this->LogToDebugFile("Rel Addr: %lx\n", opcode->begin_cond.rel_address); this->LogToDebugFile("Rel Addr: %lx\n", opcode->begin_cond.rel_address);
this->LogToDebugFile("Value: %lx\n", opcode->begin_cond.value.bit64); this->LogToDebugFile("Value: %lx\n", opcode->begin_cond.value.bit64);
break; break;
@ -160,11 +158,6 @@ namespace ams::dmnt::cheat::impl {
this->LogToDebugFile("Opcode: Begin Keypress Conditional\n"); this->LogToDebugFile("Opcode: Begin Keypress Conditional\n");
this->LogToDebugFile("Key Mask: %x\n", opcode->begin_keypress_cond.key_mask); this->LogToDebugFile("Key Mask: %x\n", opcode->begin_keypress_cond.key_mask);
break; break;
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
this->LogToDebugFile("Opcode: Begin Extended Keypress Conditional\n");
this->LogToDebugFile("Key Mask: %x\n", opcode->begin_ext_keypress_cond.key_mask);
this->LogToDebugFile("Auto Repeat: %d\n", opcode->begin_ext_keypress_cond.auto_repeat);
break;
case CheatVmOpcodeType_PerformArithmeticRegister: case CheatVmOpcodeType_PerformArithmeticRegister:
this->LogToDebugFile("Opcode: Perform Register Arithmetic\n"); this->LogToDebugFile("Opcode: Perform Register Arithmetic\n");
this->LogToDebugFile("Bit Width: %x\n", opcode->perform_math_reg.bit_width); this->LogToDebugFile("Bit Width: %x\n", opcode->perform_math_reg.bit_width);
@ -365,7 +358,6 @@ namespace ams::dmnt::cheat::impl {
switch (opcode.opcode) { switch (opcode.opcode) {
case CheatVmOpcodeType_BeginConditionalBlock: case CheatVmOpcodeType_BeginConditionalBlock:
case CheatVmOpcodeType_BeginKeypressConditionalBlock: case CheatVmOpcodeType_BeginKeypressConditionalBlock:
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
case CheatVmOpcodeType_BeginRegisterConditionalBlock: case CheatVmOpcodeType_BeginRegisterConditionalBlock:
opcode.begin_conditional_block = true; opcode.begin_conditional_block = true;
break; break;
@ -395,8 +387,6 @@ namespace ams::dmnt::cheat::impl {
opcode.begin_cond.bit_width = (first_dword >> 24) & 0xF; opcode.begin_cond.bit_width = (first_dword >> 24) & 0xF;
opcode.begin_cond.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF); opcode.begin_cond.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF);
opcode.begin_cond.cond_type = (ConditionalComparisonType)((first_dword >> 16) & 0xF); opcode.begin_cond.cond_type = (ConditionalComparisonType)((first_dword >> 16) & 0xF);
opcode.begin_cond.include_ofs_reg = ((first_dword >> 12) & 0xF) != 0;
opcode.begin_cond.ofs_reg_index = ((first_dword >> 8) & 0xF);
opcode.begin_cond.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); opcode.begin_cond.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword);
opcode.begin_cond.value = GetNextVmInt(opcode.begin_cond.bit_width); opcode.begin_cond.value = GetNextVmInt(opcode.begin_cond.bit_width);
} }
@ -437,8 +427,7 @@ namespace ams::dmnt::cheat::impl {
opcode.ldr_memory.bit_width = (first_dword >> 24) & 0xF; opcode.ldr_memory.bit_width = (first_dword >> 24) & 0xF;
opcode.ldr_memory.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF); opcode.ldr_memory.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF);
opcode.ldr_memory.reg_index = ((first_dword >> 16) & 0xF); opcode.ldr_memory.reg_index = ((first_dword >> 16) & 0xF);
opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF); opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) != 0;
opcode.ldr_memory.offset_register = ((first_dword >> 8) & 0xF);
opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword);
} }
break; break;
@ -471,14 +460,6 @@ namespace ams::dmnt::cheat::impl {
opcode.begin_keypress_cond.key_mask = first_dword & 0x0FFFFFFF; opcode.begin_keypress_cond.key_mask = first_dword & 0x0FFFFFFF;
} }
break; break;
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
{
/* C4r00000 kkkkkkkk kkkkkkkk */
/* Read additional words. */
opcode.begin_ext_keypress_cond.key_mask = (u64)GetNextDword() << 32ul | (u64)GetNextDword();
opcode.begin_ext_keypress_cond.auto_repeat = ((first_dword >> 20) & 0xF) != 0;
}
break;
case CheatVmOpcodeType_PerformArithmeticRegister: case CheatVmOpcodeType_PerformArithmeticRegister:
{ {
/* 9TCRSIs0 (VVVVVVVV (VVVVVVVV)) */ /* 9TCRSIs0 (VVVVVVVV (VVVVVVVV)) */
@ -753,8 +734,6 @@ namespace ams::dmnt::cheat::impl {
return metadata->alias_extents.base + rel_address; return metadata->alias_extents.base + rel_address;
case MemoryAccessType_Aslr: case MemoryAccessType_Aslr:
return metadata->aslr_extents.base + rel_address; return metadata->aslr_extents.base + rel_address;
case MemoryAccessType_NonRelative:
return rel_address;
} }
} }
@ -790,7 +769,6 @@ namespace ams::dmnt::cheat::impl {
return true; return true;
} }
static u64 s_keyold = 0;
void CheatVirtualMachine::Execute(const CheatProcessMetadata *metadata) { void CheatVirtualMachine::Execute(const CheatProcessMetadata *metadata) {
CheatVmOpcode cur_opcode; CheatVmOpcode cur_opcode;
u64 kHeld = 0; u64 kHeld = 0;
@ -846,7 +824,7 @@ namespace ams::dmnt::cheat::impl {
case CheatVmOpcodeType_BeginConditionalBlock: case CheatVmOpcodeType_BeginConditionalBlock:
{ {
/* Read value from memory. */ /* Read value from memory. */
u64 src_address = GetCheatProcessAddress(metadata, cur_opcode.begin_cond.mem_type, (cur_opcode.begin_cond.include_ofs_reg) ? m_registers[cur_opcode.begin_cond.ofs_reg_index] + cur_opcode.begin_cond.rel_address : cur_opcode.begin_cond.rel_address); u64 src_address = GetCheatProcessAddress(metadata, cur_opcode.begin_cond.mem_type, cur_opcode.begin_cond.rel_address);
u64 src_value = 0; u64 src_value = 0;
switch (cur_opcode.store_static.bit_width) { switch (cur_opcode.store_static.bit_width) {
case 1: case 1:
@ -918,12 +896,8 @@ namespace ams::dmnt::cheat::impl {
{ {
/* Choose source address. */ /* Choose source address. */
u64 src_address; u64 src_address;
if (cur_opcode.ldr_memory.load_from_reg == 1) { if (cur_opcode.ldr_memory.load_from_reg) {
src_address = m_registers[cur_opcode.ldr_memory.reg_index] + cur_opcode.ldr_memory.rel_address; src_address = m_registers[cur_opcode.ldr_memory.reg_index] + cur_opcode.ldr_memory.rel_address;
} else if (cur_opcode.ldr_memory.load_from_reg == 2) {
src_address = m_registers[cur_opcode.ldr_memory.offset_register] + cur_opcode.ldr_memory.rel_address;
} else if (cur_opcode.ldr_memory.load_from_reg == 3) {
src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, m_registers[cur_opcode.ldr_memory.offset_register] + cur_opcode.ldr_memory.rel_address);
} else { } else {
src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, cur_opcode.ldr_memory.rel_address); src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, cur_opcode.ldr_memory.rel_address);
} }
@ -1008,18 +982,6 @@ namespace ams::dmnt::cheat::impl {
this->SkipConditionalBlock(true); this->SkipConditionalBlock(true);
} }
break; break;
case CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock:
/* Check for keypress. */
if (!cur_opcode.begin_ext_keypress_cond.auto_repeat) {
if ((cur_opcode.begin_ext_keypress_cond.key_mask & kHeld) != (cur_opcode.begin_ext_keypress_cond.key_mask) || (cur_opcode.begin_ext_keypress_cond.key_mask & s_keyold) == (cur_opcode.begin_ext_keypress_cond.key_mask)) {
/* Keys not pressed. Skip conditional block. */
this->SkipConditionalBlock(true);
}
} else if ((cur_opcode.begin_ext_keypress_cond.key_mask & kHeld) != cur_opcode.begin_ext_keypress_cond.key_mask) {
/* Keys not pressed. Skip conditional block. */
this->SkipConditionalBlock(true);
}
break;
case CheatVmOpcodeType_PerformArithmeticRegister: case CheatVmOpcodeType_PerformArithmeticRegister:
{ {
const u64 operand_1_value = m_registers[cur_opcode.perform_math_reg.src_reg_1_index]; const u64 operand_1_value = m_registers[cur_opcode.perform_math_reg.src_reg_1_index];
@ -1060,34 +1022,6 @@ namespace ams::dmnt::cheat::impl {
case RegisterArithmeticType_None: case RegisterArithmeticType_None:
res_val = operand_1_value; res_val = operand_1_value;
break; break;
case RegisterArithmeticType_FloatAddition:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) + std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) + std::bit_cast<double>(operand_2_value));
}
break;
case RegisterArithmeticType_FloatSubtraction:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) - std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) - std::bit_cast<double>(operand_2_value));
}
break;
case RegisterArithmeticType_FloatMultiplication:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) * std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) * std::bit_cast<double>(operand_2_value));
}
break;
case RegisterArithmeticType_FloatDivision:
if (cur_opcode.perform_math_reg.bit_width == 4) {
res_val = std::bit_cast<std::uint32_t>(std::bit_cast<float>(static_cast<uint32_t>(operand_1_value)) / std::bit_cast<float>(static_cast<uint32_t>(operand_2_value)));
} else if (cur_opcode.perform_math_reg.bit_width == 8) {
res_val = std::bit_cast<std::uint64_t>(std::bit_cast<double>(operand_1_value) / std::bit_cast<double>(operand_2_value));
}
break;
} }
@ -1370,7 +1304,6 @@ namespace ams::dmnt::cheat::impl {
break; break;
} }
} }
s_keyold = kHeld;
} }
} }

View File

@ -43,7 +43,6 @@ namespace ams::dmnt::cheat::impl {
CheatVmOpcodeType_SaveRestoreRegister = 0xC1, CheatVmOpcodeType_SaveRestoreRegister = 0xC1,
CheatVmOpcodeType_SaveRestoreRegisterMask = 0xC2, CheatVmOpcodeType_SaveRestoreRegisterMask = 0xC2,
CheatVmOpcodeType_ReadWriteStaticRegister = 0xC3, CheatVmOpcodeType_ReadWriteStaticRegister = 0xC3,
CheatVmOpcodeType_BeginExtendedKeypressConditionalBlock = 0xC4,
/* This is a meta entry, and not a real opcode. */ /* This is a meta entry, and not a real opcode. */
/* This is to facilitate multi-nybble instruction decoding. */ /* This is to facilitate multi-nybble instruction decoding. */
@ -60,7 +59,6 @@ namespace ams::dmnt::cheat::impl {
MemoryAccessType_Heap = 1, MemoryAccessType_Heap = 1,
MemoryAccessType_Alias = 2, MemoryAccessType_Alias = 2,
MemoryAccessType_Aslr = 3, MemoryAccessType_Aslr = 3,
MemoryAccessType_NonRelative = 4,
}; };
enum ConditionalComparisonType : u32 { enum ConditionalComparisonType : u32 {
@ -86,10 +84,6 @@ namespace ams::dmnt::cheat::impl {
RegisterArithmeticType_LogicalXor = 8, RegisterArithmeticType_LogicalXor = 8,
RegisterArithmeticType_None = 9, RegisterArithmeticType_None = 9,
RegisterArithmeticType_FloatAddition = 10,
RegisterArithmeticType_FloatSubtraction = 11,
RegisterArithmeticType_FloatMultiplication = 12,
RegisterArithmeticType_FloatDivision = 13,
}; };
enum StoreRegisterOffsetType : u32 { enum StoreRegisterOffsetType : u32 {
@ -144,8 +138,6 @@ namespace ams::dmnt::cheat::impl {
u32 bit_width; u32 bit_width;
MemoryAccessType mem_type; MemoryAccessType mem_type;
ConditionalComparisonType cond_type; ConditionalComparisonType cond_type;
bool include_ofs_reg;
u32 ofs_reg_index;
u64 rel_address; u64 rel_address;
VmInt value; VmInt value;
}; };
@ -169,8 +161,7 @@ namespace ams::dmnt::cheat::impl {
u32 bit_width; u32 bit_width;
MemoryAccessType mem_type; MemoryAccessType mem_type;
u32 reg_index; u32 reg_index;
u8 load_from_reg; bool load_from_reg;
u8 offset_register;
u64 rel_address; u64 rel_address;
}; };
@ -194,11 +185,6 @@ namespace ams::dmnt::cheat::impl {
u32 key_mask; u32 key_mask;
}; };
struct BeginExtendedKeypressConditionalOpcode {
u64 key_mask;
bool auto_repeat;
};
struct PerformArithmeticRegisterOpcode { struct PerformArithmeticRegisterOpcode {
u32 bit_width; u32 bit_width;
RegisterArithmeticType math_type; RegisterArithmeticType math_type;
@ -273,7 +259,6 @@ namespace ams::dmnt::cheat::impl {
StoreStaticToAddressOpcode str_static; StoreStaticToAddressOpcode str_static;
PerformArithmeticStaticOpcode perform_math_static; PerformArithmeticStaticOpcode perform_math_static;
BeginKeypressConditionalOpcode begin_keypress_cond; BeginKeypressConditionalOpcode begin_keypress_cond;
BeginExtendedKeypressConditionalOpcode begin_ext_keypress_cond;
PerformArithmeticRegisterOpcode perform_math_reg; PerformArithmeticRegisterOpcode perform_math_reg;
StoreRegisterToAddressOpcode str_register; StoreRegisterToAddressOpcode str_register;
BeginRegisterConditionalOpcode begin_reg_cond; BeginRegisterConditionalOpcode begin_reg_cond;

View File

@ -25,11 +25,11 @@ namespace ams::ldr {
} }
/* ScopedCodeMount functionality. */ /* ScopedCodeMount functionality. */
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform) : m_lk(g_scoped_code_mount_lock), m_has_status(false), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) { ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, PlatformId platform) : m_lk(g_scoped_code_mount_lock), m_has_status(false), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
m_result = this->Initialize(loc, platform); m_result = this->Initialize(loc, platform);
} }
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &o, ncm::ContentMetaPlatform platform) : m_lk(g_scoped_code_mount_lock), m_override_status(o), m_has_status(true), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) { ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &o, PlatformId platform) : m_lk(g_scoped_code_mount_lock), m_override_status(o), m_has_status(true), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
m_result = this->Initialize(loc, platform); m_result = this->Initialize(loc, platform);
} }
@ -46,7 +46,7 @@ namespace ams::ldr {
} }
} }
Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform) { Result ScopedCodeMount::Initialize(const ncm::ProgramLocation &loc, PlatformId platform) {
/* Capture override status, if necessary. */ /* Capture override status, if necessary. */
this->EnsureOverrideStatus(loc); this->EnsureOverrideStatus(loc);
AMS_ABORT_UNLESS(m_has_status); AMS_ABORT_UNLESS(m_has_status);
@ -83,7 +83,7 @@ namespace ams::ldr {
} }
/* Redirection API. */ /* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform) { Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, PlatformId platform) {
/* Check for storage id none. */ /* Check for storage id none. */
if (static_cast<ncm::StorageId>(loc.storage_id) == ncm::StorageId::None) { if (static_cast<ncm::StorageId>(loc.storage_id) == ncm::StorageId::None) {
std::memset(out_path, 0, out_size); std::memset(out_path, 0, out_size);
@ -166,9 +166,9 @@ namespace ams::ldr {
R_SUCCEED(); R_SUCCEED();
} }
fs::ContentAttributes GetPlatformContentAttributes(ncm::ContentMetaPlatform platform) { fs::ContentAttributes GetPlatformContentAttributes(PlatformId platform) {
switch (platform) { switch (platform) {
case ncm::ContentMetaPlatform::Nx: case PlatformId_Nx:
return fs::ContentAttributes_None; return fs::ContentAttributes_None;
AMS_UNREACHABLE_DEFAULT_CASE(); AMS_UNREACHABLE_DEFAULT_CASE();
} }

View File

@ -34,8 +34,8 @@ namespace ams::ldr {
bool m_mounted_sd_or_code; bool m_mounted_sd_or_code;
bool m_mounted_code; bool m_mounted_code;
public: public:
ScopedCodeMount(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform); ScopedCodeMount(const ncm::ProgramLocation &loc, PlatformId platform);
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, ncm::ContentMetaPlatform platform); ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, PlatformId platform);
~ScopedCodeMount(); ~ScopedCodeMount();
Result GetResult() const { Result GetResult() const {
@ -59,7 +59,7 @@ namespace ams::ldr {
return m_base_code_verification_data; return m_base_code_verification_data;
} }
private: private:
Result Initialize(const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform); Result Initialize(const ncm::ProgramLocation &loc, PlatformId platform);
void EnsureOverrideStatus(const ncm::ProgramLocation &loc); void EnsureOverrideStatus(const ncm::ProgramLocation &loc);
}; };
@ -76,10 +76,10 @@ namespace ams::ldr {
#define ENCODE_CMPT_PATH(relative) "cmpt:" relative #define ENCODE_CMPT_PATH(relative) "cmpt:" relative
/* Redirection API. */ /* Redirection API. */
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform); Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, PlatformId platform);
Result RedirectProgramPath(const char *path, size_t size, const ncm::ProgramLocation &loc); Result RedirectProgramPath(const char *path, size_t size, const ncm::ProgramLocation &loc);
Result RedirectHtmlDocumentPathForHbl(const ncm::ProgramLocation &loc); Result RedirectHtmlDocumentPathForHbl(const ncm::ProgramLocation &loc);
fs::ContentAttributes GetPlatformContentAttributes(ncm::ContentMetaPlatform platform); fs::ContentAttributes GetPlatformContentAttributes(PlatformId platform);
} }

View File

@ -27,11 +27,11 @@ namespace ams::ldr {
constinit ArgumentStore g_argument_store; constinit ArgumentStore g_argument_store;
bool IsValidPlatform(ncm::ContentMetaPlatform platform) { bool IsValidPlatform(PlatformId platform) {
return platform == ncm::ContentMetaPlatform::Nx; return platform == PlatformId_Nx;
} }
Result CreateProcessByPlatform(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit, ncm::ContentMetaPlatform platform) { Result CreateProcessByPlatform(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit, PlatformId platform) {
/* Check that the platform is valid. */ /* Check that the platform is valid. */
R_UNLESS(IsValidPlatform(platform), ldr::ResultInvalidPlatformId()); R_UNLESS(IsValidPlatform(platform), ldr::ResultInvalidPlatformId());
@ -49,7 +49,7 @@ namespace ams::ldr {
R_RETURN(ldr::CreateProcess(out, pin_id, loc, override_status, path, g_argument_store.Get(loc.program_id), flags, resource_limit, platform)); R_RETURN(ldr::CreateProcess(out, pin_id, loc, override_status, path, g_argument_store.Get(loc.program_id), flags, resource_limit, platform));
} }
Result GetProgramInfoByPlatform(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, ncm::ContentMetaPlatform platform) { Result GetProgramInfoByPlatform(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, PlatformId platform) {
/* Check that the platform is valid. */ /* Check that the platform is valid. */
R_UNLESS(IsValidPlatform(platform), ldr::ResultInvalidPlatformId()); R_UNLESS(IsValidPlatform(platform), ldr::ResultInvalidPlatformId());
@ -88,11 +88,11 @@ namespace ams::ldr {
Result LoaderService::CreateProcess(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit) { Result LoaderService::CreateProcess(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit) {
R_RETURN(CreateProcessByPlatform(out, pin_id, flags, resource_limit, ncm::ContentMetaPlatform::Nx)); R_RETURN(CreateProcessByPlatform(out, pin_id, flags, resource_limit, PlatformId_Nx));
} }
Result LoaderService::GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) { Result LoaderService::GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
R_RETURN(GetProgramInfoByPlatform(out, out_status, loc, ncm::ContentMetaPlatform::Nx)); R_RETURN(GetProgramInfoByPlatform(out, out_status, loc, PlatformId_Nx));
} }
Result LoaderService::PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) { Result LoaderService::PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {

View File

@ -103,15 +103,15 @@ namespace ams::ldr {
R_SUCCEED(); R_SUCCEED();
} }
const u8 *GetAcidSignatureModulus(ncm::ContentMetaPlatform platform, u8 key_generation, bool unk_unused) { const u8 *GetAcidSignatureModulus(PlatformId platform, u8 key_generation, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulus(platform, !IsDevelopmentForAcidSignatureCheck(), key_generation, unk_unused); return fssystem::GetAcidSignatureKeyModulus(platform, !IsDevelopmentForAcidSignatureCheck(), key_generation, unk_unused);
} }
size_t GetAcidSignatureModulusSize(ncm::ContentMetaPlatform platform, bool unk_unused) { size_t GetAcidSignatureModulusSize(PlatformId platform, bool unk_unused) {
return fssystem::GetAcidSignatureKeyModulusSize(platform, unk_unused); return fssystem::GetAcidSignatureKeyModulusSize(platform, unk_unused);
} }
Result ValidateAcidSignature(Meta *meta, ncm::ContentMetaPlatform platform, bool unk_unused) { Result ValidateAcidSignature(Meta *meta, PlatformId platform, bool unk_unused) {
/* Loader did not check signatures prior to 10.0.0. */ /* Loader did not check signatures prior to 10.0.0. */
if (hos::GetVersion() < hos::Version_10_0_0) { if (hos::GetVersion() < hos::Version_10_0_0) {
meta->check_verification_data = false; meta->check_verification_data = false;
@ -190,7 +190,7 @@ namespace ams::ldr {
} }
/* API. */ /* API. */
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) { Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform, bool unk_unused) {
/* Set the cached program id back to zero. */ /* Set the cached program id back to zero. */
g_cached_program_id = {}; g_cached_program_id = {};
@ -282,7 +282,7 @@ namespace ams::ldr {
R_SUCCEED(); R_SUCCEED();
} }
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) { Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform) {
if (g_cached_program_id != loc.program_id || g_cached_override_status != status) { if (g_cached_program_id != loc.program_id || g_cached_override_status != status) {
R_RETURN(LoadMeta(out_meta, loc, status, platform, false)); R_RETURN(LoadMeta(out_meta, loc, status, platform, false));
} }

View File

@ -36,8 +36,8 @@ namespace ams::ldr {
}; };
/* Meta API. */ /* Meta API. */
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused); Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform, bool unk_unused);
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform); Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, PlatformId platform);
void InvalidateMetaCache(); void InvalidateMetaCache();
} }

View File

@ -664,7 +664,7 @@ namespace ams::ldr {
} }
/* Process Creation API. */ /* Process Creation API. */
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, ncm::ContentMetaPlatform platform) { Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, PlatformId platform) {
/* Mount code. */ /* Mount code. */
AMS_UNUSED(path); AMS_UNUSED(path);
ScopedCodeMount mount(loc, override_status, platform); ScopedCodeMount mount(loc, override_status, platform);
@ -720,7 +720,7 @@ namespace ams::ldr {
R_SUCCEED(); R_SUCCEED();
} }
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, ncm::ContentMetaPlatform platform) { Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform) {
Meta meta; Meta meta;
/* Load Meta. */ /* Load Meta. */

View File

@ -19,8 +19,8 @@
namespace ams::ldr { namespace ams::ldr {
/* Process Creation API. */ /* Process Creation API. */
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, ncm::ContentMetaPlatform platform); Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, PlatformId platform);
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, ncm::ContentMetaPlatform platform); Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, PlatformId platform);
Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status); Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
Result UnpinProgram(PinId id); Result UnpinProgram(PinId id);