mirror of
https://github.com/PretendoNetwork/Inkay.git
synced 2026-07-16 08:41:09 -05:00
feat(p2p): Allow overriding the p2p udp port for Minecraft
the idea is that you might port forward this in your router and give yourself NAT type A for free
This commit is contained in:
parent
a1375ca608
commit
22bebff027
20
src/main.cpp
20
src/main.cpp
|
|
@ -68,6 +68,7 @@ WUPS_USE_WUT_DEVOPTAB();
|
|||
#include <mocha/mocha.h>
|
||||
#include <function_patcher/function_patching.h>
|
||||
#include "patches/account_settings.h"
|
||||
#include "patches/game_peertopeer.h"
|
||||
#include "utils/sysconfig.h"
|
||||
|
||||
//thanks @Gary#4139 :p
|
||||
|
|
@ -127,23 +128,9 @@ INITIALIZE_PLUGIN() {
|
|||
DEBUG_FUNCTION_LINE("NotificationModule_InitLibrary failed");
|
||||
}
|
||||
|
||||
//get os version
|
||||
MCPSystemVersion os_version;
|
||||
int mcp = MCP_Open();
|
||||
int ret = MCP_GetSystemVersion(mcp, &os_version);
|
||||
if (ret < 0) {
|
||||
DEBUG_FUNCTION_LINE("getting system version failed (%d/%d)!", mcp, ret);
|
||||
os_version = (MCPSystemVersion) {
|
||||
.major = 5, .minor = 5, .patch = 5, .region = 'E'
|
||||
};
|
||||
}
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Running on %d.%d.%d%c",
|
||||
os_version.major, os_version.minor, os_version.patch, os_version.region
|
||||
);
|
||||
|
||||
// if using pretendo then (try to) apply the ssl patches
|
||||
if (Config::connect_to_network) {
|
||||
if (is555(os_version)) {
|
||||
if (is555(get_console_os_version())) {
|
||||
Mocha_IOSUKernelWrite32(0xE1019F78, 0xE3A00001); // mov r0, #1
|
||||
} else {
|
||||
Mocha_IOSUKernelWrite32(0xE1019E84, 0xE3A00001); // mov r0, #1
|
||||
|
|
@ -165,8 +152,6 @@ INITIALIZE_PLUGIN() {
|
|||
ShowNotification(get_nintendo_network_message());
|
||||
}
|
||||
|
||||
MCP_Close(mcp);
|
||||
|
||||
if (FunctionPatcher_InitLibrary() == FUNCTION_PATCHER_RESULT_SUCCESS) {
|
||||
install_matchmaking_patches();
|
||||
}
|
||||
|
|
@ -187,6 +172,7 @@ ON_APPLICATION_START() {
|
|||
DEBUG_FUNCTION_LINE_VERBOSE("Inkay " INKAY_VERSION " starting up...\n");
|
||||
|
||||
setup_olv_libs();
|
||||
peertopeer_patch();
|
||||
matchmaking_notify_titleswitch();
|
||||
patchAccountSettings();
|
||||
}
|
||||
|
|
|
|||
73
src/patches/game_peertopeer.cpp
Normal file
73
src/patches/game_peertopeer.cpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* Copyright 2024 Pretendo Network contributors <pretendo.network>
|
||||
Copyright 2024 Ash Logan <ash@heyquark.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <coreinit/title.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include "game_peertopeer.h"
|
||||
|
||||
#include "utils/sysconfig.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/rpl_info.h"
|
||||
#include "utils/replace_mem.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
static inline int digit(char a) {
|
||||
if (a < '0' || a > '9') return 0;
|
||||
return a - '0';
|
||||
}
|
||||
|
||||
static unsigned short peertopeer_port() {
|
||||
const char * serial = get_console_serial();
|
||||
|
||||
unsigned short port = 50000 +
|
||||
(digit(serial[4]) * 1000) +
|
||||
(digit(serial[5]) * 100 ) +
|
||||
(digit(serial[6]) * 10 ) +
|
||||
(digit(serial[7]) * 1 );
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
static void minecraft_peertopeer_patch() {
|
||||
std::optional<OSDynLoad_NotifyData> minecraft = search_for_rpl("Minecraft.Client.rpx");
|
||||
if (!minecraft) {
|
||||
DEBUG_FUNCTION_LINE("Couldn't find minecraft rpx!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto port = peertopeer_port();
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Will use port %d. %08x", port, minecraft->textAddr);
|
||||
|
||||
uint32_t *target_func = rpl_addr(*minecraft, 0x03579530);
|
||||
replace_instruction(&target_func[0], 0x3c600001, 0x3c600000); // li r3, 0
|
||||
replace_instruction(&target_func[1], 0x3863c000, 0x60630000 | port); // ori r3, r3, port
|
||||
// blr
|
||||
|
||||
target_func = rpl_addr(*minecraft, 0x0357953c);
|
||||
replace_instruction(&target_func[0], 0x3c600001, 0x3c600000); // li r3, 0
|
||||
replace_instruction(&target_func[1], 0x3863ffff, 0x60630000 | port); // ori r3, r3, port
|
||||
// blr
|
||||
}
|
||||
|
||||
void peertopeer_patch() {
|
||||
uint64_t tid = OSGetTitleID();
|
||||
if (tid == 0x00050000'101D7500 || // EUR
|
||||
tid == 0x00050000'101D9D00 || // USA
|
||||
tid == 0x00050000'101DBE00) { // JPN
|
||||
|
||||
minecraft_peertopeer_patch();
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Game has no p2p patches, will skip.\n");
|
||||
}
|
||||
}
|
||||
16
src/patches/game_peertopeer.h
Normal file
16
src/patches/game_peertopeer.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/* Copyright 2024 Pretendo Network contributors <pretendo.network>
|
||||
Copyright 2024 Ash Logan <ash@heyquark.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void peertopeer_patch();
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
#include <kernel/kernel.h>
|
||||
#include <coreinit/memorymap.h>
|
||||
#include <algorithm>
|
||||
#include <coreinit/cache.h>
|
||||
|
||||
bool replace(uint32_t start, uint32_t size, const char *original_val, size_t original_val_sz, const char *new_val,
|
||||
size_t new_val_sz) {
|
||||
|
|
@ -71,3 +72,18 @@ void replaceBulk(uint32_t start, uint32_t size, std::span<const replacement> rep
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool replace_instruction(uint32_t *inst, uint32_t orignal_value, uint32_t new_value) {
|
||||
if (*inst != orignal_value) return false;
|
||||
|
||||
KernelCopyData(
|
||||
OSEffectiveToPhysical((uint32_t) inst),
|
||||
OSEffectiveToPhysical((uint32_t) &new_value),
|
||||
sizeof(new_value)
|
||||
);
|
||||
DCFlushRange(inst, sizeof(new_value));
|
||||
ICInvalidateRange(inst, sizeof(new_value));
|
||||
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("%08x is now %08x", inst, *inst);
|
||||
return *inst == new_value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,3 +27,5 @@ struct replacement {
|
|||
};
|
||||
|
||||
void replaceBulk(uint32_t start, uint32_t size, std::span<const replacement> replacements);
|
||||
|
||||
bool replace_instruction(uint32_t *inst, uint32_t orignal_value, uint32_t new_value);
|
||||
|
|
|
|||
39
src/utils/rpl_info.cpp
Normal file
39
src/utils/rpl_info.cpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* Copyright 2024 Pretendo Network contributors <pretendo.network>
|
||||
Copyright 2024 Ash Logan <ash@heyquark.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "rpl_info.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
// if we get more than like.. two callsites for this, it should really be refactored out rather than doing a fresh
|
||||
// search every time
|
||||
std::optional<OSDynLoad_NotifyData> search_for_rpl(std::string_view name) {
|
||||
int num_rpls = OSDynLoad_GetNumberOfRPLs();
|
||||
if (!num_rpls)
|
||||
return std::nullopt;
|
||||
|
||||
// allocates but we free it at return
|
||||
std::vector<OSDynLoad_NotifyData> rpls(num_rpls);
|
||||
if (!OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data()))
|
||||
return std::nullopt;
|
||||
|
||||
auto rpl = std::find_if(rpls.begin(), rpls.end(), [=](const OSDynLoad_NotifyData &rpl) {
|
||||
return std::string_view(rpl.name).ends_with(name);
|
||||
});
|
||||
if (rpl == rpls.end())
|
||||
return std::nullopt;
|
||||
|
||||
return *rpl;
|
||||
}
|
||||
28
src/utils/rpl_info.h
Normal file
28
src/utils/rpl_info.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright 2024 Pretendo Network contributors <pretendo.network>
|
||||
Copyright 2024 Ash Logan <ash@heyquark.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <coreinit/dynload.h>
|
||||
|
||||
std::optional<OSDynLoad_NotifyData> search_for_rpl(std::string_view name);
|
||||
|
||||
constexpr uint32_t *rpl_addr(OSDynLoad_NotifyData rpl, uint32_t cemu_addr) {
|
||||
if (cemu_addr < 0x1000'0000) {
|
||||
return (uint32_t *)(rpl.textAddr + cemu_addr - 0x0200'0000);
|
||||
} else {
|
||||
return (uint32_t *)(rpl.dataAddr + cemu_addr - 0x1000'0000);
|
||||
}
|
||||
}
|
||||
13
src/utils/scope_exit.h
Normal file
13
src/utils/scope_exit.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
|
||||
// https://stackoverflow.com/a/61242721
|
||||
template<typename F>
|
||||
struct scope_exit
|
||||
{
|
||||
F func;
|
||||
explicit scope_exit(F&& f): func(std::forward<F>(f)) {}
|
||||
~scope_exit() { func(); }
|
||||
};
|
||||
|
||||
template<typename F> scope_exit(F&& frv) -> scope_exit<F>;
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/* Copyright 2024 Pretendo Network contributors <pretendo.network>
|
||||
Copyright 2024 Ash Logan <ash@heyquark.com>
|
||||
Copyright 2023 Maschell
|
||||
Copyright 2020-2022 V10lator <v10lator@myway.de>
|
||||
Copyright 2022 Xpl0itU <DaThinkingChair@protonmail.com>
|
||||
|
||||
|
|
@ -19,7 +20,9 @@
|
|||
|
||||
#include "sysconfig.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/scope_exit.h"
|
||||
|
||||
#include <coreinit/mcp.h>
|
||||
#include <coreinit/userconfig.h>
|
||||
#include <optional>
|
||||
|
||||
|
|
@ -28,30 +31,69 @@ nn::swkbd::LanguageType get_system_language() {
|
|||
if (cached_language) return *cached_language;
|
||||
|
||||
UCHandle handle = UCOpen();
|
||||
if (handle >= 0) {
|
||||
nn::swkbd::LanguageType language;
|
||||
|
||||
UCSysConfig settings __attribute__((__aligned__(0x40))) = {
|
||||
.name = "cafe.language",
|
||||
.access = 0,
|
||||
.dataType = UC_DATATYPE_UNSIGNED_INT,
|
||||
.error = UC_ERROR_OK,
|
||||
.dataSize = sizeof(language),
|
||||
.data = &language,
|
||||
};
|
||||
|
||||
UCError err = UCReadSysConfig(handle, 1, &settings);
|
||||
UCClose(handle);
|
||||
if (err != UC_ERROR_OK) {
|
||||
DEBUG_FUNCTION_LINE("Error reading UC: %d!", err);
|
||||
return nn::swkbd::LanguageType::English;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("System language found: %d", language);
|
||||
cached_language = language;
|
||||
return language;
|
||||
}
|
||||
} else {
|
||||
if (handle < 0) {
|
||||
DEBUG_FUNCTION_LINE("Error opening UC: %d", handle);
|
||||
return nn::swkbd::LanguageType::English;
|
||||
}
|
||||
scope_exit uc_c([&] { UCClose(handle); });
|
||||
|
||||
nn::swkbd::LanguageType language;
|
||||
|
||||
alignas(0x40) UCSysConfig settings = {
|
||||
.name = "cafe.language",
|
||||
.access = 0,
|
||||
.dataType = UC_DATATYPE_UNSIGNED_INT,
|
||||
.error = UC_ERROR_OK,
|
||||
.dataSize = sizeof(language),
|
||||
.data = &language,
|
||||
};
|
||||
|
||||
UCError err = UCReadSysConfig(handle, 1, &settings);
|
||||
if (err != UC_ERROR_OK) {
|
||||
DEBUG_FUNCTION_LINE("Error reading UC: %d!", err);
|
||||
return nn::swkbd::LanguageType::English;
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("System language found: %d", language);
|
||||
cached_language = language;
|
||||
return language;
|
||||
}
|
||||
|
||||
static std::optional<MCPSysProdSettings> mcp_config;
|
||||
static std::optional<MCPSystemVersion> mcp_os_version;
|
||||
static void get_mcp_config() {
|
||||
int mcp = MCP_Open();
|
||||
scope_exit mcp_c([&] { MCP_Close(mcp); });
|
||||
|
||||
alignas(0x40) MCPSysProdSettings config {};
|
||||
if (MCP_GetSysProdSettings(mcp, &config)) {
|
||||
DEBUG_FUNCTION_LINE("Could not get MCP system config!");
|
||||
return;
|
||||
}
|
||||
mcp_config = config;
|
||||
|
||||
//get os version
|
||||
MCPSystemVersion os_version;
|
||||
if (MCP_GetSystemVersion(mcp, &os_version)) {
|
||||
DEBUG_FUNCTION_LINE("Could not get MCP system config!");
|
||||
return;
|
||||
}
|
||||
mcp_os_version = os_version;
|
||||
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Running on %d.%d.%d%c; %s%s",
|
||||
os_version.major, os_version.minor, os_version.patch, os_version.region
|
||||
config.code_id, config.serial_id
|
||||
);
|
||||
}
|
||||
|
||||
const char * get_console_serial() {
|
||||
if (!mcp_config) get_mcp_config();
|
||||
|
||||
return mcp_config ? mcp_config->serial_id : "123456789";
|
||||
}
|
||||
|
||||
MCPSystemVersion get_console_os_version() {
|
||||
if (!mcp_os_version) get_mcp_config();
|
||||
|
||||
return mcp_os_version.value_or((MCPSystemVersion) { .major = 5, .minor = 5, .patch = 5, .region = 'E' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
#define INKAY_SYSCONFIG_H
|
||||
|
||||
#include <nn/swkbd.h>
|
||||
#include <coreinit/mcp.h>
|
||||
|
||||
nn::swkbd::LanguageType get_system_language();
|
||||
const char * get_console_serial();
|
||||
MCPSystemVersion get_console_os_version();
|
||||
|
||||
#endif //INKAY_SYSCONFIG_H
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user