gba_cartridge_scene_1.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. #include "../gba_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 <stdio.h> // Para sprintf
  8. #include <string.h> // Para strlen
  9. struct GBACartridgeScene1 {
  10. View* view;
  11. GBACartridgeScene1Callback callback;
  12. void* context;
  13. GBACartridge* app;
  14. };
  15. typedef struct {
  16. char* cart_title;
  17. char* cart_serial;
  18. char* cart_checksum;
  19. char* cart_ROMSize;
  20. char* cart_RAMSize;
  21. char* cart_gb_type;
  22. bool cart_gb_sgb;
  23. char* cart_logo;
  24. // int ramBanks;
  25. // int romBanks;
  26. // uint8_t cart_logo[48*8];
  27. } GameBoyCartridgeModel;
  28. void gameboy_information_handle_rx_data_cb(uint8_t* buf, size_t len, void* context) {
  29. furi_assert(context);
  30. UNUSED(len);
  31. UNUSED(buf);
  32. GBACartridge* instance = context;
  33. with_view_model(
  34. instance->gba_cartridge_scene_1->view,
  35. GameBoyCartridgeModel * model,
  36. {
  37. cJSON* json = cJSON_Parse((char*)buf);
  38. if (json == NULL) {
  39. model->cart_title = "Parse error";
  40. } else {;
  41. // Title to LONG
  42. // cJSON* title = cJSON_GetObjectItemCaseSensitive(json, "title");
  43. // if (cJSON_IsString(title) && (title->valuestring != NULL))
  44. // {
  45. // model->cart_title = strdup(title->valuestring);
  46. // } else {
  47. // model->cart_title = "None";
  48. // }
  49. // Title
  50. cJSON* title = cJSON_GetObjectItemCaseSensitive(json, "rom_title");
  51. if (cJSON_IsString(title) && (title->valuestring != NULL))
  52. {
  53. model->cart_title = strdup(title->valuestring);
  54. } else {
  55. model->cart_title = "None";
  56. }
  57. // Serial
  58. cJSON* serial = cJSON_GetObjectItemCaseSensitive(json, "serial");
  59. if (cJSON_IsString(serial) && (serial->valuestring != NULL))
  60. {
  61. model->cart_serial = strdup(serial->valuestring);
  62. } else {
  63. model->cart_serial = "";
  64. }
  65. // Checksum
  66. cJSON* checksum = cJSON_GetObjectItemCaseSensitive(json, "checksum");
  67. if (cJSON_IsString(checksum) && (checksum->valuestring != NULL))
  68. {
  69. model->cart_checksum = strdup(checksum->valuestring);
  70. } else {
  71. model->cart_checksum = "None";
  72. }
  73. // ROMSize
  74. cJSON* ROMSize = cJSON_GetObjectItemCaseSensitive(json, "ROMSize");
  75. if (cJSON_IsNumber(ROMSize)) {
  76. char buffer[20]; // Tamaño suficiente para almacenar un entero
  77. snprintf(buffer, sizeof(buffer), "%d", ROMSize->valueint);
  78. model->cart_ROMSize = strdup(buffer); // Asigna una copia dinámica de la cadena
  79. } else {
  80. model->cart_ROMSize = NULL; // Puedes asignar NULL o cualquier otro valor predeterminado
  81. }
  82. // RAMSize
  83. cJSON* RAMSize = cJSON_GetObjectItemCaseSensitive(json, "RAMSize");
  84. if (cJSON_IsString(RAMSize) && (RAMSize->valuestring != NULL))
  85. {
  86. model->cart_RAMSize = strdup(RAMSize->valuestring);
  87. } else {
  88. model->cart_RAMSize = "None";
  89. }
  90. // GB Type
  91. cJSON* gb_type = cJSON_GetObjectItemCaseSensitive(json, "gb_type");
  92. if (cJSON_IsString(gb_type) && (gb_type->valuestring != NULL))
  93. {
  94. model->cart_gb_type = strdup(gb_type->valuestring);
  95. } else {
  96. model->cart_gb_type = "dump";
  97. }
  98. cJSON* logo_correct = cJSON_GetObjectItemCaseSensitive(json, "logo_correct");
  99. if (cJSON_IsBool(logo_correct))
  100. {
  101. model->cart_logo = cJSON_IsTrue(logo_correct) ? "OK" : "NO";
  102. } else {
  103. model->cart_logo = "NO";
  104. }
  105. FuriString* path = furi_string_alloc();
  106. // int buffer_size = strlen(model->cart_title) + strlen(model->cart_serial) + strlen(model->cart_gb_type) + 3; // 3 para los guiones bajos y el punto
  107. // char filename[255];
  108. if (strcmp(model->cart_serial, "") == 0) {
  109. furi_string_cat_printf(path, "%s", model->cart_title);
  110. } else {
  111. furi_string_cat_printf(path, "%s_%s", model->cart_title, model->cart_serial);
  112. }
  113. // snprintf(filename,255, "%s_%s.%s", model->cart_title, model->cart_serial, model->cart_gb_type);
  114. instance->cart_dump_rom_filename = (char*)furi_string_get_cstr(path);
  115. instance->cart_dump_rom_extension = model->cart_gb_type;
  116. instance->cart_dump_ram_filename = (char*)furi_string_get_cstr(path);
  117. instance->cart_dump_ram_extension = "sav";
  118. // instance->rom_banks = model->romBanks;
  119. // instance->ram_banks = model->ramBanks;
  120. }
  121. },true);
  122. }
  123. void gba_cartridge_scene_1_set_callback(
  124. GBACartridgeScene1* instance,
  125. GBACartridgeScene1Callback callback,
  126. void* context) {
  127. furi_assert(instance);
  128. furi_assert(callback);
  129. instance->callback = callback;
  130. instance->context = context;
  131. instance->app = (GBACartridge*)context;
  132. }
  133. void gba_cartridge_scene_1_draw(Canvas* canvas, GameBoyCartridgeModel* model) {
  134. UNUSED(model);
  135. canvas_clear(canvas);
  136. // canvas_set_color(canvas, ColorBlack);
  137. // canvas_set_font(canvas, FontPrimary);
  138. // canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignTop, "This is Scene 1");
  139. // canvas_set_font(canvas, FontSecondary);
  140. // canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "An empty scene to be");
  141. // canvas_draw_str_aligned(canvas, 0, 32, AlignLeft, AlignTop, "used as boilerplate");
  142. // Clear the screen.
  143. canvas_set_color(canvas, ColorBlack);
  144. canvas_set_bitmap_mode(canvas, 1);
  145. canvas_set_font(canvas, FontPrimary);
  146. canvas_draw_str_aligned(canvas, 128 / 2, 1, AlignCenter, AlignTop, model->cart_title);
  147. // canvas_draw_str_aligned(canvas, 128 / 2, 1, AlignCenter, AlignTop, "Prueba"); // title
  148. canvas_set_font(canvas, FontSecondary);
  149. canvas_draw_str(canvas, 2, 20, "Game Code / REV");
  150. canvas_set_font(canvas, FontPrimary);
  151. // canvas_draw_str(canvas, 87, 20, "APSS-0"); // serial
  152. canvas_draw_str_aligned(canvas, 126, 20, AlignRight, AlignBottom, model->cart_serial);
  153. canvas_set_font(canvas, FontSecondary);
  154. canvas_draw_str(canvas, 2, 30, "Boot Logo");
  155. canvas_set_font(canvas, FontPrimary);
  156. canvas_draw_str_aligned(canvas, 126, 30, AlignRight, AlignBottom, model->cart_logo);
  157. canvas_set_font(canvas, FontSecondary);
  158. canvas_draw_str(canvas, 2, 40, "ROM Checksum");
  159. canvas_set_font(canvas, FontPrimary);
  160. // canvas_draw_str(canvas, 87, 40, "0X04C7"); // checksum
  161. canvas_draw_str_aligned(canvas, 126, 39, AlignRight, AlignBottom, model->cart_checksum);
  162. canvas_set_font(canvas, FontSecondary);
  163. canvas_draw_str(canvas, 2, 50, "ROM Size");
  164. canvas_set_font(canvas, FontPrimary);
  165. // canvas_draw_str(canvas, 98, 49, "1 MiB"); // ROMSize
  166. canvas_draw_str_aligned(canvas, 126, 49, AlignRight, AlignBottom, model->cart_ROMSize);
  167. canvas_set_font(canvas, FontSecondary);
  168. canvas_draw_str(canvas, 2, 60, "Save Type");
  169. canvas_set_font(canvas, FontPrimary);
  170. // canvas_draw_str(canvas, 63, 60, "SRAM 32KiB"); // RAMSize
  171. canvas_draw_str_aligned(canvas, 126, 59, AlignRight, AlignBottom, model->cart_RAMSize);
  172. }
  173. static void gba_cartridge_scene_1_model_init(GameBoyCartridgeModel* const model) {
  174. UNUSED(model);
  175. // FuriString* cart_title;
  176. // FuriString* cart_serial;
  177. // FuriString* cart_checksum;
  178. // FuriString* cart_ROMSize;
  179. // FuriString* cart_RAMSize;
  180. model->cart_title = "Loading...";
  181. model->cart_serial = "";
  182. model->cart_checksum = "";
  183. model->cart_ROMSize = "";
  184. model->cart_RAMSize = "";
  185. model->cart_gb_type = "";
  186. model->cart_logo = "";
  187. }
  188. bool gba_cartridge_scene_1_input(InputEvent* event, void* context) {
  189. furi_assert(context);
  190. GBACartridgeScene1* instance = context;
  191. bool consumed = false;
  192. if (event->type == InputTypeRelease) {
  193. switch(event->key) {
  194. case InputKeyBack:
  195. // with_view_model(
  196. // instance->view,
  197. // GameBoyCartridgeModel * model,
  198. // {
  199. // UNUSED(model);
  200. // instance->callback(GBACartridgeCustomEventScene1Back, instance->context);
  201. // },
  202. // true);
  203. consumed = true;
  204. break;
  205. case InputKeyOk:
  206. with_view_model(
  207. ((GBACartridge*)instance->app)->gba_cartridge_scene_1->view,
  208. GameBoyCartridgeModel * model,
  209. {
  210. model->cart_title = "Refresh...";
  211. model->cart_serial = "";
  212. model->cart_checksum = "";
  213. model->cart_ROMSize = "";
  214. model->cart_RAMSize = "";
  215. // Register callbacks to receive data
  216. uart_set_handle_rx_data_cb(((GBACartridge*)instance->app)->uart, gameboy_information_handle_rx_data_cb); // setup callback for general log rx thread
  217. const char GBACartridge_command[] = "gbacartridge -i\n";
  218. uart_tx((uint8_t*)GBACartridge_command, strlen(GBACartridge_command));
  219. },
  220. true);
  221. consumed = true;
  222. break;
  223. case InputKeyLeft:
  224. case InputKeyRight:
  225. case InputKeyUp:
  226. case InputKeyDown:
  227. with_view_model(
  228. instance->view,
  229. GameBoyCartridgeModel* model,
  230. {
  231. UNUSED(model);
  232. },
  233. true);
  234. consumed = true;
  235. break;
  236. case InputKeyMAX:
  237. break;
  238. }
  239. }
  240. return consumed;
  241. }
  242. void gba_cartridge_scene_1_exit(void* context) {
  243. furi_assert(context);
  244. }
  245. void gba_cartridge_scene_1_enter(void* context) {
  246. furi_assert(context);
  247. GBACartridgeScene1* instance = (GBACartridgeScene1*)context;
  248. with_view_model(
  249. instance->view,
  250. GameBoyCartridgeModel * model,
  251. {
  252. gba_cartridge_scene_1_model_init(model);
  253. },
  254. true
  255. );
  256. // Register callbacks to receive data
  257. uart_set_handle_rx_data_cb(((GBACartridge*)instance->app)->uart, gameboy_information_handle_rx_data_cb); // setup callback for general log rx thread
  258. const char GBACartridge_command[] = "gbacartridge -i\n";
  259. uart_tx((uint8_t*)GBACartridge_command, strlen(GBACartridge_command));
  260. }
  261. GBACartridgeScene1* gba_cartridge_scene_1_alloc() {
  262. GBACartridgeScene1* instance = malloc(sizeof(GBACartridgeScene1));
  263. instance->view = view_alloc();
  264. view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(GameBoyCartridgeModel));
  265. view_set_context(instance->view, instance); // furi_assert crashes in events without this
  266. view_set_draw_callback(instance->view, (ViewDrawCallback)gba_cartridge_scene_1_draw);
  267. view_set_input_callback(instance->view, gba_cartridge_scene_1_input);
  268. view_set_enter_callback(instance->view, gba_cartridge_scene_1_enter);
  269. view_set_exit_callback(instance->view, gba_cartridge_scene_1_exit);
  270. with_view_model(
  271. instance->view,
  272. GameBoyCartridgeModel * model,
  273. {
  274. gba_cartridge_scene_1_model_init(model);
  275. },
  276. true
  277. );
  278. return instance;
  279. }
  280. void gba_cartridge_scene_1_free(GBACartridgeScene1* instance) {
  281. furi_assert(instance);
  282. with_view_model(
  283. instance->view,
  284. GameBoyCartridgeModel * model,
  285. {
  286. UNUSED(model);
  287. },
  288. true);
  289. view_free(instance->view);
  290. free(instance);
  291. }
  292. View* gba_cartridge_scene_1_get_view(GBACartridgeScene1* instance) {
  293. furi_assert(instance);
  294. return instance->view;
  295. }