gb_cartridge_scene_4.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include "../gb_cartridge_app.h"
  2. #include <furi.h>
  3. #include <furi_hal.h>
  4. #include <input/input.h>
  5. #include <gui/elements.h>
  6. #include <dolphin/dolphin.h>
  7. #include <gui/elements.h>
  8. #include <notification/notification_messages.h>
  9. #include <dialogs/dialogs.h>
  10. #include <gui/modules/dialog_ex.h>
  11. #include <toolbox/stream/file_stream.h>
  12. #include "../helpers/gb_cartridge_speaker.h"
  13. #include "../helpers/sequential_file.h"
  14. #include <stdio.h> // Para sprintf
  15. #include <string.h> // Para strlen
  16. #include <lib/toolbox/stream/file_stream.h>
  17. struct GBCartridgeScene4 {
  18. View* view;
  19. GBCartridgeScene4Callback callback;
  20. void* context;
  21. GBCartridge* app;
  22. };
  23. typedef struct {
  24. char* event_type;
  25. int progress;
  26. int total_rom;
  27. int transfered;
  28. int romBanks;
  29. int elapsed_time;
  30. int start_time;
  31. char* cart_dump_rom_filename_sequential;
  32. bool rx_active;
  33. char* gameboy_rom_option_selected_text;
  34. } GameBoyCartridgeROMWriteModel;
  35. void gb_cartridge_scene_4_set_callback(
  36. GBCartridgeScene4* instance,
  37. GBCartridgeScene4Callback callback,
  38. void* context) {
  39. furi_assert(instance);
  40. furi_assert(callback);
  41. instance->callback = callback;
  42. instance->context = context;
  43. }
  44. static void drawProgressBar(Canvas* canvas, int progress) {
  45. for(int x = 0; x < 64 - 14 - UI_PADDING - UI_PADDING -UI_PADDING - UI_PADDING; x += 5) {
  46. for(int row = 0; row < 20; row += 5) {
  47. if(progress > 0) {
  48. canvas_draw_box(canvas, 14 /*ARROW*/ + UI_PADDING + 2+ x + 4, /*45*/ 26 + row, 4, 4);
  49. progress--;
  50. } else {
  51. canvas_draw_frame(canvas, 14 /*ARROW*/ + UI_PADDING + 2+ x + 4, /*45*/ 26 + row, 4, 4);
  52. }
  53. }
  54. }
  55. }
  56. void gb_cartridge_scene_4_draw(Canvas* canvas, GameBoyCartridgeROMWriteModel* model) {
  57. // Clear the screen.
  58. canvas_set_color(canvas, ColorBlack);
  59. canvas_clear(canvas);
  60. canvas_set_color(canvas, ColorBlack);
  61. canvas_set_font(canvas, FontKeyboard);
  62. canvas_draw_frame(canvas, 0, 24, (128/2), 25);
  63. canvas_set_bitmap_mode(canvas, 1);
  64. canvas_set_font(canvas, FontPrimary);
  65. char progressText[42];
  66. int progress = 0;
  67. if(model->total_rom > 0 && model->transfered > 0) {
  68. progress = model->transfered * 100 / model->total_rom;
  69. }
  70. snprintf(progressText, sizeof(progressText), "%d%% Write ROM... GB: %s", progress, model->gameboy_rom_option_selected_text);
  71. canvas_draw_str_aligned(canvas, 128 / 2, 0, AlignCenter, AlignTop, progressText);
  72. canvas_set_font(canvas, FontSecondary);
  73. // char *filename = strrchr(model->cart_dump_rom_filename_sequential, '/');
  74. // filename++;
  75. // canvas_draw_str_aligned(canvas, 128/2, 12, AlignCenter, AlignTop, filename);
  76. char total_rom_str[20];
  77. snprintf(total_rom_str, sizeof(total_rom_str), "of %.2lf MiB", (double)(model->total_rom / 1024.0 / 1024.0));
  78. char transfered_rom_str[20];
  79. snprintf(transfered_rom_str, sizeof(transfered_rom_str), "%.2lf MiB", (double)(model->transfered / 1024.0 / 1024.0));
  80. // Calcula la Tasa de Transferencia en KiB/s
  81. char transfer_rate_str[20];
  82. if(model->transfered>0 && model->elapsed_time > 0) {
  83. double transfer_rate_kibps = (double)model->transfered / ((double)model->elapsed_time ) / (double)1024.0;
  84. snprintf(transfer_rate_str, sizeof(transfer_rate_str), "%.2lf KiB/s", transfer_rate_kibps);
  85. } else {
  86. snprintf(transfer_rate_str, sizeof(transfer_rate_str), "0 KiB/s");
  87. }
  88. canvas_draw_str_aligned(canvas, (128/2) + UI_PADDING, 22 + 2, AlignLeft, AlignTop, transfered_rom_str);
  89. canvas_draw_str_aligned(canvas, (128/2) + UI_PADDING, 40 + 2, AlignLeft, AlignTop, total_rom_str);
  90. canvas_draw_str_aligned(canvas, (128/2) + UI_PADDING, 48 + 2, AlignLeft, AlignTop, transfer_rate_str);
  91. if(model->rx_active) {
  92. canvas_draw_icon_ex(canvas, UI_PADDING, 28, &I_ArrowUpFilled_14x15, IconRotation180);
  93. } else {
  94. canvas_draw_icon_ex(canvas, UI_PADDING, 28, &I_ArrowUpEmpty_14x15, IconRotation180);
  95. }
  96. char totalText[42];
  97. snprintf(totalText, sizeof(totalText), "%d", model->total_rom);
  98. // canvas_draw_str(canvas, 69, 48, totalText);
  99. drawProgressBar(canvas, (progress * UI_PROGRESS_ROWS * UI_PROGRESS_COLS) / 100); // Pinta las primeras 10 cajas de negro
  100. // free(totalText);
  101. elements_button_center(canvas, "Write");
  102. }
  103. static void gb_cartridge_scene_4_model_init(GameBoyCartridgeROMWriteModel* const model) {
  104. model->progress = 0;
  105. model->total_rom = 0;
  106. model->transfered = 0;
  107. model->romBanks = 0;
  108. model->elapsed_time = 0;
  109. model->start_time = 0;
  110. }
  111. // static bool select_rom_file(GBCartridge *app, Stream* stream) {
  112. // bool result = false;
  113. // FuriString* file_path = furi_string_alloc();
  114. // furi_string_set(file_path, MALVEKE_APP_FOLDER);
  115. // DialogsFileBrowserOptions browser_options;
  116. // dialog_file_browser_set_basic_options(
  117. // &browser_options, app->gameboy_rom_option_selected_text, NULL);
  118. // browser_options.base_path = MALVEKE_APP_FOLDER;
  119. // browser_options.skip_assets = true;
  120. // // Input events and views are managed by file_browser
  121. // bool res = dialog_file_browser_show( app->dialogs, file_path, file_path, &browser_options);
  122. // UNUSED(res);
  123. // FURI_LOG_I(TAG, "File selected: %s", furi_string_get_cstr(file_path));
  124. // if(res) {
  125. // if(!file_stream_open(stream, furi_string_get_cstr(file_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
  126. // FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(file_path));
  127. // file_stream_close(stream);
  128. // } else {
  129. // FURI_LOG_D(TAG, "Open file \"%s\"", furi_string_get_cstr(file_path));
  130. // result = true;
  131. // }
  132. // }
  133. // furi_string_free(file_path);
  134. // return result;
  135. // }
  136. bool gb_cartridge_scene_4_input(InputEvent* event, void* context) {
  137. furi_assert(context);
  138. GBCartridgeScene4* instance = context;
  139. if (event->type == InputTypeRelease) {
  140. switch(event->key) {
  141. case InputKeyBack:
  142. with_view_model(
  143. instance->view,
  144. GameBoyCartridgeROMWriteModel * model,
  145. {
  146. UNUSED(model);
  147. GBCartridge* app = (GBCartridge*)instance->context;
  148. // Unregister rx callback
  149. uart_set_handle_rx_data_cb(app->uart, NULL);
  150. // uart_set_handle_rx_data_cb(app->lp_uart, NULL);
  151. instance->callback(GBCartridgeCustomEventScene4Back, instance->context);
  152. },
  153. true);
  154. break;
  155. case InputKeyUp:
  156. case InputKeyDown:
  157. case InputKeyLeft:
  158. case InputKeyRight:
  159. break;
  160. case InputKeyOk:
  161. with_view_model(
  162. instance->view,
  163. GameBoyCartridgeROMWriteModel * model,
  164. {
  165. GBCartridge* app = ((GBCartridge*)instance->context);
  166. UNUSED(model);
  167. UNUSED(app);
  168. // uint8_t buffer[BUFFER_SIZE];
  169. // size_t bytesRead;
  170. // Stream* file_stream = file_stream_alloc(app->storage);
  171. // if(select_rom_file(app, file_stream)) {
  172. // const char gbcartridge_start_command[] = "gbcartridge -w -o -s\n";
  173. // uart_tx((uint8_t*)gbcartridge_start_command, strlen(gbcartridge_start_command));
  174. // furi_delay_ms(500);
  175. // while (file_stream_read(file_stream, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
  176. // // Send 64 bytes at a time
  177. // lp_uart_tx((uint8_t*)buffer, bytesRead);
  178. // }
  179. // const char gbcartridge_end_command[] = "gbcartridge -w -o -e\n";
  180. // uart_tx((uint8_t*)gbcartridge_end_command, strlen(gbcartridge_end_command));
  181. // file_stream_close(file_stream);
  182. // }
  183. // stream_free(file_stream);
  184. },
  185. true);
  186. break;
  187. case InputKeyMAX:
  188. break;
  189. }
  190. }
  191. return true;
  192. }
  193. void gb_cartridge_scene_4_exit(void* context) {
  194. furi_assert(context);
  195. GBCartridge* app = context;
  196. gb_cartridge_stop_all_sound(app);
  197. }
  198. void gb_cartridge_scene_4_enter(void* context) {
  199. furi_assert(context);
  200. GBCartridgeScene4* instance = context;
  201. GBCartridge* app = (GBCartridge*)instance->context;
  202. UNUSED(app);
  203. with_view_model(
  204. app->gb_cartridge_scene_4->view,
  205. GameBoyCartridgeROMWriteModel * model,
  206. {
  207. UNUSED(model);
  208. gb_cartridge_scene_4_model_init(model);
  209. model->gameboy_rom_option_selected_text = app->gameboy_rom_option_selected_text;
  210. },
  211. false);
  212. }
  213. GBCartridgeScene4* gb_cartridge_scene_4_alloc() {
  214. GBCartridgeScene4* instance = malloc(sizeof(GBCartridgeScene4));
  215. instance->view = view_alloc();
  216. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(GameBoyCartridgeROMWriteModel));
  217. view_set_context(instance->view, instance);
  218. view_set_draw_callback(instance->view, (ViewDrawCallback)gb_cartridge_scene_4_draw);
  219. view_set_input_callback(instance->view, gb_cartridge_scene_4_input);
  220. view_set_enter_callback(instance->view, gb_cartridge_scene_4_enter);
  221. view_set_exit_callback(instance->view, gb_cartridge_scene_4_exit);
  222. with_view_model(
  223. instance->view,
  224. GameBoyCartridgeROMWriteModel * model,
  225. {
  226. gb_cartridge_scene_4_model_init(model);
  227. },
  228. true);
  229. return instance;
  230. }
  231. void gb_cartridge_scene_4_free(GBCartridgeScene4* instance) {
  232. furi_assert(instance);
  233. view_free(instance->view);
  234. free(instance);
  235. }
  236. View* gb_cartridge_scene_4_get_view(GBCartridgeScene4* instance) {
  237. furi_assert(instance);
  238. return instance->view;
  239. }