From dcf3ece8f41bfa134212499ee0091c56a541d51f Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 12 Mar 2021 14:32:33 +0700 Subject: [PATCH] Implement NP Signin Dialog (faked signin) --- CMakeLists.txt | 2 + Core/Core.vcxproj | 2 + Core/Core.vcxproj.filters | 6 + Core/Dialog/PSPNpSigninDialog.cpp | 349 ++++++++++++++++++++++++++++ Core/Dialog/PSPNpSigninDialog.h | 67 ++++++ Core/HLE/sceUtility.cpp | 49 +++- Core/HLE/sceUtility.h | 1 + UWP/CoreUWP/CoreUWP.vcxproj | 2 + UWP/CoreUWP/CoreUWP.vcxproj.filters | 6 + android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 11 files changed, 481 insertions(+), 5 deletions(-) create mode 100644 Core/Dialog/PSPNpSigninDialog.cpp create mode 100644 Core/Dialog/PSPNpSigninDialog.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d4b2fdc24207..8fe807763f5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1709,6 +1709,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Dialog/PSPMsgDialog.h Core/Dialog/PSPNetconfDialog.cpp Core/Dialog/PSPNetconfDialog.h + Core/Dialog/PSPNpSigninDialog.cpp + Core/Dialog/PSPNpSigninDialog.h Core/Dialog/PSPOskDialog.cpp Core/Dialog/PSPOskDialog.h Core/Dialog/PSPPlaceholderDialog.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 05bdb72eaef5..bb5688fb30b1 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -572,6 +572,7 @@ + @@ -1118,6 +1119,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index e7a1ff33e286..8fc7db771d31 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -523,6 +523,9 @@ Dialog + + Dialog + Debugger @@ -1597,6 +1600,9 @@ Dialog + + Dialog + MIPS\JitCommon diff --git a/Core/Dialog/PSPNpSigninDialog.cpp b/Core/Dialog/PSPNpSigninDialog.cpp new file mode 100644 index 000000000000..f6621db66c22 --- /dev/null +++ b/Core/Dialog/PSPNpSigninDialog.cpp @@ -0,0 +1,349 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#if defined(_WIN32) +#include "Common/CommonWindows.h" +#endif +#include +#include "Common/Data/Text/I18n.h" +#include "Common/Serialize/Serializer.h" +#include "Common/Serialize/SerializeFuncs.h" +#include "Core/Config.h" +#include "Core/MemMapHelpers.h" +#include "Core/Util/PPGeDraw.h" +#include "Core/HLE/sceKernelMemory.h" +#include "Core/HLE/sceCtrl.h" +#include "Core/HLE/sceUtility.h" +#include "Core/HLE/sceNet.h" +#include "Core/HLE/sceNetAdhoc.h" +#include "Core/HLE/sceNp.h" +#include "Core/Dialog/PSPNpSigninDialog.h" +#include "Common/Data/Encoding/Utf8.h" +#include "Core/Reporting.h" + + +static const float FONT_SCALE = 0.65f; + +// Needs testing. +const static int NP_INIT_DELAY_US = 200000; +const static int NP_SHUTDOWN_DELAY_US = 501000; +const static int NP_RUNNING_DELAY_US = 1000000; // faked delay to simulate signin process to give chance for players to read the text on the dialog + +PSPNpSigninDialog::PSPNpSigninDialog(UtilityDialogType type) : PSPDialog(type) { +} + +PSPNpSigninDialog::~PSPNpSigninDialog() { +} + +int PSPNpSigninDialog::Init(u32 paramAddr) { + // Already running + if (ReadStatus() != SCE_UTILITY_STATUS_NONE) + return SCE_ERROR_UTILITY_INVALID_STATUS; + + requestAddr = paramAddr; + int size = Memory::Read_U32(paramAddr); + memset(&request, 0, sizeof(request)); + // Only copy the right size to support different request format + Memory::Memcpy(&request, paramAddr, size); + + WARN_LOG_REPORT_ONCE(PSPNpSigninDialogInit, SCENET, "NpSignin Init Params: %08x, %08x, %08x, %08x", request.npSigninStatus, request.unknown1, request.unknown2, request.unknown3); + + ChangeStatusInit(NP_INIT_DELAY_US); + + // Eat any keys pressed before the dialog inited. + UpdateButtons(); + okButtonImg = ImageID("I_CIRCLE"); + cancelButtonImg = ImageID("I_CROSS"); + okButtonFlag = CTRL_CIRCLE; + cancelButtonFlag = CTRL_CROSS; + if (request.common.buttonSwap == 1) + { + okButtonImg = ImageID("I_CROSS"); + cancelButtonImg = ImageID("I_CIRCLE"); + okButtonFlag = CTRL_CROSS; + cancelButtonFlag = CTRL_CIRCLE; + } + + //npSigninResult = -1; + startTime = (u64)(time_now_d() * 1000000.0); + step = 0; + + StartFade(true); + return 0; +} + +void PSPNpSigninDialog::DrawBanner() { + + PPGeDrawRect(0, 0, 480, 22, CalcFadedColor(0x65636358)); + + PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f); + textStyle.hasShadow = false; + + // TODO: Draw a hexagon icon + PPGeDrawImage(10, 5, 11.0f, 10.0f, 1, 10, 1, 10, 10, 10, FadedImageStyle()); + auto di = GetI18NCategory("Dialog"); + PPGeDrawText(di->T("Sign In"), 31, 10, textStyle); +} + +void PSPNpSigninDialog::DrawIndicator() { + // TODO: Draw animated circle as processing indicator + PPGeDrawImage(456, 248, 20.0f, 20.0f, 1, 10, 1, 10, 10, 10, FadedImageStyle()); +} + +void PSPNpSigninDialog::DrawLogo() { + // TODO: Draw OpenDNAS logo + PPGeDrawImage(416, 22, 64.0f, 64.0f, 1, 10, 1, 10, 64, 64, FadedImageStyle()); +} + +void PSPNpSigninDialog::DisplayMessage(std::string text1, std::string text2a, std::string text2b, std::string text3a, std::string text3b, bool hasYesNo, bool hasOK) { + auto di = GetI18NCategory("Dialog"); + + PPGeStyle buttonStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE); + PPGeStyle messageStyle = FadedStyle(PPGeAlign::BOX_HCENTER, FONT_SCALE); + PPGeStyle messageStyleRight = FadedStyle(PPGeAlign::BOX_RIGHT, FONT_SCALE); + PPGeStyle messageStyleLeft = FadedStyle(PPGeAlign::BOX_LEFT, FONT_SCALE); + + std::string text2 = text2a + " " + text2b; + std::string text3 = text3a + " " + text3b; + + // Without the scrollbar, we have 350 total pixels. + float WRAP_WIDTH = 300.0f; + if (UTF8StringNonASCIICount(text1.c_str()) >= (int)text1.size() / 4) { + WRAP_WIDTH = 336.0f; + if (text1.size() > 12) { + messageStyle.scale = 0.6f; + } + } + + float totalHeight1 = 0.0f; + PPGeMeasureText(nullptr, &totalHeight1, text1.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); + float totalHeight2 = 0.0f; + if (text2 != " ") + PPGeMeasureText(nullptr, &totalHeight2, text2.c_str(), FONT_SCALE, PPGE_LINE_USE_ELLIPSIS, WRAP_WIDTH); + float totalHeight3 = 0.0f; + if (text3 != " ") + PPGeMeasureText(nullptr, &totalHeight3, text3.c_str(), FONT_SCALE, PPGE_LINE_USE_ELLIPSIS, WRAP_WIDTH); + float marginTop = 0.0f; + if (text2 != " " || text3 != " ") + marginTop = 11.0f; + float totalHeight = totalHeight1 + totalHeight2 + totalHeight3 + marginTop; + // The PSP normally only shows about 8 lines at a time. + // For improved UX, we intentionally show part of the next line. + float visibleHeight = std::min(totalHeight, 175.0f); + float h2 = visibleHeight / 2.0f; + + float centerY = 135.0f; + float sy = centerY - h2 - 15.0f; + float ey = centerY + h2 + 20.0f; + float buttonY = centerY + h2 + 5.0f; + + auto drawSelectionBoxAndAdjust = [&](float x) { + // Box has a fixed size. + float w = 15.0f; + float h = 8.0f; + PPGeDrawRect(x - w, buttonY - h, x + w, buttonY + h, CalcFadedColor(0x6DCFCFCF)); + + centerY -= h + 5.0f; + sy -= h + 5.0f; + ey = buttonY + h * 2.0f + 5.0f; + }; + + if (hasYesNo) { + if (yesnoChoice == 1) { + drawSelectionBoxAndAdjust(204.0f); + } + else { + drawSelectionBoxAndAdjust(273.0f); + } + + PPGeDrawText(di->T("Yes"), 203.0f, buttonY - 1.0f, buttonStyle); + PPGeDrawText(di->T("No"), 272.0f, buttonY - 1.0f, buttonStyle); + if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) { + yesnoChoice = 1; + } + else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) { + yesnoChoice = 0; + } + buttonY += 8.0f + 5.0f; + } + + if (hasOK) { + drawSelectionBoxAndAdjust(240.0f); + + PPGeDrawText(di->T("OK"), 239.0f, buttonY - 1.0f, buttonStyle); + buttonY += 8.0f + 5.0f; + } + + PPGeScissor(0, (int)(centerY - h2 - 2), 480, (int)(centerY + h2 + 2)); + PPGeDrawTextWrapped(text1.c_str(), 240.0f, centerY - h2 - scrollPos_, WRAP_WIDTH, 0, messageStyle); + if (text2a != "") { + if (text2b != "") + PPGeDrawTextWrapped(text2a.c_str(), 240.0f - 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyleRight); + else + PPGeDrawTextWrapped(text2a.c_str(), 240.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyle); + } + if (text2b != "") + PPGeDrawTextWrapped(text2b.c_str(), 240.0f + 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyleLeft); + if (text3a != "") { + if (text3b != "") + PPGeDrawTextWrapped(text3a.c_str(), 240.0f - 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyleRight); + else + PPGeDrawTextWrapped(text3a.c_str(), 240.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyle); + } + if (text3b != "") + PPGeDrawTextWrapped(text3b.c_str(), 240.0f + 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyleLeft); + PPGeScissorReset(); + + // Do we need a scrollbar? + if (visibleHeight < totalHeight) { + float scrollSpeed = 5.0f; + float scrollMax = totalHeight - visibleHeight; + + float bobHeight = (visibleHeight / totalHeight) * visibleHeight; + float bobOffset = (scrollPos_ / scrollMax) * (visibleHeight - bobHeight); + float bobY1 = centerY - h2 + bobOffset; + PPGeDrawRect(415.0f, bobY1, 420.0f, bobY1 + bobHeight, CalcFadedColor(0xFFCCCCCC)); + + auto buttonDown = [this](int btn, int& held) { + if (IsButtonPressed(btn)) { + held = 0; + return true; + } + return IsButtonHeld(btn, held, 1, 1); + }; + if (buttonDown(CTRL_DOWN, framesDownHeld_) && scrollPos_ < scrollMax) { + scrollPos_ = std::min(scrollMax, scrollPos_ + scrollSpeed); + } + if (buttonDown(CTRL_UP, framesUpHeld_) && scrollPos_ > 0.0f) { + scrollPos_ = std::max(0.0f, scrollPos_ - scrollSpeed); + } + } + + PPGeDrawRect(60.0f, sy, 420.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawRect(60.0f, ey, 420.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); +} + +int PSPNpSigninDialog::Update(int animSpeed) { + if (ReadStatus() != SCE_UTILITY_STATUS_RUNNING) { + return SCE_ERROR_UTILITY_INVALID_STATUS; + } + + UpdateButtons(); + auto di = GetI18NCategory("Dialog"); + auto err = GetI18NCategory("Error"); + u64 now = (u64)(time_now_d() * 1000000.0); + + if (request.npSigninStatus == NP_SIGNIN_STATUS_NONE) { + UpdateFade(animSpeed); + StartDraw(); + + PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0xC0C8B2AC)); + DrawBanner(); + DrawIndicator(); + + // TODO: Not sure what should happen here.. may be something like this https://pastebin.com/1eW48zBb ? but we can do test on Open DNAS Server later https://dnas.hashsploit.net/us-gw/ + // DNAS dialog + if (step >= 2 && now - startTime > NP_RUNNING_DELAY_US) { + DrawLogo(); + DisplayMessage(di->T("PleaseWait", "Please wait...")); + step++; + } + // Signin dialog + else { + // Skipping the Select Connection screen since we only have 1 fake profile + DisplayMessage(di->T("SigninPleaseWait", "Signing in...\nPlease wait.")); + } + DisplayButtons(DS_BUTTON_CANCEL, di->T("Cancel")); + + if (step >= 2 && now - startTime > NP_RUNNING_DELAY_US*2) { + if (pendingStatus != SCE_UTILITY_STATUS_FINISHED) { + StartFade(false); + ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NP_SHUTDOWN_DELAY_US); + step++; + } + } + + else if (step == 1 && now - startTime > NP_RUNNING_DELAY_US) { + // Switch to the next message (with DNAS logo) + StartFade(true); + step++; + } + + else if (step == 0) { + /*if (npAuthResult < 0 && request.NpSigninData.IsValid()) { + npAuthResult = sceNpAuthCreateStartRequest(request.NpSigninData->paramAddr); + }*/ + step++; + } + + if (/*npAuthResult >= 0 &&*/ IsButtonPressed(cancelButtonFlag)) { + StartFade(false); + //sceNpAuthAbortRequest(npAuthResult); + //sceNpAuthDestroyRequest(npAuthResult); + ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NP_SHUTDOWN_DELAY_US); + request.common.result = SCE_UTILITY_DIALOG_RESULT_ABORT; + request.npSigninStatus = NP_SIGNIN_STATUS_CANCELED; + //step = 0; + } + + EndDraw(); + } + + if (ReadStatus() == SCE_UTILITY_STATUS_FINISHED || pendingStatus == SCE_UTILITY_STATUS_FINISHED) { + npSigninState = NP_SIGNIN_STATUS_SUCCESS; + __RtcTimeOfDay(&npSigninTimestamp); + request.npSigninStatus = npSigninState; + } + return 0; +} + +int PSPNpSigninDialog::Shutdown(bool force) { + if (ReadStatus() != SCE_UTILITY_STATUS_FINISHED && !force) + return SCE_ERROR_UTILITY_INVALID_STATUS; + + PSPDialog::Shutdown(force); + if (!force) { + ChangeStatusShutdown(NP_SHUTDOWN_DELAY_US); + } + + // FIXME: This should probably be done within FinishShutdown to prevent some games (ie. UNO) from progressing further while the Dialog is still being faded-out, since we can't override non-virtual method... so here is the closes one to FinishShutdown. + if (Memory::IsValidAddress(requestAddr)) // Need to validate first to prevent Invalid address when the game is being Shutdown/Exited to menu + Memory::Memcpy(requestAddr, &request, request.common.size, "NpSigninDialogParam"); + + return 0; +} + +void PSPNpSigninDialog::DoState(PointerWrap &p) { + PSPDialog::DoState(p); + + auto s = p.Section("PSPNpSigninDialog", 1, 1); + if (!s) + return; + + Do(p, request); + Do(p, step); + //Do(p, npSigninResult); + + if (p.mode == p.MODE_READ) { + startTime = 0; + } +} + +pspUtilityDialogCommon* PSPNpSigninDialog::GetCommonParam() +{ + return &request.common; +} diff --git a/Core/Dialog/PSPNpSigninDialog.h b/Core/Dialog/PSPNpSigninDialog.h new file mode 100644 index 000000000000..15aac7b0c956 --- /dev/null +++ b/Core/Dialog/PSPNpSigninDialog.h @@ -0,0 +1,67 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "Core/Dialog/PSPDialog.h" +#include "Core/MemMapHelpers.h" + + +struct SceUtilityNpSigninParam { + pspUtilityDialogCommon common; + // Initially all zero? Or is there a possibility for one of these unknown to be a buffer to a packet data if it wasn't null? + int npSigninStatus; + int unknown1; + int unknown2; + int unknown3; +}; + + +class PSPNpSigninDialog: public PSPDialog { +public: + PSPNpSigninDialog(UtilityDialogType type); + virtual ~PSPNpSigninDialog(); + + virtual int Init(u32 paramAddr); + virtual int Update(int animSpeed) override; + virtual int Shutdown(bool force = false) override; + virtual void DoState(PointerWrap &p) override; + virtual pspUtilityDialogCommon* GetCommonParam() override; + +protected: + bool UseAutoStatus() override { + return false; + } + +private: + void DisplayMessage(std::string text1, std::string text2a = "", std::string text2b = "", std::string text3a = "", std::string text3b = "", bool hasYesNo = false, bool hasOK = false); + void DrawBanner(); + void DrawIndicator(); + void DrawLogo(); + + SceUtilityNpSigninParam request = {}; + u32 requestAddr = 0; + //int npSigninResult = -1; + + int yesnoChoice = 0; + float scrollPos_ = 0.0f; + int framesUpHeld_ = 0; + int framesDownHeld_ = 0; + + u64 startTime = 0; + int step = 0; +}; diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index c5bdde62f8a5..e6a512460079 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -47,6 +47,7 @@ #include "Core/Dialog/PSPOskDialog.h" #include "Core/Dialog/PSPGamedataInstallDialog.h" #include "Core/Dialog/PSPNetconfDialog.h" +#include "Core/Dialog/PSPNpSigninDialog.h" #include "Core/Dialog/PSPScreenshotDialog.h" #define PSP_AV_MODULE_AVCODEC 0 @@ -132,6 +133,7 @@ static PSPOskDialog *oskDialog; static PSPNetconfDialog *netDialog; static PSPScreenshotDialog *screenshotDialog; static PSPGamedataInstallDialog *gamedataInstallDialog; +static PSPNpSigninDialog *npSigninDialog; static int oldStatus = -1; static std::map currentlyLoadedModules; @@ -195,6 +197,8 @@ static PSPDialog *CurrentDialog(UtilityDialogType type) { break; case UtilityDialogType::GAMEDATAINSTALL: return gamedataInstallDialog; + case UtilityDialogType::NPSIGNIN: + return npSigninDialog; } return nullptr; } @@ -212,6 +216,7 @@ void __UtilityInit() { netDialog = new PSPNetconfDialog(UtilityDialogType::NET); screenshotDialog = new PSPScreenshotDialog(UtilityDialogType::SCREENSHOT); gamedataInstallDialog = new PSPGamedataInstallDialog(UtilityDialogType::GAMEDATAINSTALL); + npSigninDialog = new PSPNpSigninDialog(UtilityDialogType::NPSIGNIN); currentDialogType = UtilityDialogType::NONE; DeactivateDialog(); @@ -221,7 +226,7 @@ void __UtilityInit() { } void __UtilityDoState(PointerWrap &p) { - auto s = p.Section("sceUtility", 1, 5); + auto s = p.Section("sceUtility", 1, 6); if (!s) { return; } @@ -267,6 +272,10 @@ void __UtilityDoState(PointerWrap &p) { if (s >= 5) Do(p, accessThreadFinished); + if (s >= 6) { + npSigninDialog->DoState(p); + } + if (!hasAccessThread && accessThread) { accessThread->Forget(); delete accessThread; @@ -282,6 +291,7 @@ void __UtilityShutdown() { netDialog->Shutdown(true); screenshotDialog->Shutdown(true); gamedataInstallDialog->Shutdown(true); + npSigninDialog->Shutdown(true); if (accessThread) { delete accessThread; @@ -296,6 +306,7 @@ void __UtilityShutdown() { delete netDialog; delete screenshotDialog; delete gamedataInstallDialog; + delete npSigninDialog; } void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority) { @@ -884,15 +895,43 @@ static u32 sceUtilityUnloadNetModule(u32 module) } static int sceUtilityNpSigninInitStart(u32 paramsPtr) { - return hleLogError(SCEUTILITY, 0, "not implemented"); + if (currentDialogActive && currentDialogType != UtilityDialogType::NPSIGNIN) { + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); + } + + ActivateDialog(UtilityDialogType::NPSIGNIN); + return hleLogSuccessInfoI(SCEUTILITY, npSigninDialog->Init(paramsPtr)); +} + +static int sceUtilityNpSigninShutdownStart() { + if (currentDialogType != UtilityDialogType::NPSIGNIN) { + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); + } + + DeactivateDialog(); + return hleLogSuccessI(SCEUTILITY, npSigninDialog->Shutdown()); } static int sceUtilityNpSigninUpdate(int animSpeed) { - return hleLogError(SCEUTILITY, 0, "not implemented"); + if (currentDialogType != UtilityDialogType::NPSIGNIN) { + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); + } + + return hleLogSuccessI(SCEUTILITY, npSigninDialog->Update(animSpeed)); } static int sceUtilityNpSigninGetStatus() { - return hleLogError(SCEUTILITY, 0, "not implemented"); + if (currentDialogType != UtilityDialogType::NPSIGNIN) { + return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); + } + + int status = npSigninDialog->GetStatus(); + CleanupDialogThreads(); + if (oldStatus != status) { + oldStatus = status; + return hleLogSuccessI(SCEUTILITY, status); + } + return hleLogSuccessVerboseI(SCEUTILITY, status); } static void sceUtilityInstallInitStart(u32 unknown) @@ -1066,7 +1105,7 @@ const HLEFunction sceUtility[] = {0X180F7B62, &WrapI_V, "sceUtilityGamedataInstallAbort", 'i', "" }, {0X16D02AF0, &WrapI_U, "sceUtilityNpSigninInitStart", 'i', "x" }, - {0XE19C97D6, nullptr, "sceUtilityNpSigninShutdownStart", 'i', "" }, + {0XE19C97D6, &WrapI_V, "sceUtilityNpSigninShutdownStart", 'i', "" }, {0XF3FBC572, &WrapI_I, "sceUtilityNpSigninUpdate", 'i', "i" }, {0X86ABDB1B, &WrapI_V, "sceUtilityNpSigninGetStatus", 'i', "" }, diff --git a/Core/HLE/sceUtility.h b/Core/HLE/sceUtility.h index d7358a9ae59c..9943fc839936 100644 --- a/Core/HLE/sceUtility.h +++ b/Core/HLE/sceUtility.h @@ -85,6 +85,7 @@ enum class UtilityDialogType { SCREENSHOT, GAMESHARING, GAMEDATAINSTALL, + NPSIGNIN, }; void __UtilityInit(); diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index d1e9ec43667a..16863bd6e94d 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -415,6 +415,7 @@ + @@ -650,6 +651,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 466e7867e951..6ceb09e6b5de 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -539,6 +539,9 @@ Dialog + + Dialog + Dialog @@ -1539,6 +1542,9 @@ Dialog + + Dialog + Dialog diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 03dd60d89e11..33db892245a8 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -439,6 +439,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/Dialog/PSPGamedataInstallDialog.cpp \ $(SRC)/Core/Dialog/PSPMsgDialog.cpp \ $(SRC)/Core/Dialog/PSPNetconfDialog.cpp \ + $(SRC)/Core/Dialog/PSPNpSigninDialog.cpp \ $(SRC)/Core/Dialog/PSPOskDialog.cpp \ $(SRC)/Core/Dialog/PSPScreenshotDialog.cpp \ $(SRC)/Core/Dialog/PSPPlaceholderDialog.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 37e42af0eea3..dca3bde0d121 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -459,6 +459,7 @@ SOURCES_CXX += \ $(COREDIR)/Dialog/PSPGamedataInstallDialog.cpp \ $(COREDIR)/Dialog/PSPMsgDialog.cpp \ $(COREDIR)/Dialog/PSPNetconfDialog.cpp \ + $(COREDIR)/Dialog/PSPNpSigninDialog.cpp \ $(COREDIR)/Dialog/PSPOskDialog.cpp \ $(COREDIR)/Dialog/PSPSaveDialog.cpp \ $(COREDIR)/Dialog/PSPScreenshotDialog.cpp \