boilerplate_scene_2.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include "../malveke_gb_photo.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. struct BoilerplateScene2 {
  8. View* view;
  9. BoilerplateScene2Callback callback;
  10. void* context;
  11. };
  12. typedef struct {
  13. bool in_progress;
  14. int page;
  15. BoilerplateScene2* instance;
  16. } BoilerplateScene2Model;
  17. void boilerplate_scene_2_set_callback(
  18. BoilerplateScene2* instance,
  19. BoilerplateScene2Callback callback,
  20. void* context) {
  21. furi_assert(instance);
  22. furi_assert(callback);
  23. instance->callback = callback;
  24. instance->context = context;
  25. }
  26. void draw_thumbnail(void* context, Canvas* canvas, int page) {
  27. BoilerplateScene2* instance = context;
  28. Boilerplate* app = instance->context;
  29. UNUSED(app);
  30. // Gallery
  31. // for (int s=0;s< 8 * (page+1);s++) {
  32. // int count = ((page + 2) * 0x1000) + 0x0e00;
  33. int count = ((page + 2) * GB_PHOTO_SIZE) + 0x0e00;
  34. storage_file_seek(app->camera_ram_sav, count, true);
  35. for(int y = 0; y < 4; y++) {
  36. for(int x = 0; x < 4; x++) {
  37. storage_file_read(app->camera_ram_sav, app->tile_data, sizeof(app->tile_data));
  38. for(int row = 0; row < 8; row++) {
  39. uint8_t temp1 = app->tile_data[row * 2];
  40. uint8_t temp2 = app->tile_data[row * 2 + 1];
  41. for(int pixel = 7; pixel >= 0; pixel--) {
  42. int colorIndex = ((temp1 & 1) + ((temp2 & 1) * 2));
  43. if(colorIndex >= 2) {
  44. canvas_draw_dot(canvas, (x * 8) + (pixel + 47), (y * 8) + row + 17);
  45. }
  46. temp1 >>= 1;
  47. temp2 >>= 1;
  48. }
  49. }
  50. }
  51. }
  52. // }
  53. }
  54. void boilerplate_scene_2_draw(Canvas* canvas, BoilerplateScene2Model* model) {
  55. UNUSED(model);
  56. BoilerplateScene2* instance = model->instance;
  57. Boilerplate* app = instance->context;
  58. UNUSED(app);
  59. canvas_clear(canvas);
  60. canvas_set_color(canvas, ColorBlack);
  61. canvas_set_font(canvas, FontPrimary);
  62. canvas_draw_str(canvas, 21, 13, "Export All Photos");
  63. canvas_set_font(canvas, FontPrimary);
  64. char totalText[32];
  65. snprintf(totalText, sizeof(totalText), "%02d/29", model->page);
  66. draw_thumbnail(instance, canvas, model->page);
  67. if(!model->in_progress) {
  68. elements_button_center(canvas, "OK");
  69. } else {
  70. float dict_progress = (float)(model->page * 1) / (float)(29);
  71. int progress_width = 128 / 2;
  72. int position_x = (128 / 2);
  73. int position_y = 52;
  74. elements_progress_bar_with_text(
  75. canvas,
  76. position_x - (progress_width / 2),
  77. position_y,
  78. progress_width,
  79. dict_progress,
  80. totalText);
  81. }
  82. }
  83. static void boilerplate_scene_2_model_init(BoilerplateScene2Model* const model, void* context) {
  84. BoilerplateScene2* instance = context;
  85. model->instance = instance;
  86. model->page = 0;
  87. model->in_progress = false;
  88. }
  89. void save_all_image(void* context) {
  90. BoilerplateScene2* instance = context;
  91. Boilerplate* app = instance->context;
  92. UNUSED(app);
  93. furi_assert(app);
  94. NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION);
  95. // Create MALVEKE dir
  96. if(storage_common_stat(app->storage, MALVEKE_APP_FOLDER, NULL) == FSE_NOT_EXIST) {
  97. storage_simply_mkdir(app->storage, MALVEKE_APP_FOLDER);
  98. }
  99. // Create MALVEKE Photos dir
  100. if(storage_common_stat(app->storage, MALVEKE_APP_FOLDER_PHOTOS, NULL) == FSE_NOT_EXIST) {
  101. storage_simply_mkdir(app->storage, MALVEKE_APP_FOLDER_PHOTOS);
  102. }
  103. for(int page = 0; page < 30; page++) {
  104. int count = GB_FIRST_PHOTO_OFFSET + page * GB_PHOTO_SIZE;
  105. storage_file_seek(app->camera_ram_sav, count, true);
  106. // create file name
  107. FuriString* file_name = furi_string_alloc();
  108. get_timefilename(file_name, page);
  109. File* file = storage_file_alloc(app->storage);
  110. bool result =
  111. storage_file_open(file, furi_string_get_cstr(file_name), FSAM_WRITE, FSOM_OPEN_ALWAYS);
  112. if(result) {
  113. static char bmp[BMP_SIZE(WIDTH, HEIGHT)];
  114. bmp_init(bmp, WIDTH, HEIGHT);
  115. // Selected Palette
  116. uint32_t palette[] = {
  117. bmp_encode(app->palette_color_hex_a),
  118. bmp_encode(app->palette_color_hex_b),
  119. bmp_encode(app->palette_color_hex_c),
  120. bmp_encode(app->palette_color_hex_d)};
  121. UNUSED(palette);
  122. for(int y = 0; y < 14; y++) {
  123. for(int x = 0; x < 16; x++) {
  124. storage_file_read(app->camera_ram_sav, app->tile_data, sizeof(app->tile_data));
  125. for(int row = 0; row < 8; row++) {
  126. uint8_t temp1 = app->tile_data[row * 2];
  127. uint8_t temp2 = app->tile_data[row * 2 + 1];
  128. for(int pixel = 7; pixel >= 0; pixel--) {
  129. bmp_set(
  130. bmp,
  131. (x * 8) + pixel,
  132. (y * 8) + row,
  133. palette[((temp1 & 1) + ((temp2 & 1) * 2))]);
  134. temp1 >>= 1;
  135. temp2 >>= 1;
  136. }
  137. }
  138. }
  139. }
  140. storage_file_write(file, bmp, sizeof(bmp));
  141. with_view_model(
  142. instance->view,
  143. BoilerplateScene2Model * model,
  144. {
  145. // UNUSED(model);
  146. model->page = page;
  147. },
  148. true);
  149. furi_delay_ms(120);
  150. }
  151. // Closing the "file descriptor"
  152. storage_file_close(file);
  153. // Freeing up memory
  154. storage_file_free(file);
  155. }
  156. notification_message(notifications, &sequence_success);
  157. with_view_model(
  158. instance->view, BoilerplateScene2Model * model, { model->in_progress = false; }, true);
  159. }
  160. bool boilerplate_scene_2_input(InputEvent* event, void* context) {
  161. furi_assert(context);
  162. BoilerplateScene2* instance = context;
  163. // Boilerplate *app = instance->context;
  164. if(event->type == InputTypeRelease) {
  165. switch(event->key) {
  166. case InputKeyOk:
  167. with_view_model(
  168. instance->view,
  169. BoilerplateScene2Model * model,
  170. { model->in_progress = true; },
  171. true);
  172. save_all_image(instance);
  173. break;
  174. case InputKeyBack:
  175. instance->callback(BoilerplateCustomEventScene2Back, instance->context);
  176. break;
  177. case InputKeyLeft:
  178. case InputKeyRight:
  179. case InputKeyUp:
  180. case InputKeyDown:
  181. case InputKeyMAX:
  182. break;
  183. }
  184. }
  185. return true;
  186. }
  187. void boilerplate_scene_2_exit(void* context) {
  188. furi_assert(context);
  189. Boilerplate* app = context;
  190. UNUSED(app);
  191. // boilerplate_stop_all_sound(app);
  192. // boilerplate_led_reset(app);
  193. }
  194. BoilerplateScene2* boilerplate_scene_2_alloc() {
  195. BoilerplateScene2* instance = malloc(sizeof(BoilerplateScene2));
  196. instance->view = view_alloc();
  197. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(BoilerplateScene2Model));
  198. view_set_context(instance->view, instance);
  199. view_set_draw_callback(instance->view, (ViewDrawCallback)boilerplate_scene_2_draw);
  200. view_set_input_callback(instance->view, boilerplate_scene_2_input);
  201. view_set_exit_callback(instance->view, boilerplate_scene_2_exit);
  202. with_view_model(
  203. instance->view,
  204. BoilerplateScene2Model * model,
  205. { boilerplate_scene_2_model_init(model, instance); },
  206. true);
  207. return instance;
  208. }
  209. void boilerplate_scene_2_free(BoilerplateScene2* instance) {
  210. furi_assert(instance);
  211. view_free(instance->view);
  212. free(instance);
  213. }
  214. View* boilerplate_scene_2_get_view(BoilerplateScene2* instance) {
  215. furi_assert(instance);
  216. return instance->view;
  217. }