Просмотр исходного кода

trade: Add ability to reset connection state

Allows for resetting the connection back to not connected, as if
the Flipper left the Trade Center or restarted, but keeps the current
pokemon in RAM.

This woudl allow, for example, to trade a pokemon between two real
cartridges with only a single Game Boy. By trading from Pokemon Cart A
to the Flipper, resetting the connection state on the Flipper, and
loading Pokemon Cart B in to the Game Boy, and trading from the
Flipper to the real game.

Fixes #37

Signed-off-by: Kris Bahnsen <Kris@KBEmbedded.com>
Kris Bahnsen 1 год назад
Родитель
Сommit
b6dba301b8

+ 10 - 0
README.md

@@ -15,6 +15,7 @@ The video below trades a Bulbasaur from the Flipper to a Game Boy Color with Pok
     - [Customizing Pokemon](#customizing-pokemon)
   - [Trade](#trade-pkmn)
     - [Modifying Traded Pokemon](#modifying-traded-pokemon)
+    - [Reset Trade Connection State](#reset-trade-connection-state)
 - [How it Works / Build your own Interface](#how-does-it-work)
 
 
@@ -376,6 +377,15 @@ The Game Boy should remain on and in the trade room. When the Flipper re-enters
 
 ---
 
+#### Reset Trade Connection State
+It is possible to reset the Flipper's connection state to having never been connected to a Game Boy. This allows the Flipper to restart communication with a Game Boy if it was accidentally turned off, for example, and the Game Boy needs to re-enter the Trade Center. Doing this keeps the current Pokemon the Flipper has in memory intact.
+
+This can also be used to leverage the Flipper to trade a pokemon between two Pokemon games with only a single Game Boy. For example, trade from Pokemon Blue to the Flipper (and then modifying the Pokemon on the Flipper if desired), resetting the trade state on the Flipper, swap the Game Boy game to Pokemon Silver, and on both the Game Boy and Flipper, start the trade process (using Time Capsule trade mode on the Pokemon Silver game).
+
+Once a connection has been established between the Flipper and a Pokemon game, the option `Reset Connection` will appear in the configuration screen under `Trade PKMN`. The Flipper will then ask for confirmation of the operation.
+
+---
+
 #### Special Note on MALVEKE PCB Rev. <= 2.5
 Version 2.0 of the Pokemon Trade tool fixes a bug on MALVEKE boards that are Rev. 2.5 or lower where after a trade is completed the `OK` button no longer functions. However, while on the trade screen the `OK` button will continue to not function. For example, if you try to press the `OK` button to turn the backlight on, the Flipper will not respond. The `OK` button functionality will be restored once the Flipper leaves the Trade screen.
 

+ 1 - 0
src/scenes/include/pokemon_scene_config.h

@@ -20,3 +20,4 @@ ADD_SCENE(pokemon,	select_name,		OTName)
 ADD_SCENE(pokemon,	trade,			Trade)
 ADD_SCENE(pokemon,	select_pins,		Pins)
 ADD_SCENE(pokemon,	exit_confirm,		ExitConfirm)
+ADD_SCENE(pokemon,	reset_confirm,		ResetConfirm)

+ 8 - 0
src/scenes/pokemon_gen.c

@@ -180,6 +180,14 @@ void pokemon_scene_gen_on_enter(void* context) {
     submenu_add_item(
         pokemon_fap->submenu, "Trade PKMN", PokemonSceneTrade, scene_change_from_main_cb, pokemon_fap);
 
+    if (trade_connected(pokemon_fap->trade)) {
+        submenu_add_item(pokemon_fap->submenu,
+                         "Reset Connection",
+                         PokemonSceneResetConfirm,
+                         scene_change_from_main_cb,
+                         pokemon_fap);
+    }
+
     /* TODO: Add Save pokemon option here */
 
     /* HACK: No matter what gen were in, we just store the scene state in PokemonSceneGenITrade */

+ 65 - 0
src/scenes/pokemon_trade_reset_confirm.c

@@ -0,0 +1,65 @@
+#include <gui/modules/dialog_ex.h>
+
+#include <pokemon_icons.h>
+#include <src/include/pokemon_app.h>
+#include <src/include/pokemon_data.h>
+
+#include <src/scenes/include/pokemon_scene.h>
+
+#include <src/views/select_pokemon.h>
+#include <src/views/trade.h>
+
+static void pokemon_scene_reset_confirm_dialog_callback(DialogExResult result, void* context) {
+    PokemonFap* pokemon_fap = context;
+
+    view_dispatcher_send_custom_event(pokemon_fap->view_dispatcher, result);
+}
+
+void pokemon_scene_reset_confirm_on_enter(void* context) {
+    PokemonFap* pokemon_fap = context;
+    DialogEx* dialog_ex = pokemon_fap->dialog_ex;
+
+    // Clean view
+    dialog_ex_reset(pokemon_fap->dialog_ex);
+
+    dialog_ex_set_left_button_text(dialog_ex, "Reset");
+    dialog_ex_set_right_button_text(dialog_ex, "Back");
+    dialog_ex_set_header(dialog_ex, "Reset Trade State?", 64, 0, AlignCenter, AlignTop);
+    dialog_ex_set_text(
+        dialog_ex,
+        "Trade partner will need to\nleave and re-enter the\nTrade Center!",
+        64,
+        12,
+        AlignCenter,
+        AlignTop);
+    dialog_ex_set_context(dialog_ex, pokemon_fap);
+    dialog_ex_set_result_callback(dialog_ex, pokemon_scene_reset_confirm_dialog_callback);
+
+    view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, AppViewDialogEx);
+}
+
+bool pokemon_scene_reset_confirm_on_event(void* context, SceneManagerEvent event) {
+    PokemonFap* pokemon_fap = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        switch (event.event) {
+        case DialogExResultLeft:
+            trade_reset_connection(pokemon_fap->trade);
+        [[fallthrough]];
+        case DialogExResultRight:
+            scene_manager_previous_scene(pokemon_fap->scene_manager);
+	    consumed = true;
+            break;
+        }
+    } else if(event.type == SceneManagerEventTypeBack) {
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void pokemon_scene_reset_confirm_on_exit(void* context) {
+    UNUSED(context);
+}
+

+ 23 - 0
src/views/trade.c

@@ -965,3 +965,26 @@ void trade_free(ViewDispatcher* view_dispatcher, uint32_t view_id, void* trade_c
     pokemon_data_free(trade->input_pdata);
     free(trade);
 }
+
+void trade_reset_connection(void* trade_ctx) {
+    struct trade_ctx *trade = trade_ctx;
+
+    with_view_model(
+        trade->view,
+        struct trade_model * model,
+        { model->gameboy_status = GAMEBOY_CONN_FALSE; },
+        false);
+}
+
+bool trade_connected(void* trade_ctx) {
+    struct trade_ctx *trade = trade_ctx;
+    bool connected = false;
+
+    with_view_model(
+        trade->view,
+        struct trade_model * model,
+        { connected = (model->gameboy_status > GAMEBOY_CONN_FALSE); },
+        false);
+
+    return connected;
+}

+ 4 - 0
src/views/trade.h

@@ -14,4 +14,8 @@ void* trade_alloc(
 
 void trade_free(ViewDispatcher* view_dispatcher, uint32_t view_id, void* trade_ctx);
 
+void trade_reset_connection(void* trade_ctx);
+
+bool trade_connected(void* trade_ctx);
+
 #endif /* TRADE_H */