Improve system, rewrite in Rust, get rid of the overlay

This commit is contained in:
XorTroll 2020-10-08 23:56:27 +02:00
parent 0ae0964c00
commit 16dd898934
19 changed files with 15 additions and 1039 deletions

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "Atmosphere-libs"]
path = Atmosphere-libs
url = https://github.com/Atmosphere-NX/Atmosphere-libs
[submodule "libtesla"]
path = libtesla
url = https://github.com/WerWolv/libtesla

@ -1 +0,0 @@
Subproject commit 6913aa52953f228f7abc7cc7617a6ae6baec1eca

View File

@ -2,15 +2,12 @@
.PHONY: all clean
all:
@$(MAKE) -C Atmosphere-libs/
@$(MAKE) -C aoc-mitm/
@cd aoc-mitm; sprinkle nsp --release
@rm -rf $(CURDIR)/SdOut
@mkdir -p $(CURDIR)/SdOut/atmosphere/contents/0100000000000523/flags
@touch $(CURDIR)/SdOut/atmosphere/contents/0100000000000523/flags/boot2.flag
@cp $(CURDIR)/aoc-mitm/aoc-mitm.nsp $(CURDIR)/SdOut/atmosphere/contents/0100000000000523/exefs.nsp
@mkdir -p $(CURDIR)/SdOut/switch/.overlays
@cp $(CURDIR)/overlay/aoc-mitm.ovl $(CURDIR)/SdOut/switch/.overlays/aoc-mitm.ovl
@cp $(CURDIR)/aoc-mitm/target/aarch64-none-elf/release/aoc-mitm.nsp $(CURDIR)/SdOut/atmosphere/contents/0100000000000523/exefs.nsp
clean:
@rm -rf $(CURDIR)/SdOut
@$(MAKE) clean -C aoc-mitm/
@cd aoc-mitm; xargo clean

View File

@ -1,2 +1,14 @@
# aoc-mitm
Mitm for aoc:u service, allowing for certain games to insta-unlock DLC
## Usage
Create a file named `sd:/aoc-mitm/titles.list`, or open it in a text editor if it already exists.
Each line must contain a application ID which aoc-mitm will intercept, in the form of `0x<hex-data>`, here's an example:
```
0x01006A800016E000
0x0100000000010000
```

View File

@ -1,128 +0,0 @@
#---------------------------------------------------------------------------------
# pull in (modded) common stratosphere sysmodule configuration
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../Atmosphere-libs/config/templates/stratosphere.mk
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC)
ifeq ($(strip $(CONFIG_JSON)),)
jsons := $(wildcard *.json)
ifneq (,$(findstring $(TARGET).json,$(jsons)))
export APP_JSON := $(TOPDIR)/$(TARGET).json
else
ifneq (,$(findstring config.json,$(jsons)))
export APP_JSON := $(TOPDIR)/config.json
endif
endif
else
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).nsp
ifeq ($(strip $(APP_JSON)),)
$(OUTPUT).nsp : $(OUTPUT).nso
else
$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm
endif
$(OUTPUT).nso : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,131 +0,0 @@
{
"name": "aoc-mitm",
"title_id": "0x0100000000000523",
"title_id_range_min": "0x0100000000000523",
"title_id_range_max": "0x0100000000000523",
"main_thread_stack_size": "0x00004000",
"main_thread_priority": 49,
"default_cpu_id": 3,
"process_category": 0,
"is_retail": true,
"pool_partition": 2,
"is_64_bit": true,
"address_space_type": 1,
"filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF"
},
"service_host": [ "*" ],
"service_access": [ "*" ],
"kernel_capabilities": [
{
"type": "kernel_flags",
"value": {
"highest_thread_priority": 63,
"lowest_thread_priority": 16,
"lowest_cpu_id": 3,
"highest_cpu_id": 3
}
},
{
"type": "syscalls",
"value": {
"svcSetHeapSize": "0x01",
"svcSetMemoryPermission": "0x02",
"svcSetMemoryAttribute": "0x03",
"svcMapMemory": "0x04",
"svcUnmapMemory": "0x05",
"svcQueryMemory": "0x06",
"svcExitProcess": "0x07",
"svcCreateThread": "0x08",
"svcStartThread": "0x09",
"svcExitThread": "0x0a",
"svcSleepThread": "0x0b",
"svcGetThreadPriority": "0x0c",
"svcSetThreadPriority": "0x0d",
"svcGetThreadCoreMask": "0x0e",
"svcSetThreadCoreMask": "0x0f",
"svcGetCurrentProcessorNumber": "0x10",
"svcSignalEvent": "0x11",
"svcClearEvent": "0x12",
"svcMapSharedMemory": "0x13",
"svcUnmapSharedMemory": "0x14",
"svcCreateTransferMemory": "0x15",
"svcCloseHandle": "0x16",
"svcResetSignal": "0x17",
"svcWaitSynchronization": "0x18",
"svcCancelSynchronization": "0x19",
"svcArbitrateLock": "0x1a",
"svcArbitrateUnlock": "0x1b",
"svcWaitProcessWideKeyAtomic": "0x1c",
"svcSignalProcessWideKey": "0x1d",
"svcGetSystemTick": "0x1e",
"svcConnectToNamedPort": "0x1f",
"svcSendSyncRequestLight": "0x20",
"svcSendSyncRequest": "0x21",
"svcSendSyncRequestWithUserBuffer": "0x22",
"svcSendAsyncRequestWithUserBuffer": "0x23",
"svcGetProcessId": "0x24",
"svcGetThreadId": "0x25",
"svcBreak": "0x26",
"svcOutputDebugString": "0x27",
"svcReturnFromException": "0x28",
"svcGetInfo": "0x29",
"svcWaitForAddress": "0x34",
"svcSignalToAddress": "0x35",
"svcCreateSession": "0x40",
"svcAcceptSession": "0x41",
"svcReplyAndReceiveLight": "0x42",
"svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44",
"svcCreateEvent": "0x45",
"svcCreateInterruptEvent": "0x53",
"svcReadWriteRegister": "0x4E",
"svcQueryIoMapping": "0x55",
"svcCreateDeviceAddressSpace": "0x56",
"svcAttachDeviceAddressSpace": "0x57",
"svcDetachDeviceAddressSpace": "0x58",
"svcMapDeviceAddressSpaceAligned": "0x5a",
"svcUnmapDeviceAddressSpace": "0x5c",
"svcGetSystemInfo": "0x6f",
"svcCallSecureMonitor": "0x7f",
"svcUnknown46": "0x46",
"svcUnknown47": "0x47",
"svcMapPhysicalMemoryUnsafe": "0x48",
"svcUnmapPhysicalMemoryUnsafe": "0x49",
"svcSetUnsafeLimit": "0x4A",
"svcCreateCodeMemory": "0x4B",
"svcControlCodeMemory": "0x4C",
"svcSleepSystem": "0x4D",
"svcSetProcessActivity": "0x4F",
"svcCreateSharedMemory": "0x50",
"svcMapTransferMemory": "0x51",
"svcUnmapTransferMemory": "0x52",
"svcDebugActiveProcess": "0x60",
"svcBreakDebugProcess": "0x61",
"svcTerminateDebugProcess": "0x62",
"svcGetDebugEvent": "0x63",
"svcContinueDebugEvent": "0x64",
"svcGetProcessList": "0x65",
"svcGetThreadList": "0x66",
"svcGetDebugThreadContext": "0x67",
"svcSetDebugThreadContext": "0x68",
"svcQueryDebugProcessMemory": "0x69",
"svcReadDebugProcessMemory": "0x6A",
"svcWriteDebugProcessMemory": "0x6B",
"svcSetHardwareBreakPoint": "0x6C",
"svcGetDebugThreadParam": "0x6D",
"svcConnectToPort": "0x72",
"svcSetProcessMemoryPermission": "0x73",
"svcMapProcessMemory": "0x74",
"svcUnmapProcessMemory": "0x75",
"svcQueryProcessMemory": "0x76",
"svcMapProcessCodeMemory": "0x77",
"svcUnmapProcessCodeMemory": "0x78"
}
},
{
"type": "min_kernel_version",
"value": "0x0030"
}
]
}

View File

@ -1,19 +0,0 @@
#pragma once
#include <cstring>
#include <cstdarg>
namespace aoc {
void LogBase(const char *fmt, std::va_list args);
inline void LogFmt(const char *fmt, ...) {
std::va_list args;
va_start(args, fmt);
LogBase(fmt, args);
va_end(args);
}
}
#define AOC_LOG_FMT(fmt, ...) ::aoc::LogFmt(fmt "\n", ##__VA_ARGS__)

View File

@ -1,17 +0,0 @@
#pragma once
#include <stratosphere.hpp>
#include <aoc/aoc_Log.hpp>
namespace impl {
static inline ams::os::Mutex g_logging_lock(true);
}
#define AOC_ASSERT(rc) ({ \
auto _rc = static_cast<::ams::Result>(rc); \
if(R_FAILED(_rc)) { \
fatalThrow(_rc.GetValue()); \
} \
})

View File

@ -1,26 +0,0 @@
#pragma once
#include <aoc/aoc_Types.hpp>
namespace aoc::mitm::impl {
bool IsApplicationInMitmList(ams::ncm::ApplicationId app_id);
void AddApplicationToMitmList(ams::ncm::ApplicationId app_id);
void RemoveApplicationFromMitmList(ams::ncm::ApplicationId app_id);
inline bool ShouldMitmApplication(ams::ncm::ApplicationId app_id) {
auto mitm = IsApplicationInMitmList(app_id);
if(mitm) {
RemoveApplicationFromMitmList(app_id);
}
return mitm;
}
void SetMitmdApplication(ams::ncm::ApplicationId app_id);
ams::ncm::ApplicationId GetMitmdApplication();
inline void ResetMitmdApplication() {
SetMitmdApplication(ams::ncm::InvalidApplicationId);
}
}

View File

@ -1,56 +0,0 @@
#pragma once
#include <aoc/mitm/impl/impl_MitmList.hpp>
namespace aoc::mitm {
class IMitmService : public ams::sf::IServiceObject {
private:
enum class CommandId {
IsApplicationInMitmList = 0,
AddApplicationToMitmList = 1,
RemoveApplicationFromMitmList = 2,
IsCurrentApplicationMitmd = 3,
};
public:
void IsApplicationInMitmList(ams::ncm::ApplicationId app_id, ams::sf::Out<bool> out_is) {
out_is.SetValue(impl::IsApplicationInMitmList(app_id));
}
void AddApplicationToMitmList(ams::ncm::ApplicationId app_id) {
impl::AddApplicationToMitmList(app_id);
}
void RemoveApplicationFromMitmList(ams::ncm::ApplicationId app_id) {
impl::RemoveApplicationFromMitmList(app_id);
}
void IsCurrentApplicationMitmd(ams::sf::Out<bool> out_is) {
bool is_mitmd = false;
u64 current_app_pid = 0;
auto rc = pmdmntGetApplicationProcessId(&current_app_pid);
if(R_SUCCEEDED(rc)) {
auto app_id = ams::ncm::InvalidApplicationId;
rc = pminfoGetProgramId(&app_id.value, current_app_pid);
if(R_SUCCEEDED(rc)) {
is_mitmd = impl::GetMitmdApplication() == app_id;
}
}
out_is.SetValue(is_mitmd);
}
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(IsApplicationInMitmList),
MAKE_SERVICE_COMMAND_META(AddApplicationToMitmList),
MAKE_SERVICE_COMMAND_META(RemoveApplicationFromMitmList),
MAKE_SERVICE_COMMAND_META(IsCurrentApplicationMitmd),
};
};
constexpr ams::sm::ServiceName ServiceName = ams::sm::ServiceName::Encode("aocmitm");
}

View File

@ -1,126 +0,0 @@
#pragma once
#include <aoc/mitm/impl/impl_MitmList.hpp>
namespace aoc::srv {
class IAddOnContentManager : public ams::sf::IMitmServiceObject {
private:
enum class CommandId {
CountAddOnContentByApplicationId = 0,
ListAddOnContentByApplicationId = 1,
CountAddOnContent = 2,
ListAddOnContent = 3,
GetAddOnContentBaseIdByApplicationId = 4,
GetAddOnContentBaseId = 5,
PrepareAddOnContentByApplicationId = 6,
PrepareAddOnContent = 7,
};
public:
// Note: this value is used assuming that no game will have >128 DLCs
static constexpr s32 DlcContentCount = 128;
private:
inline void CountAddOnContentBase(ams::sf::Out<u32> out_count) {
out_count.SetValue(DlcContentCount);
}
inline void ListAddOnContentBase(const ams::sf::OutBuffer &out_buf, ams::sf::Out<s32> out_count, s32 offset, s32 count) {
const auto buf_count = static_cast<s32>(out_buf.GetSize() / sizeof(s32));
const auto size = std::min({ buf_count, DlcContentCount, count });
auto dlc_idx_buf = reinterpret_cast<s32*>(out_buf.GetPointer());
for(auto i = offset; i < size; i++) {
// DLC ids consist on DLC base ID + an index (1, 2, 3...) so we will populate the array this way
dlc_idx_buf[i] = i + 1;
}
out_count.SetValue(size);
}
inline ams::ncm::ApplicationId GetApplicationIdFromProcessId(const ams::sf::ClientProcessId &client_pid) {
auto app_id = ams::ncm::InvalidApplicationId;
pminfoGetProgramId(&app_id.value, static_cast<u64>(client_pid.process_id));
return app_id;
}
inline void GetAddOnContentBaseIdBase(ams::sf::Out<ams::ncm::ApplicationId> out_dlc_base_id, ams::ncm::ApplicationId app_id) {
out_dlc_base_id.SetValue({ app_id.value + 0x1000 });
}
public:
static bool ShouldMitm(const ams::sm::MitmProcessInfo &client_info) {
const ams::ncm::ApplicationId app_id = { client_info.program_id.value };
return mitm::impl::ShouldMitmApplication(app_id);
}
IAddOnContentManager(std::shared_ptr<::Service> &&s, const ams::sm::MitmProcessInfo &c) : IMitmServiceObject(std::forward<std::shared_ptr<::Service>>(s), c) {
AOC_LOG_FMT("Initialized aoc:u with ID 0x%016lX", c.program_id.value);
mitm::impl::SetMitmdApplication({ c.program_id.value });
}
~IAddOnContentManager() {
AOC_LOG_FMT("Finalized aoc:u");
mitm::impl::ResetMitmdApplication();
}
public:
void CountAddOnContentByApplicationId(ams::sf::Out<u32> out_count, ams::ncm::ApplicationId app_id) {
AOC_LOG_FMT("CountAddOnContentByApplicationId -> ID: 0x%016lX", app_id.value);
this->CountAddOnContentBase(out_count);
}
void ListAddOnContentByApplicationId(const ams::sf::OutBuffer &out_buf, ams::sf::Out<s32> out_count, s32 offset, s32 count, ams::ncm::ApplicationId app_id) {
AOC_LOG_FMT("ListAddOnContentByApplicationId -> ID: 0x%016lX, Offset: %d, Count: %d", app_id.value, offset, count);
this->ListAddOnContentBase(out_buf, out_count, offset, count);
}
void CountAddOnContent(const ams::sf::ClientProcessId &client_pid, ams::sf::Out<u32> out_count) {
const auto app_id = this->GetApplicationIdFromProcessId(client_pid);
AOC_LOG_FMT("CountAddOnContent -> ID: 0x%016lX", app_id.value);
this->CountAddOnContentBase(out_count);
}
void ListAddOnContent(const ams::sf::ClientProcessId &client_pid, const ams::sf::OutBuffer &out_buf, ams::sf::Out<s32> out_count, s32 offset, s32 count) {
const auto app_id = this->GetApplicationIdFromProcessId(client_pid);
AOC_LOG_FMT("ListAddOnContent -> ID: 0x%016lX, Offset: %d, Count: %d", app_id.value, offset, count);
this->ListAddOnContentBase(out_buf, out_count, offset, count);
}
void GetAddOnContentBaseIdByApplicationId(ams::sf::Out<ams::ncm::ApplicationId> out_dlc_base_id, ams::ncm::ApplicationId app_id) {
AOC_LOG_FMT("GetAddOnContentBaseIdByApplicationId -> ID: 0x%016lX", app_id.value);
this->GetAddOnContentBaseIdBase(out_dlc_base_id, app_id);
}
void GetAddOnContentBaseId(const ams::sf::ClientProcessId &client_pid, ams::sf::Out<ams::ncm::ApplicationId> out_dlc_base_id) {
const auto app_id = this->GetApplicationIdFromProcessId(client_pid);
AOC_LOG_FMT("GetAddOnContentBaseId -> ID: 0x%016lX", app_id.value);
this->GetAddOnContentBaseIdBase(out_dlc_base_id, app_id);
}
void PrepareAddOnContentByApplicationId(ams::ncm::ApplicationId app_id, u32 dlc_idx) {
AOC_LOG_FMT("PrepareAddOnContentByApplicationId -> stubbed, ID: 0x%016lX, DLC index: %d", app_id.value, dlc_idx);
}
void PrepareAddOnContent(const ams::sf::ClientProcessId &client_pid, u32 dlc_idx) {
const auto app_id = this->GetApplicationIdFromProcessId(client_pid);
AOC_LOG_FMT("PrepareAddOnContent -> stubbed, ID: 0x%016lX, DLC index: %d", app_id.value, dlc_idx);
}
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(CountAddOnContentByApplicationId),
MAKE_SERVICE_COMMAND_META(ListAddOnContentByApplicationId),
MAKE_SERVICE_COMMAND_META(CountAddOnContent),
MAKE_SERVICE_COMMAND_META(ListAddOnContent),
MAKE_SERVICE_COMMAND_META(GetAddOnContentBaseIdByApplicationId),
MAKE_SERVICE_COMMAND_META(GetAddOnContentBaseId),
MAKE_SERVICE_COMMAND_META(PrepareAddOnContentByApplicationId),
MAKE_SERVICE_COMMAND_META(PrepareAddOnContent),
};
};
constexpr ams::sm::ServiceName ServiceName = ams::sm::ServiceName::Encode("aoc:u");
}

View File

@ -1,73 +0,0 @@
#include <aoc/srv/srv_IAddOnContentManager.hpp>
#include <aoc/mitm/mitm_IMitmService.hpp>
extern "C" {
extern u32 __start__;
u32 __nx_applet_type = AppletType_None;
u32 __nx_fs_num_sessions = 1;
#define INNER_HEAP_SIZE 0x10000
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
char nx_inner_heap[INNER_HEAP_SIZE];
void __libnx_init_time(void);
void __libnx_initheap(void) {
void *addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
extern char *fake_heap_start;
extern char *fake_heap_end;
fake_heap_start = (char*)addr;
fake_heap_end = (char*)addr + size;
}
void __appInit(void) {
ams::sm::DoWithSession([&]() {
AOC_ASSERT(fsInitialize());
AOC_ASSERT(fsdevMountSdmc());
AOC_ASSERT(pminfoInitialize());
AOC_ASSERT(pmdmntInitialize());
});
}
void __appExit(void) {
pmdmntExit();
pminfoExit();
fsdevUnmountAll();
fsExit();
}
}
namespace ams {
ncm::ProgramId CurrentProgramId = { 0x0100000000000523ul };
namespace result {
bool CallFatalOnResultAssertion = true;
}
}
namespace {
constexpr size_t ServerNum = 2;
constexpr size_t AocMitmMaxSessions = 0x10;
ams::sf::hipc::ServerManager<ServerNum> g_aoc_manager;
}
int main() {
// Register aoc:u
AOC_ASSERT(g_aoc_manager.RegisterMitmServer<aoc::srv::IAddOnContentManager>(aoc::srv::ServiceName));
// Register aocmitm
AOC_ASSERT(g_aoc_manager.RegisterServer<aoc::mitm::IMitmService>(aoc::mitm::ServiceName, AocMitmMaxSessions));
g_aoc_manager.LoopProcess();
return 0;
}

View File

@ -1,29 +0,0 @@
#include <aoc/aoc_Log.hpp>
#include <stratosphere.hpp>
#include <cstdio>
namespace aoc {
static ams::os::Mutex g_log_lock(true);
static bool has_cleared_logs = false;
static constexpr const char LogFile[] = "sdmc:/aoc-mitm.log";
inline static void ClearLogs() {
std::scoped_lock lk(g_log_lock);
remove(LogFile);
}
void LogBase(const char *fmt, std::va_list args) {
std::scoped_lock lk(g_log_lock);
if(!has_cleared_logs) {
ClearLogs();
has_cleared_logs = true;
}
auto file = fopen(LogFile, "a+");
if(file) {
vfprintf(file, fmt, args);
fclose(file);
}
}
}

View File

@ -1,40 +0,0 @@
#include <aoc/mitm/impl/impl_MitmList.hpp>
#include <vector>
#include <algorithm>
namespace aoc::mitm::impl {
static std::vector<ams::ncm::ApplicationId> g_mitm_app_ids;
static ams::ncm::ApplicationId g_mitmd_app_id = ams::ncm::InvalidApplicationId;
static ams::os::Mutex g_mitm_lock(true);
bool IsApplicationInMitmList(ams::ncm::ApplicationId app_id) {
std::scoped_lock lk(g_mitm_lock);
return std::find(g_mitm_app_ids.begin(), g_mitm_app_ids.end(), app_id) != g_mitm_app_ids.end();
}
void AddApplicationToMitmList(ams::ncm::ApplicationId app_id) {
std::scoped_lock lk(g_mitm_lock);
if(!IsApplicationInMitmList(app_id)) {
g_mitm_app_ids.push_back(app_id);
}
}
void RemoveApplicationFromMitmList(ams::ncm::ApplicationId app_id) {
std::scoped_lock lk(g_mitm_lock);
if(IsApplicationInMitmList(app_id)) {
g_mitm_app_ids.erase(std::remove(g_mitm_app_ids.begin(), g_mitm_app_ids.end(), app_id), g_mitm_app_ids.end());
}
}
void SetMitmdApplication(ams::ncm::ApplicationId app_id) {
std::scoped_lock lk(g_mitm_lock);
g_mitmd_app_id = app_id;
}
ams::ncm::ApplicationId GetMitmdApplication() {
std::scoped_lock lk(g_mitm_lock);
return g_mitmd_app_id;
}
}

@ -1 +0,0 @@
Subproject commit f59a3f44d46a70ac62b9b1098635d6cb36e18e38

View File

@ -1,213 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional)
#
# NO_ICON: if set to anything, do not use icon.
# NO_NACP: if set to anything, no .nacp file is generated.
# APP_TITLE is the name of the app stored in the .nacp file (Optional)
# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
# APP_VERSION is the version of the app stored in the .nacp file (Optional)
# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
# ICON is the filename of the icon (.jpg), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.jpg
# - icon.jpg
# - <libnx folder>/default_icon.jpg
#
# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.json
# - config.json
# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead
# of a homebrew executable (.nro). This is intended to be used for sysmodules.
# NACP building is skipped as well.
#---------------------------------------------------------------------------------
APP_TITLE := aoc-mitm
APP_VERSION := dev
TARGET := $(APP_TITLE)
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include ../libtesla/include
#ROMFS := romfs
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-exceptions -std=c++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lnx
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(CONFIG_JSON)),)
jsons := $(wildcard *.json)
ifneq (,$(findstring $(TARGET).json,$(jsons)))
export APP_JSON := $(TOPDIR)/$(TARGET).json
else
ifneq (,$(findstring config.json,$(jsons)))
export APP_JSON := $(TOPDIR)/config.json
endif
endif
else
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
endif
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.jpg)
ifneq (,$(findstring $(TARGET).jpg,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).jpg
else
ifneq (,$(findstring icon.jpg,$(icons)))
export APP_ICON := $(TOPDIR)/icon.jpg
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_ICON)),)
export NROFLAGS += --icon=$(APP_ICON)
endif
ifeq ($(strip $(NO_NACP)),)
export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
endif
ifneq ($(APP_TITLEID),)
export NACPFLAGS += --titleid=$(APP_TITLEID)
endif
ifneq ($(ROMFS),)
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
ifeq ($(strip $(APP_JSON)),)
@rm -fr $(BUILD) $(TARGET).ovl $(TARGET).nro $(TARGET).nacp $(TARGET).elf
else
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
endif
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).ovl
$(OUTPUT).ovl : $(OUTPUT).nro
@cp $(OUTPUT).nro $(OUTPUT).ovl
@rm -fr $(OUTPUT).nro
@echo built ... $(TARGET).ovl
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp
$(OUTPUT).elf : $(OFILES)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -1,16 +0,0 @@
#pragma once
#include <switch.h>
namespace aocmitm {
bool IsAvailable();
Result Initialize();
void Exit();
bool IsApplicationInMitmList(u64 app_id);
void AddApplicationToMitmList(u64 app_id);
void RemoveApplicationFromMitmList(u64 app_id);
}

View File

@ -1,109 +0,0 @@
#define TESLA_INIT_IMPL
#include <tesla.hpp>
#include <aocmitm.hpp>
#include <vector>
struct ApplicationData {
u64 app_id;
char name[0x200];
};
namespace {
bool g_aocmitm_initialized = false;
std::vector<ApplicationData> g_applications;
void LoadApplications() {
NsApplicationRecord rec = {};
s32 offset = 0;
s32 tmp_count = 0;
while(true) {
auto rc = nsListApplicationRecord(&rec, 1, offset, &tmp_count);
if(R_FAILED(rc) || (tmp_count < 1)) {
break;
}
ApplicationData app = {};
app.app_id = rec.application_id;
NsApplicationControlData nacp = {};
nsGetApplicationControlData(NsApplicationControlSource_Storage, app.app_id, &nacp, sizeof(nacp), nullptr);
NacpLanguageEntry *lang = nullptr;
nacpGetLanguageEntry(&nacp.nacp, &lang);
if(lang != nullptr) {
strcpy(app.name, lang->name);
g_applications.push_back(app);
}
offset++;
rec = {};
}
}
}
class AocMitmGui : public tsl::Gui {
public:
AocMitmGui() {}
virtual tsl::elm::Element *createUI() override {
auto frame = new tsl::elm::OverlayFrame("aoc-mitm manager", "dev");
auto list = new tsl::elm::List();
u32 idx = 0;
for(auto &app: g_applications) {
auto item = new tsl::elm::ListItem(app.name);
item->setClickListener([item, idx](u64 keys) {
auto &app = g_applications[idx];
if(keys & KEY_A) {
if(aocmitm::IsApplicationInMitmList(app.app_id)) {
aocmitm::RemoveApplicationFromMitmList(app.app_id);
item->setText(app.name);
}
else {
aocmitm::AddApplicationToMitmList(app.app_id);
item->setText(std::string(" * ") + app.name);
}
return true;
}
return false;
});
list->addItem(item);
idx++;
}
frame->setContent(list);
return frame;
}
};
class AocMitmOverlay : public tsl::Overlay {
public:
virtual void initServices() override {
tsl::hlp::doWithSmSession([&]() {
if(R_SUCCEEDED(nsInitialize())) {
if(aocmitm::IsAvailable()) {
if(R_SUCCEEDED(aocmitm::Initialize())) {
g_aocmitm_initialized = true;
}
}
}
});
if(g_aocmitm_initialized) {
LoadApplications();
}
}
virtual void exitServices() override {
aocmitm::Exit();
nsExit();
}
virtual std::unique_ptr<tsl::Gui> loadInitialGui() override {
return initially<AocMitmGui>(); // Initial Gui to load. It's possible to pass arguments to it's constructor like this
}
};
int main(int argc, char **argv) {
return tsl::loop<AocMitmOverlay>(argc, argv);
}

View File

@ -1,42 +0,0 @@
#include <aocmitm.hpp>
#define AOC_MITM_SRV "aocmitm"
namespace aocmitm {
static Service g_srv;
bool IsAvailable() {
bool has = false;
const auto srv_name = smServiceNameToU64(smEncodeName(AOC_MITM_SRV));
// smHasService
serviceDispatchInOut(smGetServiceSession(), 65100, srv_name, has);
return has;
}
Result Initialize() {
if(serviceIsActive(&g_srv)) {
return 0;
}
return smGetService(&g_srv, AOC_MITM_SRV);
}
void Exit() {
serviceClose(&g_srv);
}
bool IsApplicationInMitmList(u64 app_id) {
bool out = false;
serviceDispatchInOut(&g_srv, 0, app_id, out);
return out;
}
void AddApplicationToMitmList(u64 app_id) {
serviceDispatchIn(&g_srv, 1, app_id);
}
void RemoveApplicationFromMitmList(u64 app_id) {
serviceDispatchIn(&g_srv, 2, app_id);
}
}