From c331cc59a843ab82daa175c029d2a5be9359e872 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Mon, 2 Mar 2026 17:30:54 -0800 Subject: [PATCH 1/4] Retry FRLG SRs. --- .../PokemonFRLG/PokemonFRLG_Navigation.cpp | 139 ++++++++++-------- .../PokemonFRLG/PokemonFRLG_Navigation.h | 2 +- .../ShinyHunting/PokemonFRLG_GiftReset.cpp | 12 +- .../PokemonFRLG_LegendaryReset.cpp | 12 +- .../PokemonFRLG_PrizeCornerReset.cpp | 12 +- .../PokemonRSE_AudioStarterReset.cpp | 10 +- 6 files changed, 115 insertions(+), 72 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp index f33f827de..f99c0b65d 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp @@ -11,7 +11,6 @@ #include "CommonTools/Async/InferenceRoutines.h" #include "CommonTools/VisualDetectors/BlackScreenDetector.h" #include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h" -#include "NintendoSwitch/Commands/NintendoSwitch_Commands_Superscalar.h" #include "NintendoSwitch/Controllers/Procon/NintendoSwitch_ProController.h" #include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h" #include "PokemonFRLG/Inference/Dialogs/PokemonFRLG_DialogDetector.h" @@ -26,81 +25,93 @@ namespace NintendoSwitch{ namespace PokemonFRLG{ -void soft_reset(ConsoleHandle& console, ProControllerContext& context){ - // A + B + Select + Start - pbf_press_button(context, BUTTON_B | BUTTON_A | BUTTON_MINUS | BUTTON_PLUS, 360ms, 1440ms); +uint64_t soft_reset(ConsoleHandle& console, ProControllerContext& context){ + uint64_t errors = 0; + while (true){ + // A + B + Select + Start + pbf_press_button(context, BUTTON_B | BUTTON_A | BUTTON_MINUS | BUTTON_PLUS, 360ms, 1440ms); - pbf_mash_button(context, BUTTON_MINUS, GameSettings::instance().SELECT_BUTTON_MASH0); - context.wait_for_all_requests(); + pbf_mash_button(context, BUTTON_MINUS, GameSettings::instance().SELECT_BUTTON_MASH0); + context.wait_for_all_requests(); - //Random wait before pressing start/A - console.log("Randomly waiting..."); - Milliseconds rng_wait = std::chrono::milliseconds(random_u32(0, 5000)); - pbf_wait(context, rng_wait); - context.wait_for_all_requests(); + //Random wait before pressing start/A + console.log("Randomly waiting..."); + Milliseconds rng_wait = std::chrono::milliseconds(random_u32(0, 5000)); + pbf_wait(context, rng_wait); + context.wait_for_all_requests(); - //Mash A until white screen to game load menu - WhiteScreenOverWatcher whitescreen(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); - LoadMenuWatcher load_menu(COLOR_BLUE); + //Mash A until white screen to game load menu + WhiteScreenOverWatcher whitescreen(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + LoadMenuWatcher load_menu(COLOR_BLUE); - int ls = run_until( - console, context, - [](ProControllerContext& context) { - pbf_mash_button(context, BUTTON_A, 1000ms); - pbf_wait(context, 5000ms); - context.wait_for_all_requests(); - }, - { whitescreen, load_menu } - ); - context.wait_for_all_requests(); - if (ls == 0) { - console.log("Entered load menu. (WhiteScreenOver)"); - }else if (ls == 1) { - console.log("Entered load menu. (LoadMenu)"); - }else{ - console.log("Unable to enter load menu.", COLOR_RED); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "soft_reset(): Unable to enter load menu.", - console + int ls = run_until( + console, context, + [](ProControllerContext& context) { + pbf_mash_button(context, BUTTON_A, 1000ms); + pbf_wait(context, 5000ms); + context.wait_for_all_requests(); + }, + { whitescreen, load_menu } ); - } - //Let the animation finish - pbf_wait(context, 500ms); - context.wait_for_all_requests(); + context.wait_for_all_requests(); + if (ls == 0) { + console.log("Entered load menu. (WhiteScreenOver)"); + }else if (ls == 1) { + console.log("Entered load menu. (LoadMenu)"); + }else{ + console.log("Unable to enter load menu.", COLOR_RED); + errors++; + if (errors >= 5){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "soft_reset(): Failed to reset after 5 attempts.", + console + ); + } + continue; + } + //Let the animation finish + pbf_wait(context, 500ms); + context.wait_for_all_requests(); - //Load game - pbf_press_button(context, BUTTON_A, 160ms, 320ms); + //Load game + pbf_press_button(context, BUTTON_A, 160ms, 320ms); - //Wait for game to load in - BlackScreenOverWatcher detector(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); - int ret = wait_until( - console, context, - GameSettings::instance().ENTER_GAME_WAIT0, - {detector} - ); - if (ret == 0){ - console.log("Entered game!"); - }else{ - console.log("Timed out waiting to enter game.", COLOR_RED); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "soft_reset(): Timed out waiting to enter game.", - console + //Wait for game to load in + BlackScreenOverWatcher detector(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + int ret = wait_until( + console, context, + GameSettings::instance().ENTER_GAME_WAIT0, + {detector} ); - } + if (ret == 0){ + console.log("Entered game!"); + }else{ + console.log("Timed out waiting to enter game.", COLOR_RED); + errors++; + if (errors >= 5){ + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "soft_reset(): Failed to reset after 5 attempts.", + console + ); + } + continue; + } - //Mash past "previously on..." - pbf_mash_button(context, BUTTON_B, GameSettings::instance().ENTER_GAME_MASH0); - context.wait_for_all_requests(); + //Mash past "previously on..." + pbf_mash_button(context, BUTTON_B, GameSettings::instance().ENTER_GAME_MASH0); + context.wait_for_all_requests(); - //Random wait no.2 - console.log("Randomly waiting..."); - Milliseconds rng_wait2 = std::chrono::milliseconds(random_u32(0, 5000)); - pbf_wait(context, rng_wait2); - context.wait_for_all_requests(); + //Random wait no.2 + console.log("Randomly waiting..."); + Milliseconds rng_wait2 = std::chrono::milliseconds(random_u32(0, 5000)); + pbf_wait(context, rng_wait2); + context.wait_for_all_requests(); + } console.log("Soft reset completed."); + return errors; } void open_slot_six(ConsoleHandle& console, ProControllerContext& context){ diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h index 1ce2ade4b..284ce0174 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h @@ -23,7 +23,7 @@ namespace PokemonFRLG{ // There are two random waits, one before pressing start and another after loading in the game. // This is to prevent repeatedly getting the same pokemon, due to FRLG's RNG // For now this assumes no dry battery. -void soft_reset(ConsoleHandle& console, ProControllerContext &context); +uint64_t soft_reset(ConsoleHandle& console, ProControllerContext &context); // From the overworld, open the summary of the Pokemon in slot 6. This assumes the menu cursor is in the top slot (POKEDEX) void open_slot_six(ConsoleHandle& console, ProControllerContext& context); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index 67fb5eab6..4ec2c56c7 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -335,7 +335,15 @@ void GiftReset::program(SingleSwitchProgramEnvironment& env, ProControllerContex if (shiny_starter){ env.log("Shiny found!"); stats.shinies++; - send_program_notification(env, NOTIFICATION_SHINY, COLOR_YELLOW, "Shiny found!", {}, "", screen, true); + send_program_notification( + env, + NOTIFICATION_SHINY, + COLOR_YELLOW, + "Shiny found!", + {}, "", + screen, + true + ); break; }else{ env.log("Pokemon is not shiny."); @@ -344,7 +352,7 @@ void GiftReset::program(SingleSwitchProgramEnvironment& env, ProControllerContex env, NOTIFICATION_STATUS_UPDATE, "Soft resetting." ); - soft_reset(env.console, context); + stats.errors += soft_reset(env.console, context); stats.resets++; env.update_stats(); context.wait_for_all_requests(); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp index 000af92ac..22ffef956 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_LegendaryReset.cpp @@ -129,7 +129,15 @@ void LegendaryReset::program(SingleSwitchProgramEnvironment& env, ProControllerC if (legendary_shiny){ stats.shinies++; env.update_stats(); - send_program_notification(env, NOTIFICATION_SHINY, COLOR_YELLOW, "Shiny found!", {}, "", env.console.video().snapshot(), true); + send_program_notification( + env, + NOTIFICATION_SHINY, + COLOR_YELLOW, + "Shiny found!", + {}, "", + env.console.video().snapshot(), + true + ); break; } @@ -140,7 +148,7 @@ void LegendaryReset::program(SingleSwitchProgramEnvironment& env, ProControllerC "Soft resetting." ); - soft_reset(env.console, context); + stats.errors += soft_reset(env.console, context); stats.resets++; env.update_stats(); context.wait_for_all_requests(); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp index 64d6ce83f..53e576c9a 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp @@ -156,7 +156,15 @@ void PrizeCornerReset::program(SingleSwitchProgramEnvironment& env, ProControlle if (shiny_found){ env.log("Shiny found!"); stats.shinies++; - send_program_notification(env, NOTIFICATION_SHINY, COLOR_YELLOW, "Shiny found!", {}, "", screen, true); + send_program_notification( + env, + NOTIFICATION_SHINY, + COLOR_YELLOW, + "Shiny found!", + {}, "", + screen, + true + ); break; }else{ env.log("Prize is not shiny."); @@ -165,7 +173,7 @@ void PrizeCornerReset::program(SingleSwitchProgramEnvironment& env, ProControlle env, NOTIFICATION_STATUS_UPDATE, "Soft resetting." ); - soft_reset(env.console, context); + stats.errors += soft_reset(env.console, context); stats.resets++; context.wait_for_all_requests(); } diff --git a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp index 6e1351dcc..9a1073ec0 100644 --- a/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp +++ b/SerialPrograms/Source/PokemonRSE/Programs/ShinyHunting/PokemonRSE_AudioStarterReset.cpp @@ -197,7 +197,15 @@ void AudioStarterReset::program(SingleSwitchProgramEnvironment& env, ProControll env.log("Shiny starter detected!"); stats.shinystarter++; env.update_stats(); - send_program_notification(env, NOTIFICATION_SHINY_STARTER, COLOR_YELLOW, "Shiny starter found!", {}, "", env.console.video().snapshot(), true); + send_program_notification( + env, + NOTIFICATION_SHINY_STARTER, + COLOR_YELLOW, + "Shiny starter found!", + {}, "", + env.console.video().snapshot(), + true + ); shiny_starter = true; } else { From c847eab06c60a6991b8dd7512d6f7e133643e042 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Mon, 2 Mar 2026 17:48:58 -0800 Subject: [PATCH 2/4] try again --- .../PokemonFRLG/PokemonFRLG_Navigation.cpp | 151 +++++++++--------- 1 file changed, 73 insertions(+), 78 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp index f99c0b65d..8258d3da9 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp @@ -25,93 +25,88 @@ namespace NintendoSwitch{ namespace PokemonFRLG{ -uint64_t soft_reset(ConsoleHandle& console, ProControllerContext& context){ - uint64_t errors = 0; - while (true){ - // A + B + Select + Start - pbf_press_button(context, BUTTON_B | BUTTON_A | BUTTON_MINUS | BUTTON_PLUS, 360ms, 1440ms); +bool try_soft_reset(ConsoleHandle& console, ProControllerContext& context){ + // A + B + Select + Start + pbf_press_button(context, BUTTON_B | BUTTON_A | BUTTON_MINUS | BUTTON_PLUS, 360ms, 1440ms); - pbf_mash_button(context, BUTTON_MINUS, GameSettings::instance().SELECT_BUTTON_MASH0); - context.wait_for_all_requests(); + pbf_mash_button(context, BUTTON_MINUS, GameSettings::instance().SELECT_BUTTON_MASH0); + context.wait_for_all_requests(); - //Random wait before pressing start/A - console.log("Randomly waiting..."); - Milliseconds rng_wait = std::chrono::milliseconds(random_u32(0, 5000)); - pbf_wait(context, rng_wait); - context.wait_for_all_requests(); + //Random wait before pressing start/A + console.log("Randomly waiting..."); + Milliseconds rng_wait = std::chrono::milliseconds(random_u32(0, 5000)); + pbf_wait(context, rng_wait); + context.wait_for_all_requests(); - //Mash A until white screen to game load menu - WhiteScreenOverWatcher whitescreen(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); - LoadMenuWatcher load_menu(COLOR_BLUE); + //Mash A until white screen to game load menu + WhiteScreenOverWatcher whitescreen(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + LoadMenuWatcher load_menu(COLOR_BLUE); - int ls = run_until( - console, context, - [](ProControllerContext& context) { - pbf_mash_button(context, BUTTON_A, 1000ms); - pbf_wait(context, 5000ms); - context.wait_for_all_requests(); - }, - { whitescreen, load_menu } - ); - context.wait_for_all_requests(); - if (ls == 0) { - console.log("Entered load menu. (WhiteScreenOver)"); - }else if (ls == 1) { - console.log("Entered load menu. (LoadMenu)"); - }else{ - console.log("Unable to enter load menu.", COLOR_RED); - errors++; - if (errors >= 5){ - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "soft_reset(): Failed to reset after 5 attempts.", - console - ); - } - continue; - } - //Let the animation finish - pbf_wait(context, 500ms); - context.wait_for_all_requests(); + int ls = run_until( + console, context, + [](ProControllerContext& context) { + pbf_mash_button(context, BUTTON_A, 1000ms); + pbf_wait(context, 5000ms); + context.wait_for_all_requests(); + }, + { whitescreen, load_menu } + ); + context.wait_for_all_requests(); + if (ls == 0) { + console.log("Entered load menu. (WhiteScreenOver)"); + }else if (ls == 1) { + console.log("Entered load menu. (LoadMenu)"); + }else{ + console.log("soft_reset(): Unable to enter load menu.", COLOR_RED); + return false; + } + //Let the animation finish + pbf_wait(context, 500ms); + context.wait_for_all_requests(); - //Load game - pbf_press_button(context, BUTTON_A, 160ms, 320ms); + //Load game + pbf_press_button(context, BUTTON_A, 160ms, 320ms); - //Wait for game to load in - BlackScreenOverWatcher detector(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); - int ret = wait_until( - console, context, - GameSettings::instance().ENTER_GAME_WAIT0, - {detector} - ); - if (ret == 0){ - console.log("Entered game!"); - }else{ - console.log("Timed out waiting to enter game.", COLOR_RED); - errors++; - if (errors >= 5){ - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "soft_reset(): Failed to reset after 5 attempts.", - console - ); - } - continue; - } + //Wait for game to load in + BlackScreenOverWatcher detector(COLOR_RED, {0.282, 0.064, 0.448, 0.871}); + int ret = wait_until( + console, context, + GameSettings::instance().ENTER_GAME_WAIT0, + {detector} + ); + if (ret == 0){ + console.log("Entered game!"); + }else{ + console.log("soft_reset(): Timed out waiting to enter game.", COLOR_RED); + return false; + } - //Mash past "previously on..." - pbf_mash_button(context, BUTTON_B, GameSettings::instance().ENTER_GAME_MASH0); - context.wait_for_all_requests(); + //Mash past "previously on..." + pbf_mash_button(context, BUTTON_B, GameSettings::instance().ENTER_GAME_MASH0); + context.wait_for_all_requests(); - //Random wait no.2 - console.log("Randomly waiting..."); - Milliseconds rng_wait2 = std::chrono::milliseconds(random_u32(0, 5000)); - pbf_wait(context, rng_wait2); - context.wait_for_all_requests(); - } + //Random wait no.2 + console.log("Randomly waiting..."); + Milliseconds rng_wait2 = std::chrono::milliseconds(random_u32(0, 5000)); + pbf_wait(context, rng_wait2); + context.wait_for_all_requests(); - console.log("Soft reset completed."); - return errors; + return true; +} + +uint64_t soft_reset(ConsoleHandle& console, ProControllerContext& context){ + uint64_t errors = 0; + for (; errors < 5; errors++){ + if (try_soft_reset(console, context)){ + console.log("Soft reset completed."); + return errors; + } + } + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "soft_reset(): Failed to reset after 5 attempts.", + console + ); } void open_slot_six(ConsoleHandle& console, ProControllerContext& context){ From e3ebef06419e33c738ed0e58cc8ca3a383b74b26 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Mon, 2 Mar 2026 18:00:35 -0800 Subject: [PATCH 3/4] Recover from failing to enter summary as well. --- .../PokemonFRLG/PokemonFRLG_Navigation.cpp | 36 +++++++-------- .../PokemonFRLG/PokemonFRLG_Navigation.h | 2 +- .../ShinyHunting/PokemonFRLG_GiftReset.cpp | 44 +++++++++---------- .../ShinyHunting/PokemonFRLG_GiftReset.h | 3 +- .../PokemonFRLG_PrizeCornerReset.cpp | 2 +- 5 files changed, 43 insertions(+), 44 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp index 8258d3da9..856301cb1 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp @@ -109,7 +109,7 @@ uint64_t soft_reset(ConsoleHandle& console, ProControllerContext& context){ ); } -void open_slot_six(ConsoleHandle& console, ProControllerContext& context){ +bool try_open_slot_six(ConsoleHandle& console, ProControllerContext& context){ //Attempt to exit any dialog and open the start menu StartMenuWatcher start_menu(COLOR_RED); @@ -129,11 +129,8 @@ void open_slot_six(ConsoleHandle& console, ProControllerContext& context){ ); context.wait_for_all_requests(); if (ret < 0){ - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "open_slot_six(): Unable to open Start menu.", - console - ); + console.log("open_slot_six(): Unable to open Start menu.", COLOR_RED); + return false; } console.log("Navigating to party menu."); @@ -156,12 +153,8 @@ void open_slot_six(ConsoleHandle& console, ProControllerContext& context){ if (pm == 0){ console.log("Entered party menu."); }else{ - console.log("Unable to enter Party menu.", COLOR_RED); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "open_slot_six(): Unable to enter Party menu.", - console - ); + console.log("open_slot_six(): Unable to enter Party menu.", COLOR_RED); + return false; } context.wait_for_all_requests(); @@ -184,15 +177,22 @@ void open_slot_six(ConsoleHandle& console, ProControllerContext& context){ if (sm == 0){ console.log("Entered summary."); }else{ - console.log("Unable to enter summary.", COLOR_RED); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "open_slot_six(): Unable to enter summary.", - console - ); + console.log("open_slot_six(): Unable to enter summary.", COLOR_RED); + return false; } pbf_wait(context, 1000ms); context.wait_for_all_requests(); + return true; +} + +uint64_t open_slot_six(ConsoleHandle& console, ProControllerContext& context){ + uint64_t errors = 0; + for (; errors < 5; errors++){ + if (try_open_slot_six(console, context)){ + break; + } + } + return errors; } bool handle_encounter(ConsoleHandle& console, ProControllerContext& context, bool send_out_lead){ diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h index 284ce0174..8647d2b9b 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.h @@ -26,7 +26,7 @@ namespace PokemonFRLG{ uint64_t soft_reset(ConsoleHandle& console, ProControllerContext &context); // From the overworld, open the summary of the Pokemon in slot 6. This assumes the menu cursor is in the top slot (POKEDEX) -void open_slot_six(ConsoleHandle& console, ProControllerContext& context); +uint64_t open_slot_six(ConsoleHandle& console, ProControllerContext& context); // After press A/walking up to enter a battle, run this handle the battle start and to check if opponent is shiny. // Set send_out_lead to true and then use flee_battle() after if for run away resets diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index 4ec2c56c7..eff92f9cd 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -205,9 +205,7 @@ void GiftReset::obtain_lapras(SingleSwitchProgramEnvironment& env, ProController } //After declining to nickname, clear rival pickup and open your starter's summary -void GiftReset::open_summary(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ - GiftReset_Descriptor::Stats& stats = env.current_stats(); - +bool GiftReset::try_open_summary(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ //From no to nickname to overworld StartMenuWatcher start_menu(COLOR_RED); @@ -227,13 +225,9 @@ void GiftReset::open_summary(SingleSwitchProgramEnvironment& env, ProControllerC ); context.wait_for_all_requests(); if (ret < 0){ - stats.errors++; env.update_stats(); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "open_summary(): Unable to open Start menu after 10 attempts.", - env.console - ); + env.log("open_summary(): Unable to open Start menu after 10 attempts.", COLOR_RED); + return false; } if (TARGET != Target::starters){ @@ -261,12 +255,8 @@ void GiftReset::open_summary(SingleSwitchProgramEnvironment& env, ProControllerC if (pm == 0){ env.log("Entered party menu."); }else{ - env.log("Unable to enter party menu.", COLOR_RED); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "open_summary(): Unable to enter Party menu.", - env.console - ); + env.log("open_summary(): Unable to enter party menu.", COLOR_RED); + return false; } //Press up twice to get to the last slot @@ -290,16 +280,24 @@ void GiftReset::open_summary(SingleSwitchProgramEnvironment& env, ProControllerC if (sm == 0){ env.log("Entered summary."); }else{ - env.log("Unable to enter summary.", COLOR_RED); - OperationFailedException::fire( - ErrorReport::SEND_ERROR_REPORT, - "open_summary(): Unable to enter summary.", - env.console - ); + env.log("open_summary(): Unable to enter summary.", COLOR_RED); + return false; } pbf_wait(context, 1000ms); context.wait_for_all_requests(); - + return true; +} +uint64_t GiftReset::open_summary(SingleSwitchProgramEnvironment& env, ProControllerContext& context){ + uint64_t errors = 0; + for (; errors < 5; errors++){ + if (try_open_summary(env, context)){ + break; + }else{ + env.log("Mashing B to return to overworld and retry..."); + pbf_mash_button(context, BUTTON_B, 10000ms); + } + } + return errors; } @@ -325,7 +323,7 @@ void GiftReset::program(SingleSwitchProgramEnvironment& env, ProControllerContex }else{ obtain_lapras(env, context); } - open_summary(env, context); + stats.errors += open_summary(env, context); VideoSnapshot screen = env.console.video().snapshot(); diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h index b5baf3278..2da5fa7f2 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.h @@ -35,7 +35,8 @@ class GiftReset : public SingleSwitchProgramInstance{ private: void obtain_pokemon(SingleSwitchProgramEnvironment& env, ProControllerContext& context); void obtain_lapras(SingleSwitchProgramEnvironment& env, ProControllerContext& context); - void open_summary(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + bool try_open_summary(SingleSwitchProgramEnvironment& env, ProControllerContext& context); + uint64_t open_summary(SingleSwitchProgramEnvironment& env, ProControllerContext& context); enum class Target{ starters, diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp index 53e576c9a..9a4d1fd0b 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_PrizeCornerReset.cpp @@ -146,7 +146,7 @@ void PrizeCornerReset::program(SingleSwitchProgramEnvironment& env, ProControlle while (!shiny_found){ obtain_prize(env, context); - open_slot_six(env.console, context); + stats.errors += open_slot_six(env.console, context); VideoSnapshot screen = env.console.video().snapshot(); From 7c70974749d3b6429ca9a24e27ec68417577e1e6 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Mon, 2 Mar 2026 18:04:59 -0800 Subject: [PATCH 4/4] Fix error case. --- .../Source/PokemonFRLG/PokemonFRLG_Navigation.cpp | 11 +++++++++-- .../Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp | 8 ++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp index 856301cb1..867c0a5ae 100644 --- a/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp +++ b/SerialPrograms/Source/PokemonFRLG/PokemonFRLG_Navigation.cpp @@ -189,10 +189,17 @@ uint64_t open_slot_six(ConsoleHandle& console, ProControllerContext& context){ uint64_t errors = 0; for (; errors < 5; errors++){ if (try_open_slot_six(console, context)){ - break; + return errors; + }else{ + console.log("Mashing B to return to overworld and retry..."); + pbf_mash_button(context, BUTTON_B, 10000ms); } } - return errors; + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "open_slot_six(): Failed to open party summary after 5 attempts.", + console + ); } bool handle_encounter(ConsoleHandle& console, ProControllerContext& context, bool send_out_lead){ diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp index eff92f9cd..5fbcc9f68 100644 --- a/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp +++ b/SerialPrograms/Source/PokemonFRLG/Programs/ShinyHunting/PokemonFRLG_GiftReset.cpp @@ -291,13 +291,17 @@ uint64_t GiftReset::open_summary(SingleSwitchProgramEnvironment& env, ProControl uint64_t errors = 0; for (; errors < 5; errors++){ if (try_open_summary(env, context)){ - break; + return errors; }else{ env.log("Mashing B to return to overworld and retry..."); pbf_mash_button(context, BUTTON_B, 10000ms); } } - return errors; + OperationFailedException::fire( + ErrorReport::SEND_ERROR_REPORT, + "open_summary(): Failed to open party summary after 5 attempts.", + env.console + ); }