core: small fixes to local play (#1690)
Some checks failed
citra-build / source (push) Has been cancelled
citra-build / linux (appimage) (push) Has been cancelled
citra-build / linux (appimage-wayland) (push) Has been cancelled
citra-build / linux (fresh) (push) Has been cancelled
citra-build / macos (arm64) (push) Has been cancelled
citra-build / macos (x86_64) (push) Has been cancelled
citra-build / windows (msvc) (push) Has been cancelled
citra-build / windows (msys2) (push) Has been cancelled
citra-build / android (googleplay) (push) Has been cancelled
citra-build / android (vanilla) (push) Has been cancelled
citra-build / docker (push) Has been cancelled
citra-format / clang-format (push) Has been cancelled
citra-transifex / transifex (push) Has been cancelled
citra-build / macos-universal (push) Has been cancelled

This commit is contained in:
lannoene 2026-01-27 01:30:26 -08:00 committed by GitHub
parent 0a705b7449
commit a9923b6844
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 90 additions and 70 deletions

View File

@ -413,6 +413,7 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
apt->GetAppletManager()->SetSysMenuArg(restore_sys_menu_arg.value());
restore_sys_menu_arg.reset();
}
apt->SetWirelessRebootInfoBuffer(restore_wireless_reboot_info);
}
if (restore_plugin_context.has_value()) {
@ -737,6 +738,7 @@ void System::Reset() {
if (auto apt = Service::APT::GetModule(*this)) {
restore_deliver_arg = apt->GetAppletManager()->ReceiveDeliverArg();
restore_sys_menu_arg = apt->GetAppletManager()->GetSysMenuArg();
restore_wireless_reboot_info = apt->GetWirelessRebootInfoBuffer();
}
if (auto plg_ldr = Service::PLGLDR::GetService(*this)) {
restore_plugin_context = plg_ldr->GetPluginLoaderContext();

View File

@ -489,6 +489,7 @@ private:
boost::optional<Service::APT::SysMenuArg> restore_sys_menu_arg;
boost::optional<Service::PLGLDR::PLG_LDR::PluginLoaderContext> restore_plugin_context;
std::unique_ptr<IPCDebugger::Recorder> restore_ipc_recorder;
std::vector<u8> restore_wireless_reboot_info;
std::vector<u64> lle_modules;

View File

@ -1493,6 +1493,14 @@ std::shared_ptr<AppletManager> Module::GetAppletManager() const {
return applet_manager;
}
std::vector<u8> Module::GetWirelessRebootInfoBuffer() const {
return wireless_reboot_info;
}
void Module::SetWirelessRebootInfoBuffer(std::vector<u8> info_buf) {
wireless_reboot_info = info_buf;
}
std::shared_ptr<Module> GetModule(Core::System& system) {
auto apt = system.ServiceManager().GetService<Service::APT::Module::APTInterface>("APT:A");
if (!apt)

View File

@ -51,6 +51,9 @@ public:
std::shared_ptr<AppletManager> GetAppletManager() const;
std::vector<u8> GetWirelessRebootInfoBuffer() const;
void SetWirelessRebootInfoBuffer(std::vector<u8> info_buf);
class NSInterface : public ServiceFramework<NSInterface> {
public:
NSInterface(std::shared_ptr<Module> apt, const char* name, u32 max_session);

View File

@ -613,76 +613,6 @@ void NWM_UDS::Shutdown(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NWM, "called");
}
void NWM_UDS::RecvBeaconBroadcastData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 out_buffer_size = rp.Pop<u32>();
// scan input struct
u32 unk1 = rp.Pop<u32>();
u32 unk2 = rp.Pop<u32>();
MacAddress mac_address;
rp.PopRaw(mac_address);
// uninitialized data in scan input struct
rp.Skip(9, false);
// end scan input struct
u32 wlan_comm_id = rp.Pop<u32>();
u32 id = rp.Pop<u32>();
// From 3dbrew:
// 'Official user processes create a new event handle which is then passed to this command.
// However, those user processes don't save that handle anywhere afterwards.'
// So we don't save/use that event too.
std::shared_ptr<Kernel::Event> input_event = rp.PopObject<Kernel::Event>();
Kernel::MappedBuffer out_buffer = rp.PopMappedBuffer();
ASSERT(out_buffer.GetSize() == out_buffer_size);
std::size_t cur_buffer_size = sizeof(BeaconDataReplyHeader);
// Retrieve all beacon frames that were received from the desired mac address.
auto beacons = GetReceivedBeacons(mac_address);
BeaconDataReplyHeader data_reply_header{};
data_reply_header.total_entries = static_cast<u32>(beacons.size());
data_reply_header.max_output_size = out_buffer_size;
// Write each of the received beacons into the buffer
for (const auto& beacon : beacons) {
BeaconEntryHeader entry{};
// TODO(Subv): Figure out what this size is used for.
entry.unk_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
entry.total_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
entry.wifi_channel = beacon.channel;
entry.header_size = sizeof(BeaconEntryHeader);
entry.mac_address = beacon.transmitter_address;
ASSERT(cur_buffer_size < out_buffer_size);
out_buffer.Write(&entry, cur_buffer_size, sizeof(BeaconEntryHeader));
cur_buffer_size += sizeof(BeaconEntryHeader);
const unsigned char* beacon_data = beacon.data.data();
out_buffer.Write(beacon_data, cur_buffer_size, beacon.data.size());
cur_buffer_size += beacon.data.size();
}
// Update the total size in the structure and write it to the buffer again.
data_reply_header.total_size = static_cast<u32>(cur_buffer_size);
out_buffer.Write(&data_reply_header, 0, sizeof(BeaconDataReplyHeader));
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess);
rb.PushMappedBuffer(out_buffer);
LOG_DEBUG(Service_NWM,
"called out_buffer_size=0x{:08X}, wlan_comm_id=0x{:08X}, id=0x{:08X},"
"unk1=0x{:08X}, unk2=0x{:08X}, offset={}",
out_buffer_size, wlan_comm_id, id, unk1, unk2, cur_buffer_size);
}
ResultVal<std::shared_ptr<Kernel::Event>> NWM_UDS::Initialize(
u32 sharedmem_size, const NodeInfo& node, u16 version,
std::shared_ptr<Kernel::SharedMemory> sharedmem) {
@ -1307,6 +1237,82 @@ private:
friend class boost::serialization::access;
};
void NWM_UDS::RecvBeaconBroadcastData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
u32 out_buffer_size = rp.Pop<u32>();
// scan input struct
u32 unk1 = rp.Pop<u32>();
u32 unk2 = rp.Pop<u32>();
MacAddress mac_address;
rp.PopRaw(mac_address);
// uninitialized data in scan input struct
rp.Skip(9, false);
// end scan input struct
u32 wlan_comm_id = rp.Pop<u32>();
u32 id = rp.Pop<u32>();
// From 3dbrew:
// 'Official user processes create a new event handle which is then passed to this command.
// However, those user processes don't save that handle anywhere afterwards.'
// So we don't save/use that event too.
std::shared_ptr<Kernel::Event> input_event = rp.PopObject<Kernel::Event>();
Kernel::MappedBuffer out_buffer = rp.PopMappedBuffer();
ASSERT(out_buffer.GetSize() == out_buffer_size);
std::size_t cur_buffer_size = sizeof(BeaconDataReplyHeader);
// on a real 3ds this is about 0.38 seconds
static constexpr std::chrono::nanoseconds UDSBeaconScanInterval{300000000};
ctx.SleepClientThread("uds::RecvBeaconBroadcastData", UDSBeaconScanInterval,
std::make_shared<ThreadCallback>(0xF));
// Retrieve all beacon frames that were received from the desired mac address.
auto beacons = GetReceivedBeacons(mac_address);
BeaconDataReplyHeader data_reply_header{};
data_reply_header.total_entries = static_cast<u32>(beacons.size());
data_reply_header.max_output_size = out_buffer_size;
// Write each of the received beacons into the buffer
for (const auto& beacon : beacons) {
BeaconEntryHeader entry{};
// TODO(Subv): Figure out what this size is used for.
entry.unk_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
entry.total_size = static_cast<u32>(sizeof(BeaconEntryHeader) + beacon.data.size());
entry.wifi_channel = beacon.channel;
entry.header_size = sizeof(BeaconEntryHeader);
entry.mac_address = beacon.transmitter_address;
ASSERT(cur_buffer_size < out_buffer_size);
out_buffer.Write(&entry, cur_buffer_size, sizeof(BeaconEntryHeader));
cur_buffer_size += sizeof(BeaconEntryHeader);
const unsigned char* beacon_data = beacon.data.data();
out_buffer.Write(beacon_data, cur_buffer_size, beacon.data.size());
cur_buffer_size += beacon.data.size();
}
// Update the total size in the structure and write it to the buffer again.
data_reply_header.total_size = static_cast<u32>(cur_buffer_size);
out_buffer.Write(&data_reply_header, 0, sizeof(BeaconDataReplyHeader));
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess);
rb.PushMappedBuffer(out_buffer);
LOG_DEBUG(Service_NWM,
"called out_buffer_size=0x{:08X}, wlan_comm_id=0x{:08X}, id=0x{:08X},"
"unk1=0x{:08X}, unk2=0x{:08X}, offset={}",
out_buffer_size, wlan_comm_id, id, unk1, unk2, cur_buffer_size);
}
void NWM_UDS::ConnectToNetwork(Kernel::HLERequestContext& ctx, u16 command_id,
std::span<const u8> network_info_buffer, u8 connection_type,
std::vector<u8> passphrase) {