mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-31 12:35:51 +00:00
guest_msg_dialog_native opens a dialog focused on No with a 40 ms bound and never reads its view: it runs until the bound, then finishes with button 1 and the session releases the input. A dialog whose view was read keeps running past the bound and returns the player's answer.
235 lines
11 KiB
C++
235 lines
11 KiB
C++
#include "prx/libSceMsgDialog.native/libSceMsgDialog.native.hpp"
|
|
#include "prx/libSceMsgDialog/include/MsgDialogParam.hpp"
|
|
#include "prx/libSceIme/include/ModalDialog.hpp"
|
|
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <chrono>
|
|
#include <cstring>
|
|
#include <thread>
|
|
|
|
extern "C" {
|
|
extern int SceMsgDialogNativeModuleLoaded_nid_no_patch;
|
|
|
|
}
|
|
|
|
namespace {
|
|
|
|
void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
constexpr int kStatusInitialized = 1;
|
|
constexpr int kStatusFinished = 3;
|
|
constexpr int kErrAlreadyInitialized = static_cast<int>(0x80B80004u);
|
|
constexpr int kErrNotInitialized = static_cast<int>(0x80B80003u);
|
|
constexpr int kErrNotFinished = static_cast<int>(0x80B80005u);
|
|
constexpr int kErrNotRunning = static_cast<int>(0x80B8000Bu);
|
|
constexpr int kErrArgNull = static_cast<int>(0x80B8000Du);
|
|
constexpr int kButtonIdOk = 1;
|
|
constexpr int kButtonIdNo = 2;
|
|
constexpr int kStatusRunning = 2;
|
|
|
|
struct UserMessage {
|
|
std::int32_t buttonType;
|
|
std::int32_t pad;
|
|
const char* message;
|
|
};
|
|
|
|
struct UserParam {
|
|
std::uint8_t bytes[MsgDialog::ParamBytes] = {};
|
|
|
|
UserParam(std::int32_t mode, const UserMessage* user) {
|
|
std::memcpy(bytes + 0x38, &mode, 4);
|
|
std::memcpy(bytes + 0x40, &user, 8);
|
|
}
|
|
};
|
|
|
|
ModalDialogState Session() {
|
|
std::size_t chosen = 0;
|
|
return ModalDialogPoll_nid_postfix(chosen);
|
|
}
|
|
|
|
void CancelAndFallbacks() {
|
|
MsgDialogResult result{};
|
|
UserMessage yesNo{MsgDialog::ButtonTypeYesNo, 0, "Continue?"};
|
|
UserParam param(MsgDialog::ModeUserMsg, &yesNo);
|
|
ModalDialogSetPresenter_nid_postfix(true);
|
|
Require(sceMsgDialogInitialize() == 0);
|
|
Require(sceMsgDialogOpen(¶m) == 0);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Cancel);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdNo);
|
|
|
|
UserMessage okOnly{MsgDialog::ButtonTypeOk, 0, "Saved"};
|
|
UserParam okParam(MsgDialog::ModeUserMsg, &okOnly);
|
|
Require(sceMsgDialogOpen(&okParam) == 0 && sceMsgDialogGetStatus() == kStatusRunning);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Cancel);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdOk);
|
|
|
|
UserMessage none{MsgDialog::ButtonTypeNone, 0, "Wait"};
|
|
UserParam noneParam(MsgDialog::ModeUserMsg, &none);
|
|
Require(sceMsgDialogOpen(&noneParam) == 0 && sceMsgDialogGetStatus() == kStatusFinished && Session() != ModalDialogState::Showing);
|
|
UserParam progress(MsgDialog::ModeProgressBar, &yesNo);
|
|
Require(sceMsgDialogOpen(&progress) == 0 && sceMsgDialogGetStatus() == kStatusFinished && Session() != ModalDialogState::Showing);
|
|
UserParam system(MsgDialog::ModeSystemMsg, &yesNo);
|
|
Require(sceMsgDialogOpen(&system) == 0 && sceMsgDialogGetStatus() == kStatusFinished && Session() != ModalDialogState::Showing);
|
|
result = MsgDialogResult{};
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdOk);
|
|
|
|
ModalDialogSetPresenter_nid_postfix(false);
|
|
UserMessage focusNo{MsgDialog::ButtonTypeYesNoFocusNo, 0, "Delete?"};
|
|
UserParam focusParam(MsgDialog::ModeUserMsg, &focusNo);
|
|
Require(sceMsgDialogOpen(&focusParam) == 0 && sceMsgDialogGetStatus() == kStatusFinished && Session() != ModalDialogState::Showing);
|
|
result = MsgDialogResult{};
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdOk);
|
|
Require(sceMsgDialogTerminate() == 0);
|
|
}
|
|
|
|
void CloseAndTerminate() {
|
|
MsgDialogResult result{};
|
|
UserMessage yesNo{MsgDialog::ButtonTypeYesNo, 0, "Continue?"};
|
|
UserParam param(MsgDialog::ModeUserMsg, &yesNo);
|
|
ModalDialogSetPresenter_nid_postfix(true);
|
|
Require(sceMsgDialogInitialize() == 0);
|
|
Require(sceMsgDialogOpen(¶m) == 0 && Session() == ModalDialogState::Showing);
|
|
Require(sceMsgDialogClose() == 0);
|
|
Require(Session() == ModalDialogState::Closed);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
Require(sceMsgDialogClose() == kErrNotRunning);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdOk);
|
|
|
|
Require(sceMsgDialogOpen(¶m) == 0 && Session() == ModalDialogState::Showing);
|
|
UserMessage okOnly{MsgDialog::ButtonTypeOk, 0, "Saved"};
|
|
UserParam okParam(MsgDialog::ModeUserMsg, &okOnly);
|
|
Require(sceMsgDialogOpen(&okParam) == 0 && Session() == ModalDialogState::Showing);
|
|
ModalDialogView view;
|
|
Require(ModalDialogReadView_nid_postfix(view) && view.message == u"Saved" && view.buttons.size() == 1);
|
|
Require(sceMsgDialogGetStatus() == kStatusRunning);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
|
|
Require(sceMsgDialogOpen(¶m) == 0 && Session() == ModalDialogState::Showing);
|
|
Require(sceMsgDialogTerminate() == 0);
|
|
Require(Session() == ModalDialogState::Idle);
|
|
Require(!ModalDialogCapturesInput_nid_postfix());
|
|
ModalDialogSetPresenter_nid_postfix(false);
|
|
}
|
|
|
|
void WithoutFlips() {
|
|
MsgDialogResult result{};
|
|
UserMessage focusNo{MsgDialog::ButtonTypeYesNoFocusNo, 0, "Delete?"};
|
|
UserParam param(MsgDialog::ModeUserMsg, &focusNo);
|
|
ModalDialogSetPresenter_nid_postfix(true);
|
|
ModalDialogSetShowTimeout_nid_postfix(40);
|
|
Require(sceMsgDialogInitialize() == 0);
|
|
Require(sceMsgDialogOpen(¶m) == 0);
|
|
Require(sceMsgDialogGetStatus() == kStatusRunning);
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(120));
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdOk);
|
|
Require(!ModalDialogCapturesInput_nid_postfix() && Session() == ModalDialogState::Unshown);
|
|
|
|
Require(sceMsgDialogOpen(¶m) == 0 && sceMsgDialogGetStatus() == kStatusRunning);
|
|
ModalDialogView view;
|
|
Require(ModalDialogReadView_nid_postfix(view));
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(120));
|
|
Require(sceMsgDialogUpdateStatus() == kStatusRunning);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
|
|
Require(sceMsgDialogUpdateStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdNo);
|
|
Require(sceMsgDialogTerminate() == 0);
|
|
ModalDialogSetShowTimeout_nid_postfix(ModalDialogShowTimeoutMilliseconds);
|
|
ModalDialogSetPresenter_nid_postfix(false);
|
|
}
|
|
|
|
void ShownDialog() {
|
|
UserMessage yesNo{MsgDialog::ButtonTypeYesNo, 0, "Continue?"};
|
|
UserParam param(MsgDialog::ModeUserMsg, &yesNo);
|
|
MsgDialogResult result{};
|
|
ModalDialogSetPresenter_nid_postfix(true);
|
|
Require(sceMsgDialogInitialize() == 0);
|
|
Require(sceMsgDialogOpen(¶m) == 0);
|
|
Require(Session() == ModalDialogState::Showing);
|
|
for (int poll = 0; poll < 3; ++poll) Require(sceMsgDialogUpdateStatus() == kStatusRunning && sceMsgDialogGetStatus() == kStatusRunning);
|
|
Require(sceMsgDialogGetResult(&result) == kErrNotFinished);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Next);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
result = MsgDialogResult{};
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.result == 0 && result.button_id == kButtonIdNo);
|
|
|
|
Require(sceMsgDialogOpen(¶m) == 0 && sceMsgDialogGetStatus() == kStatusRunning);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
|
|
Require(sceMsgDialogUpdateStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdOk);
|
|
|
|
UserMessage focusNo{MsgDialog::ButtonTypeYesNoFocusNo, 0, "Delete?"};
|
|
UserParam focusParam(MsgDialog::ModeUserMsg, &focusNo);
|
|
Require(sceMsgDialogOpen(&focusParam) == 0);
|
|
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetResult(&result) == 0 && result.button_id == kButtonIdNo);
|
|
Require(sceMsgDialogTerminate() == 0);
|
|
ModalDialogSetPresenter_nid_postfix(false);
|
|
}
|
|
|
|
}
|
|
|
|
int main() {
|
|
Require(SceMsgDialogNativeModuleLoaded_nid_no_patch == 1);
|
|
std::uint8_t param[0x60]{};
|
|
MsgDialogResult result{};
|
|
|
|
Require(sceMsgDialogTerminate() == kErrNotInitialized);
|
|
Require(sceMsgDialogClose() == kErrNotRunning);
|
|
Require(sceMsgDialogOpen(nullptr) == kErrNotInitialized);
|
|
Require(sceMsgDialogOpen(param) == kErrNotInitialized);
|
|
Require(sceMsgDialogGetResult(nullptr) == kErrNotInitialized);
|
|
Require(sceMsgDialogGetResult(&result) == kErrNotInitialized);
|
|
Require(sceMsgDialogUpdateStatus() == 0);
|
|
Require(sceMsgDialogGetStatus() == 0);
|
|
|
|
Require(sceMsgDialogInitialize() == 0);
|
|
Require(sceMsgDialogInitialize() == kErrAlreadyInitialized);
|
|
Require(sceMsgDialogClose() == kErrNotRunning);
|
|
Require(sceMsgDialogGetResult(&result) == kErrNotFinished);
|
|
Require(sceMsgDialogGetResult(nullptr) == kErrArgNull);
|
|
Require(sceMsgDialogOpen(nullptr) == kErrArgNull);
|
|
Require(sceMsgDialogUpdateStatus() == kStatusInitialized);
|
|
Require(sceMsgDialogGetStatus() == kStatusInitialized);
|
|
|
|
Require(sceMsgDialogProgressBarSetValue(0, 50) == kErrNotRunning);
|
|
Require(sceMsgDialogOpen(param) == 0);
|
|
Require(sceMsgDialogUpdateStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
Require(sceMsgDialogOpen(nullptr) == kErrArgNull);
|
|
Require(sceMsgDialogOpen(param) == 0);
|
|
Require(sceMsgDialogProgressBarInc(0, 10) == kErrNotRunning);
|
|
Require(sceMsgDialogProgressBarSetMsg(0, "progress") == kErrNotRunning);
|
|
Require(sceMsgDialogProgressBarSetValue(0, 100) == kErrNotRunning);
|
|
Require(sceMsgDialogClose() == kErrNotRunning);
|
|
Require(sceMsgDialogUpdateStatus() == kStatusFinished);
|
|
Require(sceMsgDialogGetStatus() == kStatusFinished);
|
|
|
|
result = MsgDialogResult{};
|
|
result.button_id = -1;
|
|
Require(sceMsgDialogGetResult(&result) == 0);
|
|
Require(result.result == 0);
|
|
Require(result.button_id == kButtonIdOk);
|
|
|
|
Require(sceMsgDialogTerminate() == 0);
|
|
Require(sceMsgDialogTerminate() == kErrNotInitialized);
|
|
Require(sceMsgDialogOpen(nullptr) == kErrNotInitialized);
|
|
Require(sceMsgDialogOpen(param) == kErrNotInitialized);
|
|
Require(sceMsgDialogGetResult(nullptr) == kErrNotInitialized);
|
|
Require(sceMsgDialogGetResult(&result) == kErrNotInitialized);
|
|
Require(sceMsgDialogClose() == kErrNotRunning);
|
|
Require(sceMsgDialogGetStatus() == 0);
|
|
|
|
ShownDialog();
|
|
CancelAndFallbacks();
|
|
CloseAndTerminate();
|
|
WithoutFlips();
|
|
}
|