From 77ab09b21e64ab375179d71c196c70b6acbf6fb2 Mon Sep 17 00:00:00 2001 From: XorTroll Date: Sun, 18 Apr 2021 01:58:26 +0200 Subject: [PATCH] Support 12.x and latest Atmosphere --- Makefile | 2 +- emuiibo/Cargo.toml | 2 +- emuiibo/src/amiibo.rs | 4 +- emuiibo/src/area.rs | 2 +- emuiibo/src/emu.rs | 2 +- emuiibo/src/ipc/emu.rs | 48 +++---- emuiibo/src/ipc/nfp.rs | 68 +++++----- emuiibo/src/main.rs | 2 +- emuiibo/src/miiext.rs | 10 +- overlay/include/tipc.hpp | 271 +++++++++++++++++++++++++++++++++++++ overlay/source/Main.cpp | 76 +++++------ overlay/source/emuiibo.cpp | 43 +++--- 12 files changed, 404 insertions(+), 126 deletions(-) create mode 100644 overlay/include/tipc.hpp diff --git a/Makefile b/Makefile index abdbb2f..7624781 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ export EMUIIBO_MAJOR := 0 export EMUIIBO_MINOR := 6 -export EMUIIBO_MICRO := 2 +export EMUIIBO_MICRO := 3 .PHONY: all clean diff --git a/emuiibo/Cargo.toml b/emuiibo/Cargo.toml index 30922fa..b332841 100644 --- a/emuiibo/Cargo.toml +++ b/emuiibo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "emuiibo" -version = "0.6.2" +version = "0.6.3" authors = ["XorTroll"] edition = "2018" diff --git a/emuiibo/src/amiibo.rs b/emuiibo/src/amiibo.rs index 4f9ccd7..04d4df4 100644 --- a/emuiibo/src/amiibo.rs +++ b/emuiibo/src/amiibo.rs @@ -6,8 +6,8 @@ use nx::fs; use nx::util; use nx::rand; use nx::rand::RandomGenerator; -use nx::ipc::sf::mii; -use nx::ipc::sf::nfp; +use nx::ipc::cmif::sf::mii; +use nx::ipc::cmif::sf::nfp; use crate::fsext; use crate::miiext; diff --git a/emuiibo/src/area.rs b/emuiibo/src/area.rs index 28a67b9..3f889fc 100644 --- a/emuiibo/src/area.rs +++ b/emuiibo/src/area.rs @@ -1,6 +1,6 @@ use nx::result::*; use nx::fs; -use nx::ipc::sf::nfp; +use nx::ipc::cmif::sf::nfp; use alloc::string::String; use crate::amiibo; use crate::fsext; diff --git a/emuiibo/src/emu.rs b/emuiibo/src/emu.rs index 7370441..9943d7d 100644 --- a/emuiibo/src/emu.rs +++ b/emuiibo/src/emu.rs @@ -34,7 +34,7 @@ pub enum VirtualAmiiboStatus { Disconnected } -pub const CURRENT_VERSION: Version = Version::from(0, 6, 2, false); +pub const CURRENT_VERSION: Version = Version::from(0, 6, 3, true); static mut G_EMULATION_STATUS: sync::Locked = sync::Locked::new(false, EmulationStatus::Off); static mut G_ACTIVE_VIRTUAL_AMIIBO_STATUS: sync::Locked = sync::Locked::new(false, VirtualAmiiboStatus::Invalid); diff --git a/emuiibo/src/ipc/emu.rs b/emuiibo/src/ipc/emu.rs index 92388aa..90e16db 100644 --- a/emuiibo/src/ipc/emu.rs +++ b/emuiibo/src/ipc/emu.rs @@ -1,6 +1,6 @@ use nx::result::*; -use nx::ipc::sf; -use nx::ipc::server; +use nx::ipc::cmif::sf; +use nx::ipc::cmif::server; use alloc::string::String; use crate::resultsext; @@ -9,17 +9,17 @@ use crate::amiibo; use crate::fsext; pub trait IEmulationService { - ipc_interface_define_command!(get_version: () => (version: emu::Version)); - ipc_interface_define_command!(get_virtual_amiibo_directory: (out_path: sf::OutMapAliasBuffer) => ()); - ipc_interface_define_command!(get_emulation_status: () => (status: emu::EmulationStatus)); - ipc_interface_define_command!(set_emulation_status: (status: emu::EmulationStatus) => ()); - ipc_interface_define_command!(get_active_virtual_amiibo: (out_path: sf::OutMapAliasBuffer) => (virtual_amiibo: amiibo::VirtualAmiiboData)); - ipc_interface_define_command!(set_active_virtual_amiibo: (path: sf::InMapAliasBuffer) => ()); - ipc_interface_define_command!(reset_active_virtual_amiibo: () => ()); - ipc_interface_define_command!(get_active_virtual_amiibo_status: () => (status: emu::VirtualAmiiboStatus)); - ipc_interface_define_command!(set_active_virtual_amiibo_status: (status: emu::VirtualAmiiboStatus) => ()); - ipc_interface_define_command!(is_application_id_intercepted: (application_id: u64) => (is_intercepted: bool)); - ipc_interface_define_command!(try_parse_virtual_amiibo: (path: sf::InMapAliasBuffer) => (virtual_amiibo: amiibo::VirtualAmiiboData)); + ipc_cmif_interface_define_command!(get_version: () => (version: emu::Version)); + ipc_cmif_interface_define_command!(get_virtual_amiibo_directory: (out_path: sf::OutMapAliasBuffer) => ()); + ipc_cmif_interface_define_command!(get_emulation_status: () => (status: emu::EmulationStatus)); + ipc_cmif_interface_define_command!(set_emulation_status: (status: emu::EmulationStatus) => ()); + ipc_cmif_interface_define_command!(get_active_virtual_amiibo: (out_path: sf::OutMapAliasBuffer) => (virtual_amiibo: amiibo::VirtualAmiiboData)); + ipc_cmif_interface_define_command!(set_active_virtual_amiibo: (path: sf::InMapAliasBuffer) => ()); + ipc_cmif_interface_define_command!(reset_active_virtual_amiibo: () => ()); + ipc_cmif_interface_define_command!(get_active_virtual_amiibo_status: () => (status: emu::VirtualAmiiboStatus)); + ipc_cmif_interface_define_command!(set_active_virtual_amiibo_status: (status: emu::VirtualAmiiboStatus) => ()); + ipc_cmif_interface_define_command!(is_application_id_intercepted: (application_id: u64) => (is_intercepted: bool)); + ipc_cmif_interface_define_command!(try_parse_virtual_amiibo: (path: sf::InMapAliasBuffer) => (virtual_amiibo: amiibo::VirtualAmiiboData)); } pub struct EmulationService { @@ -33,17 +33,17 @@ impl sf::IObject for EmulationService { fn get_command_table(&self) -> sf::CommandMetadataTable { vec! [ - ipc_interface_make_command_meta!(get_version: 0), - ipc_interface_make_command_meta!(get_virtual_amiibo_directory: 1), - ipc_interface_make_command_meta!(get_emulation_status: 2), - ipc_interface_make_command_meta!(set_emulation_status: 3), - ipc_interface_make_command_meta!(get_active_virtual_amiibo: 4), - ipc_interface_make_command_meta!(set_active_virtual_amiibo: 5), - ipc_interface_make_command_meta!(reset_active_virtual_amiibo: 6), - ipc_interface_make_command_meta!(get_active_virtual_amiibo_status: 7), - ipc_interface_make_command_meta!(set_active_virtual_amiibo_status: 8), - ipc_interface_make_command_meta!(is_application_id_intercepted: 9), - ipc_interface_make_command_meta!(try_parse_virtual_amiibo: 10) + ipc_cmif_interface_make_command_meta!(get_version: 0), + ipc_cmif_interface_make_command_meta!(get_virtual_amiibo_directory: 1), + ipc_cmif_interface_make_command_meta!(get_emulation_status: 2), + ipc_cmif_interface_make_command_meta!(set_emulation_status: 3), + ipc_cmif_interface_make_command_meta!(get_active_virtual_amiibo: 4), + ipc_cmif_interface_make_command_meta!(set_active_virtual_amiibo: 5), + ipc_cmif_interface_make_command_meta!(reset_active_virtual_amiibo: 6), + ipc_cmif_interface_make_command_meta!(get_active_virtual_amiibo_status: 7), + ipc_cmif_interface_make_command_meta!(set_active_virtual_amiibo_status: 8), + ipc_cmif_interface_make_command_meta!(is_application_id_intercepted: 9), + ipc_cmif_interface_make_command_meta!(try_parse_virtual_amiibo: 10) ] } } diff --git a/emuiibo/src/ipc/nfp.rs b/emuiibo/src/ipc/nfp.rs index f389132..306a007 100644 --- a/emuiibo/src/ipc/nfp.rs +++ b/emuiibo/src/ipc/nfp.rs @@ -1,16 +1,16 @@ use nx::result::*; use nx::results; use nx::mem; -use nx::ipc::sf; -use nx::ipc::server; -use nx::ipc::sf::applet; -use nx::ipc::sf::nfp; -use nx::ipc::sf::nfp::IUser; -use nx::ipc::sf::nfp::IUserManager; -use nx::ipc::sf::sm; +use nx::ipc::cmif::sf; +use nx::ipc::cmif::server; +use nx::ipc::cmif::sf::applet; +use nx::ipc::cmif::sf::nfp; +use nx::ipc::cmif::sf::nfp::IUser; +use nx::ipc::cmif::sf::nfp::IUserManager; +use nx::ipc::tipc::sf::sm; use nx::wait; use nx::sync; -use nx::service::hid; +use nx::service::cmif::hid; use nx::input; use nx::thread; @@ -99,31 +99,31 @@ impl sf::IObject for User { fn get_command_table(&self) -> sf::CommandMetadataTable { vec! [ - ipc_interface_make_command_meta!(initialize: 0), - ipc_interface_make_command_meta!(finalize: 1), - ipc_interface_make_command_meta!(list_devices: 2), - ipc_interface_make_command_meta!(start_detection: 3), - ipc_interface_make_command_meta!(stop_detection: 4), - ipc_interface_make_command_meta!(mount: 5), - ipc_interface_make_command_meta!(unmount: 6), - ipc_interface_make_command_meta!(open_application_area: 7), - ipc_interface_make_command_meta!(get_application_area: 8), - ipc_interface_make_command_meta!(set_application_area: 9), - ipc_interface_make_command_meta!(flush: 10), - ipc_interface_make_command_meta!(restore: 11), - ipc_interface_make_command_meta!(create_application_area: 12), - ipc_interface_make_command_meta!(get_tag_info: 13), - ipc_interface_make_command_meta!(get_register_info: 14), - ipc_interface_make_command_meta!(get_common_info: 15), - ipc_interface_make_command_meta!(get_model_info: 16), - ipc_interface_make_command_meta!(attach_activate_event: 17), - ipc_interface_make_command_meta!(attach_deactivate_event: 18), - ipc_interface_make_command_meta!(get_state: 19), - ipc_interface_make_command_meta!(get_device_state: 20), - ipc_interface_make_command_meta!(get_npad_id: 21), - ipc_interface_make_command_meta!(get_application_area_size: 22), - ipc_interface_make_command_meta!(attach_availability_change_event: 23, [(3, 0, 0) =>]), - ipc_interface_make_command_meta!(recreate_application_area: 24, [(3, 0, 0) =>]) + ipc_cmif_interface_make_command_meta!(initialize: 0), + ipc_cmif_interface_make_command_meta!(finalize: 1), + ipc_cmif_interface_make_command_meta!(list_devices: 2), + ipc_cmif_interface_make_command_meta!(start_detection: 3), + ipc_cmif_interface_make_command_meta!(stop_detection: 4), + ipc_cmif_interface_make_command_meta!(mount: 5), + ipc_cmif_interface_make_command_meta!(unmount: 6), + ipc_cmif_interface_make_command_meta!(open_application_area: 7), + ipc_cmif_interface_make_command_meta!(get_application_area: 8), + ipc_cmif_interface_make_command_meta!(set_application_area: 9), + ipc_cmif_interface_make_command_meta!(flush: 10), + ipc_cmif_interface_make_command_meta!(restore: 11), + ipc_cmif_interface_make_command_meta!(create_application_area: 12), + ipc_cmif_interface_make_command_meta!(get_tag_info: 13), + ipc_cmif_interface_make_command_meta!(get_register_info: 14), + ipc_cmif_interface_make_command_meta!(get_common_info: 15), + ipc_cmif_interface_make_command_meta!(get_model_info: 16), + ipc_cmif_interface_make_command_meta!(attach_activate_event: 17), + ipc_cmif_interface_make_command_meta!(attach_deactivate_event: 18), + ipc_cmif_interface_make_command_meta!(get_state: 19), + ipc_cmif_interface_make_command_meta!(get_device_state: 20), + ipc_cmif_interface_make_command_meta!(get_npad_id: 21), + ipc_cmif_interface_make_command_meta!(get_application_area_size: 22), + ipc_cmif_interface_make_command_meta!(attach_availability_change_event: 23, [(3, 0, 0) =>]), + ipc_cmif_interface_make_command_meta!(recreate_application_area: 24, [(3, 0, 0) =>]) ] } } @@ -376,7 +376,7 @@ impl sf::IObject for UserManager { fn get_command_table(&self) -> sf::CommandMetadataTable { vec! [ - ipc_interface_make_command_meta!(create_user_interface: 0) + ipc_cmif_interface_make_command_meta!(create_user_interface: 0) ] } } diff --git a/emuiibo/src/main.rs b/emuiibo/src/main.rs index 2df29fe..edc63ef 100644 --- a/emuiibo/src/main.rs +++ b/emuiibo/src/main.rs @@ -16,7 +16,7 @@ use nx::util; use nx::thread; use nx::diag::assert; use nx::diag::log; -use nx::ipc::server; +use nx::ipc::cmif::server; use nx::fs; use core::panic; diff --git a/emuiibo/src/miiext.rs b/emuiibo/src/miiext.rs index 7629a5f..3759085 100644 --- a/emuiibo/src/miiext.rs +++ b/emuiibo/src/miiext.rs @@ -1,9 +1,9 @@ use nx::result::*; -use nx::ipc::sf; +use nx::ipc::cmif::sf; use nx::service; -use nx::service::mii; -use nx::service::mii::IDatabaseService; -use nx::service::mii::IStaticService; +use nx::service::cmif::mii; +use nx::service::cmif::mii::IDatabaseService; +use nx::service::cmif::mii::IStaticService; use nx::mem; use nx::fs; use alloc::vec::Vec; @@ -17,7 +17,7 @@ static mut G_INIT: bool = false; pub fn initialize() -> Result<()> { unsafe { if !G_INIT { - G_STATIC_SRV = service::new_service_object()?; + G_STATIC_SRV = service::cmif::new_service_object()?; G_DB_SRV = G_STATIC_SRV.get().get_database_service(mii::SpecialKeyCode::Normal)?.to::(); G_INIT = true; } diff --git a/overlay/include/tipc.hpp b/overlay/include/tipc.hpp new file mode 100644 index 0000000..abe5254 --- /dev/null +++ b/overlay/include/tipc.hpp @@ -0,0 +1,271 @@ + +#pragma once +#include + +// TODO: remove this when libnx drops a new release + +extern "C" { + + typedef enum TipcCommandType { + TipcCommandType_Close = 15, + } TipcCommandType; + + /// tipc Service object structure + typedef struct TipcService { + Handle session; + } TipcService; + + typedef struct TipcDispatchParams { + SfBufferAttrs buffer_attrs; + SfBuffer buffers[8]; + + bool in_send_pid; + + u32 in_num_handles; + Handle in_handles[8]; + + u32 out_num_objects; + TipcService* out_objects; + + SfOutHandleAttrs out_handle_attrs; + Handle* out_handles; + } TipcDispatchParams; + + typedef struct TipcRequestFormat { + u32 request_id; + u32 data_size; + u32 num_in_buffers; + u32 num_out_buffers; + u32 num_inout_buffers; + u32 num_handles; + u32 send_pid; + } TipcRequestFormat; + + /** + * @brief Creates a tipc service object from an IPC session handle. + * @param[out] s TIPC service object. + * @param[in] h IPC session handle. + */ + NX_CONSTEXPR void tipcCreate(TipcService* s, Handle h) { + s->session = h; + } + + /** + * @brief Closes a tipc service. + * @param[in] s TIPC service object. + */ + NX_INLINE void tipcClose(TipcService* s) + { + hipcMakeRequestInline(armGetTls(), .type = TipcCommandType_Close); + svcSendSyncRequest(s->session); + svcCloseHandle(s->session); + *s = (TipcService){}; + } + + NX_CONSTEXPR void tipcRequestInBuffer(HipcRequest* req, const void* buffer, size_t size, HipcBufferMode mode) + { + *req->send_buffers++ = hipcMakeBuffer(buffer, size, mode); + } + + NX_CONSTEXPR void tipcRequestOutBuffer(HipcRequest* req, void* buffer, size_t size, HipcBufferMode mode) + { + *req->recv_buffers++ = hipcMakeBuffer(buffer, size, mode); + } + + NX_CONSTEXPR void tipcRequestInOutBuffer(HipcRequest* req, void* buffer, size_t size, HipcBufferMode mode) + { + *req->exch_buffers++ = hipcMakeBuffer(buffer, size, mode); + } + + NX_CONSTEXPR void tipcRequestHandle(HipcRequest* req, Handle handle) + { + *req->copy_handles++ = handle; + } + + NX_CONSTEXPR void _tipcRequestFormatProcessBuffer(TipcRequestFormat* fmt, u32 attr) + { + if (!attr) return; + const bool is_in = (attr & SfBufferAttr_In) != 0; + const bool is_out = (attr & SfBufferAttr_Out) != 0; + + if (attr & SfBufferAttr_HipcMapAlias) { + if (is_in && is_out) + fmt->num_inout_buffers ++; + else if (is_in) + fmt->num_in_buffers ++; + else if (is_out) + fmt->num_out_buffers ++; + } + } + + NX_CONSTEXPR void _tipcRequestProcessBuffer(HipcRequest* req, const SfBuffer* buf, u32 attr) + { + if (!attr) return; + const bool is_in = (attr & SfBufferAttr_In); + const bool is_out = (attr & SfBufferAttr_Out); + + if (attr & SfBufferAttr_HipcMapAlias) { + HipcBufferMode mode = HipcBufferMode_Normal; + if (attr & SfBufferAttr_HipcMapTransferAllowsNonSecure) + mode = HipcBufferMode_NonSecure; + if (attr & SfBufferAttr_HipcMapTransferAllowsNonDevice) + mode = HipcBufferMode_NonDevice; + + if (is_in && is_out) + tipcRequestInOutBuffer(req, (void*)buf->ptr, buf->size, mode); + else if (is_in) + tipcRequestInBuffer(req, buf->ptr, buf->size, mode); + else if (is_out) + tipcRequestOutBuffer(req, (void*)buf->ptr, buf->size, mode); + } + } + + NX_INLINE void* tipcMakeRequest( + const TipcService *s, u32 request_id, u32 data_size, bool send_pid, + const SfBufferAttrs buffer_attrs, const SfBuffer* buffers, + u32 num_handles, const Handle* handles) { + TipcRequestFormat fmt = {}; + fmt.request_id = request_id + 16; + fmt.data_size = data_size; + fmt.num_handles = num_handles; + fmt.send_pid = send_pid; + + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr0); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr1); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr2); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr3); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr4); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr5); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr6); + _tipcRequestFormatProcessBuffer(&fmt, buffer_attrs.attr7); + + HipcRequest req = hipcMakeRequestInline(armGetTls(), + .type = fmt.request_id, + .num_send_statics = 0, + .num_send_buffers = fmt.num_in_buffers, + .num_recv_buffers = fmt.num_out_buffers, + .num_exch_buffers = fmt.num_inout_buffers, + .num_data_words = (data_size + 3) / 4, + .num_recv_statics = 0, + .send_pid = fmt.send_pid, + .num_copy_handles = fmt.num_handles, + .num_move_handles = 0, + ); + + for (u32 i = 0; i < num_handles; i ++) + tipcRequestHandle(&req, handles[i]); + + _tipcRequestProcessBuffer(&req, &buffers[0], buffer_attrs.attr0); + _tipcRequestProcessBuffer(&req, &buffers[1], buffer_attrs.attr1); + _tipcRequestProcessBuffer(&req, &buffers[2], buffer_attrs.attr2); + _tipcRequestProcessBuffer(&req, &buffers[3], buffer_attrs.attr3); + _tipcRequestProcessBuffer(&req, &buffers[4], buffer_attrs.attr4); + _tipcRequestProcessBuffer(&req, &buffers[5], buffer_attrs.attr5); + _tipcRequestProcessBuffer(&req, &buffers[6], buffer_attrs.attr6); + _tipcRequestProcessBuffer(&req, &buffers[7], buffer_attrs.attr7); + + return req.data_words; + } + + NX_CONSTEXPR Handle tipcResponseGetCopyHandle(HipcResponse* res) + { + return *res->copy_handles++; + } + + NX_CONSTEXPR Handle tipcResponseGetMoveHandle(HipcResponse* res) + { + return *res->move_handles++; + } + + NX_CONSTEXPR void _tipcResponseGetHandle(HipcResponse* res, SfOutHandleAttr type, Handle* out) + { + switch (type) { + default: + case SfOutHandleAttr_None: + break; + case SfOutHandleAttr_HipcCopy: + *out = tipcResponseGetCopyHandle(res); + break; + case SfOutHandleAttr_HipcMove: + *out = tipcResponseGetMoveHandle(res); + break; + } + } + + NX_INLINE Result tipcParseResponse( + const TipcService* s, u32 out_size, void** out_data, + u32 num_out_objects, TipcService* out_objects, + const SfOutHandleAttrs out_handle_attrs, Handle* out_handles + ) { + + HipcResponse res = hipcParseResponse(armGetTls()); + + Result rc = *res.data_words++; + if (R_FAILED(rc)) + return rc; + + if (out_size) + *out_data = res.data_words; + + for (u32 i = 0; i < num_out_objects; i ++) { + tipcCreate(&out_objects[i], tipcResponseGetMoveHandle(&res)); + } + + _tipcResponseGetHandle(&res, out_handle_attrs.attr0, &out_handles[0]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr1, &out_handles[1]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr2, &out_handles[2]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr3, &out_handles[3]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr4, &out_handles[4]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr5, &out_handles[5]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr6, &out_handles[6]); + _tipcResponseGetHandle(&res, out_handle_attrs.attr7, &out_handles[7]); + + return 0; + } + + NX_INLINE Result tipcDispatchImpl( + TipcService* s, u32 request_id, + const void* in_data, u32 in_data_size, + void* out_data, u32 out_data_size, + TipcDispatchParams disp + ) + { + // Make a copy of the service struct, so that the compiler can assume that it won't be modified by function calls. + const TipcService srv = *s; + + void* in = tipcMakeRequest(&srv, request_id, + in_data_size, disp.in_send_pid, + disp.buffer_attrs, disp.buffers, + disp.in_num_handles, disp.in_handles); + + if (in_data_size) + __builtin_memcpy(in, in_data, in_data_size); + + Result rc = svcSendSyncRequest(s->session); + if (R_SUCCEEDED(rc)) { + void* out = NULL; + rc = tipcParseResponse(&srv, + out_data_size, &out, + disp.out_num_objects, disp.out_objects, + disp.out_handle_attrs, disp.out_handles); + + if (R_SUCCEEDED(rc) && out_data && out_data_size) + __builtin_memcpy(out_data, out, out_data_size); + } + + return rc; + } + + #define tipcDispatch(_s,_rid,...) \ + tipcDispatchImpl((_s),(_rid),NULL,0,NULL,0,(TipcDispatchParams){ __VA_ARGS__ }) + + #define tipcDispatchIn(_s,_rid,_in,...) \ + tipcDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(TipcDispatchParams){ __VA_ARGS__ }) + + #define tipcDispatchOut(_s,_rid,_out,...) \ + tipcDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(TipcDispatchParams){ __VA_ARGS__ }) + + #define tipcDispatchInOut(_s,_rid,_in,_out,...) \ + tipcDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(TipcDispatchParams){ __VA_ARGS__ }) + +} \ No newline at end of file diff --git a/overlay/source/Main.cpp b/overlay/source/Main.cpp index c283479..2eb4a09 100644 --- a/overlay/source/Main.cpp +++ b/overlay/source/Main.cpp @@ -6,29 +6,29 @@ namespace { - bool g_emuiibo_init_ok = false; - bool g_category_list_update_flag = false; - bool g_main_update_flag = false; - bool g_current_app_intercepted = false; - char g_emuiibo_amiibo_dir[FS_MAX_PATH]; - emu::Version g_emuiibo_version; + bool g_Initialized = false; + bool g_NeedsUpdateCategoryList = false; + bool g_NeedsUpdateMainGui = false; + bool g_CurrentApplicationIntercepted = false; + char g_VirtualAmiiboDirectory[FS_MAX_PATH]; + emu::Version g_Version; - char g_active_amiibo_path[FS_MAX_PATH]; - emu::VirtualAmiiboData g_active_amiibo_data; + char g_ActiveVirtualAmiiboPath[FS_MAX_PATH]; + emu::VirtualAmiiboData g_ActiveVirtualAmiiboData; inline bool IsActiveAmiiboValid() { - return strlen(g_active_amiibo_path) > 0; + return strlen(g_ActiveVirtualAmiiboPath) > 0; } inline void UpdateActiveAmiibo() { - emu::GetActiveVirtualAmiibo(&g_active_amiibo_data, g_active_amiibo_path, FS_MAX_PATH); + emu::GetActiveVirtualAmiibo(&g_ActiveVirtualAmiiboData, g_ActiveVirtualAmiiboPath, sizeof(g_ActiveVirtualAmiiboPath)); } // Returns true if the value changed inline bool UpdateCurrentApplicationIntercepted() { bool ret = emu::IsCurrentApplicationIdIntercepted(); - if(ret != g_current_app_intercepted) { - g_current_app_intercepted = ret; + if(ret != g_CurrentApplicationIntercepted) { + g_CurrentApplicationIntercepted = ret; return true; } return false; @@ -36,20 +36,20 @@ namespace { inline std::string MakeActiveAmiiboText() { if(IsActiveAmiiboValid()) { - return std::string("Active virtual amiibo: ") + g_active_amiibo_data.name; + return std::string("Active virtual amiibo: ") + g_ActiveVirtualAmiiboData.name; } return "No active virtual amiibo"; } inline std::string MakeTitleText() { - if(!g_emuiibo_init_ok) { + if(!g_Initialized) { return "emuiibo"; } - return "emuiibo v" + std::to_string(g_emuiibo_version.major) + "." + std::to_string(g_emuiibo_version.minor) + "." + std::to_string(g_emuiibo_version.micro) + " (" + (g_emuiibo_version.dev_build ? "dev" : "release") + ")"; + return "emuiibo v" + std::to_string(g_Version.major) + "." + std::to_string(g_Version.minor) + "." + std::to_string(g_Version.micro) + " (" + (g_Version.dev_build ? "dev" : "release") + ")"; } inline std::string MakeStatusText() { - if(!g_emuiibo_init_ok) { + if(!g_Initialized) { return "emuiibo was not accessed."; } std::string msg = "Emulation: "; @@ -65,19 +65,19 @@ namespace { } case emu::VirtualAmiiboStatus::Connected: { msg += "Virtual amiibo: "; - msg += g_active_amiibo_data.name; + msg += g_ActiveVirtualAmiiboData.name; msg += " (connected - select to disconnect)"; break; } case emu::VirtualAmiiboStatus::Disconnected: { msg += "Virtual amiibo: "; - msg += g_active_amiibo_data.name; + msg += g_ActiveVirtualAmiiboData.name; msg += " (disconnected - select to connect)"; break; } } msg += "\n"; - if(g_current_app_intercepted) { + if(g_CurrentApplicationIntercepted) { msg += "Current game is being intercepted by emuiibo."; } else { @@ -113,7 +113,7 @@ class AmiiboList : public tsl::Gui { char amiibo_path[FS_MAX_PATH] = {0}; strcpy(amiibo_path, path.c_str()); if(IsActiveAmiiboValid()) { - if(strcmp(g_active_amiibo_path, amiibo_path) == 0) { + if(strcmp(g_ActiveVirtualAmiiboPath, amiibo_path) == 0) { // User selected the active amiibo, so let's change connection then auto status = emu::GetActiveVirtualAmiiboStatus(); switch(status) { @@ -134,7 +134,7 @@ class AmiiboList : public tsl::Gui { } } // Set active amiibo and update our active amiibo value - emu::SetActiveVirtualAmiibo(amiibo_path, FS_MAX_PATH); + emu::SetActiveVirtualAmiibo(amiibo_path, sizeof(amiibo_path)); UpdateActiveAmiibo(); selected_header->setText(MakeActiveAmiiboText()); root_frame->setSubtitle(MakeStatusText()); @@ -161,7 +161,7 @@ class AmiiboList : public tsl::Gui { strcpy(path, str_path.c_str()); // Find virtual amiibo emu::VirtualAmiiboData data = {}; - if(R_SUCCEEDED(emu::TryParseVirtualAmiibo(path, FS_MAX_PATH, &data))) { + if(R_SUCCEEDED(emu::TryParseVirtualAmiibo(path, sizeof(path), &data))) { auto item = new tsl::elm::SmallListItem(data.name); item->setClickListener(std::bind(&AmiiboList::OnItemClick, this, std::placeholders::_1, str_path)); list->addItem(item); @@ -211,7 +211,7 @@ class CategoryList : public tsl::Gui { static bool OnItemClick(u64 keys, const std::string &path) { if(keys & KEY_A) { tsl::changeTo(path); - g_category_list_update_flag = true; + g_NeedsUpdateCategoryList = true; return true; } return false; @@ -223,12 +223,12 @@ class CategoryList : public tsl::Gui { // Root auto root_item = new tsl::elm::SmallListItem(""); - root_item->setClickListener(std::bind(&CategoryList::OnItemClick, std::placeholders::_1, g_emuiibo_amiibo_dir)); + root_item->setClickListener(std::bind(&CategoryList::OnItemClick, std::placeholders::_1, g_VirtualAmiiboDirectory)); this->list->addItem(root_item); u32 count = 1; // Root tsl::hlp::doWithSDCardHandle([&](){ - auto dir = opendir(g_emuiibo_amiibo_dir); + auto dir = opendir(g_VirtualAmiiboDirectory); if(dir) { while(true) { auto entry = readdir(dir); @@ -236,11 +236,11 @@ class CategoryList : public tsl::Gui { break; } char path[FS_MAX_PATH] = {0}; - auto str_path = std::string(g_emuiibo_amiibo_dir) + "/" + entry->d_name; + auto str_path = std::string(g_VirtualAmiiboDirectory) + "/" + entry->d_name; strcpy(path, str_path.c_str()); // If it's a valid amiibo, skip emu::VirtualAmiiboData tmp_data; - if(R_SUCCEEDED(emu::TryParseVirtualAmiibo(path, FS_MAX_PATH, &tmp_data))) { + if(R_SUCCEEDED(emu::TryParseVirtualAmiibo(path, sizeof(path), &tmp_data))) { continue; } if(entry->d_type & DT_DIR) { @@ -266,9 +266,9 @@ class CategoryList : public tsl::Gui { virtual void update() override { bool upd = false; - if(g_category_list_update_flag) { + if(g_NeedsUpdateCategoryList) { upd = true; - g_category_list_update_flag = false; + g_NeedsUpdateCategoryList = false; } if(UpdateCurrentApplicationIntercepted()) { upd = true; @@ -297,7 +297,7 @@ class MainGui : public tsl::Gui { virtual tsl::elm::Element *createUI() override { auto list = new tsl::elm::List(); - if(g_emuiibo_init_ok) { + if(g_Initialized) { auto status = emu::GetEmulationStatus(); auto *toggle_item = new tsl::elm::NamedStepTrackBar("\u22EF", { "Off", "On" }); @@ -331,7 +331,7 @@ class MainGui : public tsl::Gui { select_item->setClickListener([](u64 keys) { if(keys & KEY_A) { tsl::changeTo(); - g_main_update_flag = true; + g_NeedsUpdateMainGui = true; return true; } return false; @@ -352,9 +352,9 @@ class MainGui : public tsl::Gui { virtual void update() override { bool upd = false; - if(g_main_update_flag) { + if(g_NeedsUpdateMainGui) { upd = true; - g_main_update_flag = false; + g_NeedsUpdateMainGui = false; } if(UpdateCurrentApplicationIntercepted()) { upd = true; @@ -372,14 +372,14 @@ class Overlay : public tsl::Overlay { virtual void initServices() override { tsl::hlp::doWithSmSession([&] { if(emu::IsAvailable()) { - g_emuiibo_init_ok = R_SUCCEEDED(emu::Initialize()) && R_SUCCEEDED(pmdmntInitialize()) && R_SUCCEEDED(pminfoInitialize()); - if(g_emuiibo_init_ok) { - g_emuiibo_version = emu::GetVersion(); - emu::GetVirtualAmiiboDirectory(g_emuiibo_amiibo_dir, FS_MAX_PATH); + g_Initialized = R_SUCCEEDED(emu::Initialize()) && R_SUCCEEDED(pmdmntInitialize()) && R_SUCCEEDED(pminfoInitialize()); + if(g_Initialized) { + g_Version = emu::GetVersion(); + emu::GetVirtualAmiiboDirectory(g_VirtualAmiiboDirectory, sizeof(g_VirtualAmiiboDirectory)); } } }); - if(g_emuiibo_init_ok) { + if(g_Initialized) { UpdateActiveAmiibo(); } } diff --git a/overlay/source/emuiibo.cpp b/overlay/source/emuiibo.cpp index 96d9589..2f5777a 100644 --- a/overlay/source/emuiibo.cpp +++ b/overlay/source/emuiibo.cpp @@ -1,44 +1,51 @@ #include +#include -#define EMU_EMUIIBO_SRV "emuiibo" +#define EMU_EMUIIBO_SERVICE_NAME "emuiibo" namespace emu { namespace { - Service g_emuiibo_srv; + Service g_EmuiiboService; + + inline TipcService GetSmTipcService() { + auto sm_srv_ref = smGetServiceSession(); + return { sm_srv_ref->session }; + } bool smAtmosphereHasService(SmServiceName name) { bool has = false; - serviceDispatchInOut(smGetServiceSession(), 65100, name, has); + auto sm_tipc_srv = GetSmTipcService(); + tipcDispatchInOut(&sm_tipc_srv, 65100, name, has); return has; } } bool IsAvailable() { - return smAtmosphereHasService(smEncodeName(EMU_EMUIIBO_SRV)); + return smAtmosphereHasService(smEncodeName(EMU_EMUIIBO_SERVICE_NAME)); } Result Initialize() { - if(serviceIsActive(&g_emuiibo_srv)) { + if(serviceIsActive(&g_EmuiiboService)) { return 0; } - return smGetService(&g_emuiibo_srv, EMU_EMUIIBO_SRV); + return smGetService(&g_EmuiiboService, EMU_EMUIIBO_SERVICE_NAME); } void Exit() { - serviceClose(&g_emuiibo_srv); + serviceClose(&g_EmuiiboService); } Version GetVersion() { Version ver = {}; - serviceDispatchOut(&g_emuiibo_srv, 0, ver); + serviceDispatchOut(&g_EmuiiboService, 0, ver); return ver; } void GetVirtualAmiiboDirectory(char *out_path, size_t out_path_size) { - serviceDispatch(&g_emuiibo_srv, 1, + serviceDispatch(&g_EmuiiboService, 1, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { out_path, out_path_size } }, ); @@ -46,17 +53,17 @@ namespace emu { EmulationStatus GetEmulationStatus() { u32 out = 0; - serviceDispatchOut(&g_emuiibo_srv, 2, out); + serviceDispatchOut(&g_EmuiiboService, 2, out); return static_cast(out); } void SetEmulationStatus(EmulationStatus status) { u32 in = static_cast(status); - serviceDispatchIn(&g_emuiibo_srv, 3, in); + serviceDispatchIn(&g_EmuiiboService, 3, in); } Result GetActiveVirtualAmiibo(VirtualAmiiboData *out_amiibo_data, char *out_path, size_t out_path_size) { - return serviceDispatchOut(&g_emuiibo_srv, 4, *out_amiibo_data, + return serviceDispatchOut(&g_EmuiiboService, 4, *out_amiibo_data, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, @@ -67,33 +74,33 @@ namespace emu { } Result SetActiveVirtualAmiibo(char *path, size_t path_size) { - return serviceDispatch(&g_emuiibo_srv, 5, + return serviceDispatch(&g_EmuiiboService, 5, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { path, path_size } }, ); } void ResetActiveVirtualAmiibo() { - serviceDispatch(&g_emuiibo_srv, 6); + serviceDispatch(&g_EmuiiboService, 6); } VirtualAmiiboStatus GetActiveVirtualAmiiboStatus() { u32 out = 0; - serviceDispatchOut(&g_emuiibo_srv, 7, out); + serviceDispatchOut(&g_EmuiiboService, 7, out); return static_cast(out); } void SetActiveVirtualAmiiboStatus(VirtualAmiiboStatus status) { u32 in = static_cast(status); - serviceDispatchIn(&g_emuiibo_srv, 8, in); + serviceDispatchIn(&g_EmuiiboService, 8, in); } void IsApplicationIdIntercepted(u64 app_id, bool *out_intercepted) { - serviceDispatchInOut(&g_emuiibo_srv, 9, app_id, *out_intercepted); + serviceDispatchInOut(&g_EmuiiboService, 9, app_id, *out_intercepted); } Result TryParseVirtualAmiibo(char *path, size_t path_size, VirtualAmiiboData *out_amiibo_data) { - return serviceDispatchOut(&g_emuiibo_srv, 10, *out_amiibo_data, + return serviceDispatchOut(&g_EmuiiboService, 10, *out_amiibo_data, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },