From 8270b5417e036b27465d8f03f249bb6646f49d3a Mon Sep 17 00:00:00 2001 From: jw098 Date: Tue, 11 Nov 2025 22:15:13 -0800 Subject: [PATCH 1/4] add CloseGameDetector --- .../DevPrograms/TestProgramSwitch.cpp | 16 +++ .../NintendoSwitch_CloseGameDetector.cpp | 97 +++++++++++++++++++ .../NintendoSwitch_CloseGameDetector.h | 48 +++++++++ SerialPrograms/SourceFiles.cmake | 2 + 4 files changed, 163 insertions(+) create mode 100644 SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.cpp create mode 100644 SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h diff --git a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp index 7589a47b52..91079ae723 100644 --- a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp +++ b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp @@ -124,6 +124,7 @@ #include "NintendoSwitch/Programs/DateSpam/NintendoSwitch_HomeToDateTime.h" #include "NintendoSwitch/Inference/NintendoSwitch_ConsoleTypeDetector.h" #include "NintendoSwitch/Inference/NintendoSwitch_HomeMenuDetector.h" +#include "NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h" #include "NintendoSwitch/Inference/NintendoSwitch_StartGameUserSelectDetector.h" #include "NintendoSwitch/Inference/NintendoSwitch_UpdatePopupDetector.h" #include "NintendoSwitch/Programs/DateSpam/NintendoSwitch_RollDateForward1.h" @@ -293,6 +294,21 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope& + +#if 0 + // auto snapshot = feed.snapshot(); + // CloseGameDetector detector(console); + // cout << detector.detect(snapshot) << endl; + CloseGameWatcher watcher(console); + + int ret = wait_until(console, context, Seconds(10), {watcher}); + + if (ret == 0){ + console.log("CloseGameWatcher detected."); + } + +#endif + #if 0 ImageRGB32 image1("itemprinter.png"); PokemonSV::ItemPrinterMaterialDetector detector(COLOR_RED, Language::ChineseTraditional); diff --git a/SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.cpp b/SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.cpp new file mode 100644 index 0000000000..f4475f6caa --- /dev/null +++ b/SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.cpp @@ -0,0 +1,97 @@ +/* Close Game Detector + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" +#include "CommonTools/Images/SolidColorTest.h" +#include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h" +#include "NintendoSwitch_CloseGameDetector.h" + +#include +using std::cout; +using std::endl; + +namespace PokemonAutomation{ +namespace NintendoSwitch{ + + + +CloseGameDetector::CloseGameDetector(ConsoleHandle& console, Color color) + : m_color(color) + , m_top_box(0.226358, 0.272648, 0.407445, 0.033989) + , m_left_box(0.225, 0.275, 0.01995, 0.350) + , m_close_game_text_row(0.330986, 0.649052, 0.342052, 0.051878) +{} +void CloseGameDetector::make_overlays(VideoOverlaySet& items) const{ + items.add(m_color, m_top_box); + items.add(m_color, m_left_box); + items.add(m_color, m_close_game_text_row); +} + + +bool CloseGameDetector::detect(const ImageViewRGB32& screen){ + + ImageStats stats_top = image_stats(extract_box_reference(screen, m_top_box)); // the top portion of the Close game popup + ImageStats stats_left = image_stats(extract_box_reference(screen, m_left_box)); // the left portion of the Close game popup + ImageStats stats_close_game_text = image_stats(extract_box_reference(screen, m_close_game_text_row)); // the bottom portion of the Close game popup. overlapping with the close game text. + +// cout << "stats_close_game_text.stddev.sum()" << stats_close_game_text.stddev.sum() << endl; + bool white; +// cout << "stats_top.average.sum() = " << stats_top.average.sum() << endl; + if (stats_top.average.sum() < 300){ + white = false; + }else if (stats_top.average.sum() > 500){ + white = true; + }else{ + return false; + } + +// cout << "stats_top.stddev.sum() = " << stats_top.stddev.sum() << endl; + + // ensure top is uniform in color + if (stats_top.stddev.sum() > 20){ + return false; + } + +// cout << "stats_left.stddev.sum() = " << stats_left.stddev.sum() << endl; + // ensure left is uniform in color + if (stats_left.stddev.sum() > 20){ + return false; + } + + // ensure bottom is NOT uniform in color + if (stats_close_game_text.stddev.sum() < 50){ + return false; + } + + if (white){ // if top is white, ensure left is also white + if (!is_white(stats_top) || !is_white(stats_left)){ +// cout << "asdf" << endl; + return false; + } + }else{ + if (!is_grey(stats_top, 0, 300) || !is_grey(stats_left, 0, 300)){ +// cout << "qwer" << endl; + return false; + } + } + + // ensure top and left are the same color. + if (euclidean_distance(stats_top.average, stats_left.average) > 20){ +// cout << "qwer = " << euclidean_distance(stats_bottom_row.average, stats_bottom_row.average) << endl; + return false; + } + + + return true; +} + + + + + + +} +} diff --git a/SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h b/SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h new file mode 100644 index 0000000000..c02b643589 --- /dev/null +++ b/SerialPrograms/Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h @@ -0,0 +1,48 @@ +/* Close Game Detector + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_NintendoSwitch_CloseGameDetector_H +#define PokemonAutomation_NintendoSwitch_CloseGameDetector_H + +#include "Common/Cpp/Color.h" +#include "CommonFramework/ImageTools/ImageBoxes.h" +#include "CommonTools/VisualDetector.h" + +namespace PokemonAutomation{ +namespace NintendoSwitch{ + + + +class CloseGameDetector : public StaticScreenDetector{ +public: + CloseGameDetector(ConsoleHandle& console, Color color = COLOR_RED); + + virtual void make_overlays(VideoOverlaySet& items) const override; + virtual bool detect(const ImageViewRGB32& screen) override; + +private: + Color m_color; + ImageFloatBox m_top_box; + ImageFloatBox m_left_box; + ImageFloatBox m_close_game_text_row; + +}; +class CloseGameWatcher : public DetectorToFinder{ +public: + CloseGameWatcher( + ConsoleHandle& console, + std::chrono::milliseconds hold_duration = std::chrono::milliseconds(250) + ) + : DetectorToFinder("CloseGameWatcher", hold_duration, console) + {} +}; + + + + +} +} +#endif diff --git a/SerialPrograms/SourceFiles.cmake b/SerialPrograms/SourceFiles.cmake index 56a90fc197..bbc50d8183 100644 --- a/SerialPrograms/SourceFiles.cmake +++ b/SerialPrograms/SourceFiles.cmake @@ -1000,6 +1000,8 @@ file(GLOB LIBRARY_SOURCES Source/NintendoSwitch/Framework/UI/NintendoSwitch_SwitchSystemWidget.h Source/NintendoSwitch/Inference/NintendoSwitch2_BinarySliderDetector.cpp Source/NintendoSwitch/Inference/NintendoSwitch2_BinarySliderDetector.h + Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.cpp + Source/NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h Source/NintendoSwitch/Inference/NintendoSwitch_ConsoleTypeDetector.cpp Source/NintendoSwitch/Inference/NintendoSwitch_ConsoleTypeDetector.h Source/NintendoSwitch/Inference/NintendoSwitch_DateChangeDetector.cpp From 4672884f165ff4d3fe6bf57a6985a7ebb882ab72 Mon Sep 17 00:00:00 2001 From: jw098 Date: Tue, 11 Nov 2025 23:26:18 -0800 Subject: [PATCH 2/4] close_game_from_home: updated to handle the case where the game is not selected. --- .../Programs/NintendoSwitch_GameEntry.cpp | 63 ++++++++++++++++--- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp b/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp index 8d4f2768ea..b10e00551a 100644 --- a/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp +++ b/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp @@ -18,6 +18,7 @@ #include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" #include "NintendoSwitch/Inference/NintendoSwitch_DetectHome.h" #include "NintendoSwitch/Inference/NintendoSwitch_HomeMenuDetector.h" +#include "NintendoSwitch/Inference/NintendoSwitch_CloseGameDetector.h" #include "NintendoSwitch/Inference/NintendoSwitch_StartGameUserSelectDetector.h" #include "NintendoSwitch/Inference/NintendoSwitch_UpdatePopupDetector.h" #include "NintendoSwitch_GameEntry.h" @@ -99,6 +100,11 @@ void ensure_at_home(ConsoleHandle& console, JoyconContext& context){ } +bool is_close_game_menu_visible(ConsoleHandle& console){ + CloseGameDetector close_game(console); + auto snapshot = console.video().snapshot(); + return close_game.detect(snapshot); +} // // close_game_from_home() @@ -116,10 +122,31 @@ void close_game_from_home(ConsoleHandle& console, ProControllerContext& context) // if game initially open. | if game initially closed pbf_mash_button(context, BUTTON_X, 100); // - Close game. | - does nothing - ssf_press_dpad_ptv(context, DPAD_DOWN); // - Does nothing. | - moves selector away from the closed game to avoid opening it. - ssf_press_dpad_ptv(context, DPAD_DOWN); // - Does nothing. | - Press Down a second time in case we drop one. - pbf_mash_button(context, BUTTON_A, 50); // - Confirm close game. | - opens an app on the home screen (e.g. Online) - go_home(console, context); // - Does nothing. | - goes back to home screen. + context.wait_for_all_requests(); + if (is_close_game_menu_visible(console)){ // game was initially open. + console.log("Detected close game menu."); + pbf_mash_button(context, BUTTON_A, 50); + ensure_at_home(console, context); + }else{ // either game is initially closed, or the game is not selected. The game not being selected can happen in Switch 2, when you touch the touchscreen on empty space on the Home screen. + console.log("Either game is initially closed, or the game is not selected."); + ssf_press_dpad_ptv(context, DPAD_DOWN); // moving the DPAD/joystick will allow the selection to come back. + ssf_press_dpad_ptv(context, DPAD_DOWN); + ssf_press_dpad_ptv(context, DPAD_DOWN); + console.log("Click the Home button to ensure that current game is selected."); + pbf_press_button(context, BUTTON_HOME, 160ms, 500ms); // clicking home ensures that the cursor is selected on the current game. + go_home(console, context); + + pbf_mash_button(context, BUTTON_X, 100); // try again to close the game. + context.wait_for_all_requests(); + if (is_close_game_menu_visible(console)){ // If close game menu visible, then close the game. Otherwise, we assume the game is already closed. + console.log("Detected close game menu."); + pbf_mash_button(context, BUTTON_A, 50); + ensure_at_home(console, context); + }else{ + console.log("Game was already closed."); + } + + } // fail-safe against button drops and unexpected error messages. pbf_mash_button(context, BUTTON_X, 50); @@ -136,11 +163,31 @@ void close_game_from_home(ConsoleHandle& console, JoyconContext& context){ // if game initially open. | if game initially closed pbf_mash_button(context, BUTTON_X, 800ms); // - Close game. | - does nothing - pbf_move_joystick(context, 128, 255, 100ms, 10ms); // - Does nothing. | - moves selector away from the closed game to avoid opening it. - pbf_move_joystick(context, 128, 255, 100ms, 10ms); // - Does nothing. | - Press Down a second time in case we drop one. - pbf_mash_button(context, BUTTON_A, 400ms); // - Confirm close game. | - opens an app on the home screen (e.g. Online) - go_home(console, context); // - Does nothing. | - goes back to home screen. + context.wait_for_all_requests(); + if (is_close_game_menu_visible(console)){ // game was initially open. + console.log("Detected close game menu."); + pbf_mash_button(context, BUTTON_A, 400ms); + ensure_at_home(console, context); + }else{ // either game is initially closed, or the game is not selected. The game not being selected can happen in Switch 2, when you touch the touchscreen on empty space on the Home screen. + console.log("Either game is initially closed, or the game is not selected."); + pbf_move_joystick(context, 128, 255, 100ms, 10ms); // press down + pbf_move_joystick(context, 128, 255, 100ms, 10ms); + pbf_move_joystick(context, 128, 255, 100ms, 10ms); + console.log("Click the Home button to ensure that current game is selected."); + pbf_press_button(context, BUTTON_HOME, 160ms, 500ms); // clicking home ensures that the cursor is selected on the current game. + go_home(console, context); + + pbf_mash_button(context, BUTTON_X, 800ms); // try again to close the game. + context.wait_for_all_requests(); + if (is_close_game_menu_visible(console)){ // If close game menu visible, then close the game. Otherwise, we assume the game is already closed. + console.log("Detected close game menu."); + pbf_mash_button(context, BUTTON_A, 400ms); + ensure_at_home(console, context); + }else{ + console.log("Game was already closed."); + } + } // fail-safe against button drops and unexpected error messages. pbf_mash_button(context, BUTTON_X, 400ms); pbf_mash_button(context, BUTTON_B, 2000ms); From a5acedcdb2fbf4a7d3d97a5795457d581c1009bc Mon Sep 17 00:00:00 2001 From: jw098 Date: Thu, 13 Nov 2025 16:49:31 -0800 Subject: [PATCH 3/4] refactor close_game_from_home to state machine and use template. --- .../Programs/NintendoSwitch_GameEntry.cpp | 151 +++++++++++------- 1 file changed, 93 insertions(+), 58 deletions(-) diff --git a/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp b/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp index b10e00551a..c987e7beb6 100644 --- a/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp +++ b/SerialPrograms/Source/NintendoSwitch/Programs/NintendoSwitch_GameEntry.cpp @@ -100,18 +100,12 @@ void ensure_at_home(ConsoleHandle& console, JoyconContext& context){ } -bool is_close_game_menu_visible(ConsoleHandle& console){ - CloseGameDetector close_game(console); - auto snapshot = console.video().snapshot(); - return close_game.detect(snapshot); -} - // // close_game_from_home() // -void close_game_from_home(ConsoleHandle& console, ProControllerContext& context){ - console.log("close_game_from_home"); +void close_game_from_home_blind(ConsoleHandle& console, ProControllerContext& context){ + console.log("close_game_from_home_blind"); ensure_at_home(console, context); // Use mashing to ensure that the X press succeeds. If it fails, the SR @@ -122,38 +116,18 @@ void close_game_from_home(ConsoleHandle& console, ProControllerContext& context) // if game initially open. | if game initially closed pbf_mash_button(context, BUTTON_X, 100); // - Close game. | - does nothing - context.wait_for_all_requests(); - if (is_close_game_menu_visible(console)){ // game was initially open. - console.log("Detected close game menu."); - pbf_mash_button(context, BUTTON_A, 50); - ensure_at_home(console, context); - }else{ // either game is initially closed, or the game is not selected. The game not being selected can happen in Switch 2, when you touch the touchscreen on empty space on the Home screen. - console.log("Either game is initially closed, or the game is not selected."); - ssf_press_dpad_ptv(context, DPAD_DOWN); // moving the DPAD/joystick will allow the selection to come back. - ssf_press_dpad_ptv(context, DPAD_DOWN); - ssf_press_dpad_ptv(context, DPAD_DOWN); - console.log("Click the Home button to ensure that current game is selected."); - pbf_press_button(context, BUTTON_HOME, 160ms, 500ms); // clicking home ensures that the cursor is selected on the current game. - go_home(console, context); - - pbf_mash_button(context, BUTTON_X, 100); // try again to close the game. - context.wait_for_all_requests(); - if (is_close_game_menu_visible(console)){ // If close game menu visible, then close the game. Otherwise, we assume the game is already closed. - console.log("Detected close game menu."); - pbf_mash_button(context, BUTTON_A, 50); - ensure_at_home(console, context); - }else{ - console.log("Game was already closed."); - } - - } + ssf_press_dpad_ptv(context, DPAD_DOWN); // - Does nothing. | - moves selector away from the closed game to avoid opening it. + ssf_press_dpad_ptv(context, DPAD_DOWN); // - Does nothing. | - Press Down a second time in case we drop one. + pbf_mash_button(context, BUTTON_A, 50); // - Confirm close game. | - opens an app on the home screen (e.g. Online) + go_home(console, context); // - Does nothing. | - goes back to home screen. // fail-safe against button drops and unexpected error messages. pbf_mash_button(context, BUTTON_X, 50); pbf_mash_button(context, BUTTON_B, 350); } -void close_game_from_home(ConsoleHandle& console, JoyconContext& context){ - console.log("close_game_from_home"); + +void close_game_from_home_blind(ConsoleHandle& console, JoyconContext& context){ + console.log("close_game_from_home_blind"); ensure_at_home(console, context); // Use mashing to ensure that the X press succeeds. If it fails, the SR // will fail and can kill a den for the autohosts. @@ -163,36 +137,97 @@ void close_game_from_home(ConsoleHandle& console, JoyconContext& context){ // if game initially open. | if game initially closed pbf_mash_button(context, BUTTON_X, 800ms); // - Close game. | - does nothing - context.wait_for_all_requests(); - if (is_close_game_menu_visible(console)){ // game was initially open. - console.log("Detected close game menu."); - pbf_mash_button(context, BUTTON_A, 400ms); - ensure_at_home(console, context); - }else{ // either game is initially closed, or the game is not selected. The game not being selected can happen in Switch 2, when you touch the touchscreen on empty space on the Home screen. - console.log("Either game is initially closed, or the game is not selected."); - pbf_move_joystick(context, 128, 255, 100ms, 10ms); // press down - pbf_move_joystick(context, 128, 255, 100ms, 10ms); - pbf_move_joystick(context, 128, 255, 100ms, 10ms); - console.log("Click the Home button to ensure that current game is selected."); - pbf_press_button(context, BUTTON_HOME, 160ms, 500ms); // clicking home ensures that the cursor is selected on the current game. - go_home(console, context); - - pbf_mash_button(context, BUTTON_X, 800ms); // try again to close the game. + pbf_move_joystick(context, 128, 255, 100ms, 10ms); // - Does nothing. | - moves selector away from the closed game to avoid opening it. + pbf_move_joystick(context, 128, 255, 100ms, 10ms); // - Does nothing. | - Press Down a second time in case we drop one. + pbf_mash_button(context, BUTTON_A, 400ms); // - Confirm close game. | - opens an app on the home screen (e.g. Online) + go_home(console, context); // - Does nothing. | - goes back to home screen. + + // fail-safe against button drops and unexpected error messages. + pbf_mash_button(context, BUTTON_X, 400ms); + pbf_mash_button(context, BUTTON_B, 2000ms); +} + +template +void close_game_from_home(ConsoleHandle& console, ControllerContext& context){ + if (!console.video().snapshot()){ // no visual feedback available + close_game_from_home_blind(console, context); + return; + } + + console.log("close_game_from_home"); + ensure_at_home(console, context); + + // this sequence will close the game from the home screen, + // regardless of whether the game is initially open or closed. + bool seen_close_game = false; + size_t times_seen_home_before = 0; + while (true){ context.wait_for_all_requests(); - if (is_close_game_menu_visible(console)){ // If close game menu visible, then close the game. Otherwise, we assume the game is already closed. + + CloseGameWatcher close_game(console); + HomeMenuWatcher home(console); + int ret = wait_until( + console, context, + Seconds(10), + {close_game, home} + ); + + switch(ret){ + case 0: // close_game console.log("Detected close game menu."); pbf_mash_button(context, BUTTON_A, 400ms); - ensure_at_home(console, context); - }else{ - console.log("Game was already closed."); - } + seen_close_game = true; + continue; + case 1: // home + if (seen_close_game){ // successfully closed the game + return; + } + + if (times_seen_home_before == 0){ // Try closing the game + pbf_mash_button(context, BUTTON_X, 800ms); + times_seen_home_before++; + continue; + } + + if (times_seen_home_before == 1){ // The game not being selected can happen in Switch 2, when you touch the touchscreen on empty space on the Home screen. + console.log("Failed to close game once. Either game is already closed, or the game is not selected."); + ssf_issue_scroll(context, DPAD_DOWN, 24ms); // moving the DPAD/joystick will allow the selection to come back. + ssf_issue_scroll(context, DPAD_DOWN, 24ms); + ssf_issue_scroll(context, DPAD_DOWN, 24ms); + console.log("Click the Home button to ensure that current game is selected."); + pbf_press_button(context, BUTTON_HOME, 160ms, 500ms); // clicking home ensures that the cursor is selected on the current game. + go_home(console, context); + console.log("Try again to close the game."); + pbf_mash_button(context, BUTTON_X, 800ms); // try again to close the game. + times_seen_home_before++; + continue; + } + + if (times_seen_home_before == 2){ + console.log("Game was already closed."); + return; + } + throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "close_game_from_home: Unexpected state."); + + default: + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "close_game_from_home(): Failed to detect either the Home screen or the Close game menu after 10 seconds.", + console + ); + } } - // fail-safe against button drops and unexpected error messages. - pbf_mash_button(context, BUTTON_X, 400ms); - pbf_mash_button(context, BUTTON_B, 2000ms); + +} + +void close_game_from_home(ConsoleHandle& console, ProControllerContext& context){ + close_game_from_home(console, context); } +void close_game_from_home(ConsoleHandle& console, JoyconContext& context){ + close_game_from_home(console, context); +} // From 99f1b56412dfe00475582733321e5e45db0a3f16 Mon Sep 17 00:00:00 2001 From: jw098 Date: Thu, 13 Nov 2025 17:04:25 -0800 Subject: [PATCH 4/4] test close_game_from_home --- .../Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp index 91079ae723..3a2ca8d8a8 100644 --- a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp +++ b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramSwitch.cpp @@ -290,10 +290,14 @@ void TestProgram::program(MultiSwitchProgramEnvironment& env, CancellableScope& [[maybe_unused]] VideoFeed& feed = env.consoles[0]; [[maybe_unused]] VideoOverlay& overlay = env.consoles[0]; ProControllerContext context(scope, console.controller()); + // JoyconContext context(scope, console.controller()); VideoOverlaySet overlays(overlay); - +#if 0 +close_game_from_home(console, context); +// ssf_issue_scroll(context, DPAD_DOWN, 24ms); +#endif #if 0 // auto snapshot = feed.snapshot();