trade.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. /*
  2. * NOTE:
  3. * The documentation below is slightly out of date but mostly still correct,
  4. * and only for gen i trades. Gen ii trades are very similar but have a few
  5. * different patterns. I'm currently lazy and working on features, so better
  6. * documentation on the trade protocol to follow, and potentially will push
  7. * it all to bulbapedia or similar for the world to benefit from.
  8. *
  9. *
  10. * This setup always forces the flipper to the follower/slave role in the link.
  11. * This just makes our logic consistent and since we're going to be gobs faster
  12. * than a real Game Boy, we can be guaranteed to always be ready to respond.
  13. *
  14. * As documented here: http://www.adanscotney.com/2014/01/spoofing-pokemon-trades-with-stellaris.html
  15. * The general gist of the communication is as follows:
  16. * 1) Each Game Boy tries to listen for an external clock coming in on the link cable.
  17. * After some unknown timeout, this Game Boy decides its going to take the leader/master role.
  18. * In this state, it generates a clock and repeatedly sends out PKMN_MASTER(0x01)
  19. * 2) The other side, sensing a clock from the leader/master, then responds with PKMN_SLAVE(0x02)
  20. * 3) Once both sides understand their roles, they both respond with PKMN_BLANK(0x00) for a bit.
  21. * 4) Next, the leader/master sends CONNECTED(0x60) bytes that the follower/slave repeats
  22. * back. Then a bunch of BLANK bytes.
  23. * 5) At this point, each Game Boy repeatedly sends the menu item it has highlighted,
  24. * prepended by a BLANK, in groups of 3 bytes. These are ITEM_*_HIGHLIGHTED.
  25. * 6) Then, once both sides send ITEM_*_SELECTED, the next step occurs.
  26. * This application, from steps 3 through 6, just repeats bytes back and lets the Game Boy
  27. * dictate the steps. We stay here until we start seeing PREAMBLE(0xFD) bytes,
  28. * as those dictate the start of the next sections.
  29. *
  30. * The Flipper is now in the "READY" state.
  31. *
  32. * 7) Once the player on the Game Boy side uses the trade table, a block of data is
  33. * transmitted. This starts with 10x PREAMBLE(0xFD) bytes, 10x random bytes (to
  34. *
  35. * I missed another 9x fd bytes after rand? State machine below confirms these bytes
  36. *
  37. * sync the RNG between two devices, unused at this time), and then the 415 trade_block,
  38. * struct gets transferred. At the end of this is 3 ending bytes, DF FE 15. And, weirdly,
  39. * 3 PREAMBLE(0xFD) bytes.
  40. * 8) The patch list starts with 3x more PREAMBLE(0xFD) bytes for a total of 6x PREAMBLE,
  41. * followed by 7x BLANK bytes. Then remaining 189 bytes of patch list data. The patch
  42. * list is used to compensate for byte values of NO_DATA_BYE(0xFE) being transmitted.
  43. * The patch list is specifically for the party data of the trade_block. To patch
  44. * outgoing data, if a byte is 0xFE, it is changed to 0xFF, and the index+1 is
  45. * added to the patch list. There are two parts to the patch list as the data it
  46. * covers is longer than 0xFC. After each part is complete, 0xFF is added to the
  47. * patch list. The first part of the patch list can patch 0x00:0xFB of the party,
  48. * the second part can patch 0xFC:0x107 of the party. If there are no bytes to
  49. * patch in a part, 0xFF is just appended. After both terminators, it is expected
  50. * all remaining bytes are 0x00.
  51. *
  52. * The Flipper is now in the "WAITING" state.
  53. *
  54. * 9) At this point, both sides have full copies of each other's current party. The sides
  55. * simply indicate which Pokemon they are sending. This is done with a BLANK byte to
  56. * start, and then each side indicates which Pokemon it wants to trade with SEL_NUM_MASK(0x60)
  57. * + party index. We always transmit the first Pokemon. Once in a agreement, both
  58. * sides transmit a handful of BLANK bytes.
  59. *
  60. * The Flipper is now in the "DEAL?" state.
  61. *
  62. * A) Starting with another BLANK byte, both sides need to agree to the trade by
  63. * sending TRADE_ACCEPT(0x62) repeatedly, and then a handful of BLANK bytes.
  64. * To disagree with a trade, either side would send TRADE_REJECT(0x61), the
  65. * Flipper will never send this on its own. If the Game Boy does, both it and
  66. * the flipper got back to step 9 again.
  67. *
  68. * The Flipper is now in the "TRADING" state.
  69. *
  70. * B) The Flipper actually goes back to step 7, but keeps the drawing mode as
  71. * TRADING. After the trade is complete on the Game Boy, it re-sends the
  72. * trade_block data. This re-syncs the states between the Flipper and
  73. * Game Boy and another trade can occur.
  74. *
  75. * *) A point of note is that the Flipper can go back to the main menu from
  76. * any state. Though, doing so in the TRADING state might actually cause
  77. * the Game Boy to have issues. When in READY or WAITING state, the Flipper
  78. * can go back and modify the Pokemon that the Game Boy sent to it. If the
  79. * Flipper then goes back to Trade from the main menu, it will be in the
  80. * READY state. If the Game Boy is still on the trade menu, and it tries
  81. * to trade, the trade will be rejected. The Game Boy needs to exit the
  82. * trade menu, and then re-enter it by selecting the table in the trade
  83. * center. This will then push the Flipper to the WAITING state, and the
  84. * trade_blocks will re-sync between them with the new data. If the Game Boy
  85. * leave the trade menu while the Flipper is in the WAITING state, the
  86. * Flipper will go back to the READY state.
  87. */
  88. #include <furi.h>
  89. #include <furi_hal.h>
  90. #include <dolphin/dolphin.h>
  91. #include <notification/notification_messages.h>
  92. #include <gui/elements.h>
  93. #include <gui/view.h>
  94. #include <pokemon_icons.h>
  95. #include <gblink.h>
  96. #include "../pokemon_app.h"
  97. #include "../pokemon_data.h"
  98. #include "trade_patch_list.h"
  99. /* Uncomment the following line to enable graphics testing for the different
  100. * phases of the trade view. Pressing the okay button will step through each
  101. * gameboy_status. Note that while trades will still function with this enabled,
  102. * forcing the advance of the status will certainly break trades.
  103. */
  104. //#define GRAPHICS_TESTING
  105. #define DELAY_MICROSECONDS 15
  106. #define PKMN_BLANK 0x00
  107. #define ITEM_1_HIGHLIGHTED 0xD0
  108. #define ITEM_2_HIGHLIGHTED 0xD1
  109. #define ITEM_3_HIGHLIGHTED 0xD2
  110. #define ITEM_1_SELECTED 0xD4
  111. #define ITEM_2_SELECTED 0xD5
  112. #define ITEM_3_SELECTED 0xD6
  113. #define SERIAL_PREAMBLE_BYTE 0xFD
  114. #define SERIAL_PREAMBLE_LENGTH 6
  115. #define SERIAL_RN_PREAMBLE_LENGTH 7
  116. #define SERIAL_TRADE_PREAMBLE_LENGTH 9
  117. #define SERIAL_RNS_LENGTH 10
  118. #define SERIAL_PATCH_LIST_PART_TERMINATOR 0xFF
  119. #define SERIAL_NO_DATA_BYTE 0xFE
  120. #define PKMN_MASTER 0x01
  121. #define PKMN_SLAVE 0x02
  122. #define PKMN_CONNECTED 0x60
  123. #define PKMN_CONNECTED_II 0x61
  124. #define PKMN_TRADE_ACCEPT_GEN_I 0x62
  125. #define PKMN_TRADE_ACCEPT_GEN_II 0x72
  126. #define PKMN_TRADE_REJECT_GEN_I 0x61
  127. #define PKMN_TRADE_REJECT_GEN_II 0x71
  128. #define PKMN_TABLE_LEAVE_GEN_I 0x6f
  129. #define PKMN_TABLE_LEAVE_GEN_II 0x7f
  130. #define PKMN_SEL_NUM_MASK_GEN_I 0x60
  131. #define PKMN_SEL_NUM_MASK_GEN_II 0x70
  132. #define PKMN_SEL_NUM_ONE_GEN_I 0x60
  133. #define PKMN_SEL_NUM_ONE_GEN_II 0x70
  134. #define PKMN_ACTION 0x60
  135. #define PKMN_TRADE_CENTRE ITEM_1_SELECTED
  136. #define PKMN_COLOSSEUM ITEM_2_SELECTED
  137. #define PKMN_BREAK_LINK ITEM_3_SELECTED
  138. struct important_bytes {
  139. const uint8_t connected;
  140. const uint8_t trade_accept;
  141. const uint8_t trade_reject;
  142. const uint8_t table_leave;
  143. const uint8_t sel_num_mask;
  144. const uint8_t sel_num_one;
  145. };
  146. static const struct important_bytes gen_i = {
  147. PKMN_CONNECTED,
  148. PKMN_TRADE_ACCEPT_GEN_I,
  149. PKMN_TRADE_REJECT_GEN_I,
  150. PKMN_TABLE_LEAVE_GEN_I,
  151. PKMN_SEL_NUM_MASK_GEN_I,
  152. PKMN_SEL_NUM_ONE_GEN_I,
  153. };
  154. static const struct important_bytes gen_ii = {
  155. PKMN_CONNECTED_II,
  156. PKMN_TRADE_ACCEPT_GEN_II,
  157. PKMN_TRADE_REJECT_GEN_II,
  158. PKMN_TABLE_LEAVE_GEN_II,
  159. PKMN_SEL_NUM_MASK_GEN_II,
  160. PKMN_SEL_NUM_ONE_GEN_II,
  161. };
  162. /* States specific to the trade process. */
  163. typedef enum {
  164. TRADE_RESET,
  165. TRADE_INIT,
  166. TRADE_RANDOM,
  167. TRADE_DATA,
  168. TRADE_PATCH_HEADER,
  169. TRADE_PATCH_DATA,
  170. TRADE_SELECT,
  171. TRADE_MAIL,
  172. TRADE_PENDING,
  173. TRADE_CONFIRMATION,
  174. TRADE_DONE,
  175. TRADE_CANCEL
  176. } trade_centre_state_t;
  177. /* Global states for the trade logic. These are used to dictate what gets drawn
  178. * to the screen but also handle a few sync states. The CONN states are to denote
  179. * if a link has been established or note. READY through TRADING are all specific
  180. * screens to draw in the trade center. COLOSSEUM causes a data loopback so the
  181. * player can fight themselves.
  182. */
  183. typedef enum {
  184. GAMEBOY_CONN_FALSE,
  185. GAMEBOY_CONN_TRUE,
  186. GAMEBOY_READY,
  187. GAMEBOY_WAITING,
  188. GAMEBOY_TRADE_PENDING,
  189. GAMEBOY_TRADING,
  190. GAMEBOY_TRADE_CANCEL,
  191. GAMEBOY_COLOSSEUM,
  192. GAMEBOY_STATE_COUNT
  193. } render_gameboy_state_t;
  194. /* Anonymous struct */
  195. struct trade_ctx {
  196. trade_centre_state_t trade_centre_state;
  197. FuriTimer* draw_timer;
  198. View* view;
  199. uint8_t in_data;
  200. uint8_t out_data;
  201. uint8_t shift;
  202. PokemonData* input_pdata;
  203. struct patch_list* patch_list;
  204. void* gblink_handle;
  205. struct gblink_pins* gblink_pins;
  206. PokemonData* pdata;
  207. NotificationApp* notifications;
  208. };
  209. /* These are the needed variables for the draw callback */
  210. struct trade_model {
  211. render_gameboy_state_t gameboy_status;
  212. bool ledon; // Controls the blue LED during trade
  213. uint8_t curr_pokemon;
  214. PokemonData* pdata;
  215. };
  216. /* Input callback, used to handle the user trying to back out of the trade
  217. * screen.
  218. * Normally, when trade_centre_state is <= READY, pressing back would just go
  219. * back without issue. However, when WAITING, we need to tell the gameboy that
  220. * the flipper wants to exit the trade menu. Anything beyond WAITING should not
  221. * go back nor try to tell the gameboy to cancel; instead, by holding back in
  222. * these states, we can forcefully go back one menu.
  223. *
  224. * Returning false here then ends up calling the view_dispatcher nav callback
  225. * if the button pressed/held is Back. Returning true tells the OS that we
  226. * dealt with the button press and no further action is needed.
  227. */
  228. static bool trade_input_callback(InputEvent* event, void* context) {
  229. furi_assert(context);
  230. struct trade_ctx* trade = context;
  231. render_gameboy_state_t gameboy_status;
  232. #ifdef GRAPHICS_TESTING
  233. if(event->type == InputTypePress) {
  234. with_view_model(
  235. trade->view,
  236. struct trade_model * model,
  237. {
  238. if(event->key == InputKeyRight) {
  239. model->gameboy_status++;
  240. if(model->gameboy_status == GAMEBOY_STATE_COUNT)
  241. model->gameboy_status = GAMEBOY_CONN_FALSE;
  242. } else if(event->key == InputKeyLeft) {
  243. if(model->gameboy_status == GAMEBOY_CONN_FALSE)
  244. model->gameboy_status = GAMEBOY_COLOSSEUM;
  245. else
  246. model->gameboy_status--;
  247. }
  248. },
  249. true);
  250. }
  251. #endif
  252. /* Only handling back button */
  253. if(event->key != InputKeyBack) return false;
  254. with_view_model(
  255. trade->view,
  256. struct trade_model * model,
  257. { gameboy_status = model->gameboy_status; },
  258. false);
  259. /* States READY or lower can be exited without issue, let the view_dispatcher
  260. * nav callback handle it.
  261. */
  262. if(gameboy_status <= GAMEBOY_READY) return false;
  263. /* Long presses we want the view_dispatcher nav callback to handle */
  264. if(event->type == InputTypeLong) return false;
  265. /* In the waiting state, we need to move to cancelled. This locks us up
  266. * until the gameboy side gets the hint and cancels as well.
  267. */
  268. if(gameboy_status == GAMEBOY_WAITING && event->type == InputTypeShort) {
  269. with_view_model(
  270. trade->view,
  271. struct trade_model * model,
  272. { model->gameboy_status = GAMEBOY_TRADE_CANCEL; },
  273. false);
  274. trade->trade_centre_state = TRADE_CANCEL;
  275. }
  276. /* Anything here, we should consider handled */
  277. return true;
  278. }
  279. /* A callback function that must be called outside of an interrupt context,
  280. * This will completely destroy the current patch list, and then rebuild it from
  281. * the current trade_block state. This is used mostly after a trade to rebuild
  282. * the list with the new data we just copied in.
  283. */
  284. static void pokemon_plist_recreate_callback(void* context, uint32_t arg) {
  285. furi_assert(context);
  286. UNUSED(arg);
  287. struct trade_ctx* trade = context;
  288. /* Award some XP to the dolphin after a completed trade. This needs to
  289. * happen outside of an ISR context, so we slap it here.
  290. */
  291. dolphin_deed(DolphinDeedPluginGameWin);
  292. plist_create(&(trade->patch_list), trade->pdata);
  293. }
  294. /* Call this at any point to reset the timer on the backlight turning off.
  295. * During trade, this should get called pretty frequently so long as data
  296. * is moving in and out.
  297. *
  298. * I hesitate to force the backlight on, as I don't want to be responsible
  299. * for draining someone's battery on accident.
  300. */
  301. static void trade_backlight_bump_callback(void* context, uint32_t arg) {
  302. furi_assert(context);
  303. UNUSED(arg);
  304. struct trade_ctx* trade = context;
  305. notification_message(trade->notifications, &sequence_display_backlight_on);
  306. }
  307. static void trade_draw_bottom_bar(Canvas* const canvas) {
  308. furi_assert(canvas);
  309. /* Paint the area behind the bottom background bar white to prevent overlap */
  310. canvas_set_color(canvas, ColorWhite);
  311. canvas_draw_box(canvas, 0, 53, 9, 7);
  312. canvas_draw_box(canvas, 6, 56, 59, 6);
  313. canvas_draw_box(canvas, 60, 53, 32, 7);
  314. canvas_draw_box(canvas, 87, 56, 38, 6);
  315. canvas_set_color(canvas, ColorBlack);
  316. /* Draw bar with transparencies */
  317. canvas_set_bitmap_mode(canvas, 1);
  318. canvas_draw_icon(canvas, 0, 53, &I_Background_128x11);
  319. canvas_set_bitmap_mode(canvas, 0);
  320. }
  321. /* Draws a whole screen image with Flipper mascot, Game Boy, etc. */
  322. static void trade_draw_connection(Canvas* const canvas, bool connected) {
  323. furi_assert(canvas);
  324. canvas_draw_icon(canvas, 9, 26, &I_dolphin);
  325. trade_draw_bottom_bar(canvas);
  326. canvas_draw_icon(canvas, 80, 0, &I_game_boy);
  327. elements_frame(canvas, 9, 2, 64, 17);
  328. if(connected) {
  329. canvas_draw_str(canvas, 18, 13, "Connected!");
  330. canvas_draw_icon(canvas, 61, 23, &I_hand_thumbsup);
  331. } else {
  332. canvas_draw_str(canvas, 18, 13, "Connect GB");
  333. canvas_draw_icon(canvas, 56, 23, &I_hand_cable);
  334. }
  335. }
  336. /* Draws a frame around the screen, with a box at the top for a text string,
  337. * and an icon of the player.
  338. */
  339. static void trade_draw_frame(Canvas* canvas, const char* str) {
  340. furi_assert(canvas);
  341. trade_draw_bottom_bar(canvas);
  342. /* Paint the area behind the text box white to prevent overlap, similar
  343. * to the bottom background bar */
  344. canvas_set_color(canvas, ColorWhite);
  345. canvas_draw_box(canvas, 59, 0, 67, 19);
  346. canvas_set_color(canvas, ColorBlack);
  347. /* Draw text box and populate it with string and Red icon */
  348. elements_frame(canvas, 59, 0, 67, 19);
  349. canvas_draw_str(canvas, 82, 12, str);
  350. canvas_draw_icon(canvas, 61, 2, &I_red_16x15);
  351. }
  352. /* Draws the Pokemon's image in the middle of the screen */
  353. static void trade_draw_pkmn_avatar(Canvas* canvas, PokemonData* pdata) {
  354. furi_assert(canvas);
  355. furi_assert(pdata);
  356. /* First, ensure the icon we want is already loaded in to pdata->bitmap */
  357. pokemon_icon_get(pdata, pokemon_stat_get(pdata, STAT_NUM, NONE) + 1);
  358. canvas_draw_xbm(
  359. canvas, 0, 0, pdata->bitmap->width, pdata->bitmap->height, pdata->bitmap->data);
  360. furi_hal_light_set(LightBlue, 0x00);
  361. furi_hal_light_set(LightGreen, 0x00);
  362. }
  363. /* Called every 250 ms on a timer. This controls the blue LED when in TRADING
  364. * state. This is necessary as Flipper OS does not make any guarantees on when
  365. * draw updates may or may not be called. There are situations where a draw
  366. * update is called much faster. Therefore, we need to control the update rate
  367. * via the ledon view_model variable.
  368. */
  369. static void trade_draw_timer_callback(void* context) {
  370. furi_assert(context);
  371. struct trade_ctx* trade = (struct trade_ctx*)context;
  372. with_view_model(
  373. trade->view, struct trade_model * model, { model->ledon ^= 1; }, true);
  374. }
  375. static void trade_draw_callback(Canvas* canvas, void* view_model) {
  376. furi_assert(view_model);
  377. struct trade_model* model = view_model;
  378. canvas_clear(canvas);
  379. switch(model->gameboy_status) {
  380. case GAMEBOY_CONN_FALSE:
  381. furi_hal_light_set(LightGreen, 0x00);
  382. furi_hal_light_set(LightRed, 0xff);
  383. trade_draw_connection(canvas, false);
  384. break;
  385. case GAMEBOY_CONN_TRUE:
  386. furi_hal_light_set(LightGreen, 0xff);
  387. furi_hal_light_set(LightRed, 0x00);
  388. trade_draw_connection(canvas, true);
  389. break;
  390. case GAMEBOY_READY:
  391. trade_draw_pkmn_avatar(canvas, model->pdata);
  392. trade_draw_frame(canvas, "READY");
  393. break;
  394. case GAMEBOY_WAITING:
  395. trade_draw_pkmn_avatar(canvas, model->pdata);
  396. trade_draw_frame(canvas, "WAITING");
  397. break;
  398. case GAMEBOY_TRADE_PENDING:
  399. trade_draw_pkmn_avatar(canvas, model->pdata);
  400. trade_draw_frame(canvas, "DEAL?");
  401. break;
  402. case GAMEBOY_TRADING:
  403. furi_hal_light_set(LightGreen, 0x00);
  404. if(model->ledon) {
  405. furi_hal_light_set(LightBlue, 0xff);
  406. canvas_draw_icon(canvas, 0, 5, &I_gb_step_1);
  407. } else {
  408. furi_hal_light_set(LightBlue, 0x00);
  409. canvas_draw_icon(canvas, 0, 5, &I_gb_step_2);
  410. }
  411. trade_draw_frame(canvas, "TRADING");
  412. break;
  413. case GAMEBOY_TRADE_CANCEL:
  414. trade_draw_frame(canvas, "CANCEL");
  415. break;
  416. case GAMEBOY_COLOSSEUM:
  417. trade_draw_frame(canvas, "FIGHT!");
  418. break;
  419. default:
  420. trade_draw_frame(canvas, "INITIAL");
  421. break;
  422. }
  423. }
  424. /* Get the response byte from the link partner, updating the connection
  425. * state if needed.
  426. */
  427. static uint8_t getConnectResponse(struct trade_ctx* trade) {
  428. furi_assert(trade);
  429. uint8_t ret = trade->in_data;
  430. switch(trade->in_data) {
  431. case PKMN_CONNECTED:
  432. case PKMN_CONNECTED_II:
  433. with_view_model(
  434. trade->view,
  435. struct trade_model * model,
  436. { model->gameboy_status = GAMEBOY_CONN_TRUE; },
  437. false);
  438. break;
  439. case PKMN_MASTER:
  440. ret = PKMN_SLAVE;
  441. break;
  442. case PKMN_BLANK:
  443. ret = PKMN_BLANK;
  444. break;
  445. default:
  446. with_view_model(
  447. trade->view,
  448. struct trade_model * model,
  449. { model->gameboy_status = GAMEBOY_CONN_FALSE; },
  450. false);
  451. ret = PKMN_BREAK_LINK;
  452. break;
  453. }
  454. return ret;
  455. }
  456. /* Receive what the Pokemon game is requesting and move to that mode.
  457. *
  458. * This reads bytes sent by the Game Boy and responds. The only things
  459. * we care about are when menu items are actually selected. The protocol
  460. * seems to send data both when one of the link menu items is highlighted
  461. * and when one of them is selected.
  462. *
  463. * If somehow we get a leader/master byte received, then go back to the
  464. * NOT_CONNECTED state. For the leader/master byte likely means that
  465. * the linked Game Boy is still trying to negotiate roles and we need to
  466. * respond with a follower/slave byte.
  467. *
  468. * Note that, we can probably eventually drop colosseum/battle connections,
  469. * though it may be an interesting exercise in better understanding how the
  470. * "random" seeding is done between the units. As noted here:
  471. * http://www.adanscotney.com/2014/01/spoofing-pokemon-trades-with-stellaris.html
  472. * it is presumed these bytes are to sync the RNG seed between the units to
  473. * not need arbitration on various die rolls.
  474. */
  475. static uint8_t getMenuResponse(struct trade_ctx* trade) {
  476. furi_assert(trade);
  477. uint8_t response = PKMN_BLANK;
  478. switch(trade->in_data) {
  479. case PKMN_CONNECTED:
  480. case PKMN_CONNECTED_II:
  481. response = trade->in_data;
  482. break;
  483. case ITEM_2_HIGHLIGHTED:
  484. if(trade->pdata->gen == GEN_I) {
  485. response = trade->in_data;
  486. break;
  487. }
  488. [[fallthrough]];
  489. case PKMN_TRADE_CENTRE:
  490. with_view_model(
  491. trade->view,
  492. struct trade_model * model,
  493. { model->gameboy_status = GAMEBOY_READY; },
  494. false);
  495. break;
  496. case PKMN_COLOSSEUM:
  497. with_view_model(
  498. trade->view,
  499. struct trade_model * model,
  500. { model->gameboy_status = GAMEBOY_COLOSSEUM; },
  501. false);
  502. break;
  503. case PKMN_BREAK_LINK:
  504. case PKMN_MASTER:
  505. with_view_model(
  506. trade->view,
  507. struct trade_model * model,
  508. { model->gameboy_status = GAMEBOY_CONN_FALSE; },
  509. false);
  510. response = PKMN_BREAK_LINK;
  511. break;
  512. default:
  513. response = trade->in_data;
  514. break;
  515. }
  516. return response;
  517. }
  518. static uint8_t getTradeCentreResponse(struct trade_ctx* trade) {
  519. furi_assert(trade);
  520. uint8_t* trade_block_flat = (uint8_t*)trade->pdata->trade_block;
  521. uint8_t* input_block_flat = (uint8_t*)trade->input_pdata->trade_block;
  522. uint8_t* input_party_flat = (uint8_t*)trade->input_pdata->party;
  523. struct trade_model* model = NULL;
  524. uint8_t in = trade->in_data;
  525. uint8_t send = in;
  526. static bool patch_pt_2;
  527. static size_t counter;
  528. static uint8_t in_pkmn_idx;
  529. const struct important_bytes* bytes = NULL;
  530. if(trade->pdata->gen == GEN_I) bytes = &gen_i;
  531. if(trade->pdata->gen == GEN_II) bytes = &gen_ii;
  532. /* TODO: Figure out how we should respond to a no_data_byte and/or how to
  533. * send one and what response to expect.
  534. *
  535. * This isn't a high priority since it should be unlikely that we would
  536. * actually ever receive a NO_DATA_BYE as the Game Boy is the leader/master
  537. * and therefore would only transmit when it has data ready.
  538. */
  539. /* Since this is a fairly long function, it doesn't call any other functions,
  540. * the view model isn't locked, and we're in an interrupt context, lets just
  541. * map the view model to a local var and commit it back when we're done.
  542. */
  543. model = view_get_model(trade->view);
  544. /* There is a handful of communications that happen once the Game Boy
  545. * clicks on the table. For all of them, the Flipper can just mirror back
  546. * the byte the Game Boy sends. We can spin in this forever until we see 10x
  547. * SERIAL_PREAMBLE_BYTEs. Once we receive those, the counters are synced,
  548. * and every byte after that can be easily counted for the actual transfer
  549. * of Pokemon data.
  550. */
  551. switch(trade->trade_centre_state) {
  552. case TRADE_RESET:
  553. /* Reset counters and other static variables */
  554. counter = 0;
  555. patch_pt_2 = false;
  556. trade->trade_centre_state = TRADE_INIT;
  557. break;
  558. /* This state runs through the end of the random preamble */
  559. case TRADE_INIT:
  560. if(in == SERIAL_PREAMBLE_BYTE) {
  561. counter++;
  562. model->gameboy_status = GAMEBOY_WAITING;
  563. }
  564. if(counter == SERIAL_RNS_LENGTH) {
  565. trade->trade_centre_state = TRADE_RANDOM;
  566. counter = 0;
  567. }
  568. break;
  569. /* Once we start getting PKMN_BLANKs, we mirror them until we get 10x
  570. * SERIAL_PREAMBLE_BYTE, and then 10 random numbers. The 10 random
  571. * numbers are for synchronizing the PRNG between the two systems,
  572. * we do not use these numbers at this time.
  573. *
  574. * This waits through the end of the trade block preamble, a total of 19
  575. * bytes.
  576. */
  577. case TRADE_RANDOM:
  578. counter++;
  579. if(counter == (SERIAL_RNS_LENGTH + SERIAL_TRADE_PREAMBLE_LENGTH)) {
  580. trade->trade_centre_state = TRADE_DATA;
  581. counter = 0;
  582. }
  583. break;
  584. /* This is where we exchange trade_block data with the Game Boy */
  585. case TRADE_DATA:
  586. input_block_flat[counter] = in;
  587. send = trade_block_flat[counter];
  588. counter++;
  589. if(counter == trade->input_pdata->trade_block_sz) {
  590. trade->trade_centre_state = TRADE_PATCH_HEADER;
  591. counter = 0;
  592. }
  593. break;
  594. /* This absorbs the 3 byte ending sequence (DF FE 15) after the trade data is
  595. * swapped, then the 3x SERIAL_PREAMBLE_BYTEs that end the trade data, and
  596. * another 3x of them that start the patch data. By the time we're done with
  597. * this state, the patch list BLANK bytes are ready to be transmitted.
  598. * We only care about the 6x total preamble bytes.
  599. */
  600. case TRADE_PATCH_HEADER:
  601. if(in == SERIAL_PREAMBLE_BYTE) {
  602. counter++;
  603. }
  604. if(counter == 6) {
  605. counter = 0;
  606. trade->trade_centre_state = TRADE_PATCH_DATA;
  607. } else {
  608. break;
  609. }
  610. [[fallthrough]];
  611. case TRADE_PATCH_DATA:
  612. counter++;
  613. /* This magic number is basically the header length, 10, minus
  614. * the 3x 0xFD that we should be transmitting as part of the patch
  615. * list header.
  616. */
  617. if(counter > 8) {
  618. send = plist_index_get(trade->patch_list, (counter - 9));
  619. }
  620. /* Patch received data */
  621. /* This relies on the data sent only ever sending 0x00 after
  622. * part 2 of the patch list has been terminated. This is the
  623. * case in official Gen I code at this time.
  624. */
  625. switch(in) {
  626. case PKMN_BLANK:
  627. break;
  628. case SERIAL_PATCH_LIST_PART_TERMINATOR:
  629. patch_pt_2 = true;
  630. break;
  631. default: // Any nonzero value will cause a patch
  632. if(!patch_pt_2) {
  633. /* Pt 1 is 0x00 - 0xFB */
  634. input_party_flat[in - 1] = SERIAL_NO_DATA_BYTE;
  635. } else {
  636. /* Pt 2 is 0xFC - 0x107
  637. * 0xFC + in - 1
  638. */
  639. input_party_flat[0xFB + in] = SERIAL_NO_DATA_BYTE;
  640. }
  641. break;
  642. }
  643. /* What is interesting about the following check, is the Pokemon code
  644. * seems to allocate 203 bytes, 3x for the preamble, and then 200 bytes
  645. * of patch list. But in practice, the Game Boy seems to transmit 3x
  646. * preamble bytes, 7x 0x00, then 189 bytes for the patch list. A
  647. * total of 199 bytes transmitted.
  648. */
  649. /* Gen I and II patch lists seem to be the same length */
  650. if(counter == 196) {
  651. if(trade->pdata->gen == GEN_I)
  652. trade->trade_centre_state = TRADE_SELECT;
  653. else if(trade->pdata->gen == GEN_II)
  654. trade->trade_centre_state = TRADE_MAIL;
  655. counter = 0;
  656. }
  657. break;
  658. /* Preambled with 6x 0x20 bytes; 33*6 == 198 bytes of Mail, for each pokemon,
  659. * even if they have no mail set; 14*6 == 84 bytes, for each pokemon's mail,
  660. * the OT Name and ID; a 0xff; 100 zero bytes (unsure if they are always 0).
  661. * This is 6 + 198 + 84 + 1 + 100 == 389.
  662. */
  663. case TRADE_MAIL:
  664. counter++;
  665. if(counter == 389) trade->trade_centre_state = TRADE_SELECT;
  666. break;
  667. /* Resets the incoming Pokemon index, and once a BLANK byte is received,
  668. * moves to the pending state.
  669. */
  670. case TRADE_SELECT:
  671. in_pkmn_idx = 0;
  672. if(in == PKMN_BLANK) {
  673. trade->trade_centre_state = TRADE_PENDING;
  674. } else {
  675. break;
  676. }
  677. [[fallthrough]];
  678. /* Handle the Game Boy selecting a Pokemon to trade, or leaving the table */
  679. /* XXX: TODO: Clean this up. Easiest is probably to use vars rather than
  680. * macros to check against and set output to.
  681. */
  682. case TRADE_PENDING:
  683. /* If the player leaves the trade menu and returns to the room */
  684. if(in == bytes->table_leave) {
  685. trade->trade_centre_state = TRADE_RESET;
  686. send = bytes->table_leave;
  687. model->gameboy_status = GAMEBOY_READY;
  688. /* If the player selected a Pokemon to send from the Game Boy */
  689. } else if((in & bytes->sel_num_mask) == bytes->sel_num_mask) {
  690. in_pkmn_idx = in;
  691. send = bytes->sel_num_one; // We always send the first pokemon
  692. model->gameboy_status = GAMEBOY_TRADE_PENDING;
  693. /* BLANKs are sent in a few places, we want to do nothing about them
  694. * unless the Game Boy already sent us an index they want to trade.
  695. */
  696. } else if(in == PKMN_BLANK) {
  697. if(in_pkmn_idx != 0) {
  698. send = 0;
  699. trade->trade_centre_state = TRADE_CONFIRMATION;
  700. in_pkmn_idx &= 0x0F;
  701. }
  702. }
  703. break;
  704. /* Handle the Game Boy accepting or rejecting a trade deal */
  705. case TRADE_CONFIRMATION:
  706. if(in == bytes->trade_reject) {
  707. trade->trade_centre_state = TRADE_SELECT;
  708. model->gameboy_status = GAMEBOY_WAITING;
  709. } else if(in == bytes->trade_accept) {
  710. trade->trade_centre_state = TRADE_DONE;
  711. }
  712. break;
  713. /* Start the actual trade. Waits in reset until the Game Boy is done with
  714. * its animation and re-exchanges updated party data.
  715. */
  716. case TRADE_DONE:
  717. if(in == PKMN_BLANK) {
  718. trade->trade_centre_state = TRADE_RESET;
  719. model->gameboy_status = GAMEBOY_TRADING;
  720. /* Copy the traded-in Pokemon's main data to our struct */
  721. pokemon_stat_memcpy(trade->pdata, trade->input_pdata, in_pkmn_idx);
  722. model->curr_pokemon = pokemon_stat_get(trade->pdata, STAT_NUM, NONE);
  723. /* Schedule a callback outside of ISR context to rebuild the patch
  724. * list with the new Pokemon that we just accepted.
  725. */
  726. furi_timer_pending_callback(pokemon_plist_recreate_callback, trade, 0);
  727. }
  728. break;
  729. case TRADE_CANCEL:
  730. if(in == bytes->table_leave) {
  731. trade->trade_centre_state = TRADE_RESET;
  732. model->gameboy_status = GAMEBOY_READY;
  733. }
  734. send = bytes->table_leave;
  735. break;
  736. default:
  737. // Do Nothing
  738. break;
  739. }
  740. view_commit_model(trade->view, false);
  741. return send;
  742. }
  743. static void transferBit(void* context, uint8_t in_byte) {
  744. furi_assert(context);
  745. struct trade_ctx* trade = (struct trade_ctx*)context;
  746. render_gameboy_state_t status;
  747. with_view_model(
  748. trade->view, struct trade_model * model, { status = model->gameboy_status; }, false);
  749. trade->in_data = in_byte;
  750. /* Once a byte of data has been shifted in, process it */
  751. switch(status) {
  752. case GAMEBOY_CONN_FALSE:
  753. gblink_transfer(trade->gblink_handle, getConnectResponse(trade));
  754. break;
  755. case GAMEBOY_CONN_TRUE:
  756. gblink_transfer(trade->gblink_handle, getMenuResponse(trade));
  757. break;
  758. case GAMEBOY_COLOSSEUM:
  759. gblink_transfer(trade->gblink_handle, in_byte);
  760. break;
  761. /* Every other state is trade related */
  762. default:
  763. gblink_transfer(trade->gblink_handle, getTradeCentreResponse(trade));
  764. break;
  765. }
  766. /* Each byte that comes in, bump the backlight timer so it stays on during a trade */
  767. furi_timer_pending_callback(trade_backlight_bump_callback, trade, 0);
  768. }
  769. void trade_enter_callback(void* context) {
  770. furi_assert(context);
  771. struct trade_ctx* trade = (struct trade_ctx*)context;
  772. struct trade_model* model;
  773. struct gblink_def gblink_def = {0};
  774. model = view_get_model(trade->view);
  775. if(model->gameboy_status == GAMEBOY_COLOSSEUM) {
  776. model->gameboy_status = GAMEBOY_CONN_FALSE;
  777. } else if(model->gameboy_status > GAMEBOY_READY) {
  778. model->gameboy_status = GAMEBOY_READY;
  779. }
  780. trade->trade_centre_state = TRADE_RESET;
  781. model->curr_pokemon = pokemon_stat_get(trade->pdata, STAT_NUM, NONE);
  782. model->ledon = false;
  783. view_commit_model(trade->view, true);
  784. gblink_def.pins = trade->gblink_pins;
  785. gblink_def.callback = transferBit;
  786. gblink_def.cb_context = trade;
  787. trade->gblink_handle = gblink_alloc(&gblink_def);
  788. gblink_nobyte_set(trade->gblink_handle, SERIAL_NO_DATA_BYTE);
  789. /* Every 250 ms, trigger a draw update. 250 ms was chosen so that during
  790. * the trade process, each update can flip the LED and screen to make the
  791. * trade animation.
  792. */
  793. trade->draw_timer = furi_timer_alloc(trade_draw_timer_callback, FuriTimerTypePeriodic, trade);
  794. furi_timer_start(trade->draw_timer, furi_ms_to_ticks(250));
  795. /* Create a trade patch list from the current trade block */
  796. plist_create(&(trade->patch_list), trade->pdata);
  797. }
  798. void disconnect_pin(const GpioPin* pin) {
  799. /* Existing projects seem to set the pin back to analog mode upon exit */
  800. furi_hal_gpio_init_simple(pin, GpioModeAnalog);
  801. }
  802. void trade_exit_callback(void* context) {
  803. furi_assert(context);
  804. struct trade_ctx* trade = (struct trade_ctx*)context;
  805. furi_hal_light_set(LightGreen, 0x00);
  806. furi_hal_light_set(LightBlue, 0x00);
  807. furi_hal_light_set(LightRed, 0x00);
  808. /* Stop the timer, and deallocate it as the enter callback allocates it on entry */
  809. furi_timer_free(trade->draw_timer);
  810. trade->draw_timer = NULL;
  811. /* Unset the pin settings */
  812. gblink_free(trade->gblink_handle);
  813. /* Destroy the patch list, it is allocated on the enter callback */
  814. plist_free(trade->patch_list);
  815. trade->patch_list = NULL;
  816. }
  817. void* trade_alloc(
  818. PokemonData* pdata,
  819. struct gblink_pins* gblink_pins,
  820. ViewDispatcher* view_dispatcher,
  821. uint32_t view_id) {
  822. furi_assert(pdata);
  823. struct trade_ctx* trade = malloc(sizeof(struct trade_ctx));
  824. memset(trade, '\0', sizeof(struct trade_ctx));
  825. trade->view = view_alloc();
  826. trade->pdata = pdata;
  827. trade->input_pdata = pokemon_data_alloc(pdata->gen);
  828. trade->patch_list = NULL;
  829. trade->gblink_pins = gblink_pins;
  830. trade->notifications = furi_record_open(RECORD_NOTIFICATION);
  831. view_set_context(trade->view, trade);
  832. view_allocate_model(trade->view, ViewModelTypeLockFree, sizeof(struct trade_model));
  833. with_view_model(
  834. trade->view, struct trade_model * model, { model->pdata = pdata; }, false);
  835. view_set_draw_callback(trade->view, trade_draw_callback);
  836. view_set_input_callback(trade->view, trade_input_callback);
  837. view_set_enter_callback(trade->view, trade_enter_callback);
  838. view_set_exit_callback(trade->view, trade_exit_callback);
  839. view_dispatcher_add_view(view_dispatcher, view_id, trade->view);
  840. return trade;
  841. }
  842. void trade_free(ViewDispatcher* view_dispatcher, uint32_t view_id, void* trade_ctx) {
  843. furi_assert(trade_ctx);
  844. struct trade_ctx* trade = (struct trade_ctx*)trade_ctx;
  845. view_dispatcher_remove_view(view_dispatcher, view_id);
  846. furi_record_close(RECORD_NOTIFICATION);
  847. view_free(trade->view);
  848. pokemon_data_free(trade->input_pdata);
  849. free(trade);
  850. }