CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/Dialog/PSPNpSigninDialog.cpp
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include <algorithm>18#if defined(_WIN32)19#include "Common/CommonWindows.h"20#endif21#include "Common/TimeUtil.h"22#include "Common/Data/Text/I18n.h"23#include "Common/Serialize/Serializer.h"24#include "Common/Serialize/SerializeFuncs.h"25#include "Core/Config.h"26#include "Core/MemMapHelpers.h"27#include "Core/Util/PPGeDraw.h"28#include "Core/HLE/sceKernelMemory.h"29#include "Core/HLE/sceCtrl.h"30#include "Core/HLE/sceUtility.h"31#include "Core/HLE/sceNet.h"32#include "Core/HLE/sceNetAdhoc.h"33#include "Core/HLE/sceNp.h"34#include "Core/Dialog/PSPNpSigninDialog.h"35#include "Common/Data/Encoding/Utf8.h"36#include "Core/Reporting.h"373839static const float FONT_SCALE = 0.65f;4041// Needs testing.42const static int NP_INIT_DELAY_US = 200000;43const static int NP_SHUTDOWN_DELAY_US = 501000;44const static int NP_RUNNING_DELAY_US = 1000000; // faked delay to simulate signin process to give chance for players to read the text on the dialog4546PSPNpSigninDialog::PSPNpSigninDialog(UtilityDialogType type) : PSPDialog(type) {47}4849PSPNpSigninDialog::~PSPNpSigninDialog() {50}5152int PSPNpSigninDialog::Init(u32 paramAddr) {53// Already running54if (ReadStatus() != SCE_UTILITY_STATUS_NONE)55return SCE_ERROR_UTILITY_INVALID_STATUS;5657requestAddr = paramAddr;58int size = Memory::Read_U32(paramAddr);59memset(&request, 0, sizeof(request));60// Only copy the right size to support different request format61Memory::Memcpy(&request, paramAddr, size);6263WARN_LOG_REPORT_ONCE(PSPNpSigninDialogInit, Log::sceNet, "NpSignin Init Params: %08x, %08x, %08x, %08x", request.npSigninStatus, request.unknown1, request.unknown2, request.unknown3);6465ChangeStatusInit(NP_INIT_DELAY_US);6667// Eat any keys pressed before the dialog inited.68UpdateButtons();69InitCommon();7071//npSigninResult = -1;72startTime = (u64)(time_now_d() * 1000000.0);73step = 0;7475StartFade(true);76return 0;77}7879void PSPNpSigninDialog::DrawBanner() {8081PPGeDrawRect(0, 0, 480, 22, CalcFadedColor(0x65636358));8283PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_VCENTER, 0.6f);84textStyle.hasShadow = false;8586// TODO: Draw a hexagon icon87PPGeDrawImage(10, 5, 11.0f, 10.0f, 1, 10, 1, 10, 10, 10, FadedImageStyle());88auto di = GetI18NCategory(I18NCat::DIALOG);89PPGeDrawText(di->T("Sign In"), 31, 10, textStyle);90}9192void PSPNpSigninDialog::DrawIndicator() {93// TODO: Draw animated circle as processing indicator94PPGeDrawImage(456, 248, 20.0f, 20.0f, 1, 10, 1, 10, 10, 10, FadedImageStyle());95}9697void PSPNpSigninDialog::DrawLogo() {98// TODO: Draw OpenDNAS logo99PPGeDrawImage(416, 22, 64.0f, 64.0f, 1, 10, 1, 10, 64, 64, FadedImageStyle());100}101102void PSPNpSigninDialog::DisplayMessage(std::string_view text1, std::string_view text2a, std::string_view text2b, std::string_view text3a, std::string_view text3b, bool hasYesNo, bool hasOK) {103auto di = GetI18NCategory(I18NCat::DIALOG);104105PPGeStyle buttonStyle = FadedStyle(PPGeAlign::BOX_CENTER, FONT_SCALE);106PPGeStyle messageStyle = FadedStyle(PPGeAlign::BOX_HCENTER, FONT_SCALE);107PPGeStyle messageStyleRight = FadedStyle(PPGeAlign::BOX_RIGHT, FONT_SCALE);108PPGeStyle messageStyleLeft = FadedStyle(PPGeAlign::BOX_LEFT, FONT_SCALE);109110std::string text2 = std::string(text2a) + " " + std::string(text2b);111std::string text3 = std::string(text3a) + " " + std::string(text3b);112113// Without the scrollbar, we have 350 total pixels.114float WRAP_WIDTH = 300.0f;115if (UTF8StringNonASCIICount(text1) >= (int)text1.size() / 4) {116WRAP_WIDTH = 336.0f;117if (text1.size() > 12) {118messageStyle.scale = 0.6f;119}120}121122float totalHeight1 = 0.0f;123PPGeMeasureText(nullptr, &totalHeight1, text1, FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);124float totalHeight2 = 0.0f;125if (text2 != " ")126PPGeMeasureText(nullptr, &totalHeight2, text2, FONT_SCALE, PPGE_LINE_USE_ELLIPSIS, WRAP_WIDTH);127float totalHeight3 = 0.0f;128if (text3 != " ")129PPGeMeasureText(nullptr, &totalHeight3, text3, FONT_SCALE, PPGE_LINE_USE_ELLIPSIS, WRAP_WIDTH);130float marginTop = 0.0f;131if (text2 != " " || text3 != " ")132marginTop = 11.0f;133float totalHeight = totalHeight1 + totalHeight2 + totalHeight3 + marginTop;134// The PSP normally only shows about 8 lines at a time.135// For improved UX, we intentionally show part of the next line.136float visibleHeight = std::min(totalHeight, 175.0f);137float h2 = visibleHeight / 2.0f;138139float centerY = 135.0f;140float sy = centerY - h2 - 15.0f;141float ey = centerY + h2 + 20.0f;142float buttonY = centerY + h2 + 5.0f;143144auto drawSelectionBoxAndAdjust = [&](float x) {145// Box has a fixed size.146float w = 15.0f;147float h = 8.0f;148PPGeDrawRect(x - w, buttonY - h, x + w, buttonY + h, CalcFadedColor(0x6DCFCFCF));149150centerY -= h + 5.0f;151sy -= h + 5.0f;152ey = buttonY + h * 2.0f + 5.0f;153};154155if (hasYesNo) {156if (yesnoChoice == 1) {157drawSelectionBoxAndAdjust(204.0f);158}159else {160drawSelectionBoxAndAdjust(273.0f);161}162163PPGeDrawText(di->T("Yes"), 203.0f, buttonY - 1.0f, buttonStyle);164PPGeDrawText(di->T("No"), 272.0f, buttonY - 1.0f, buttonStyle);165if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) {166yesnoChoice = 1;167}168else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) {169yesnoChoice = 0;170}171buttonY += 8.0f + 5.0f;172}173174if (hasOK) {175drawSelectionBoxAndAdjust(240.0f);176177PPGeDrawText(di->T("OK"), 239.0f, buttonY - 1.0f, buttonStyle);178buttonY += 8.0f + 5.0f;179}180181PPGeScissor(0, (int)(centerY - h2 - 2), 480, (int)(centerY + h2 + 2));182PPGeDrawTextWrapped(text1, 240.0f, centerY - h2 - scrollPos_, WRAP_WIDTH, 0, messageStyle);183if (!text2a.empty()) {184if (!text2b.empty())185PPGeDrawTextWrapped(text2a, 240.0f - 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyleRight);186else187PPGeDrawTextWrapped(text2a, 240.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyle);188}189if (!text2b.empty())190PPGeDrawTextWrapped(text2b, 240.0f + 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + marginTop, WRAP_WIDTH, 0, messageStyleLeft);191if (!text3a.empty()) {192if (!text3b.empty())193PPGeDrawTextWrapped(text3a, 240.0f - 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyleRight);194else195PPGeDrawTextWrapped(text3a, 240.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyle);196}197if (!text3b.empty())198PPGeDrawTextWrapped(text3b, 240.0f + 5.0f, centerY - h2 - scrollPos_ + totalHeight1 + totalHeight2 + marginTop, WRAP_WIDTH, 0, messageStyleLeft);199PPGeScissorReset();200201// Do we need a scrollbar?202if (visibleHeight < totalHeight) {203float scrollSpeed = 5.0f;204float scrollMax = totalHeight - visibleHeight;205206float bobHeight = (visibleHeight / totalHeight) * visibleHeight;207float bobOffset = (scrollPos_ / scrollMax) * (visibleHeight - bobHeight);208float bobY1 = centerY - h2 + bobOffset;209PPGeDrawRect(415.0f, bobY1, 420.0f, bobY1 + bobHeight, CalcFadedColor(0xFFCCCCCC));210211auto buttonDown = [this](int btn, int& held) {212if (IsButtonPressed(btn)) {213held = 0;214return true;215}216return IsButtonHeld(btn, held, 1, 1);217};218if (buttonDown(CTRL_DOWN, framesDownHeld_) && scrollPos_ < scrollMax) {219scrollPos_ = std::min(scrollMax, scrollPos_ + scrollSpeed);220}221if (buttonDown(CTRL_UP, framesUpHeld_) && scrollPos_ > 0.0f) {222scrollPos_ = std::max(0.0f, scrollPos_ - scrollSpeed);223}224}225226PPGeDrawRect(60.0f, sy, 420.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF));227PPGeDrawRect(60.0f, ey, 420.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF));228}229230int PSPNpSigninDialog::Update(int animSpeed) {231if (ReadStatus() != SCE_UTILITY_STATUS_RUNNING) {232return SCE_ERROR_UTILITY_INVALID_STATUS;233}234235UpdateButtons();236UpdateCommon();237auto err = GetI18NCategory(I18NCat::ERRORS);238u64 now = (u64)(time_now_d() * 1000000.0);239240if (request.npSigninStatus == NP_SIGNIN_STATUS_NONE) {241auto di = GetI18NCategory(I18NCat::DIALOG);242UpdateFade(animSpeed);243StartDraw();244245PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0xC0C8B2AC));246DrawBanner();247DrawIndicator();248249// 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/250// DNAS dialog251if (step >= 2 && now - startTime > NP_RUNNING_DELAY_US) {252DrawLogo();253DisplayMessage(di->T("PleaseWait", "Please wait..."));254step++;255}256// Signin dialog257else {258// Skipping the Select Connection screen since we only have 1 fake profile259DisplayMessage(di->T("SigninPleaseWait", "Signing in...\nPlease wait."));260}261DisplayButtons(DS_BUTTON_CANCEL, di->T("Cancel"));262263if (step >= 2 && now - startTime > NP_RUNNING_DELAY_US*2) {264if (pendingStatus != SCE_UTILITY_STATUS_FINISHED) {265StartFade(false);266ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NP_SHUTDOWN_DELAY_US);267step++;268}269}270271else if (step == 1 && now - startTime > NP_RUNNING_DELAY_US) {272// Switch to the next message (with DNAS logo)273StartFade(true);274step++;275}276277else if (step == 0) {278/*if (npAuthResult < 0 && request.NpSigninData.IsValid()) {279npAuthResult = sceNpAuthCreateStartRequest(request.NpSigninData->paramAddr);280}*/281step++;282}283284if (/*npAuthResult >= 0 &&*/ IsButtonPressed(cancelButtonFlag)) {285StartFade(false);286//sceNpAuthAbortRequest(npAuthResult);287//sceNpAuthDestroyRequest(npAuthResult);288ChangeStatus(SCE_UTILITY_STATUS_FINISHED, NP_SHUTDOWN_DELAY_US);289request.common.result = SCE_UTILITY_DIALOG_RESULT_ABORT;290request.npSigninStatus = NP_SIGNIN_STATUS_CANCELED;291//step = 0;292}293294EndDraw();295}296297if (ReadStatus() == SCE_UTILITY_STATUS_FINISHED || pendingStatus == SCE_UTILITY_STATUS_FINISHED) {298npSigninState = NP_SIGNIN_STATUS_SUCCESS;299__RtcTimeOfDay(&npSigninTimestamp);300request.npSigninStatus = npSigninState;301}302return 0;303}304305int PSPNpSigninDialog::Shutdown(bool force) {306if (ReadStatus() != SCE_UTILITY_STATUS_FINISHED && !force)307return SCE_ERROR_UTILITY_INVALID_STATUS;308309PSPDialog::Shutdown(force);310if (!force) {311ChangeStatusShutdown(NP_SHUTDOWN_DELAY_US);312}313314// 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.315if (Memory::IsValidAddress(requestAddr)) // Need to validate first to prevent Invalid address when the game is being Shutdown/Exited to menu316Memory::Memcpy(requestAddr, &request, request.common.size, "NpSigninDialogParam");317318return 0;319}320321void PSPNpSigninDialog::DoState(PointerWrap &p) {322PSPDialog::DoState(p);323324auto s = p.Section("PSPNpSigninDialog", 1, 1);325if (!s)326return;327328Do(p, request);329Do(p, step);330//Do(p, npSigninResult);331332if (p.mode == p.MODE_READ) {333startTime = 0;334}335}336337pspUtilityDialogCommon* PSPNpSigninDialog::GetCommonParam()338{339return &request.common;340}341342343