Fix weird bug related to using too many input contexts

This commit is contained in:
XorTroll 2023-05-16 00:51:39 +02:00
parent 97326a0aa7
commit 2e0d9f1f33
8 changed files with 54 additions and 27 deletions

View File

@ -1,7 +1,11 @@
name: Build emuiibo
on: [push]
on:
push:
paths:
- 'emuiibo/**'
- 'overlay/**'
jobs:
emuiibo:

View File

@ -45,6 +45,7 @@ Table of contents
- [Per-game access IDs](#per-game-access-ids)
- [Usage and controlling](#usage-and-controlling)
- [Boot procedure](#boot-procedure)
- [Compiling](#compiling)
- [For developers](#for-developers)
- [Credits](#credits)
- [License exemption](#license-exemption)
@ -189,6 +190,12 @@ To go back in the menus, just press **B** button.
- The bin dump file does not get removed, but it will get moved inside the modern amiibo format, along with the decrypted file.
## Compiling
In order to compile emuiibo you need to [setup Rust for Nintendo Switch development](https://github.com/aarch64-switch-rs/setup-guide). You'll also need devkitPro (devkitA64 specifically).
With this requirements satisfied, simply clone (recursively) this repo and hit `make`
## For developers
emuiibo hosts a custom IPC service, also named `emuiibo`, which can be used to control amiibo emulation by other homebrew tools.

4
emuiibo/Cargo.lock generated
View File

@ -56,9 +56,9 @@ checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "proc-macro2"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16"
dependencies = [
"unicode-ident",
]

View File

@ -7,10 +7,26 @@ use nx::sync;
use nx::service::hid;
use nx::input;
use nx::thread;
use crate::area;
use crate::emu;
static mut G_INPUT_CTX: Option<input::Context> = None;
pub fn initialize() -> Result<()> {
let supported_tags = hid::NpadStyleTag::FullKey() | hid::NpadStyleTag::Handheld() | hid::NpadStyleTag::JoyDual() | hid::NpadStyleTag::JoyLeft() | hid::NpadStyleTag::JoyRight();
let supported_npad_ids = [hid::NpadIdType::No1, hid::NpadIdType::Handheld];
unsafe {
G_INPUT_CTX = Some(input::Context::new(supported_tags, &supported_npad_ids)?);
}
Ok(())
}
pub fn get_input_context() -> &'static input::Context {
unsafe {
G_INPUT_CTX.as_ref().unwrap()
}
}
pub struct EmulationHandler {
application_id: u64,
activate_event: wait::SystemEvent,
@ -20,17 +36,13 @@ pub struct EmulationHandler {
device_state: sync::Locked<nfp::DeviceState>,
should_end_thread: sync::Locked<bool>,
current_opened_area: area::ApplicationArea,
emu_handler_thread: thread::Thread,
input_ctx: input::Context
emu_handler_thread: thread::Thread
}
impl EmulationHandler {
pub fn new(application_id: u64) -> Result<Self> {
log!("\n[{:#X}] New handler!\n", application_id);
let supported_tags = hid::NpadStyleTag::FullKey() | hid::NpadStyleTag::Handheld() | hid::NpadStyleTag::JoyDual() | hid::NpadStyleTag::JoyLeft() | hid::NpadStyleTag::JoyRight();
let supported_npad_ids = [hid::NpadIdType::No1, hid::NpadIdType::Handheld];
let input_ctx = input::Context::new(supported_tags, &supported_npad_ids)?;
Ok(Self { application_id, activate_event: wait::SystemEvent::new()?, deactivate_event: wait::SystemEvent::new()?, availability_change_event: wait::SystemEvent::new()?, state: sync::Locked::new(false, nfp::State::NonInitialized), device_state: sync::Locked::new(false, nfp::DeviceState::Unavailable), should_end_thread: sync::Locked::new(false, false), emu_handler_thread: thread::Thread::empty(), current_opened_area: area::ApplicationArea::new(), input_ctx })
Ok(Self { application_id, activate_event: wait::SystemEvent::new()?, deactivate_event: wait::SystemEvent::new()?, availability_change_event: wait::SystemEvent::new()?, state: sync::Locked::new(false, nfp::State::NonInitialized), device_state: sync::Locked::new(false, nfp::DeviceState::Unavailable), should_end_thread: sync::Locked::new(false, false), emu_handler_thread: thread::Thread::empty(), current_opened_area: area::ApplicationArea::new() })
}
#[inline]
@ -117,15 +129,17 @@ impl EmulationHandler {
// Send a single fake device handle
let fake_device_npad_id = {
let p1 = self.input_ctx.get_player(hid::NpadIdType::No1);
if p1.get_style_tag_attributes(hid::NpadStyleTag::FullKey()).contains(hid::NpadAttribute::IsConnected())
|| p1.get_style_tag_attributes(hid::NpadStyleTag::JoyDual()).contains(hid::NpadAttribute::IsConnected())
|| p1.get_style_tag_attributes(hid::NpadStyleTag::JoyLeft()).contains(hid::NpadAttribute::IsConnected())
|| p1.get_style_tag_attributes(hid::NpadStyleTag::JoyRight()).contains(hid::NpadAttribute::IsConnected()) {
hid::NpadIdType::No1
}
else {
hid::NpadIdType::Handheld
unsafe {
let p1 = get_input_context().get_player(hid::NpadIdType::No1);
if p1.get_style_tag_attributes(hid::NpadStyleTag::FullKey()).contains(hid::NpadAttribute::IsConnected())
|| p1.get_style_tag_attributes(hid::NpadStyleTag::JoyDual()).contains(hid::NpadAttribute::IsConnected())
|| p1.get_style_tag_attributes(hid::NpadStyleTag::JoyLeft()).contains(hid::NpadAttribute::IsConnected())
|| p1.get_style_tag_attributes(hid::NpadStyleTag::JoyRight()).contains(hid::NpadAttribute::IsConnected()) {
hid::NpadIdType::No1
}
else {
hid::NpadIdType::Handheld
}
}
};

View File

@ -72,9 +72,10 @@ pub fn main() -> Result<()> {
miiext::export_miis()?;
amiibo::compat::convert_deprecated_virtual_amiibos();
emu::load_emulation_status();
ipc::nfp::initialize()?;
const POINTER_BUF_SIZE: usize = 0x1000;
type Manager = server::ServerManager<POINTER_BUF_SIZE>;

View File

@ -74,15 +74,15 @@ namespace emu {
VirtualAmiiboStatus GetActiveVirtualAmiiboStatus();
void SetActiveVirtualAmiiboStatus(const VirtualAmiiboStatus status);
void IsApplicationIdIntercepted(const u64 app_id, bool *out_intercepted);
bool IsApplicationIdIntercepted(const u64 app_id);
inline bool IsCurrentApplicationIdIntercepted() {
bool intercepted = false;
u64 process_id = 0;
if(R_SUCCEEDED(pmdmntGetApplicationProcessId(&process_id))) {
u64 program_id = 0;
if(R_SUCCEEDED(pminfoGetProgramId(&program_id, process_id))) {
IsApplicationIdIntercepted(program_id, &intercepted);
if(R_SUCCEEDED(pmdmntGetProgramId(&program_id, process_id))) {
intercepted = IsApplicationIdIntercepted(program_id);
}
}
return intercepted;

View File

@ -779,7 +779,7 @@ class AmiiboGui : public tsl::Gui {
class EmuiiboOverlay : public tsl::Overlay {
public:
virtual void initServices() override {
g_InitializationOk = tr::Load() && emu::IsAvailable() && R_SUCCEEDED(emu::Initialize()) && R_SUCCEEDED(pmdmntInitialize()) && R_SUCCEEDED(pminfoInitialize()) && R_SUCCEEDED(nsInitialize());
g_InitializationOk = tr::Load() && emu::IsAvailable() && R_SUCCEEDED(emu::Initialize()) && R_SUCCEEDED(pmdmntInitialize()) && R_SUCCEEDED(nsInitialize());
if(g_InitializationOk) {
g_Version = emu::GetVersion();
g_InitializationOk &= g_Version.EqualsExceptBuild(ExpectedVersion);
@ -795,7 +795,6 @@ class EmuiiboOverlay : public tsl::Overlay {
virtual void exitServices() override {
SaveFavorites();
nsExit();
pminfoExit();
pmdmntExit();
emu::Exit();
}

View File

@ -87,8 +87,10 @@ namespace emu {
serviceDispatchIn(&g_EmuiiboService, 8, status);
}
void IsApplicationIdIntercepted(const u64 app_id, bool *out_intercepted) {
serviceDispatchInOut(&g_EmuiiboService, 9, app_id, *out_intercepted);
bool IsApplicationIdIntercepted(const u64 app_id) {
bool intercepted;
serviceDispatchInOut(&g_EmuiiboService, 9, app_id, intercepted);
return intercepted;
}
Result TryParseVirtualAmiibo(const char *path, const size_t path_size, VirtualAmiiboData *out_amiibo_data) {