diff --git a/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.cpp b/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.cpp
index b68c4563df..799ea19442 100644
--- a/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.cpp
@@ -26,6 +26,7 @@ namespace PokemonFRLG {
TrainerIdReader::TrainerIdReader(Color color)
: m_color(color)
, m_box_tid(0.742683, 0.117314, 0.129734, 0.076006)
+ , m_box_tid_jpn(0.712981, 0.118836, 0.207212, 0.077373)
{}
void TrainerIdReader::make_overlays(VideoOverlaySet &items) const {
@@ -34,13 +35,13 @@ void TrainerIdReader::make_overlays(VideoOverlaySet &items) const {
}
uint16_t TrainerIdReader::read_tid(
- Logger &logger, const ImageViewRGB32 &frame
+ Logger& logger, Language language, const ImageViewRGB32& frame
){
ImageViewRGB32 game_screen =
extract_box_reference(frame, GameSettings::instance().GAME_BOX);
- ImageViewRGB32 tid_region = extract_box_reference(game_screen, m_box_tid);
+ ImageViewRGB32 tid_region = extract_box_reference(game_screen, language == Language::Japanese ? m_box_tid_jpn : m_box_tid);
if (!GlobalSettings::instance().USE_PADDLE_OCR){
// Tesseract-free path: waterfill segmentation + template matching
diff --git a/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.h b/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.h
index e8b00cf8cc..c33fdbcbe1 100644
--- a/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.h
+++ b/SerialPrograms/Source/PokemonFRLG/Inference/PokemonFRLG_TrainerIdReader.h
@@ -31,13 +31,13 @@ class TrainerIdReader {
// Reads the Trainer ID on the Trainer Card
uint16_t read_tid(
- Logger &logger, const ImageViewRGB32 &frame
+ Logger& logger, Language language, const ImageViewRGB32& frame
);
private:
Color m_color;
ImageFloatBox m_box_tid;
-
+ ImageFloatBox m_box_tid_jpn;
};
} // namespace PokemonFRLG
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_BlindNavigation.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_BlindNavigation.cpp
index f2e06aac71..621f81a657 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_BlindNavigation.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_BlindNavigation.cpp
@@ -22,7 +22,7 @@ void set_seed_after_delay(ProControllerContext& context, SeedButton SEED_BUTTON,
switch (console_type){
case ConsoleType::Switch1:
// Switch 1 enters the game a little bit earlier
- pbf_wait(context, 755ms);
+ pbf_wait(context, 750ms);
break;
default:
break;
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp
index 4656f249a3..dc0da6120c 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_GiftRng.cpp
@@ -539,7 +539,8 @@ void GiftRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
RngAdvanceHistory ADVANCE_HISTORY;
RngCalibrationHistory CALIBRATION_HISTORY;
uint64_t INITIAL_ADVANCES_RADIUS = USE_TEACHY_TV ? 8192 : 1024;
- uint64_t resets = 0;
+
+ uint16_t failed_searches = 0;
while (true){
if (CALIBRATION_HISTORY.results.size() > 0){
@@ -552,7 +553,17 @@ void GiftRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
env.log("Missed target.");
}
- if (resets > MAX_RESETS){
+ if (failed_searches >= 5){
+ env.log("Failed to find any matches 5 times in a row");
+ OperationFailedException::fire(
+ ErrorReport::NO_ERROR_REPORT,
+ "Failed to find any matches 5 times in a row. Check your seed and advances settings.",
+ env.console
+ );
+ break;
+ }
+
+ if (stats.resets > MAX_RESETS){
env.log("Max resets reached.");
break;
}
@@ -670,6 +681,11 @@ void GiftRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
bool finished = update_history(env.console, ADVANCE_HISTORY, CALIBRATION_HISTORY, MAX_HISTORY_LENGTH, SEED_CALIBRATION_FRAMES, ADVANCES_CALIBRATION, CONTINUE_SCREEN_ADJUSTMENT, search_hits, 1);
if (finished || (MAX_RARE_CANDIES == 0)){
env.log("RNG search finished.");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
continue;
}
@@ -694,6 +710,12 @@ void GiftRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
);
if (finished){
+ env.log("RNG Search finished");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
break;
}
}
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SidHelper.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SidHelper.cpp
index 9f4a8863a9..ac902fe525 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SidHelper.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_SidHelper.cpp
@@ -72,7 +72,7 @@ SidHelper::SidHelper()
"The target advances for finalizing the SID. This is arbitrary unless you're attempting to hit a specific TID/SID combination.
"
"This value should always be odd.",
LockMode::LOCK_WHILE_RUNNING,
- 2301, 2275 // default, min
+ 3001, 2275 // default, min
)
, NUM_CANDIDATES(
"# Candidate SIDs:
"
@@ -125,8 +125,8 @@ void set_sid_from_name_screen(
);
if (extra_press_at_end){
- pbf_press_button(context, BUTTON_A, 200ms, 800ms);
- delay = delay > 1000ms ? delay - 1000ms : 0ms;
+ pbf_press_button(context, BUTTON_A, 200ms, 1300ms);
+ delay = delay > 1500ms ? delay - 1500ms : 0ms;
}
pbf_press_button(context, BUTTON_A, 200ms, delay);
@@ -209,7 +209,7 @@ void navigate_to_trainer_card(SingleSwitchProgramEnvironment& env, ProController
}
}
-uint16_t read_tid(SingleSwitchProgramEnvironment& env, ProControllerContext& context){
+uint16_t read_tid(SingleSwitchProgramEnvironment& env, ProControllerContext& context, Language lang){
TrainerIdReader reader;
VideoOverlaySet overlays(env.console.overlay());
reader.make_overlays(overlays);
@@ -217,7 +217,7 @@ uint16_t read_tid(SingleSwitchProgramEnvironment& env, ProControllerContext& con
VideoSnapshot screen = env.console.video().snapshot();
env.log("Trainer Card detected.");
env.log("Reading TID...");
- uint16_t tid = reader.read_tid(env.logger(), screen);
+ uint16_t tid = reader.read_tid(env.logger(), lang, screen);
env.log("TID: " + std::to_string(tid));
context.wait_for_all_requests();
@@ -299,7 +299,10 @@ void SidHelper::program(SingleSwitchProgramEnvironment& env, ProControllerContex
const double& FIXED_ADVANCES_OFFSET = 7; // determined empirically. Probably not console/setup dependent
- bool extra_press_at_end = (LANGUAGE == Language::German);
+ bool extra_press_at_end = (
+ LANGUAGE == Language::German ||
+ LANGUAGE == Language::Japanese
+ );
const uint64_t SID_DELAY = uint64_t((TARGET_ADVANCES - 2*FINAL_TEXT_FRAMES + FIXED_ADVANCES_OFFSET) * FRAME_DURATION / 2); // advances pass 2 by 2
env.log("Delay: " + std::to_string(SID_DELAY) + "ms");
@@ -308,7 +311,7 @@ void SidHelper::program(SingleSwitchProgramEnvironment& env, ProControllerContex
finish_intro_animations(env, context);
navigate_to_trainer_card(env, context);
- uint16_t tid = read_tid(env, context);
+ uint16_t tid = read_tid(env, context, lang);
std::vector> sid_messages = get_sid_messages(
env, context, tid, TARGET_ADVANCES, NUM_CANDIDATES
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StarterRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StarterRng.cpp
index 084c4ca8e1..91e886ca68 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StarterRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StarterRng.cpp
@@ -688,9 +688,10 @@ void StarterRng::program(SingleSwitchProgramEnvironment& env, ProControllerConte
RngAdvanceHistory ADVANCE_HISTORY;
RngCalibrationHistory CALIBRATION_HISTORY;
uint64_t INITIAL_ADVANCES_RADIUS = 1024;
- uint64_t resets = 0;
bool wildshiny_found = false;
+ uint16_t failed_searches = 0;
+
while (true){
if (CALIBRATION_HISTORY.results.size() > 0){
env.log("Checking for nonshiny target hit...");
@@ -702,7 +703,17 @@ void StarterRng::program(SingleSwitchProgramEnvironment& env, ProControllerConte
env.log("Missed target.");
}
- if (resets > MAX_RESETS){
+ if (failed_searches >= 5){
+ env.log("Failed to find any matches 5 times in a row");
+ OperationFailedException::fire(
+ ErrorReport::NO_ERROR_REPORT,
+ "Failed to find any matches 5 times in a row. Check your seed and advances settings.",
+ env.console
+ );
+ break;
+ }
+
+ if (stats.resets > MAX_RESETS){
env.log("Max resets reached.");
break;
}
@@ -812,6 +823,11 @@ void StarterRng::program(SingleSwitchProgramEnvironment& env, ProControllerConte
bool finished = update_history(env.console, ADVANCE_HISTORY, CALIBRATION_HISTORY, MAX_HISTORY_LENGTH, SEED_CALIBRATION_FRAMES, ADVANCES_CALIBRATION, CONTINUE_SCREEN_ADJUSTMENT, search_hits, 1);
if (finished){
env.log("RNG search finished.");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
continue;
}
@@ -838,6 +854,11 @@ void StarterRng::program(SingleSwitchProgramEnvironment& env, ProControllerConte
finished = update_history(env.console, ADVANCE_HISTORY, CALIBRATION_HISTORY, MAX_HISTORY_LENGTH, SEED_CALIBRATION_FRAMES, ADVANCES_CALIBRATION, CONTINUE_SCREEN_ADJUSTMENT, search_hits, 5);
if (finished){
env.log("RNG search finished.");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
continue;
}
}
@@ -898,6 +919,11 @@ void StarterRng::program(SingleSwitchProgramEnvironment& env, ProControllerConte
finished = update_history(env.console, ADVANCE_HISTORY, CALIBRATION_HISTORY, MAX_HISTORY_LENGTH, SEED_CALIBRATION_FRAMES, ADVANCES_CALIBRATION, CONTINUE_SCREEN_ADJUSTMENT, search_hits, 5);
if (finished){
env.log("RNG search finished.");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
break;
}
}
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StaticRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StaticRng.cpp
index e674c2262a..86a5333e14 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StaticRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_StaticRng.cpp
@@ -677,7 +677,8 @@ void StaticRng::program(SingleSwitchProgramEnvironment& env, ProControllerContex
RngAdvanceHistory ADVANCE_HISTORY;
RngCalibrationHistory CALIBRATION_HISTORY;
uint64_t INITIAL_ADVANCES_RADIUS = USE_TEACHY_TV ? 8192 : 1024;
- uint64_t resets = 0;
+
+ uint16_t failed_searches = 0;
while (true){
if (CALIBRATION_HISTORY.results.size() > 0){
@@ -690,7 +691,17 @@ void StaticRng::program(SingleSwitchProgramEnvironment& env, ProControllerContex
env.log("Missed target.");
}
- if (resets > MAX_RESETS){
+ if (failed_searches >= 5){
+ env.log("Failed to find any matches 5 times in a row");
+ OperationFailedException::fire(
+ ErrorReport::NO_ERROR_REPORT,
+ "Failed to find any matches 5 times in a row. Check your seed and advances settings.",
+ env.console
+ );
+ break;
+ }
+
+ if (stats.resets > MAX_RESETS){
env.log("Max resets reached.");
break;
}
@@ -814,6 +825,11 @@ void StaticRng::program(SingleSwitchProgramEnvironment& env, ProControllerContex
bool finished = update_history(env.console, ADVANCE_HISTORY, CALIBRATION_HISTORY, MAX_HISTORY_LENGTH, SEED_CALIBRATION_FRAMES, ADVANCES_CALIBRATION, CONTINUE_SCREEN_ADJUSTMENT, search_hits, 1);
if (finished || (MAX_RARE_CANDIES == 0)){
env.log("RNG search finished.");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
continue;
}
@@ -838,6 +854,12 @@ void StaticRng::program(SingleSwitchProgramEnvironment& env, ProControllerContex
);
if (finished){
+ env.log("RNG Search finished");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
break;
}
}
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_WildRng.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_WildRng.cpp
index 4b6cebc004..5a0685f0a9 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_WildRng.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/RngManipulation/PokemonFRLG_WildRng.cpp
@@ -722,7 +722,8 @@ void WildRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
RngAdvanceHistory ADVANCE_HISTORY;
RngCalibrationHistory CALIBRATION_HISTORY;
uint64_t INITIAL_ADVANCES_RADIUS = USE_TEACHY_TV ? 8192 : 1024;
- uint64_t resets = 0;
+
+ uint16_t failed_searches = 0;
while (true){
if (CALIBRATION_HISTORY.results.size() > 0){
@@ -735,7 +736,17 @@ void WildRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
env.log("Missed target.");
}
- if (resets > MAX_RESETS){
+ if (failed_searches >= 5){
+ env.log("Failed to find any matches 5 times in a row");
+ OperationFailedException::fire(
+ ErrorReport::NO_ERROR_REPORT,
+ "Failed to find any matches 5 times in a row. Check your seed and advances settings.",
+ env.console
+ );
+ break;
+ }
+
+ if (stats.resets > MAX_RESETS){
env.log("Max resets reached.");
break;
}
@@ -877,6 +888,11 @@ void WildRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
finished = finished || all_indistinguishable(search_hits, searcher, SUPER_ROD);
if (finished || (MAX_RARE_CANDIES == 0)){
env.log("RNG search finished.");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
continue;
}
@@ -902,6 +918,12 @@ void WildRng::program(SingleSwitchProgramEnvironment& env, ProControllerContext&
finished = finished || all_indistinguishable(search_hits, searcher, SUPER_ROD);
if (finished){
+ env.log("RNG Search finished");
+ if (search_hits.size() == 0){
+ failed_searches++;
+ }else{
+ failed_searches = 0;
+ }
break;
}
}
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.cpp b/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.cpp
index a2d365f1c9..f1765a8a5a 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.cpp
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.cpp
@@ -36,7 +36,23 @@ ReadTrainerId_Descriptor::ReadTrainerId_Descriptor()
){}
ReadTrainerId::ReadTrainerId()
-{}
+ : LANGUAGE(
+ "Game Language:
"
+ "Language affects the number of advances (based on the number of text characters) that pass after the last button press.",
+ {
+ Language::English,
+ Language::Japanese,
+ Language::Spanish,
+ Language::French,
+ Language::German,
+ Language::Italian,
+ },
+ LockMode::LOCK_WHILE_RUNNING,
+ true
+ )
+{
+ PA_ADD_OPTION(LANGUAGE);
+}
void ReadTrainerId::program(
SingleSwitchProgramEnvironment &env,
@@ -56,7 +72,7 @@ void ReadTrainerId::program(
if (trainercard){
env.log("Trainer Card detected.");
env.log("Reading TID...");
- uint16_t tid = reader.read_tid(env.logger(), screen);
+ uint16_t tid = reader.read_tid(env.logger(), LANGUAGE, screen);
env.log("TID: " + std::to_string(tid));
}else{
env.log("Trainer Card not detected!");
diff --git a/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.h b/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.h
index fff3c2c268..54886c3e71 100644
--- a/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.h
+++ b/SerialPrograms/Source/PokemonFRLG/Programs/TestPrograms/PokemonFRLG_ReadTrainerId.h
@@ -33,6 +33,8 @@ class ReadTrainerId : public SingleSwitchProgramInstance{
VideoStream &stream, FeedbackType feedback_type
) override{}
+private:
+ OCR::LanguageOCROption LANGUAGE;
};
} // namespace PokemonFRLG