gb_cartridge_scene_4.c 10 KB

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