diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 4c31353f8b..d2a9f50fc6 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -148,10 +148,12 @@ set(SRCS ActionReplay.cpp IOS/FS/FS.cpp IOS/Network/Config.cpp IOS/Network/ICMPLin.cpp - IOS/Network/NWC24Config.cpp IOS/Network/Socket.cpp IOS/Network/Net.cpp IOS/Network/SSL.cpp + IOS/Network/KD/NetKDRequest.cpp + IOS/Network/KD/NetKDTime.cpp + IOS/Network/KD/NWC24Config.cpp IOS/SDIO/SDIOSlot0.cpp IOS/STM/STM.cpp IOS/USB/Common.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 60a6de3fd5..6e87990bb8 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -180,10 +180,12 @@ - + + + @@ -417,11 +419,13 @@ - + + + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index b96b206c0f..5597349a1a 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -127,6 +127,9 @@ {ab9cdd90-54d7-4f42-9248-d7903ce52cc8} + + {165768ae-ee50-4789-8051-5c5b7023fa4b} + {3db8c364-1d72-4660-9179-86d1c46904b9} @@ -758,18 +761,24 @@ IOS\Network - - IOS\Network - - - IOS\SDIO - IOS\Network IOS\Network + + IOS\Network\KD + + + IOS\Network\KD + + + IOS\Network\KD + + + IOS\SDIO + IOS\STM @@ -1344,30 +1353,36 @@ IOS\USB\Bluetooth + + IOS\USB\Bluetooth + IOS\Network IOS\Network - - IOS\USB\Bluetooth - IOS\Network - - IOS\Network - - - IOS\SDIO - IOS\Network IOS\Network + + IOS\Network\KD + + + IOS\Network\KD + + + IOS\Network\KD + + + IOS\SDIO + IOS\STM diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index 903d586d96..acda13e05f 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -16,6 +16,8 @@ // Ioctlv: Depends on the handler // Replies may be sent immediately or asynchronously for ioctls and ioctlvs. +#include "Core/IOS/IPC.h" + #include #include #include @@ -41,8 +43,9 @@ #include "Core/IOS/ES/ES.h" #include "Core/IOS/FS/FS.h" #include "Core/IOS/FS/FileIO.h" -#include "Core/IOS/IPC.h" #include "Core/IOS/MIOS.h" +#include "Core/IOS/Network/KD/NetKDRequest.h" +#include "Core/IOS/Network/KD/NetKDTime.h" #include "Core/IOS/Network/Net.h" #include "Core/IOS/Network/SSL.h" #include "Core/IOS/Network/Socket.h" diff --git a/Source/Core/Core/IOS/Network/NWC24Config.cpp b/Source/Core/Core/IOS/Network/KD/NWC24Config.cpp similarity index 98% rename from Source/Core/Core/IOS/Network/NWC24Config.cpp rename to Source/Core/Core/IOS/Network/KD/NWC24Config.cpp index 6cfb374898..4492f22443 100644 --- a/Source/Core/Core/IOS/Network/NWC24Config.cpp +++ b/Source/Core/Core/IOS/Network/KD/NWC24Config.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. -#include "Core/IOS/Network/NWC24Config.h" +#include "Core/IOS/Network/KD/NWC24Config.h" #include diff --git a/Source/Core/Core/IOS/Network/NWC24Config.h b/Source/Core/Core/IOS/Network/KD/NWC24Config.h similarity index 100% rename from Source/Core/Core/IOS/Network/NWC24Config.h rename to Source/Core/Core/IOS/Network/KD/NWC24Config.h diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp new file mode 100644 index 0000000000..4bdd738c51 --- /dev/null +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp @@ -0,0 +1,246 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/IOS/Network/KD/NetKDRequest.h" + +#include +#include + +#include "Common/CommonPaths.h" +#include "Common/CommonTypes.h" +#include "Common/FileUtil.h" +#include "Common/Logging/Log.h" +#include "Common/NandPaths.h" +#include "Common/SettingsHandler.h" + +#include "Core/HW/Memmap.h" +#include "Core/IOS/Network/Socket.h" +#include "Core/ec_wii.h" + +namespace IOS +{ +namespace HLE +{ +namespace Device +{ +NetKDRequest::NetKDRequest(u32 device_id, const std::string& device_name) + : Device(device_id, device_name) +{ +} + +NetKDRequest::~NetKDRequest() +{ + WiiSockMan::GetInstance().Clean(); +} + +IPCCommandResult NetKDRequest::IOCtl(const IOCtlRequest& request) +{ + s32 return_value = 0; + switch (request.request) + { + case IOCTL_NWC24_SUSPEND_SCHEDULAR: + // NWC24iResumeForCloseLib from NWC24SuspendScheduler (Input: none, Output: 32 bytes) + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_SUSPEND_SCHEDULAR - NI"); + Memory::Write_U32(0, request.buffer_out); // no error + break; + + case IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR: // NWC24iResumeForCloseLib + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR - NI"); + break; + + case IOCTL_NWC24_EXEC_RESUME_SCHEDULAR: // NWC24iResumeForCloseLib + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_EXEC_RESUME_SCHEDULAR - NI"); + Memory::Write_U32(0, request.buffer_out); // no error + break; + + case IOCTL_NWC24_STARTUP_SOCKET: // NWC24iStartupSocket + Memory::Write_U32(0, request.buffer_out); + Memory::Write_U32(0, request.buffer_out + 4); + return_value = 0; + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI"); + break; + + case IOCTL_NWC24_CLEANUP_SOCKET: + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_CLEANUP_SOCKET - NI"); + break; + + case IOCTL_NWC24_LOCK_SOCKET: // WiiMenu + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_LOCK_SOCKET - NI"); + break; + + case IOCTL_NWC24_UNLOCK_SOCKET: + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_UNLOCK_SOCKET - NI"); + break; + + case IOCTL_NWC24_REQUEST_REGISTER_USER_ID: + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_REGISTER_USER_ID"); + Memory::Write_U32(0, request.buffer_out); + Memory::Write_U32(0, request.buffer_out + 4); + break; + + case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes) + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID"); + if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_INITIAL) + { + const std::string settings_file_path( + Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_SETTING); + SettingsHandler gen; + std::string area, model; + bool got_settings = false; + + if (File::Exists(settings_file_path) && gen.Open(settings_file_path)) + { + area = gen.GetValue("AREA"); + model = gen.GetValue("MODEL"); + got_settings = true; + } + if (got_settings) + { + u8 area_code = GetAreaCode(area); + u8 id_ctr = config.IdGen(); + u8 hardware_model = GetHardwareModel(model); + + const EcWii& ec = EcWii::GetInstance(); + u32 HollywoodID = ec.GetNGID(); + u64 UserID = 0; + + s32 ret = NWC24MakeUserID(&UserID, HollywoodID, id_ctr, hardware_model, area_code); + config.SetId(UserID); + config.IncrementIdGen(); + config.SetCreationStage(NWC24::NWC24Config::NWC24_IDCS_GENERATED); + config.WriteConfig(); + + Memory::Write_U32(ret, request.buffer_out); + } + else + { + Memory::Write_U32(NWC24::WC24_ERR_FATAL, request.buffer_out); + } + } + else if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_GENERATED) + { + Memory::Write_U32(NWC24::WC24_ERR_ID_GENERATED, request.buffer_out); + } + else if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_REGISTERED) + { + Memory::Write_U32(NWC24::WC24_ERR_ID_REGISTERED, request.buffer_out); + } + Memory::Write_U64(config.Id(), request.buffer_out + 4); + Memory::Write_U32(config.CreationStage(), request.buffer_out + 0xC); + break; + + case IOCTL_NWC24_GET_SCHEDULAR_STAT: + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_GET_SCHEDULAR_STAT - NI"); + break; + + case IOCTL_NWC24_SAVE_MAIL_NOW: + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_SAVE_MAIL_NOW - NI"); + break; + + case IOCTL_NWC24_REQUEST_SHUTDOWN: + // if ya set the IOS version to a very high value this happens ... + INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_SHUTDOWN - NI"); + break; + + default: + request.Log(GetDeviceName(), LogTypes::IOS_WC24); + } + + return GetDefaultReply(return_value); +} + +u8 NetKDRequest::GetAreaCode(const std::string& area) const +{ + static std::map regions = { + {"JPN", 0}, {"USA", 1}, {"EUR", 2}, {"AUS", 2}, {"BRA", 1}, {"TWN", 3}, {"ROC", 3}, + {"KOR", 4}, {"HKG", 5}, {"ASI", 5}, {"LTN", 1}, {"SAF", 2}, {"CHN", 6}, + }; + + auto entryPos = regions.find(area); + if (entryPos != regions.end()) + return entryPos->second; + + return 7; // Unknown +} + +u8 NetKDRequest::GetHardwareModel(const std::string& model) const +{ + static std::map models = { + {"RVL", MODEL_RVL}, {"RVT", MODEL_RVT}, {"RVV", MODEL_RVV}, {"RVD", MODEL_RVD}, + }; + + auto entryPos = models.find(model); + if (entryPos != models.end()) + return entryPos->second; + + return MODEL_ELSE; +} + +static u8 u64_get_byte(u64 value, u8 shift) +{ + return (u8)(value >> (shift * 8)); +} + +static u64 u64_insert_byte(u64 value, u8 shift, u8 byte) +{ + u64 mask = 0x00000000000000FFULL << (shift * 8); + u64 inst = (u64)byte << (shift * 8); + return (value & ~mask) | inst; +} + +s32 NetKDRequest::NWC24MakeUserID(u64* nwc24_id, u32 hollywood_id, u16 id_ctr, u8 hardware_model, + u8 area_code) +{ + const u8 table2[8] = {0x1, 0x5, 0x0, 0x4, 0x2, 0x3, 0x6, 0x7}; + const u8 table1[16] = {0x4, 0xB, 0x7, 0x9, 0xF, 0x1, 0xD, 0x3, + 0xC, 0x2, 0x6, 0xE, 0x8, 0x0, 0xA, 0x5}; + + u64 mix_id = ((u64)area_code << 50) | ((u64)hardware_model << 47) | ((u64)hollywood_id << 15) | + ((u64)id_ctr << 10); + u64 mix_id_copy1 = mix_id; + + int ctr = 0; + for (ctr = 0; ctr <= 42; ctr++) + { + u64 value = mix_id >> (52 - ctr); + if (value & 1) + { + value = 0x0000000000000635ULL << (42 - ctr); + mix_id ^= value; + } + } + + mix_id = (mix_id_copy1 | (mix_id & 0xFFFFFFFFUL)) ^ 0x0000B3B3B3B3B3B3ULL; + mix_id = (mix_id >> 10) | ((mix_id & 0x3FF) << (11 + 32)); + + for (ctr = 0; ctr <= 5; ctr++) + { + u8 ret = u64_get_byte(mix_id, ctr); + u8 foobar = ((table1[(ret >> 4) & 0xF]) << 4) | (table1[ret & 0xF]); + mix_id = u64_insert_byte(mix_id, ctr, foobar & 0xff); + } + u64 mix_id_copy2 = mix_id; + + for (ctr = 0; ctr <= 5; ctr++) + { + u8 ret = u64_get_byte(mix_id_copy2, ctr); + mix_id = u64_insert_byte(mix_id, table2[ctr], ret); + } + + mix_id &= 0x001FFFFFFFFFFFFFULL; + mix_id = (mix_id << 1) | ((mix_id >> 52) & 1); + + mix_id ^= 0x00005E5E5E5E5E5EULL; + mix_id &= 0x001FFFFFFFFFFFFFULL; + + *nwc24_id = mix_id; + + if (mix_id > 9999999999999999ULL) + return NWC24::WC24_ERR_FATAL; + + return NWC24::WC24_OK; +} +} // namespace Device +} // namespace HLE +} // namespace IOS diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.h b/Source/Core/Core/IOS/Network/KD/NetKDRequest.h new file mode 100644 index 0000000000..eeb7c48b31 --- /dev/null +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.h @@ -0,0 +1,75 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "Common/CommonTypes.h" +#include "Core/IOS/Device.h" +#include "Core/IOS/Network/KD/NWC24Config.h" + +namespace IOS +{ +namespace HLE +{ +namespace Device +{ +// KD is the IOS module responsible for implementing WiiConnect24 functionality. +// It can perform HTTPS downloads, send and receive mail via SMTP, and execute a +// JavaScript-like language while the Wii is in standby mode. +class NetKDRequest : public Device +{ +public: + NetKDRequest(u32 device_id, const std::string& device_name); + ~NetKDRequest() override; + + IPCCommandResult IOCtl(const IOCtlRequest& request) override; + +private: + enum + { + IOCTL_NWC24_SUSPEND_SCHEDULAR = 0x01, + IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR = 0x02, + IOCTL_NWC24_EXEC_RESUME_SCHEDULAR = 0x03, + IOCTL_NWC24_KD_GET_TIME_TRIGGERS = 0x04, + IOCTL_NWC24_SET_SCHEDULE_SPAN = 0x05, + IOCTL_NWC24_STARTUP_SOCKET = 0x06, + IOCTL_NWC24_CLEANUP_SOCKET = 0x07, + IOCTL_NWC24_LOCK_SOCKET = 0x08, + IOCTL_NWC24_UNLOCK_SOCKET = 0x09, + IOCTL_NWC24_CHECK_MAIL_NOW = 0x0A, + IOCTL_NWC24_SEND_MAIL_NOW = 0x0B, + IOCTL_NWC24_RECEIVE_MAIL_NOW = 0x0C, + IOCTL_NWC24_SAVE_MAIL_NOW = 0x0D, + IOCTL_NWC24_DOWNLOAD_NOW_EX = 0x0E, + IOCTL_NWC24_REQUEST_GENERATED_USER_ID = 0x0F, + IOCTL_NWC24_REQUEST_REGISTER_USER_ID = 0x10, + IOCTL_NWC24_GET_SCHEDULAR_STAT = 0x1E, + IOCTL_NWC24_SET_FILTER_MODE = 0x1F, + IOCTL_NWC24_SET_DEBUG_MODE = 0x20, + IOCTL_NWC24_KD_SET_NEXT_WAKEUP = 0x21, + IOCTL_NWC24_SET_SCRIPT_MODE = 0x22, + IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28, + }; + + enum + { + MODEL_RVT = 0, + MODEL_RVV = 0, + MODEL_RVL = 1, + MODEL_RVD = 2, + MODEL_ELSE = 7 + }; + + u8 GetAreaCode(const std::string& area) const; + u8 GetHardwareModel(const std::string& model) const; + + s32 NWC24MakeUserID(u64* nwc24_id, u32 hollywood_id, u16 id_ctr, u8 hardware_model, u8 area_code); + + NWC24::NWC24Config config; +}; +} // namespace Device +} // namespace HLE +} // namespace IOS diff --git a/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp b/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp new file mode 100644 index 0000000000..9878755066 --- /dev/null +++ b/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp @@ -0,0 +1,77 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/IOS/Network/KD/NetKDTime.h" + +#include + +#include "Common/CommonTypes.h" +#include "Core/HW/EXI/EXI_DeviceIPL.h" +#include "Core/HW/Memmap.h" + +namespace IOS +{ +namespace HLE +{ +namespace Device +{ +NetKDTime::NetKDTime(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +{ +} + +NetKDTime::~NetKDTime() = default; + +IPCCommandResult NetKDTime::IOCtl(const IOCtlRequest& request) +{ + s32 result = 0; + u32 common_result = 0; + // TODO Writes stuff to /shared2/nwc24/misc.bin + // u32 update_misc = 0; + + switch (request.request) + { + case IOCTL_NW24_GET_UNIVERSAL_TIME: + Memory::Write_U64(GetAdjustedUTC(), request.buffer_out + 4); + break; + + case IOCTL_NW24_SET_UNIVERSAL_TIME: + SetAdjustedUTC(Memory::Read_U64(request.buffer_in)); + // update_misc = Memory::Read_U32(request.buffer_in + 8); + break; + + case IOCTL_NW24_SET_RTC_COUNTER: + rtc = Memory::Read_U32(request.buffer_in); + // update_misc = Memory::Read_U32(request.buffer_in + 4); + break; + + case IOCTL_NW24_GET_TIME_DIFF: + Memory::Write_U64(GetAdjustedUTC() - rtc, request.buffer_out + 4); + break; + + case IOCTL_NW24_UNIMPLEMENTED: + result = -9; + break; + + default: + ERROR_LOG(IOS_NET, "%s - unknown IOCtl: %x", GetDeviceName().c_str(), request.request); + break; + } + + // write return values + Memory::Write_U32(common_result, request.buffer_out); + return GetDefaultReply(result); +} + +u64 NetKDTime::GetAdjustedUTC() const +{ + return CEXIIPL::GetEmulatedTime(CEXIIPL::WII_EPOCH) + utcdiff; +} + +void NetKDTime::SetAdjustedUTC(u64 wii_utc) +{ + utcdiff = CEXIIPL::GetEmulatedTime(CEXIIPL::WII_EPOCH) - wii_utc; +} +} // namespace Device +} // namespace HLE +} // namespace IOS diff --git a/Source/Core/Core/IOS/Network/KD/NetKDTime.h b/Source/Core/Core/IOS/Network/KD/NetKDTime.h new file mode 100644 index 0000000000..04cce2d68f --- /dev/null +++ b/Source/Core/Core/IOS/Network/KD/NetKDTime.h @@ -0,0 +1,53 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "Common/CommonTypes.h" +#include "Core/IOS/Device.h" + +namespace IOS +{ +namespace HLE +{ +namespace Device +{ +class NetKDTime : public Device +{ +public: + NetKDTime(u32 device_id, const std::string& device_name); + ~NetKDTime() override; + + IPCCommandResult IOCtl(const IOCtlRequest& request) override; + +private: + // TODO: depending on CEXIIPL is a hack which I don't feel like + // removing because the function itself is pretty hackish; + // wait until I re-port my netplay rewrite + + // Returns seconds since Wii epoch + // +/- any bias set from IOCTL_NW24_SET_UNIVERSAL_TIME + u64 GetAdjustedUTC() const; + + // Store the difference between what the Wii thinks is UTC and + // what the host OS thinks + void SetAdjustedUTC(u64 wii_utc); + + enum + { + IOCTL_NW24_GET_UNIVERSAL_TIME = 0x14, + IOCTL_NW24_SET_UNIVERSAL_TIME = 0x15, + IOCTL_NW24_UNIMPLEMENTED = 0x16, + IOCTL_NW24_SET_RTC_COUNTER = 0x17, + IOCTL_NW24_GET_TIME_DIFF = 0x18, + }; + + u64 rtc = 0; + s64 utcdiff = 0; +}; +} // namespace Device +} // namespace HLE +} // namespace IOS diff --git a/Source/Core/Core/IOS/Network/Net.cpp b/Source/Core/Core/IOS/Network/Net.cpp index a8754b2d37..f080079b12 100644 --- a/Source/Core/Core/IOS/Network/Net.cpp +++ b/Source/Core/Core/IOS/Network/Net.cpp @@ -2,12 +2,13 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "Core/IOS/Network/Net.h" + #include #include #include #include #include -#include #include #include #include @@ -19,19 +20,15 @@ #include "Common/Assert.h" #include "Common/CommonFuncs.h" -#include "Common/CommonPaths.h" -#include "Common/FileUtil.h" +#include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Common/NandPaths.h" #include "Common/Network.h" -#include "Common/SettingsHandler.h" #include "Common/StringUtil.h" #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/HW/Memmap.h" #include "Core/IOS/Network/ICMP.h" -#include "Core/IOS/Network/Net.h" #include "Core/IOS/Network/Socket.h" -#include "Core/ec_wii.h" #ifdef _WIN32 #include @@ -65,226 +62,6 @@ namespace HLE { namespace Device { -// ********************************************************************************** -// Handle /dev/net/kd/request requests -NetKDRequest::NetKDRequest(u32 device_id, const std::string& device_name) - : Device(device_id, device_name) -{ -} - -NetKDRequest::~NetKDRequest() -{ - WiiSockMan::GetInstance().Clean(); -} - -IPCCommandResult NetKDRequest::IOCtl(const IOCtlRequest& request) -{ - s32 return_value = 0; - switch (request.request) - { - case IOCTL_NWC24_SUSPEND_SCHEDULAR: - // NWC24iResumeForCloseLib from NWC24SuspendScheduler (Input: none, Output: 32 bytes) - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_SUSPEND_SCHEDULAR - NI"); - Memory::Write_U32(0, request.buffer_out); // no error - break; - - case IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR: // NWC24iResumeForCloseLib - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR - NI"); - break; - - case IOCTL_NWC24_EXEC_RESUME_SCHEDULAR: // NWC24iResumeForCloseLib - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_EXEC_RESUME_SCHEDULAR - NI"); - Memory::Write_U32(0, request.buffer_out); // no error - break; - - case IOCTL_NWC24_STARTUP_SOCKET: // NWC24iStartupSocket - Memory::Write_U32(0, request.buffer_out); - Memory::Write_U32(0, request.buffer_out + 4); - return_value = 0; - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI"); - break; - - case IOCTL_NWC24_CLEANUP_SOCKET: - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_CLEANUP_SOCKET - NI"); - break; - - case IOCTL_NWC24_LOCK_SOCKET: // WiiMenu - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_LOCK_SOCKET - NI"); - break; - - case IOCTL_NWC24_UNLOCK_SOCKET: - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_UNLOCK_SOCKET - NI"); - break; - - case IOCTL_NWC24_REQUEST_REGISTER_USER_ID: - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_REGISTER_USER_ID"); - Memory::Write_U32(0, request.buffer_out); - Memory::Write_U32(0, request.buffer_out + 4); - break; - - case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes) - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_GENERATED_USER_ID"); - if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_INITIAL) - { - const std::string settings_file_path( - Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_SETTING); - SettingsHandler gen; - std::string area, model; - bool got_settings = false; - - if (File::Exists(settings_file_path) && gen.Open(settings_file_path)) - { - area = gen.GetValue("AREA"); - model = gen.GetValue("MODEL"); - got_settings = true; - } - if (got_settings) - { - u8 area_code = GetAreaCode(area); - u8 id_ctr = config.IdGen(); - u8 hardware_model = GetHardwareModel(model); - - const EcWii& ec = EcWii::GetInstance(); - u32 HollywoodID = ec.GetNGID(); - u64 UserID = 0; - - s32 ret = NWC24MakeUserID(&UserID, HollywoodID, id_ctr, hardware_model, area_code); - config.SetId(UserID); - config.IncrementIdGen(); - config.SetCreationStage(NWC24::NWC24Config::NWC24_IDCS_GENERATED); - config.WriteConfig(); - - Memory::Write_U32(ret, request.buffer_out); - } - else - { - Memory::Write_U32(NWC24::WC24_ERR_FATAL, request.buffer_out); - } - } - else if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_GENERATED) - { - Memory::Write_U32(NWC24::WC24_ERR_ID_GENERATED, request.buffer_out); - } - else if (config.CreationStage() == NWC24::NWC24Config::NWC24_IDCS_REGISTERED) - { - Memory::Write_U32(NWC24::WC24_ERR_ID_REGISTERED, request.buffer_out); - } - Memory::Write_U64(config.Id(), request.buffer_out + 4); - Memory::Write_U32(config.CreationStage(), request.buffer_out + 0xC); - break; - - case IOCTL_NWC24_GET_SCHEDULAR_STAT: - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_GET_SCHEDULAR_STAT - NI"); - break; - - case IOCTL_NWC24_SAVE_MAIL_NOW: - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_SAVE_MAIL_NOW - NI"); - break; - - case IOCTL_NWC24_REQUEST_SHUTDOWN: - // if ya set the IOS version to a very high value this happens ... - INFO_LOG(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_SHUTDOWN - NI"); - break; - - default: - request.Log(GetDeviceName(), LogTypes::IOS_WC24); - } - - return GetDefaultReply(return_value); -} - -u8 NetKDRequest::GetAreaCode(const std::string& area) const -{ - static std::map regions = { - {"JPN", 0}, {"USA", 1}, {"EUR", 2}, {"AUS", 2}, {"BRA", 1}, {"TWN", 3}, {"ROC", 3}, - {"KOR", 4}, {"HKG", 5}, {"ASI", 5}, {"LTN", 1}, {"SAF", 2}, {"CHN", 6}, - }; - - auto entryPos = regions.find(area); - if (entryPos != regions.end()) - return entryPos->second; - else - return 7; // Unknown -} - -u8 NetKDRequest::GetHardwareModel(const std::string& model) const -{ - static std::map models = { - {"RVL", MODEL_RVL}, {"RVT", MODEL_RVT}, {"RVV", MODEL_RVV}, {"RVD", MODEL_RVD}, - }; - - auto entryPos = models.find(model); - if (entryPos != models.end()) - return entryPos->second; - else - return MODEL_ELSE; -} - -static inline u8 u64_get_byte(u64 value, u8 shift) -{ - return (u8)(value >> (shift * 8)); -} - -static inline u64 u64_insert_byte(u64 value, u8 shift, u8 byte) -{ - u64 mask = 0x00000000000000FFULL << (shift * 8); - u64 inst = (u64)byte << (shift * 8); - return (value & ~mask) | inst; -} - -s32 NetKDRequest::NWC24MakeUserID(u64* nwc24_id, u32 hollywood_id, u16 id_ctr, u8 hardware_model, - u8 area_code) -{ - const u8 table2[8] = {0x1, 0x5, 0x0, 0x4, 0x2, 0x3, 0x6, 0x7}; - const u8 table1[16] = {0x4, 0xB, 0x7, 0x9, 0xF, 0x1, 0xD, 0x3, - 0xC, 0x2, 0x6, 0xE, 0x8, 0x0, 0xA, 0x5}; - - u64 mix_id = ((u64)area_code << 50) | ((u64)hardware_model << 47) | ((u64)hollywood_id << 15) | - ((u64)id_ctr << 10); - u64 mix_id_copy1 = mix_id; - - int ctr = 0; - for (ctr = 0; ctr <= 42; ctr++) - { - u64 value = mix_id >> (52 - ctr); - if (value & 1) - { - value = 0x0000000000000635ULL << (42 - ctr); - mix_id ^= value; - } - } - - mix_id = (mix_id_copy1 | (mix_id & 0xFFFFFFFFUL)) ^ 0x0000B3B3B3B3B3B3ULL; - mix_id = (mix_id >> 10) | ((mix_id & 0x3FF) << (11 + 32)); - - for (ctr = 0; ctr <= 5; ctr++) - { - u8 ret = u64_get_byte(mix_id, ctr); - u8 foobar = ((table1[(ret >> 4) & 0xF]) << 4) | (table1[ret & 0xF]); - mix_id = u64_insert_byte(mix_id, ctr, foobar & 0xff); - } - u64 mix_id_copy2 = mix_id; - - for (ctr = 0; ctr <= 5; ctr++) - { - u8 ret = u64_get_byte(mix_id_copy2, ctr); - mix_id = u64_insert_byte(mix_id, table2[ctr], ret); - } - - mix_id &= 0x001FFFFFFFFFFFFFULL; - mix_id = (mix_id << 1) | ((mix_id >> 52) & 1); - - mix_id ^= 0x00005E5E5E5E5E5EULL; - mix_id &= 0x001FFFFFFFFFFFFFULL; - - *nwc24_id = mix_id; - - if (mix_id > 9999999999999999ULL) - return NWC24::WC24_ERR_FATAL; - - return NWC24::WC24_OK; -} - static void SaveMacAddress(u8* mac) { SConfig::GetInstance().m_WirelessMac = Common::MacAddressToString(mac); diff --git a/Source/Core/Core/IOS/Network/Net.h b/Source/Core/Core/IOS/Network/Net.h index 0ab06deb90..672ec6d3b5 100644 --- a/Source/Core/Core/IOS/Network/Net.h +++ b/Source/Core/Core/IOS/Network/Net.h @@ -7,13 +7,9 @@ #include #include "Common/CommonTypes.h" -#include "Common/Logging/Log.h" -#include "Core/HW/EXI/EXI_DeviceIPL.h" -#include "Core/HW/Memmap.h" #include "Core/IOS/Device.h" #include "Core/IOS/IPC.h" #include "Core/IOS/Network/Config.h" -#include "Core/IOS/Network/NWC24Config.h" #ifdef _WIN32 #include @@ -65,143 +61,6 @@ enum NET_IOCTL // TODO: split this up. namespace Device { -////////////////////////////////////////////////////////////////////////// -// KD is the IOS module responsible for implementing WiiConnect24 functionality. -// It can perform HTTPS downloads, send and receive mail via SMTP, and execute a -// JavaScript-like language while the Wii is in standby mode. -class NetKDRequest : public Device -{ -public: - NetKDRequest(u32 device_id, const std::string& device_name); - - virtual ~NetKDRequest(); - - IPCCommandResult IOCtl(const IOCtlRequest& request) override; - -private: - enum - { - IOCTL_NWC24_SUSPEND_SCHEDULAR = 0x01, - IOCTL_NWC24_EXEC_TRY_SUSPEND_SCHEDULAR = 0x02, - IOCTL_NWC24_EXEC_RESUME_SCHEDULAR = 0x03, - IOCTL_NWC24_KD_GET_TIME_TRIGGERS = 0x04, - IOCTL_NWC24_SET_SCHEDULE_SPAN = 0x05, - IOCTL_NWC24_STARTUP_SOCKET = 0x06, - IOCTL_NWC24_CLEANUP_SOCKET = 0x07, - IOCTL_NWC24_LOCK_SOCKET = 0x08, - IOCTL_NWC24_UNLOCK_SOCKET = 0x09, - IOCTL_NWC24_CHECK_MAIL_NOW = 0x0A, - IOCTL_NWC24_SEND_MAIL_NOW = 0x0B, - IOCTL_NWC24_RECEIVE_MAIL_NOW = 0x0C, - IOCTL_NWC24_SAVE_MAIL_NOW = 0x0D, - IOCTL_NWC24_DOWNLOAD_NOW_EX = 0x0E, - IOCTL_NWC24_REQUEST_GENERATED_USER_ID = 0x0F, - IOCTL_NWC24_REQUEST_REGISTER_USER_ID = 0x10, - IOCTL_NWC24_GET_SCHEDULAR_STAT = 0x1E, - IOCTL_NWC24_SET_FILTER_MODE = 0x1F, - IOCTL_NWC24_SET_DEBUG_MODE = 0x20, - IOCTL_NWC24_KD_SET_NEXT_WAKEUP = 0x21, - IOCTL_NWC24_SET_SCRIPT_MODE = 0x22, - IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28, - }; - - enum - { - MODEL_RVT = 0, - MODEL_RVV = 0, - MODEL_RVL = 1, - MODEL_RVD = 2, - MODEL_ELSE = 7 - }; - - u8 GetAreaCode(const std::string& area) const; - u8 GetHardwareModel(const std::string& model) const; - - s32 NWC24MakeUserID(u64* nwc24_id, u32 hollywood_id, u16 id_ctr, u8 hardware_model, u8 area_code); - - NWC24::NWC24Config config; -}; - -////////////////////////////////////////////////////////////////////////// -class NetKDTime : public Device -{ -public: - NetKDTime(u32 device_id, const std::string& device_name) - : Device(device_id, device_name), rtc(), utcdiff() - { - } - - virtual ~NetKDTime() {} - IPCCommandResult IOCtl(const IOCtlRequest& request) override - { - s32 result = 0; - u32 common_result = 0; - // TODO Writes stuff to /shared2/nwc24/misc.bin - // u32 update_misc = 0; - - switch (request.request) - { - case IOCTL_NW24_GET_UNIVERSAL_TIME: - Memory::Write_U64(GetAdjustedUTC(), request.buffer_out + 4); - break; - - case IOCTL_NW24_SET_UNIVERSAL_TIME: - SetAdjustedUTC(Memory::Read_U64(request.buffer_in)); - // update_misc = Memory::Read_U32(request.buffer_in + 8); - break; - - case IOCTL_NW24_SET_RTC_COUNTER: - rtc = Memory::Read_U32(request.buffer_in); - // update_misc = Memory::Read_U32(request.buffer_in + 4); - break; - - case IOCTL_NW24_GET_TIME_DIFF: - Memory::Write_U64(GetAdjustedUTC() - rtc, request.buffer_out + 4); - break; - - case IOCTL_NW24_UNIMPLEMENTED: - result = -9; - break; - - default: - ERROR_LOG(IOS_NET, "%s - unknown IOCtl: %x", GetDeviceName().c_str(), request.request); - break; - } - - // write return values - Memory::Write_U32(common_result, request.buffer_out); - return GetDefaultReply(result); - } - -private: - enum - { - IOCTL_NW24_GET_UNIVERSAL_TIME = 0x14, - IOCTL_NW24_SET_UNIVERSAL_TIME = 0x15, - IOCTL_NW24_UNIMPLEMENTED = 0x16, - IOCTL_NW24_SET_RTC_COUNTER = 0x17, - IOCTL_NW24_GET_TIME_DIFF = 0x18, - }; - - u64 rtc; - s64 utcdiff; - - // TODO: depending on CEXIIPL is a hack which I don't feel like - // removing because the function itself is pretty hackish; - // wait until I re-port my netplay rewrite - - // Returns seconds since Wii epoch - // +/- any bias set from IOCTL_NW24_SET_UNIVERSAL_TIME - u64 GetAdjustedUTC() const { return CEXIIPL::GetEmulatedTime(CEXIIPL::WII_EPOCH) + utcdiff; } - // Store the difference between what the Wii thinks is UTC and - // what the host OS thinks - void SetAdjustedUTC(u64 wii_utc) - { - utcdiff = CEXIIPL::GetEmulatedTime(CEXIIPL::WII_EPOCH) - wii_utc; - } -}; - -////////////////////////////////////////////////////////////////////////// class NetIPTop : public Device { public: