Multigame Migration Plan Overview Refactor the existing monolithic tic-tac-toe implementation into a modular game architecture that allows multiple games to run on the RP2350 platform while preserving the interrupt-driven, dual-core reactive architecture. Goals Abstract game logic from hardware/display management Create reusable input processing system Enable multiple games to coexist in the codebase Maintain the efficient reactive architecture (event-driven, dual-core) Keep hardware-specific code isolated in basic1.cpp Architecture Components 1. Input Event System Files: lib/input_event.h Defines shared input event structures used by both InputManager and Game classes: InputType enum (NONE, TOUCH_DOWN, TOUCH_MOVE, TOUCH_UP, BUTTON_0, BUTTON_1, GESTURE) InputEvent struct with coordinates, gesture codes, button IDs, pressure, validity flag 2. Input Manager Files: lib/input_manager.h, lib/input_manager.cpp Handles all input processing and debouncing: Constructor: InputManager(LowLevelTouch* touch, GameConfig* config) Methods: process_touch_input(uint32_t* last_time), process_button_input() Returns InputEvent objects to be passed to games Manages touch debouncing and gesture recognition Does NOT handle button GPIO setup (stays in basic1.cpp) 3. Abstract Game Base Class Files: lib/game.h Defines the interface all games must implement: Constructor: Game(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui) Protected members: width, height, renderer, gui Pure virtual methods: virtual void init() = 0 - Initialize game state virtual bool update(const InputEvent& event) = 0 - Process input, return true if redraw needed virtual void draw() = 0 - Render game to buffer Virtual destructor: virtual ~Game() {} 4. Tic-Tac-Toe Game Implementation Files: games/tic_tac_toe.h, games/tic_tac_toe.cpp Concrete implementation of the Game interface: Private GameState struct with board, current player, winner, statistics Private method: check_winner() Private constants: BOARD_SIZE, CELL_SIZE, BOARD_Y, LINE_WIDTH Overrides: init(), update(const InputEvent& event), draw() Encapsulates all tic-tac-toe logic extracted from basic1.cpp lines 162-770 5. Main Loop Refactor File: basic1.cpp Simplified main program focusing on hardware management: Keep: Display initialization, dual-core setup, interrupt handlers, GPIO configuration Remove: Game-specific logic (moves to TicTacToeGame) Add: InputManager instantiation, Game* pointer instantiation Modify main loop: Migration Steps Step 1: Create Input Event Header Extract input structures from basic1.cpp (lines 134-156) to new file lib/input_event.h. Validation: Compile successfully No duplicate definitions Both basic1.cpp and new files include this header Step 2: Create Input Manager Move input processing functions (lines 313-442) to new InputManager class. Validation: Constructor properly stores touch pointer and config process_touch_input() returns valid InputEvent on touch process_button_input() returns valid InputEvent on button press Debouncing still works correctly Compile and run - verify touch/button detection unchanged Step 3: Create Abstract Game Class Create lib/game.h with base class definition. Validation: Header compiles successfully Pure virtual methods defined correctly Protected members accessible to derived classes Step 4: Extract Tic-Tac-Toe Game Create TicTacToeGame class inheriting from Game. Validation: Move GameState struct (lines 162-176) - verify all members present Move check_winner() (lines 447-495) - verify logic identical Move game_init() to init() override (lines 505-522) Move game_update() to update() override (lines 536-668) Move game_draw() to draw() override (lines 671-770) Move constants: BOARD_SIZE, CELL_SIZE, BOARD_Y Compile successfully Step 5: Refactor Main Loop Update basic1.cpp to use new architecture. Validation: Remove old GameState state variable Remove old game functions Instantiate InputManager after hardware init Instantiate TicTacToeGame as Game* Update main loop to use polymorphic calls Compile successfully Run and verify: Touch input works, buttons work, game plays correctly Verify dual-core refresh still works (Core 1 handles display) Test full game: place pieces, win conditions, restart Step 6: Update Build System Modify CMakeLists.txt to include new source files. Validation: Add lib/input_manager.cpp Add games/tic_tac_toe.cpp Clean build succeeds Binary size reasonable (no major bloat) Step 7: Final Testing Comprehensive system test. Validation: Touch detection works (tap cells) Button navigation works (KEY0/KEY1) Game logic correct (wins, ties, restart) Display refreshes properly (no artifacts) Statistics persist across games Debug output shows correct events System remains responsive during e-ink refresh Future Extensions Adding New Games To add a new game (e.g., Snake, Pong): Create games/snake.h and games/snake.cpp Inherit from Game base class Implement init(), update(), draw() Define game-specific state as private members Add to CMakeLists.txt Change game selection in basic1.cpp: Game* current_game = new SnakeGame(...) Game Launcher (Future) Create GameLauncher class to display menu Allow runtime game switching Handle cleanup: delete current_game; current_game = new SnakeGame(...) Store game selection preference in flash Key Design Principles Hardware Isolation: All GPIO, interrupts, hardware config stay in basic1.cpp State Encapsulation: Each game owns its state completely Polymorphism: Use Game* pointer for runtime flexibility Event-Driven: Games respond to InputEvent objects only Reactive Rendering: Only redraw when update() returns true Dual-Core Efficiency: Core 0 handles logic, Core 1 handles display refresh