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:
bunnei 2020-11-12 21:55:06 -08:00 committed by GitHub
commit 87f220efff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 26 deletions

View File

@ -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;

View File

@ -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};