Merge pull request #4895 from Morph1984/cave-story-plus-applet-fix
applets/controller: Introduce additional checks for mode and caller
This commit is contained in:
commit
87f220efff
|
@ -62,7 +62,7 @@ void Controller::Initialize() {
|
||||||
common_args.play_startup_sound, common_args.size, common_args.system_tick,
|
common_args.play_startup_sound, common_args.size, common_args.system_tick,
|
||||||
common_args.theme_color);
|
common_args.theme_color);
|
||||||
|
|
||||||
library_applet_version = LibraryAppletVersion{common_args.library_version};
|
controller_applet_version = ControllerAppletVersion{common_args.library_version};
|
||||||
|
|
||||||
const auto private_arg_storage = broker.PopNormalDataToApplet();
|
const auto private_arg_storage = broker.PopNormalDataToApplet();
|
||||||
ASSERT(private_arg_storage != nullptr);
|
ASSERT(private_arg_storage != nullptr);
|
||||||
|
@ -70,39 +70,78 @@ void Controller::Initialize() {
|
||||||
const auto& private_arg = private_arg_storage->GetData();
|
const auto& private_arg = private_arg_storage->GetData();
|
||||||
ASSERT(private_arg.size() == sizeof(ControllerSupportArgPrivate));
|
ASSERT(private_arg.size() == sizeof(ControllerSupportArgPrivate));
|
||||||
|
|
||||||
std::memcpy(&controller_private_arg, private_arg.data(), sizeof(ControllerSupportArgPrivate));
|
std::memcpy(&controller_private_arg, private_arg.data(), private_arg.size());
|
||||||
ASSERT_MSG(controller_private_arg.arg_private_size == sizeof(ControllerSupportArgPrivate),
|
ASSERT_MSG(controller_private_arg.arg_private_size == sizeof(ControllerSupportArgPrivate),
|
||||||
"Unknown ControllerSupportArgPrivate revision={} with size={}",
|
"Unknown ControllerSupportArgPrivate revision={} with size={}",
|
||||||
library_applet_version, controller_private_arg.arg_private_size);
|
controller_applet_version, controller_private_arg.arg_private_size);
|
||||||
|
|
||||||
|
// Some games such as Cave Story+ set invalid values for the ControllerSupportMode.
|
||||||
|
// Defer to arg_size to set the ControllerSupportMode.
|
||||||
|
if (controller_private_arg.mode >= ControllerSupportMode::MaxControllerSupportMode) {
|
||||||
|
switch (controller_private_arg.arg_size) {
|
||||||
|
case sizeof(ControllerSupportArgOld):
|
||||||
|
case sizeof(ControllerSupportArgNew):
|
||||||
|
controller_private_arg.mode = ControllerSupportMode::ShowControllerSupport;
|
||||||
|
break;
|
||||||
|
case sizeof(ControllerUpdateFirmwareArg):
|
||||||
|
controller_private_arg.mode = ControllerSupportMode::ShowControllerFirmwareUpdate;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED_MSG("Unknown ControllerPrivateArg mode={} with arg_size={}",
|
||||||
|
controller_private_arg.mode, controller_private_arg.arg_size);
|
||||||
|
controller_private_arg.mode = ControllerSupportMode::ShowControllerSupport;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some games such as Cave Story+ set invalid values for the ControllerSupportCaller.
|
||||||
|
// This is always 0 (Application) except with ShowControllerFirmwareUpdateForSystem.
|
||||||
|
if (controller_private_arg.caller >= ControllerSupportCaller::MaxControllerSupportCaller) {
|
||||||
|
if (controller_private_arg.flag_1 &&
|
||||||
|
controller_private_arg.mode == ControllerSupportMode::ShowControllerFirmwareUpdate) {
|
||||||
|
controller_private_arg.caller = ControllerSupportCaller::System;
|
||||||
|
} else {
|
||||||
|
controller_private_arg.caller = ControllerSupportCaller::Application;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (controller_private_arg.mode) {
|
switch (controller_private_arg.mode) {
|
||||||
case ControllerSupportMode::ShowControllerSupport: {
|
case ControllerSupportMode::ShowControllerSupport:
|
||||||
|
case ControllerSupportMode::ShowControllerStrapGuide: {
|
||||||
const auto user_arg_storage = broker.PopNormalDataToApplet();
|
const auto user_arg_storage = broker.PopNormalDataToApplet();
|
||||||
ASSERT(user_arg_storage != nullptr);
|
ASSERT(user_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& user_arg = user_arg_storage->GetData();
|
const auto& user_arg = user_arg_storage->GetData();
|
||||||
switch (library_applet_version) {
|
switch (controller_applet_version) {
|
||||||
case LibraryAppletVersion::Version3:
|
case ControllerAppletVersion::Version3:
|
||||||
case LibraryAppletVersion::Version4:
|
case ControllerAppletVersion::Version4:
|
||||||
case LibraryAppletVersion::Version5:
|
case ControllerAppletVersion::Version5:
|
||||||
ASSERT(user_arg.size() == sizeof(ControllerSupportArgOld));
|
ASSERT(user_arg.size() == sizeof(ControllerSupportArgOld));
|
||||||
std::memcpy(&controller_user_arg_old, user_arg.data(), sizeof(ControllerSupportArgOld));
|
std::memcpy(&controller_user_arg_old, user_arg.data(), user_arg.size());
|
||||||
break;
|
break;
|
||||||
case LibraryAppletVersion::Version7:
|
case ControllerAppletVersion::Version7:
|
||||||
ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew));
|
ASSERT(user_arg.size() == sizeof(ControllerSupportArgNew));
|
||||||
std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew));
|
std::memcpy(&controller_user_arg_new, user_arg.data(), user_arg.size());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unknown ControllerSupportArg revision={} with size={}",
|
UNIMPLEMENTED_MSG("Unknown ControllerSupportArg revision={} with size={}",
|
||||||
library_applet_version, controller_private_arg.arg_size);
|
controller_applet_version, controller_private_arg.arg_size);
|
||||||
ASSERT(user_arg.size() >= sizeof(ControllerSupportArgNew));
|
ASSERT(user_arg.size() >= sizeof(ControllerSupportArgNew));
|
||||||
std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew));
|
std::memcpy(&controller_user_arg_new, user_arg.data(), sizeof(ControllerSupportArgNew));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ControllerSupportMode::ShowControllerStrapGuide:
|
case ControllerSupportMode::ShowControllerFirmwareUpdate: {
|
||||||
case ControllerSupportMode::ShowControllerFirmwareUpdate:
|
const auto update_arg_storage = broker.PopNormalDataToApplet();
|
||||||
|
ASSERT(update_arg_storage != nullptr);
|
||||||
|
|
||||||
|
const auto& update_arg = update_arg_storage->GetData();
|
||||||
|
ASSERT(update_arg.size() == sizeof(ControllerUpdateFirmwareArg));
|
||||||
|
|
||||||
|
std::memcpy(&controller_update_arg, update_arg.data(), update_arg.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode);
|
UNIMPLEMENTED_MSG("Unimplemented ControllerSupportMode={}", controller_private_arg.mode);
|
||||||
break;
|
break;
|
||||||
|
@ -126,10 +165,10 @@ void Controller::Execute() {
|
||||||
switch (controller_private_arg.mode) {
|
switch (controller_private_arg.mode) {
|
||||||
case ControllerSupportMode::ShowControllerSupport: {
|
case ControllerSupportMode::ShowControllerSupport: {
|
||||||
const auto parameters = [this] {
|
const auto parameters = [this] {
|
||||||
switch (library_applet_version) {
|
switch (controller_applet_version) {
|
||||||
case LibraryAppletVersion::Version3:
|
case ControllerAppletVersion::Version3:
|
||||||
case LibraryAppletVersion::Version4:
|
case ControllerAppletVersion::Version4:
|
||||||
case LibraryAppletVersion::Version5:
|
case ControllerAppletVersion::Version5:
|
||||||
return ConvertToFrontendParameters(
|
return ConvertToFrontendParameters(
|
||||||
controller_private_arg, controller_user_arg_old.header,
|
controller_private_arg, controller_user_arg_old.header,
|
||||||
controller_user_arg_old.enable_explain_text,
|
controller_user_arg_old.enable_explain_text,
|
||||||
|
@ -138,7 +177,7 @@ void Controller::Execute() {
|
||||||
controller_user_arg_old.identification_colors.end()),
|
controller_user_arg_old.identification_colors.end()),
|
||||||
std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(),
|
std::vector<ExplainText>(controller_user_arg_old.explain_text.begin(),
|
||||||
controller_user_arg_old.explain_text.end()));
|
controller_user_arg_old.explain_text.end()));
|
||||||
case LibraryAppletVersion::Version7:
|
case ControllerAppletVersion::Version7:
|
||||||
default:
|
default:
|
||||||
return ConvertToFrontendParameters(
|
return ConvertToFrontendParameters(
|
||||||
controller_private_arg, controller_user_arg_new.header,
|
controller_private_arg, controller_user_arg_new.header,
|
||||||
|
@ -170,6 +209,9 @@ void Controller::Execute() {
|
||||||
}
|
}
|
||||||
case ControllerSupportMode::ShowControllerStrapGuide:
|
case ControllerSupportMode::ShowControllerStrapGuide:
|
||||||
case ControllerSupportMode::ShowControllerFirmwareUpdate:
|
case ControllerSupportMode::ShowControllerFirmwareUpdate:
|
||||||
|
UNIMPLEMENTED_MSG("ControllerSupportMode={} is not implemented",
|
||||||
|
controller_private_arg.mode);
|
||||||
|
[[fallthrough]];
|
||||||
default: {
|
default: {
|
||||||
ConfigurationComplete();
|
ConfigurationComplete();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Service::AM::Applets {
|
||||||
using IdentificationColor = std::array<u8, 4>;
|
using IdentificationColor = std::array<u8, 4>;
|
||||||
using ExplainText = std::array<char, 0x81>;
|
using ExplainText = std::array<char, 0x81>;
|
||||||
|
|
||||||
enum class LibraryAppletVersion : u32_le {
|
enum class ControllerAppletVersion : u32_le {
|
||||||
Version3 = 0x3, // 1.0.0 - 2.3.0
|
Version3 = 0x3, // 1.0.0 - 2.3.0
|
||||||
Version4 = 0x4, // 3.0.0 - 5.1.0
|
Version4 = 0x4, // 3.0.0 - 5.1.0
|
||||||
Version5 = 0x5, // 6.0.0 - 7.0.1
|
Version5 = 0x5, // 6.0.0 - 7.0.1
|
||||||
|
@ -29,14 +29,18 @@ enum class LibraryAppletVersion : u32_le {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ControllerSupportMode : u8 {
|
enum class ControllerSupportMode : u8 {
|
||||||
ShowControllerSupport = 0,
|
ShowControllerSupport,
|
||||||
ShowControllerStrapGuide = 1,
|
ShowControllerStrapGuide,
|
||||||
ShowControllerFirmwareUpdate = 2,
|
ShowControllerFirmwareUpdate,
|
||||||
|
|
||||||
|
MaxControllerSupportMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ControllerSupportCaller : u8 {
|
enum class ControllerSupportCaller : u8 {
|
||||||
Application = 0,
|
Application,
|
||||||
System = 1,
|
System,
|
||||||
|
|
||||||
|
MaxControllerSupportCaller,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ControllerSupportArgPrivate {
|
struct ControllerSupportArgPrivate {
|
||||||
|
@ -84,6 +88,13 @@ struct ControllerSupportArgNew {
|
||||||
static_assert(sizeof(ControllerSupportArgNew) == 0x430,
|
static_assert(sizeof(ControllerSupportArgNew) == 0x430,
|
||||||
"ControllerSupportArgNew has incorrect size.");
|
"ControllerSupportArgNew has incorrect size.");
|
||||||
|
|
||||||
|
struct ControllerUpdateFirmwareArg {
|
||||||
|
bool enable_force_update{};
|
||||||
|
INSERT_PADDING_BYTES(3);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ControllerUpdateFirmwareArg) == 0x4,
|
||||||
|
"ControllerUpdateFirmwareArg has incorrect size.");
|
||||||
|
|
||||||
struct ControllerSupportResultInfo {
|
struct ControllerSupportResultInfo {
|
||||||
s8 player_count{};
|
s8 player_count{};
|
||||||
INSERT_PADDING_BYTES(3);
|
INSERT_PADDING_BYTES(3);
|
||||||
|
@ -110,10 +121,11 @@ public:
|
||||||
private:
|
private:
|
||||||
const Core::Frontend::ControllerApplet& frontend;
|
const Core::Frontend::ControllerApplet& frontend;
|
||||||
|
|
||||||
LibraryAppletVersion library_applet_version;
|
ControllerAppletVersion controller_applet_version;
|
||||||
ControllerSupportArgPrivate controller_private_arg;
|
ControllerSupportArgPrivate controller_private_arg;
|
||||||
ControllerSupportArgOld controller_user_arg_old;
|
ControllerSupportArgOld controller_user_arg_old;
|
||||||
ControllerSupportArgNew controller_user_arg_new;
|
ControllerSupportArgNew controller_user_arg_new;
|
||||||
|
ControllerUpdateFirmwareArg controller_update_arg;
|
||||||
bool complete{false};
|
bool complete{false};
|
||||||
ResultCode status{RESULT_SUCCESS};
|
ResultCode status{RESULT_SUCCESS};
|
||||||
bool is_single_mode{false};
|
bool is_single_mode{false};
|
||||||
|
|
Reference in New Issue