ldr_oc_suite: adopt ams style return code; test is now clang compatible; loader.kip will not crash if pcv/ptm sysmodules is manually patched.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
export CC := g++-11
|
||||
export CC := g++
|
||||
|
||||
all: test
|
||||
|
||||
|
||||
@@ -28,33 +28,33 @@ namespace ams::ldr::oc {
|
||||
namespace pcv {
|
||||
Result MemPllmLimitHandler(u32* ptr) {
|
||||
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||
if (entry->max_0 != entry->max_1)
|
||||
return ResultFailure();
|
||||
R_UNLESS(entry->max_0 == entry->max_1, ldr::ResultInvalidMemPllmEntry());
|
||||
|
||||
// Double the max clk simply
|
||||
u32 max_clk = entry->max_0 * 2;
|
||||
entry->max_0 = max_clk;
|
||||
entry->max_1 = max_clk;
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
template<typename M>
|
||||
Result MtcOverwrite(M* des, M* src) {
|
||||
constexpr u32 mtc_magic = 0x5F43544D;
|
||||
if (src->rev != mtc_magic)
|
||||
return ResultFailure();
|
||||
R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic());
|
||||
|
||||
// Ignore params from dvfs_ver to clock_src;
|
||||
for (size_t offset = offsetof(M, clk_src_emc); offset < sizeof(M); offset += sizeof(u32)) {
|
||||
u32* src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
|
||||
u32* des_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(des) + offset);
|
||||
u32 src_val = *src_ent;
|
||||
if (src_val != UINT32_MAX) {
|
||||
|
||||
constexpr u32 ignore_val = UINT32_MAX;
|
||||
if (src_val != ignore_val) {
|
||||
PatchOffset(des_ent, src_val);
|
||||
}
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace ams::ldr::oc {
|
||||
constexpr u32 CpuClkOSLimit = 1785'000;
|
||||
constexpr u32 CpuClkOfficial = 1963'500;
|
||||
constexpr u32 CpuVoltOfficial = 1120;
|
||||
constexpr u32 GpuClkOSLimit = 921'600;
|
||||
// constexpr u32 GpuClkOSLimit = 921'600;
|
||||
constexpr u32 GpuClkOfficial = 1267'200;
|
||||
constexpr u32 MemClkOSLimit = 1600'000;
|
||||
constexpr u32 MemClkOSAlt = 1331'200;
|
||||
@@ -677,16 +677,13 @@ namespace ams::ldr::oc {
|
||||
}
|
||||
|
||||
Result CpuClockVddHandler(u32* ptr) {
|
||||
u32 value_1 = *(ptr + 2);
|
||||
u32 value_2 = *(ptr + 12);
|
||||
constexpr u32 pattern_1 = 0;
|
||||
constexpr u32 pattern_2 = 1525000;
|
||||
if (value_1 != pattern_1 || value_2 != pattern_2)
|
||||
return ResultFailure();
|
||||
R_UNLESS(*(ptr + 2) == 0, ldr::ResultInvalidCpuClockVddEntry());
|
||||
R_UNLESS(*(ptr + 12) == 1525000, ldr::ResultInvalidCpuClockVddEntry());
|
||||
|
||||
if (C.marikoCpuMaxClock)
|
||||
PatchOffset(ptr, C.marikoCpuMaxClock);
|
||||
return ResultSuccess();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result CpuDvfsHandler(u32* ptr, uintptr_t nso_end_offset) {
|
||||
@@ -696,21 +693,17 @@ namespace ams::ldr::oc {
|
||||
cpu_freq_cvb_table_t* entry_1020 = entry_204 + 8;
|
||||
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewCpuTables) - sizeof(u32);
|
||||
|
||||
if ( entry_end_offset >= nso_end_offset
|
||||
|| *(reinterpret_cast<u32 *>(entry_free)) != 0
|
||||
|| *(reinterpret_cast<u32 *>(entry_204)) != 204'000
|
||||
|| *(reinterpret_cast<u32 *>(entry_end_offset)) != 0 )
|
||||
{
|
||||
return ResultFailure();
|
||||
}
|
||||
R_UNLESS(entry_end_offset < nso_end_offset, ldr::ResultOutOfRange());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_free)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_204)) == 204'000, ldr::ResultInvalidCpuDvfs());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_end_offset)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||
|
||||
if (C.marikoCpuMaxClock > CpuClkOfficial)
|
||||
std::memcpy(reinterpret_cast<void *>(entry_free), NewCpuTables, sizeof(NewCpuTables));
|
||||
|
||||
// Patch CPU max volt in CPU dvfs table
|
||||
cpu_freq_cvb_table_t* entry_current = entry_1020;
|
||||
if (entry_current->cvb_pll_param.c0 != CpuVoltOfficial * 1000)
|
||||
return ResultFailure();
|
||||
R_UNLESS(entry_current->cvb_pll_param.c0 == CpuVoltOfficial * 1000, ldr::ResultInvalidCpuDvfs());
|
||||
|
||||
if (C.marikoCpuMaxVolt) {
|
||||
while (entry_current->cvb_pll_param.c0 == CpuVoltOfficial * 1000) {
|
||||
@@ -719,7 +712,7 @@ namespace ams::ldr::oc {
|
||||
}
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GpuDvfsHandler(u32* ptr, uintptr_t nso_end_offset) {
|
||||
@@ -728,17 +721,15 @@ namespace ams::ldr::oc {
|
||||
gpu_cvb_pll_table_t* entry_76_8 = entry_free - 17;
|
||||
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewGpuTables) - sizeof(u32);
|
||||
|
||||
if ( entry_end_offset >= nso_end_offset
|
||||
|| *(reinterpret_cast<u32 *>(entry_free)) != 0
|
||||
|| *(reinterpret_cast<u32 *>(entry_76_8)) != 76'800
|
||||
|| *(reinterpret_cast<u32 *>(entry_end_offset)) != 0 )
|
||||
{
|
||||
return ResultFailure();
|
||||
}
|
||||
R_UNLESS(entry_end_offset < nso_end_offset, ldr::ResultOutOfRange());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_free)) == 0, ldr::ResultInvalidGpuDvfs());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_76_8)) == 76'800, ldr::ResultInvalidGpuDvfs());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_end_offset)) == 0, ldr::ResultInvalidGpuDvfs());
|
||||
|
||||
if (C.marikoGpuMaxClock > GpuClkOfficial)
|
||||
std::memcpy(reinterpret_cast<void *>(entry_free), NewGpuTables, sizeof(NewGpuTables));
|
||||
return ResultSuccess();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result CpuVoltRangeHandler(u32* ptr) {
|
||||
@@ -750,9 +741,9 @@ namespace ams::ldr::oc {
|
||||
case 610:
|
||||
if (C.marikoCpuMaxVolt)
|
||||
PatchOffset(ptr, C.marikoCpuMaxVolt);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
default:
|
||||
return ResultFailure();
|
||||
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,20 +762,19 @@ namespace ams::ldr::oc {
|
||||
PatchOffset(ptr_next, gpuMaxClockMarikoPattern[1] | reg_id);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
return ResultFailure();
|
||||
R_THROW(ldr::ResultInvalidGpuMaxClkPattern());
|
||||
}
|
||||
|
||||
Result MtcTableHandler(u32* ptr) {
|
||||
MarikoMtcTable* const mtc_table_max = reinterpret_cast<MarikoMtcTable *>(ptr - offsetof(MarikoMtcTable, rate_khz) / sizeof(u32));
|
||||
MarikoMtcTable* const mtc_table_alt = mtc_table_max - 1;
|
||||
constexpr u32 mtc_mariko_rev = 3;
|
||||
if ( mtc_table_max->rev != mtc_mariko_rev
|
||||
|| mtc_table_alt->rev != mtc_mariko_rev
|
||||
|| mtc_table_alt->rate_khz != MemClkOSAlt )
|
||||
return ResultFailure();
|
||||
R_UNLESS(mtc_table_max->rev == mtc_mariko_rev, ldr::ResultInvalidMtcTable());
|
||||
R_UNLESS(mtc_table_alt->rev == mtc_mariko_rev, ldr::ResultInvalidMtcTable());
|
||||
R_UNLESS(mtc_table_alt->rate_khz == MemClkOSAlt, ldr::ResultInvalidMtcTable());
|
||||
|
||||
MarikoMtcTable* const table = const_cast<MarikoMtcTable *>(C.marikoMtc);
|
||||
bool replace_entire_table = (C.mtcConf == ENTIRE_TABLE_MARIKO);
|
||||
@@ -797,7 +787,7 @@ namespace ams::ldr::oc {
|
||||
MtcTableAutoAdjust(mtc_table_max, mtc_table_alt);
|
||||
MtcPllmbDivHandler(mtc_table_max);
|
||||
std::memcpy(reinterpret_cast<void *>(mtc_table_alt), reinterpret_cast<void *>(table), sizeof(MarikoMtcTable));
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DvbTableHandler(u32* ptr) {
|
||||
@@ -805,11 +795,10 @@ namespace ams::ldr::oc {
|
||||
emc_dvb_dvfs_table_t* dvb_1331_entry = dvb_max_entry - 1;
|
||||
|
||||
u32* dvb_1331_offset = reinterpret_cast<u32 *>(dvb_1331_entry);
|
||||
if (*(dvb_1331_offset) != MemClkOSAlt)
|
||||
return ResultFailure();
|
||||
R_UNLESS(*(dvb_1331_offset) == MemClkOSAlt, ldr::ResultInvalidDvbTable());
|
||||
|
||||
PatchOffset(dvb_1331_offset, MemClkOSLimit);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemMaxClockHandler(u32* ptr) {
|
||||
@@ -821,26 +810,24 @@ namespace ams::ldr::oc {
|
||||
constexpr u32 mtc_min_volt = 1100;
|
||||
constexpr u32 dvb_entry_volt = 675;
|
||||
|
||||
Result rc = ResultSuccess();
|
||||
|
||||
if (value_next == mtc_min_volt) {
|
||||
rc = MtcTableHandler(ptr);
|
||||
R_TRY(MtcTableHandler(ptr));
|
||||
} else if (value_next2 == dvb_entry_volt) {
|
||||
rc = DvbTableHandler(ptr);
|
||||
R_TRY(DvbTableHandler(ptr));
|
||||
}
|
||||
|
||||
PatchOffset(ptr, C.marikoEmcMaxClock);
|
||||
return rc;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GpuPllLimitHandler(u32* ptr) {
|
||||
u32 value_next = *(ptr + 1);
|
||||
if (value_next != 0)
|
||||
return ResultFailure();
|
||||
R_UNLESS(value_next == 0, ldr::ResultInvalidGpuPllEntry());
|
||||
|
||||
// Double the max clk simply
|
||||
u32 max_clk = *(ptr) * 2;
|
||||
PatchOffset(ptr, max_clk);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||
@@ -922,14 +909,13 @@ namespace ams::ldr::oc {
|
||||
cnt[MEM_PLL_CLK],
|
||||
cnt[GPU_MAX_CLOCK]);
|
||||
|
||||
if ( cnt[CPU_CLOCK_VDD] != 1
|
||||
|| cnt[CPU_TABLE] != 1
|
||||
|| cnt[GPU_TABLE] != 1
|
||||
|| cnt[CPU_MAX_VOLT] > 13 || !cnt[CPU_MAX_VOLT]
|
||||
|| cnt[MEM_CLOCK] == 0
|
||||
|| cnt[GPU_PLL_CLK] != 1
|
||||
|| cnt[MEM_PLL_CLK] != 2
|
||||
|| cnt[GPU_MAX_CLOCK] != 2)
|
||||
if (cnt[CPU_CLOCK_VDD] > 1 ||
|
||||
cnt[CPU_TABLE] > 1 ||
|
||||
cnt[GPU_TABLE] > 1 ||
|
||||
cnt[CPU_MAX_VOLT] > 13 ||
|
||||
cnt[GPU_PLL_CLK] > 1 ||
|
||||
cnt[MEM_PLL_CLK] > 2 ||
|
||||
cnt[GPU_MAX_CLOCK] > 2)
|
||||
{
|
||||
CRASH();
|
||||
}
|
||||
@@ -974,18 +960,15 @@ namespace ams::ldr::oc {
|
||||
cpu_freq_cvb_table_t* entry_204 = entry_free - 16;
|
||||
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewCpuTables) - sizeof(u32);
|
||||
|
||||
if ( entry_end_offset >= nso_end_offset
|
||||
|| *(reinterpret_cast<u32 *>(entry_free)) != 0
|
||||
|| *(reinterpret_cast<u32 *>(entry_204)) != 204'000
|
||||
|| *(reinterpret_cast<u32 *>(entry_end_offset)) != 0 )
|
||||
{
|
||||
return ResultFailure();
|
||||
}
|
||||
R_UNLESS(entry_end_offset < nso_end_offset, ldr::ResultOutOfRange());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_free)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_204)) == 204'000, ldr::ResultInvalidCpuDvfs());
|
||||
R_UNLESS(*(reinterpret_cast<u32 *>(entry_end_offset)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||
|
||||
if (C.eristaCpuOCEnable)
|
||||
std::memcpy(reinterpret_cast<void *>(entry_free), NewCpuTables, sizeof(NewCpuTables));
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result CpuVoltRangeHandler(u32* ptr) {
|
||||
@@ -997,10 +980,10 @@ namespace ams::ldr::oc {
|
||||
case 810:
|
||||
if (C.eristaCpuMaxVolt)
|
||||
PatchOffset(ptr, C.eristaCpuMaxVolt);
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
default:
|
||||
LOGGING("Invalid min voltage: %u @%p!", *(ptr-1), ptr-1);
|
||||
return ResultFailure();
|
||||
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1012,21 +995,20 @@ namespace ams::ldr::oc {
|
||||
return MtcOverwrite(mtc_table_max, table);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemMaxClockHandler(u32* ptr) {
|
||||
u32 value_next = *(ptr + 1);
|
||||
constexpr u32 mtc_min_volt = 887;
|
||||
|
||||
Result rc = ResultSuccess();
|
||||
if (value_next == mtc_min_volt) {
|
||||
rc = MtcTableHandler(ptr);
|
||||
}
|
||||
if (value_next == mtc_min_volt)
|
||||
R_TRY(MtcTableHandler(ptr));
|
||||
|
||||
if (C.eristaEmcMaxClock > MemClkOSLimit)
|
||||
PatchOffset(ptr, C.eristaEmcMaxClock);
|
||||
return rc;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result MemVoltHandler(u32* ptr) {
|
||||
@@ -1035,10 +1017,11 @@ namespace ams::ldr::oc {
|
||||
constexpr u32 uv_step = 12'500;
|
||||
if (emc_uv % uv_step)
|
||||
emc_uv = emc_uv / uv_step * uv_step;
|
||||
|
||||
PatchOffset(ptr, emc_uv);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||
@@ -1099,11 +1082,9 @@ namespace ams::ldr::oc {
|
||||
cnt[MEM_VOLT],
|
||||
cnt[MEM_PLL_CLK]);
|
||||
|
||||
if ( cnt[CPU_CLOCK] != 1
|
||||
|| cnt[CPU_MAX_VOLT] < 2
|
||||
|| cnt[MEM_CLOCK] == 0
|
||||
|| cnt[MEM_VOLT] != 2
|
||||
|| cnt[MEM_PLL_CLK] != 2)
|
||||
if (cnt[CPU_CLOCK] > 1 ||
|
||||
cnt[MEM_VOLT] > 2 ||
|
||||
cnt[MEM_PLL_CLK] > 2)
|
||||
{
|
||||
CRASH();
|
||||
}
|
||||
@@ -1112,10 +1093,11 @@ namespace ams::ldr::oc {
|
||||
|
||||
namespace pcv {
|
||||
void SafetyCheck() {
|
||||
if ( C.custRev != CUST_REV
|
||||
|| C.marikoCpuMaxVolt >= 1300
|
||||
|| C.eristaCpuMaxVolt >= 1400
|
||||
|| (C.eristaEmcVolt && (C.eristaEmcVolt < 600'000 || C.eristaEmcVolt > 1250'000)))
|
||||
if (C.custRev != CUST_REV ||
|
||||
C.marikoCpuMaxVolt >= 1300 ||
|
||||
C.eristaCpuMaxVolt >= 1400 ||
|
||||
(C.eristaEmcVolt &&
|
||||
(C.eristaEmcVolt < 600'000 || C.eristaEmcVolt > 1250'000)))
|
||||
{
|
||||
CRASH();
|
||||
}
|
||||
|
||||
@@ -14,9 +14,30 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "mtc_timing_table.hpp"
|
||||
|
||||
#define CUST_REV 2
|
||||
#include "mtc_timing_table.hpp"
|
||||
|
||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||
#include <vapours/results/results_common.hpp>
|
||||
#define LOGGING(fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define CRASH() { AMS_ABORT(); __builtin_unreachable(); }
|
||||
|
||||
namespace ams::ldr {
|
||||
R_DEFINE_ERROR_RESULT(OutOfRange, 1000);
|
||||
R_DEFINE_ERROR_RESULT(InvalidMemPllmEntry, 1001);
|
||||
R_DEFINE_ERROR_RESULT(InvalidMtcMagic, 1002);
|
||||
R_DEFINE_ERROR_RESULT(InvalidMtcTable, 1003);
|
||||
R_DEFINE_ERROR_RESULT(InvalidDvbTable, 1004);
|
||||
R_DEFINE_ERROR_RESULT(InvalidCpuClockVddEntry, 1005);
|
||||
R_DEFINE_ERROR_RESULT(InvalidCpuDvfs, 1006);
|
||||
R_DEFINE_ERROR_RESULT(InvalidCpuMinVolt, 1007);
|
||||
R_DEFINE_ERROR_RESULT(InvalidGpuDvfs, 1008);
|
||||
R_DEFINE_ERROR_RESULT(InvalidGpuMaxClkPattern, 1009);
|
||||
R_DEFINE_ERROR_RESULT(InvalidGpuPllEntry, 1010);
|
||||
}
|
||||
|
||||
namespace ams::ldr::oc {
|
||||
enum MtcConfig {
|
||||
@@ -26,7 +47,7 @@ namespace ams::ldr::oc {
|
||||
ENTIRE_TABLE_MARIKO = 3,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
typedef struct CustomizeTable {
|
||||
u8 cust[4] = {'C', 'U', 'S', 'T'};
|
||||
u16 custRev = CUST_REV;
|
||||
u16 mtcConf = AUTO_ADJ_MARIKO_SAFE;
|
||||
@@ -47,16 +68,8 @@ namespace ams::ldr::oc {
|
||||
|
||||
inline void PatchOffset(u32* offset, u32 value) { *(offset) = value; }
|
||||
|
||||
inline Result ResultFailure() { return -1; }
|
||||
|
||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||
#define LOGGING(fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#define CRASH() { AMS_ABORT(); __builtin_unreachable(); }
|
||||
|
||||
namespace pcv {
|
||||
typedef struct {
|
||||
typedef struct cvb_coefficients {
|
||||
s32 c0 = 0;
|
||||
s32 c1 = 0;
|
||||
s32 c2 = 0;
|
||||
@@ -65,24 +78,24 @@ namespace ams::ldr::oc {
|
||||
s32 c5 = 0;
|
||||
} cvb_coefficients;
|
||||
|
||||
typedef struct {
|
||||
typedef struct cpu_freq_cvb_table_t {
|
||||
u64 freq;
|
||||
cvb_coefficients cvb_dfll_param;
|
||||
cvb_coefficients cvb_pll_param; // only c0 is reserved
|
||||
} cpu_freq_cvb_table_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct gpu_cvb_pll_table_t {
|
||||
u64 freq;
|
||||
cvb_coefficients cvb_dfll_param; // empty, dfll clock source not selected
|
||||
cvb_coefficients cvb_pll_param;
|
||||
} gpu_cvb_pll_table_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct emc_dvb_dvfs_table_t {
|
||||
u64 freq;
|
||||
s32 volt[4] = {0};
|
||||
} emc_dvb_dvfs_table_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct clk_pll_param {
|
||||
u32 max_0;
|
||||
u32 unk[5];
|
||||
u32 max_1;
|
||||
|
||||
@@ -11,12 +11,17 @@ typedef int32_t s32;
|
||||
typedef uint64_t u64;
|
||||
typedef int Result;
|
||||
|
||||
#define R_SUCCEEDED(arg) (arg == ResultSuccess())
|
||||
#define R_FAILED(arg) (!R_SUCCEEDED(arg))
|
||||
#define LOGGING(fmt, ...) { printf(fmt "\n\tin %s\n", ##__VA_ARGS__, __PRETTY_FUNCTION__); }
|
||||
#define AMS_ABORT() { fprintf(stderr, "Failed in %s!\n", __PRETTY_FUNCTION__); exit(-1); }
|
||||
#define R_SUCCEEDED(arg) (arg == 0)
|
||||
#define R_FAILED(arg) (arg != 0)
|
||||
#define LOGGING(fmt, ...) { printf(fmt "\n\tin %s\n", ##__VA_ARGS__, __PRETTY_FUNCTION__); }
|
||||
#define AMS_ABORT() { fprintf(stderr, "Failed in %s!\n", __PRETTY_FUNCTION__); exit(-1); }
|
||||
#define R_SUCCEED() { return 0; }
|
||||
#define R_THROW(err) { return err; }
|
||||
#define R_TRY(expr) { Result _rc = (expr); if (R_FAILED(_rc)) { return _rc; } }
|
||||
#define R_UNLESS(expr, rc) { if (!(expr)) { return rc; } }
|
||||
|
||||
inline Result ResultSuccess() { return 0; }
|
||||
#define R_DEFINE_ERROR_RESULT(name, rc) \
|
||||
inline Result Result##name() { return rc; }
|
||||
|
||||
#include "ldr_oc_suite.hpp"
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ams::ldr::oc {
|
||||
namespace pcv {
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
fw_dir="/Volumes/RAM/NX-14.0.0/"
|
||||
tmp_dir="/Volumes/RAM/"
|
||||
repack_out_dir="/Volumes/RAM/out/"
|
||||
oc_test_dir="$HOME/Source/Switch-OC-Suite/Source/Atmosphere/stratosphere/loader/source/oc"
|
||||
prodkeys="$HOME/.switch/prod.keys"
|
||||
hactool_exe="$HOME/Source/hactool/hactool"
|
||||
nx2elf_exe="$HOME/Source/nx2elf/nx2elf"
|
||||
elf2nso_exe="$HOME/Source/switch-tools/elf2nso"
|
||||
hacpack_exe="$HOME/Source/hacPack/hacpack"
|
||||
|
||||
should_remove_tmp="Y"
|
||||
should_save_repack="Y"
|
||||
option_Mariko_Erista="M"
|
||||
|
||||
echo -e "\nExtracting nca..."
|
||||
out_pcv="${tmp_dir}pcv/"
|
||||
out_ptm="${tmp_dir}ptm/"
|
||||
mkdir -p "${out_pcv}"
|
||||
mkdir -p "${out_ptm}"
|
||||
cd $fw_dir
|
||||
|
||||
pcv_nca_name=""
|
||||
ptm_nca_name=""
|
||||
for file_00 in ./*.nca/00
|
||||
do
|
||||
if [ -e "${file_00}" ]; then
|
||||
echo "Processing \"*.nca/00\" files..."
|
||||
find "${fw_dir}" -type f -name "00" -exec sh -c 'DIR=$(dirname "{}"); FW_DIR=$(dirname "${DIR}"); mv "{}" "${FW_DIR}/00"; rm -r "${DIR}"; mv "${FW_DIR}/00" "${DIR}"' \;
|
||||
fi
|
||||
break
|
||||
done
|
||||
|
||||
for nca_file in ./*.nca
|
||||
do
|
||||
file_size=`wc -c "$nca_file" | awk '{print $1}'`
|
||||
if [[ "$nca_file" == *".cnmt."* || file_size -lt 16384 ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
titleid=`$hactool_exe -k $prodkeys --disablekeywarns -t nca $nca_file | grep 'Title ID'`
|
||||
|
||||
if [[ $titleid == *"010000000000001a"* ]]; then
|
||||
pcv_nca_name="$(basename $nca_file)"
|
||||
echo "$pcv_nca_name (pcv) -> $out_pcv"
|
||||
$hactool_exe -k $prodkeys --disablekeywarns -t nca $nca_file --exefsdir "$out_pcv" 1> /dev/null
|
||||
fi
|
||||
|
||||
if [[ $titleid == *"0100000000000010"* ]]; then
|
||||
ptm_nca_name="$(basename $nca_file)"
|
||||
echo "$ptm_nca_name (ptm) -> $out_ptm"
|
||||
$hactool_exe -k $prodkeys --disablekeywarns -t nca $nca_file --exefsdir "$out_ptm" 1> /dev/null
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\nConverting nca to elf..."
|
||||
$nx2elf_exe "${out_pcv}main" 1> /dev/null
|
||||
$nx2elf_exe "${out_ptm}main" 1> /dev/null
|
||||
|
||||
echo -e "\nBuilding..."
|
||||
cd $oc_test_dir
|
||||
make test 1> /dev/null
|
||||
|
||||
echo -e "\nPatching..."
|
||||
|
||||
[ -z "$should_save_repack" ] && read -p "Save and repack to nca (y/N)? " should_save_repack
|
||||
SAVE_OPT=" "
|
||||
case $should_save_repack in
|
||||
Y|y ) SAVE_OPT="-s ";;
|
||||
esac
|
||||
|
||||
./test pcv $SAVE_OPT "${out_pcv}main.elf"
|
||||
./test ptm $SAVE_OPT "${out_ptm}main.elf"
|
||||
make clean 1> /dev/null
|
||||
|
||||
if [ ! -z $SAVE_OPT ]; then
|
||||
case $should_save_repack in
|
||||
Y|y )
|
||||
patched_ext=".mariko"
|
||||
[ -z "$option_Mariko_Erista" ] && read -p "[M]ariko (Default) | [E]rista ? " option_Mariko_Erista
|
||||
case $option_Mariko_Erista in
|
||||
E|e ) patched_ext=".erista";;
|
||||
esac
|
||||
mkdir -p "${repack_out_dir}"
|
||||
cd "${tmp_dir}"
|
||||
echo -e "\nRepacking pcv to ${repack_out_dir}${pcv_nca_name}..."
|
||||
TMP="${out_pcv}temp/"
|
||||
mkdir -p "${TMP}"
|
||||
$elf2nso_exe "${out_pcv}main.elf${patched_ext}" "${TMP}main" 1> /dev/null
|
||||
cp "${out_pcv}main.npdm" "${TMP}main.npdm"
|
||||
$hacpack_exe -k $prodkeys -o "${TMP}nca" --type nca --ncatype program --titleid 010000000000001A --exefsdir "${TMP}" 1> /dev/null
|
||||
find "${TMP}nca" -name "*.nca" -exec mv {} "${repack_out_dir}${pcv_nca_name}" \;
|
||||
|
||||
if [[ $patched_ext == ".mariko" ]]; then
|
||||
echo -e "\nRepacking ptm (Mariko Only) to ${repack_out_dir}${ptm_nca_name}..."
|
||||
TMP="${out_ptm}temp/"
|
||||
mkdir -p "${TMP}"
|
||||
$elf2nso_exe "${out_ptm}main.elf${patched_ext}" "${TMP}main" 1> /dev/null
|
||||
cp "${out_ptm}main.npdm" "${TMP}main.npdm"
|
||||
$hacpack_exe -k $prodkeys -o "${TMP}nca" --type nca --ncatype program --titleid 0100000000000010 --exefsdir "${TMP}" 1> /dev/null
|
||||
find "${TMP}nca" -name "*.nca" -exec mv {} "${repack_out_dir}${ptm_nca_name}" \;
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
[ -z "$should_remove_tmp" ] && read -p "Remove temp files (Y/n)? " should_remove_tmp
|
||||
case $should_remove_tmp in
|
||||
N|n )
|
||||
exit;;
|
||||
esac
|
||||
|
||||
rm -fr $out_pcv
|
||||
rm -fr $out_ptm
|
||||
rm -fr "${tmp_dir}hacpack_backup"
|
||||
|
||||
echo -e "\nDone!"
|
||||
Reference in New Issue
Block a user