From 4277b04e4a579e5cb7e78392e4dc4c3c260e072e Mon Sep 17 00:00:00 2001 From: Kris Bahnsen Date: Mon, 29 May 2023 20:17:44 -0700 Subject: [PATCH] pokemon: refactor This accomplishes a few things: - Retype vars introduced in previous commits to match format of existing project code. - Move common elements to a single struct for the whole application. This also removes the struct for each of the two current views and passes around the main struct as callback contexts. - Remove the use of view models as copies of data and instead point the model for each view at the main struct. All of the draw callbacks for existing views end up needing this data and only have access to a view model at runtime. - Partial cleanup of circular dependencies and unneeded variables. Some headers had circular includes which would compile but caused issues. --- pokemon_app.cpp | 71 ++++++++++-------- pokemon_app.h | 53 ++++++++----- views/select_pokemon.cpp | 151 +++++++++++++------------------------ views/select_pokemon.hpp | 15 ++-- views/trade.cpp | 156 +++++++++++++++------------------------ views/trade.hpp | 15 +--- 6 files changed, 196 insertions(+), 265 deletions(-) diff --git a/pokemon_app.cpp b/pokemon_app.cpp index ffad2a5410f..58a8c24709c 100644 --- a/pokemon_app.cpp +++ b/pokemon_app.cpp @@ -1,6 +1,8 @@ #include "pokemon_app.h" +#include "views/trade.hpp" +#include "views/select_pokemon.hpp" -struct pokemon_lut pokemon_table[] = { +const PokemonTable pokemon_table[] = { {"Bulbasaur", &I_bulbasaur, 0x99}, {"Ivysaur", &I_ivysaur, 0x09}, {"Venusaur", &I_venusaur, 0x9A}, @@ -159,66 +161,77 @@ uint32_t pokemon_exit_confirm_view(void* context) { UNUSED(context); return AppViewExitConfirm; } -App* pokemon_alloc() { - App* app = (App*)malloc(sizeof(App)); + +PokemonFap* pokemon_alloc() { + PokemonFap* pokemon_fap = (PokemonFap*)malloc(sizeof(PokemonFap)); // Gui - app->gui = (Gui*)furi_record_open(RECORD_GUI); + /* XXX: what is furi_record open for? It doesn't return a Gui handle. */ + pokemon_fap->gui = (Gui*)furi_record_open(RECORD_GUI); + // View dispatcher - app->view_dispatcher = view_dispatcher_alloc(); + pokemon_fap->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_set_event_callback_context(app->view_dispatcher, app); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_enable_queue(pokemon_fap->view_dispatcher); + view_dispatcher_set_event_callback_context(pokemon_fap->view_dispatcher, pokemon_fap); + view_dispatcher_attach_to_gui( + pokemon_fap->view_dispatcher, pokemon_fap->gui, ViewDispatcherTypeFullscreen); // Start Index first pokemon - app->current_pokemon = 0; + pokemon_fap->curr_pokemon = 0; + + // Set up pointer to pokemon table + pokemon_fap->pokemon_table = pokemon_table; + // Select Pokemon View - app->select_pokemon = select_pokemon_alloc(app); - view_set_previous_callback(select_pokemon_get_view(app), pokemon_exit_confirm_view); + pokemon_fap->select_view = select_pokemon_alloc(pokemon_fap); + view_set_previous_callback(select_pokemon_get_view(pokemon_fap), pokemon_exit_confirm_view); view_dispatcher_add_view( - app->view_dispatcher, AppViewSelectPokemon, select_pokemon_get_view(app)); + pokemon_fap->view_dispatcher, AppViewSelectPokemon, select_pokemon_get_view(pokemon_fap)); // Trade View - app->trade = trade_alloc(app); - view_set_previous_callback(trade_get_view(app), pokemon_exit_confirm_view); - view_dispatcher_add_view(app->view_dispatcher, AppViewTrade, trade_get_view(app)); + pokemon_fap->trade_view = trade_alloc(pokemon_fap); + view_set_previous_callback(pokemon_fap->trade_view, pokemon_exit_confirm_view); + view_dispatcher_add_view(pokemon_fap->view_dispatcher, AppViewTrade, pokemon_fap->trade_view); - view_dispatcher_switch_to_view(app->view_dispatcher, AppViewSelectPokemon); + view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, AppViewSelectPokemon); - return app; + return pokemon_fap; } -void free_app(App* app) { - furi_assert(app); +void free_app(PokemonFap* pokemon_fap) { + furi_assert(pokemon_fap); // Free views - view_dispatcher_remove_view(app->view_dispatcher, AppViewSelectPokemon); - select_pokemon_free(app); - view_dispatcher_remove_view(app->view_dispatcher, AppViewTrade); - trade_free(app); + view_dispatcher_remove_view(pokemon_fap->view_dispatcher, AppViewSelectPokemon); + /* XXX: Still need to deal with select_pokemon code */ + select_pokemon_free(pokemon_fap); + view_dispatcher_remove_view(pokemon_fap->view_dispatcher, AppViewTrade); + trade_free(pokemon_fap); // Close records furi_record_close(RECORD_GUI); - app->gui = NULL; + /* XXX: Since furi_record doesn't appear to be a Gui function, it wouldn't clear the pointer */ + pokemon_fap->gui = NULL; // Free rest - free(app); + free(pokemon_fap); + pokemon_fap = NULL; } extern "C" int32_t pokemon_app(void* p) { UNUSED(p); //FURI_LOG_D(TAG, "init scene"); - App* app = (App*)pokemon_alloc(); + //App* app = (App*)pokemon_alloc(); + PokemonFap* pokemon_fap = pokemon_alloc(); furi_hal_light_set(LightRed, 0x00); furi_hal_light_set(LightGreen, 0x00); furi_hal_light_set(LightBlue, 0x00); //switch view and run dispatcher - view_dispatcher_run(app->view_dispatcher); + view_dispatcher_run(pokemon_fap->view_dispatcher); // Free resources - free_app(app); - furi_record_close(RECORD_GUI); + free_app(pokemon_fap); return 0; } diff --git a/pokemon_app.h b/pokemon_app.h index 574a89f9f47..43b957d995d 100644 --- a/pokemon_app.h +++ b/pokemon_app.h @@ -10,18 +10,16 @@ #include #include -#include "views/select_pokemon.hpp" -#include "views/trade.hpp" - #define TAG "Pokemon" -struct pokemon_lut { +struct pokemon_data_table { const char* name; const Icon* icon; const uint8_t hex; }; -typedef struct App App; +typedef struct pokemon_data_table PokemonTable; + typedef enum { GAMEBOY_INITIAL, GAMEBOY_READY, @@ -32,6 +30,7 @@ typedef enum { GAMEBOY_TRADING } render_gameboy_state_t; +#if 0 struct App { Gui* gui; ViewDispatcher* view_dispatcher; @@ -42,6 +41,37 @@ struct App { int current_pokemon = 0; char pokemon_hex_code = ' '; }; +#endif + +struct pokemon_fap { + Gui* gui; + ViewDispatcher* view_dispatcher; + + /* View ports for each of the application's steps */ + View* select_view; + View* trade_view; + + /* Table of pokemon data for Gen I */ + const PokemonTable* pokemon_table; + + /* The currently selected pokemon */ + int curr_pokemon; + + /* Some state tracking */ + /* This, combined with some globals in trade.cpp, can probably be better + * consolidated at some point. + */ + bool trading; + bool connected; + render_gameboy_state_t gameboy_status; + + /* TODO: Other variables will end up here, like selected level, EV/IV, + * moveset, etc. Likely will want to be another sub struct similar to + * the actual pokemon data structure. + */ +}; + +typedef struct pokemon_fap PokemonFap; typedef enum { AppViewSelectPokemon, @@ -49,17 +79,4 @@ typedef enum { AppViewExitConfirm, } AppView; -typedef void (*SelectPokemonCallback)(void* context, uint32_t index); -typedef struct SelectPokemonModel { - int current_pokemon = 0; - char pokemon_hex_code = ' '; - bool trading = false; - bool connected = false; - render_gameboy_state_t gameboy_status = GAMEBOY_INITIAL; - SelectPokemonCallback callback; - void* callback_context; -} SelectPokemonModel; - -extern struct pokemon_lut pokemon_table[]; - #endif /* POKEMON_APP_H */ diff --git a/views/select_pokemon.cpp b/views/select_pokemon.cpp index 08c7daa8899..7ca7430e086 100644 --- a/views/select_pokemon.cpp +++ b/views/select_pokemon.cpp @@ -1,11 +1,9 @@ #include "../pokemon_app.h" #include "select_pokemon.hpp" -static void select_pokemon_render_callback(Canvas* canvas, void* context) { - canvas_clear(canvas); - - SelectPokemonModel* model = (SelectPokemonModel*)context; - const uint8_t current_index = model->current_pokemon; +static void select_pokemon_render_callback(Canvas* canvas, void* model) { + PokemonFap* pokemon_fap = *(PokemonFap**)model; + const uint8_t current_index = pokemon_fap->curr_pokemon; char pokedex_num[5]; snprintf(pokedex_num, sizeof(pokedex_num), "#%03d", current_index + 1); @@ -15,7 +13,7 @@ static void select_pokemon_render_callback(Canvas* canvas, void* context) { canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned(canvas, 55, 38, AlignLeft, AlignTop, pokedex_num); - canvas_draw_icon(canvas, 0, 0, pokemon_table[current_index].icon); + canvas_draw_icon(canvas, 0, 0, pokemon_fap->pokemon_table[current_index].icon); canvas_draw_icon(canvas, 128 - 80, 0, &I_Space_80x18); canvas_draw_str_aligned(canvas, (128 - 40), 5, AlignCenter, AlignTop, "Select Pokemon"); @@ -24,104 +22,64 @@ static void select_pokemon_render_callback(Canvas* canvas, void* context) { } static bool select_pokemon_input_callback(InputEvent* event, void* context) { - furi_assert(context); - SelectPokemon* select_pokemon = (SelectPokemon*)context; + PokemonFap* pokemon_fap = (PokemonFap*)context; bool consumed = false; + furi_assert(context); + /* We only handle InputTypePress at the moment */ if(event->type != InputTypePress) return consumed; switch(event->key) { /* Advance to next view with the selected pokemon */ case InputKeyOk: - with_view_model_cpp( - select_pokemon->view, - SelectPokemonModel*, - model, - { - select_pokemon->app->current_pokemon = model->current_pokemon; - select_pokemon->app->pokemon_hex_code = pokemon_table[model->current_pokemon].hex; - }, - false); - view_dispatcher_switch_to_view(select_pokemon->app->view_dispatcher, AppViewTrade); + view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, AppViewTrade); consumed = true; break; /* Return to the previous view */ case InputKeyBack: - view_dispatcher_switch_to_view(select_pokemon->app->view_dispatcher, VIEW_NONE); + view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, VIEW_NONE); consumed = true; break; /* Move back one through the pokedex listing */ case InputKeyLeft: - with_view_model_cpp( - select_pokemon->view, - SelectPokemonModel*, - model, - { - if(model->current_pokemon == 0) { - model->current_pokemon = 150; - } else { - model->current_pokemon--; - } - }, - true); + if(pokemon_fap->curr_pokemon == 0) + pokemon_fap->curr_pokemon = 150; + else + pokemon_fap->curr_pokemon--; consumed = true; break; - /* Move back ten through the pokemon listing, wrap to max pokemon on + /* Move back ten through the pokemon listing, wrap to max pokemon on * underflow. */ case InputKeyDown: - with_view_model_cpp( - select_pokemon->view, - SelectPokemonModel*, - model, - { - if(model->current_pokemon >= 10) { - model->current_pokemon -= 10; - } else { - model->current_pokemon = 150; - } - }, - true); + if(pokemon_fap->curr_pokemon >= 10) + pokemon_fap->curr_pokemon -= 10; + else + pokemon_fap->curr_pokemon = 150; consumed = true; break; /* Move forward one through the pokedex listing */ case InputKeyRight: - with_view_model_cpp( - select_pokemon->view, - SelectPokemonModel*, - model, - { - if(model->current_pokemon == 150) { - model->current_pokemon = 0; - } else { - model->current_pokemon++; - } - }, - true); + if(pokemon_fap->curr_pokemon == 150) + pokemon_fap->curr_pokemon = 0; + else + pokemon_fap->curr_pokemon++; consumed = true; break; - /* Move forward ten through the pokemon listing, wrap to min pokemon on + /* Move forward ten through the pokemon listing, wrap to min pokemon on * overflow. */ case InputKeyUp: - with_view_model_cpp( - select_pokemon->view, - SelectPokemonModel*, - model, - { - if(model->current_pokemon <= 140) { - model->current_pokemon += 10; - } else { - model->current_pokemon = 0; - } - }, - true); + if(pokemon_fap->curr_pokemon <= 140) + pokemon_fap->curr_pokemon += 10; + else + pokemon_fap->curr_pokemon = 0; consumed = true; break; @@ -139,10 +97,10 @@ void select_pokemon_enter_callback(void* context) { } bool select_pokemon_custom_callback(uint32_t event, void* context) { + PokemonFap* pokemon_fap = (PokemonFap*)context; UNUSED(event); furi_assert(context); - SelectPokemon* select_pokemon = (SelectPokemon*)context; - view_dispatcher_send_custom_event(select_pokemon->app->view_dispatcher, 0); + view_dispatcher_send_custom_event(pokemon_fap->view_dispatcher, 0); return true; } @@ -151,38 +109,31 @@ void select_pokemon_exit_callback(void* context) { UNUSED(context); } -SelectPokemon* select_pokemon_alloc(App* app) { - SelectPokemon* select_pokemon = (SelectPokemon*)malloc(sizeof(SelectPokemon)); - select_pokemon->app = app; - select_pokemon->view = view_alloc(); - view_set_context(select_pokemon->view, select_pokemon); - view_allocate_model(select_pokemon->view, ViewModelTypeLockFree, sizeof(SelectPokemonModel)); +View* select_pokemon_alloc(PokemonFap* pokemon_fap) { + View* view; + + view = view_alloc(); + + view_set_context(view, pokemon_fap); + view_allocate_model(view, ViewModelTypeLockFree, sizeof(PokemonFap**)); with_view_model_cpp( - select_pokemon->view, - SelectPokemonModel*, - model, - { - model->current_pokemon = app->current_pokemon; - model->pokemon_hex_code = app->pokemon_hex_code; - }, - true); - - view_set_draw_callback(select_pokemon->view, select_pokemon_render_callback); - view_set_input_callback(select_pokemon->view, select_pokemon_input_callback); - view_set_enter_callback(select_pokemon->view, select_pokemon_enter_callback); - view_set_custom_callback(select_pokemon->view, select_pokemon_custom_callback); - - view_set_exit_callback(select_pokemon->view, select_pokemon_exit_callback); - return select_pokemon; + view, PokemonFap**, model_fap, { *model_fap = pokemon_fap; }, false); + + view_set_draw_callback(view, select_pokemon_render_callback); + view_set_input_callback(view, select_pokemon_input_callback); + view_set_enter_callback(view, select_pokemon_enter_callback); + view_set_custom_callback(view, select_pokemon_custom_callback); + + view_set_exit_callback(view, select_pokemon_exit_callback); + return view; } -void select_pokemon_free(App* app) { - furi_assert(app->select_pokemon); - view_free(app->select_pokemon->view); - free(app->select_pokemon); +void select_pokemon_free(PokemonFap* pokemon_fap) { + furi_assert(pokemon_fap); + view_free(pokemon_fap->select_view); } -View* select_pokemon_get_view(App* app) { - furi_assert(app->select_pokemon); - return app->select_pokemon->view; +View* select_pokemon_get_view(PokemonFap* pokemon_fap) { + furi_assert(pokemon_fap); + return pokemon_fap->select_view; } diff --git a/views/select_pokemon.hpp b/views/select_pokemon.hpp index 169e43805e8..a5f7fa0baa8 100644 --- a/views/select_pokemon.hpp +++ b/views/select_pokemon.hpp @@ -9,17 +9,12 @@ #include #include -typedef struct App App; +#include "../pokemon_app.h" -typedef struct { - View* view; - App* app; -} SelectPokemon; +View* select_pokemon_alloc(PokemonFap* pokemon_fap); -SelectPokemon* select_pokemon_alloc(App* app); +void select_pokemon_free(PokemonFap* pokemon_fap); -void select_pokemon_free(App* app); +View* select_pokemon_get_view(PokemonFap* pokemon_fap); -View* select_pokemon_get_view(App* app); - -#endif /* SELECCT_POKEMON_HPP */ \ No newline at end of file +#endif /* SELECCT_POKEMON_HPP */ diff --git a/views/trade.cpp b/views/trade.cpp index 91f7e6f5b8e..75c574f687c 100644 --- a/views/trade.cpp +++ b/views/trade.cpp @@ -3,6 +3,7 @@ #include "../pokemon_data.h" +/* XXX: Convert all of these to be maintained in a struct in the Trade context */ uint8_t out_data = 0; uint8_t in_data = 0; uint8_t shift = 0; @@ -31,13 +32,13 @@ void screen_gameboy_connected(Canvas* const canvas) { int time_in_seconds = 0; -static void trade_draw_callback(Canvas* canvas, void* context) { +static void trade_draw_callback(Canvas* canvas, void* model) { const char* gameboy_status_text = NULL; + PokemonFap* pokemon_fap = *(PokemonFap**)model; canvas_clear(canvas); - SelectPokemonModel* model = (SelectPokemonModel*)context; - if(!model->trading) { - if(!model->connected) { + if(!pokemon_fap->trading) { + if(!pokemon_fap->connected) { furi_hal_light_set(LightGreen, 0x00); furi_hal_light_set(LightBlue, 0x00); furi_hal_light_set(LightRed, 0xff); @@ -49,7 +50,7 @@ static void trade_draw_callback(Canvas* canvas, void* context) { screen_gameboy_connected(canvas); } } else { - switch(model->gameboy_status) { + switch(pokemon_fap->gameboy_status) { case GAMEBOY_TRADING: furi_hal_light_set(LightGreen, 0x00); furi_hal_light_set(LightRed, 0x00); @@ -64,7 +65,8 @@ static void trade_draw_callback(Canvas* canvas, void* context) { case GAMEBOY_READY: case GAMEBOY_WAITING: case GAMEBOY_SEND: - canvas_draw_icon(canvas, 38, 11, pokemon_table[model->current_pokemon].icon); + canvas_draw_icon( + canvas, 38, 11, pokemon_fap->pokemon_table[pokemon_fap->curr_pokemon].icon); break; default: // Default state added to eliminated enum warning @@ -75,7 +77,7 @@ static void trade_draw_callback(Canvas* canvas, void* context) { canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_icon(canvas, 24, 0, &I_Space_80x18); - switch(model->gameboy_status) { + switch(pokemon_fap->gameboy_status) { case GAMEBOY_READY: gameboy_status_text = "READY"; break; @@ -108,12 +110,13 @@ static void trade_draw_callback(Canvas* canvas, void* context) { } static bool trade_input_callback(InputEvent* event, void* context) { - furi_assert(context); - Trade* trade = (Trade*)context; bool consumed = false; + PokemonFap* pokemon_fap = (PokemonFap*)context; + + furi_assert(context); if(event->type == InputTypePress && event->key == InputKeyBack) { - view_dispatcher_switch_to_view(trade->app->view_dispatcher, AppViewSelectPokemon); + view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, AppViewSelectPokemon); consumed = true; } @@ -180,10 +183,11 @@ byte getMenuResponse(byte in) { } byte getTradeCentreResponse(byte in, void* context) { - UNUSED(context); - Trade* trade = (Trade*)context; + PokemonFap* pokemon_fap = (PokemonFap*)context; byte send = in; + furi_assert(context); + switch(trade_centre_state) { case INIT: // TODO: What does this value of in mean? @@ -192,12 +196,7 @@ byte getTradeCentreResponse(byte in, void* context) { if(counter == 5) { trade_centre_state = READY_TO_GO; // CLICK EN LA MESA - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { model->gameboy_status = GAMEBOY_READY; }, - false); + pokemon_fap->gameboy_status = GAMEBOY_READY; } counter++; } @@ -218,12 +217,7 @@ byte getTradeCentreResponse(byte in, void* context) { if((in & 0xF0) == 0xF0) { if(counter == 5) { trade_centre_state = WAITING_TO_SEND_DATA; - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { model->gameboy_status = GAMEBOY_WAITING; }, - false); + pokemon_fap->gameboy_status = GAMEBOY_WAITING; } counter++; } @@ -263,20 +257,10 @@ byte getTradeCentreResponse(byte in, void* context) { if(in == 0x6F) { trade_centre_state = READY_TO_GO; send = 0x6F; - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { model->gameboy_status = GAMEBOY_TRADE_READY; }, - false); + pokemon_fap->gameboy_status = GAMEBOY_TRADE_READY; } else if((in & 0x60) == 0x60) { send = 0x60; // first pokemon - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { model->gameboy_status = GAMEBOY_SEND; }, - false); + pokemon_fap->gameboy_status = GAMEBOY_SEND; } else if(in == 0x00) { send = 0; trade_centre_state = TRADE_CONFIRMATION; @@ -286,12 +270,7 @@ byte getTradeCentreResponse(byte in, void* context) { case TRADE_CONFIRMATION: if(in == 0x61) { trade_centre_state = TRADE_PENDING; - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { model->gameboy_status = GAMEBOY_PENDING; }, - false); + pokemon_fap->gameboy_status = GAMEBOY_PENDING; } else if((in & 0x60) == 0x60) { trade_centre_state = DONE; } @@ -301,12 +280,7 @@ byte getTradeCentreResponse(byte in, void* context) { if(in == 0x00) { send = 0; trade_centre_state = INIT; - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { model->gameboy_status = GAMEBOY_TRADING; }, - false); + pokemon_fap->gameboy_status = GAMEBOY_TRADING; } break; @@ -319,7 +293,8 @@ byte getTradeCentreResponse(byte in, void* context) { } void transferBit(void* context) { - Trade* trade = (Trade*)context; + PokemonFap* pokemon_fap = (PokemonFap*)context; + furi_assert(context); byte raw_data = furi_hal_gpio_read(&GAME_BOY_SI); in_data |= raw_data << (7 - shift); @@ -327,17 +302,15 @@ void transferBit(void* context) { shift = 0; switch(connection_state) { case NOT_CONNECTED: - with_view_model_cpp( - trade->view, SelectPokemonModel*, model, { model->connected = false; }, true); + pokemon_fap->connected = false; out_data = getConnectResponse(in_data); break; case CONNECTED: - with_view_model_cpp( - trade->view, SelectPokemonModel*, model, { model->connected = true; }, true); + pokemon_fap->connected = true; out_data = getMenuResponse(in_data); break; case TRADE_CENTRE: - out_data = getTradeCentreResponse(in_data, trade); + out_data = getTradeCentreResponse(in_data, pokemon_fap); break; default: out_data = in_data; @@ -355,15 +328,14 @@ void transferBit(void* context) { DELAY_MICROSECONDS); // Wait 20-60us ... 120us max (in slave mode is not necessary) // TODO: The above comment doesn't make sense as DELAY_MICROSECONDS is defined as 15 - if(trade_centre_state == READY_TO_GO) { - with_view_model_cpp( - trade->view, SelectPokemonModel*, model, { model->trading = true; }, true); - } + if(trade_centre_state == READY_TO_GO) pokemon_fap->trading = true; + out_data = out_data << 1; } void input_clk_gameboy(void* context) { furi_assert(context); + if(time > 0) { // if there is no response from the master in 120 microseconds, the counters are reset if(micros() - time > 120) { @@ -378,22 +350,15 @@ void input_clk_gameboy(void* context) { } void trade_enter_callback(void* context) { + PokemonFap* pokemon_fap = (PokemonFap*)context; furi_assert(context); - Trade* trade = (Trade*)context; - with_view_model_cpp( - trade->view, - SelectPokemonModel*, - model, - { - model->current_pokemon = trade->app->current_pokemon; - model->pokemon_hex_code = trade->app->pokemon_hex_code; - model->trading = false; - model->connected = false; - model->gameboy_status = GAMEBOY_INITIAL; - }, - true); - - DATA_BLOCK[12] = trade->app->pokemon_hex_code; + + pokemon_fap->trading = false; + pokemon_fap->connected = false; + pokemon_fap->gameboy_status = GAMEBOY_INITIAL; + + /* XXX: Change hex to species to match pokemon nomenclature */ + DATA_BLOCK[12] = pokemon_fap->pokemon_table[pokemon_fap->curr_pokemon].hex; // B3 (Pin6) / SO (2) furi_hal_gpio_write(&GAME_BOY_SO, false); furi_hal_gpio_init(&GAME_BOY_SO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); @@ -407,7 +372,7 @@ void trade_enter_callback(void* context) { GpioPullNo, GpioSpeedVeryHigh); // <-- This line causes the "OK" to stop functioning when exiting the application, so a reboot of the Flipper Zero is required. furi_hal_gpio_remove_int_callback(&GAME_BOY_CLK); - furi_hal_gpio_add_int_callback(&GAME_BOY_CLK, input_clk_gameboy, trade); + furi_hal_gpio_add_int_callback(&GAME_BOY_CLK, input_clk_gameboy, pokemon_fap); // furi_hal_gpio_disable_int_callback(&GAME_BOY_CLK); // furi_hal_gpio_remove_int_callback(&GAME_BOY_CLK); @@ -417,9 +382,9 @@ void trade_enter_callback(void* context) { bool trade_custom_callback(uint32_t event, void* context) { UNUSED(event); + PokemonFap* pokemon_fap = (PokemonFap*)context; furi_assert(context); - Trade* trade = (Trade*)context; - view_dispatcher_send_custom_event(trade->app->view_dispatcher, 0); + view_dispatcher_send_custom_event(pokemon_fap->view_dispatcher, 0); return true; } @@ -436,35 +401,32 @@ void trade_exit_callback(void* context) { furi_hal_light_set(LightRed, 0x00); } -Trade* trade_alloc(App* app) { - Trade* trade = (Trade*)malloc(sizeof(Trade)); - trade->app = app; - trade->view = view_alloc(); +View* trade_alloc(PokemonFap* pokemon_fap) { + View* view; + + view = view_alloc(); procesing = true; - view_set_context(trade->view, trade); - view_allocate_model(trade->view, ViewModelTypeLockFree, sizeof(SelectPokemonModel)); - view_set_draw_callback(trade->view, trade_draw_callback); - view_set_input_callback(trade->view, trade_input_callback); - view_set_enter_callback(trade->view, trade_enter_callback); - view_set_custom_callback(trade->view, trade_custom_callback); - view_set_exit_callback(trade->view, trade_exit_callback); + view_set_context(view, pokemon_fap); + view_allocate_model(view, ViewModelTypeLockFree, sizeof(PokemonFap**)); + with_view_model_cpp( + view, PokemonFap**, model_fap, { *model_fap = pokemon_fap; }, false); + + view_set_draw_callback(view, trade_draw_callback); + view_set_input_callback(view, trade_input_callback); + view_set_enter_callback(view, trade_enter_callback); + view_set_custom_callback(view, trade_custom_callback); + view_set_exit_callback(view, trade_exit_callback); - return trade; + return view; } -void trade_free(App* app) { - furi_assert(app); +void trade_free(PokemonFap* pokemon_fap) { + furi_assert(pokemon_fap); // Free resources procesing = false; furi_hal_gpio_remove_int_callback(&GAME_BOY_CLK); disconnect_pin(&GAME_BOY_CLK); - view_free(app->trade->view); - free(app->trade); -} - -View* trade_get_view(App* app) { - furi_assert(app); - return app->trade->view; + view_free(pokemon_fap->trade_view); } diff --git a/views/trade.hpp b/views/trade.hpp index 885c2c126fb..aa21f454d86 100644 --- a/views/trade.hpp +++ b/views/trade.hpp @@ -9,6 +9,8 @@ #include #include +#include "../pokemon_app.h" + #define GAME_BOY_CLK gpio_ext_pb2 #define GAME_BOY_SI gpio_ext_pc3 #define GAME_BOY_SO gpio_ext_pb3 @@ -53,18 +55,9 @@ typedef enum { DONE } trade_centre_state_t; -typedef struct App App; - -typedef struct { - View* view; - App* app; -} Trade; - -Trade* trade_alloc(App* app); - -void trade_free(App* app); +View* trade_alloc(PokemonFap* pokemon_fap); -View* trade_get_view(App* app); +void trade_free(PokemonFap* pokemon_fap); extern unsigned char INPUT_BLOCK[405]; extern unsigned char* DATA_BLOCK;