暂无描述

pokedex_detail.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. #include <agb_debug.h>
  2. #include <pokeagb/pokeagb.h>
  3. #include <pokedex/pdexArrowRotated.h>
  4. #include <pokedex/pdexDetailBg.h>
  5. #include "pokedex_common.h"
  6. #define TB_PKNAME 0
  7. #define TB_PKSIZE 1
  8. #define TB_DESC 2
  9. #define TB_PKNAME_W 30
  10. #define TB_SW_W 12
  11. extern pchar pdex_str_size[];
  12. extern pchar pdex_str_weight[];
  13. extern pchar pdex_str_size_unit[];
  14. extern pchar pdex_str_weight_unit[];
  15. extern pchar pdex_str_comma[];
  16. struct TextboxTemplate dexdetail_boxes[] = {
  17. {.bg_id = 0, .x = 0, .y = 0, .width = TB_PKNAME_W, .height = 4, .pal_id = 15, .charbase = 1},
  18. {.bg_id = 0, .x = 17, .y = 5, .width = TB_SW_W, .height = 4, .pal_id = 15, .charbase = 121},
  19. {.bg_id = 1, .x = 1, .y = 0, .width = 28, .height = 20, .pal_id = 15, .charbase = 161},
  20. {.bg_id = 0xFF},
  21. };
  22. u8 dexdetail_type_to_oam_type[18] = {0, 9, 8, 12, 6, 5, 11, 10, 14, 17, 1, 2, 3, 4, 13, 7, 16, 15};
  23. #define O_TYPE(t) (dexdetail_type_to_oam_type[t])
  24. struct OamData dexdetail_type_oam = {
  25. .affine_mode = 0,
  26. .obj_mode = 0,
  27. .mosaic = false,
  28. .shape = 1,
  29. .size = 2,
  30. };
  31. void dexdetail_update_type_oam(u8 type, struct Object *obj) {
  32. memcpy((void *)((0x06010000) + (obj->final_oam.tile_num * 0x20)),
  33. pokemon_type_chart_gfx + (128 * O_TYPE(type)) + (512 * (O_TYPE(type) >> 2)), 128);
  34. memcpy((void *)((0x06010000) + 128 + (obj->final_oam.tile_num * 0x20)),
  35. pokemon_type_chart_gfx + 512 + (128 * O_TYPE(type)) + (512 * (O_TYPE(type) >> 2)), 128);
  36. }
  37. s8 dexdetail_load_type_oam(u8 type, u16 tag) {
  38. struct SpriteTiles typeTiles = {(&pokemon_type_chart_gfx[0]) + 256 * O_TYPE(type), 256, tag};
  39. gpu_tile_obj_alloc_tag_and_upload(&typeTiles);
  40. const struct Template typeTemplate = {
  41. .tiles_tag = tag,
  42. .pal_tag = DEX_DETAIL_TYPEPAL,
  43. .oam = &dexdetail_type_oam,
  44. .animation = &anim_image_empty,
  45. .graphics = &typeTiles,
  46. .rotscale = &rotscale_empty,
  47. .callback = oac_nullsub,
  48. };
  49. s8 id = (s8)template_instanciate_forward_search(&typeTemplate, 100, 100, 0);
  50. dexdetail_update_type_oam(type, &objects[id]);
  51. return id;
  52. }
  53. extern pchar pdex_str_form_alola[];
  54. void dexdetail_load_pokemon(u16 dexindex, enum DexFormType formType) {
  55. u16 species = pdex_lazy_lookup_entry(dexindex)->species;
  56. rboxid_clear_pixels(TB_PKNAME, 0);
  57. rboxid_clear_pixels(TB_PKSIZE, 0);
  58. rboxid_clear_pixels(TB_DESC, 0);
  59. pstrcpy(string_buffer, &pokemon_names[species][0]);
  60. switch (formType) {
  61. case ALOLA:
  62. pstrcat(string_buffer, pdex_str_form_alola);
  63. break;
  64. default:
  65. break;
  66. }
  67. u16 twidth = font_get_width_of_string(FONT_DEX_STD, string_buffer, 0x0000);
  68. rboxid_print(TB_PKNAME, FONT_DEX_STD, TB_STD_CENTER(twidth, 8 * TB_PKNAME_W), 0, &pdex_text_color, 0,
  69. string_buffer);
  70. pchar *strType = &pokedex_data[dexindex].category_name[0];
  71. u16 typeTwidth = font_get_width_of_string(FONT_DEX_STD, strType, 0x0000);
  72. rboxid_print(TB_PKNAME, FONT_DEX_STD, TB_STD_CENTER(typeTwidth, 88) + 110, 14, &pdex_text_color, 0, strType);
  73. rboxid_print(TB_PKSIZE, FONT_DEX_STD, 4, 1, &pdex_text_color, 0, pdex_str_size);
  74. rboxid_print(TB_PKSIZE, FONT_DEX_STD, 4, 14, &pdex_text_color, 0, pdex_str_weight);
  75. u16 weightNumber = pokedex_data[dexindex].weight / 10;
  76. u16 weightDecimal = pokedex_data[dexindex].weight % 10;
  77. pchar buffer[20];
  78. fmt_int_10(string_buffer, weightNumber, 0, 3);
  79. fmt_int_10(&buffer[0], weightDecimal, 0, 1);
  80. pstrcat(string_buffer, pdex_str_comma);
  81. pstrcat(string_buffer, buffer);
  82. pstrcat(string_buffer, pdex_str_weight_unit);
  83. u16 weightTwidth = font_get_width_of_string(FONT_DEX_STD, string_buffer, 0x0000);
  84. rboxid_print(TB_PKSIZE, FONT_DEX_STD, TB_STD_RIGHT(weightTwidth, TB_SW_W * 8) - 6, 14, &pdex_text_color, 0,
  85. string_buffer);
  86. u16 sizeNumber = pokedex_data[dexindex].height / 10;
  87. u16 sizeDecimal = pokedex_data[dexindex].height % 10;
  88. fmt_int_10(string_buffer, sizeNumber, 0, 3);
  89. fmt_int_10(&buffer[0], sizeDecimal, 0, 1);
  90. pstrcat(string_buffer, pdex_str_comma);
  91. pstrcat(string_buffer, buffer);
  92. pstrcat(string_buffer, pdex_str_size_unit);
  93. rboxid_print(TB_PKSIZE, FONT_DEX_STD, TB_STD_RIGHT(weightTwidth, TB_SW_W * 8) - 6, 1, &pdex_text_color, 0,
  94. string_buffer);
  95. rboxid_print(TB_DESC, FONT_DEX_STD, 3, 2, &pdex_text_color, 0, pokedex_data[dexindex].description1);
  96. /* setup scrolling parameters */
  97. u8 descLines = pstr_lines(&pokedex_data[dexindex].description1[0]);
  98. if (descLines > 4)
  99. pokedex_context->detail_scroll_max = descLines - 4;
  100. else
  101. pokedex_context->detail_scroll_max = 0;
  102. /* load the species sprite */
  103. if (pokedex_context->detail_pokemon_oam != -1) {
  104. lz77UnCompVram(
  105. pokemon_graphics_front[species].data,
  106. ((void *)(objects[pokedex_context->detail_pokemon_oam].final_oam.tile_num * 32) + ADDR_VRAM + 0x10000));
  107. gpu_pal_apply_compressed(pokemon_palette_normal[species].data,
  108. 16 * (objects[pokedex_context->detail_pokemon_oam].final_oam.palette_num + 16), 32);
  109. } else {
  110. struct SpriteTiles pkmnTiles = {pokemon_graphics_front[species].data, 2048, DEX_PKMN_TAG_ONE};
  111. struct SpritePalette pkmnPal = {pokemon_palette_normal[species].data, DEX_PKMN_TAG_ONE};
  112. const struct Template pkmnTemplate = {
  113. .tiles_tag = DEX_PKMN_TAG_ONE,
  114. .pal_tag = DEX_PKMN_TAG_ONE,
  115. .oam = &pdex_oam_pkmn,
  116. .animation = &anim_image_empty,
  117. .graphics = &pkmnTiles,
  118. .rotscale = &rotscale_empty,
  119. .callback = oac_nullsub,
  120. };
  121. gpu_tile_obj_decompress_alloc_tag_and_upload(&pkmnTiles);
  122. gpu_pal_decompress_alloc_tag_and_upload(&pkmnPal);
  123. pokedex_context->detail_pokemon_oam = (s8)template_instanciate_forward_search(&pkmnTemplate, 10, 10, 0);
  124. objects[pokedex_context->detail_pokemon_oam].pos1.x = 55;
  125. objects[pokedex_context->detail_pokemon_oam].pos1.y = 55;
  126. }
  127. // draw the first type icon
  128. if (pokedex_context->detail_type_oam[0] != -1) {
  129. dexdetail_update_type_oam(pokemon_base_stats[species].type[0], &objects[pokedex_context->detail_type_oam[0]]);
  130. } else {
  131. pokedex_context->detail_type_oam[0] =
  132. dexdetail_load_type_oam(pokemon_base_stats[species].type[0], DEX_DETAIL_TYPE1);
  133. objects[pokedex_context->detail_type_oam[0]].pos1.x = 156;
  134. objects[pokedex_context->detail_type_oam[0]].pos1.y = 80;
  135. }
  136. // draw the second type icon eventually
  137. if (pokemon_base_stats[species].type[0] != pokemon_base_stats[species].type[1]) {
  138. if (pokedex_context->detail_type_oam[1] != -1) {
  139. dexdetail_update_type_oam(pokemon_base_stats[species].type[1],
  140. &objects[pokedex_context->detail_type_oam[1]]);
  141. } else {
  142. pokedex_context->detail_type_oam[1] =
  143. dexdetail_load_type_oam(pokemon_base_stats[species].type[1], DEX_DETAIL_TYPE2);
  144. objects[pokedex_context->detail_type_oam[1]].pos1.x = 210;
  145. objects[pokedex_context->detail_type_oam[1]].pos1.y = 80;
  146. }
  147. OBJID_SHOW(pokedex_context->detail_type_oam[1]);
  148. } else {
  149. OBJID_HIDE(pokedex_context->detail_type_oam[1]);
  150. }
  151. rboxid_update_tilemap_and_tileset(TB_DESC);
  152. rboxid_update_tilemap_and_tileset(TB_PKNAME);
  153. rboxid_update_tilemap_and_tileset(TB_PKSIZE);
  154. }
  155. void dexdetail_update_form(u16 form) {
  156. REG_DISPCNT &= ~((1 << 8) | (1 << 9));
  157. if (form == 0) {
  158. dexdetail_load_pokemon(pokedex_context->cursor_position_top + pokedex_context->cursor_position_internal,
  159. NORMAL);
  160. } else {
  161. form--;
  162. if (pokedex_context->detail_forms[form].index > PDEX_LAST_SHOWN) {
  163. dexdetail_load_pokemon(pokedex_context->detail_forms[form].index, pokedex_context->detail_forms[form].type);
  164. } else {
  165. // update the oam only
  166. u16 species = pokedex_context->detail_forms[form].species;
  167. lz77UnCompVram(
  168. pokemon_graphics_front[species].data,
  169. ((void *)(objects[pokedex_context->detail_pokemon_oam].final_oam.tile_num * 32) + ADDR_VRAM + 0x10000));
  170. gpu_pal_apply_compressed(pokemon_palette_normal[species].data,
  171. 16 * (objects[pokedex_context->detail_pokemon_oam].final_oam.palette_num + 16),
  172. 32);
  173. }
  174. }
  175. REG_DISPCNT |= ((1 << 8) | (1 << 9));
  176. }
  177. struct DexFormEntry *dexdetail_get_forms(u16 index) {
  178. u16 current = 0;
  179. while (pdex_forms[current].index != 0xFFFF) {
  180. if (pdex_forms[current].index == index)
  181. return &pdex_forms[current].forms[0];
  182. current++;
  183. }
  184. return NULL;
  185. }
  186. void dexdetail_oac_arrow(struct Object *obj) {
  187. if (pokedex_context->detail_forms != NULL) {
  188. if (obj->priv[0]) {
  189. // this is the left arrow
  190. if (pokedex_context->detail_form_position != 0) {
  191. obj->final_oam.palette_num = obj->priv[1];
  192. } else {
  193. obj->final_oam.palette_num = obj->priv[2];
  194. }
  195. } else {
  196. // this is the right arrow
  197. if (pokedex_context->detail_forms[pokedex_context->detail_form_position].type != FORM_END) {
  198. obj->final_oam.palette_num = obj->priv[1];
  199. } else {
  200. obj->final_oam.palette_num = obj->priv[2];
  201. }
  202. }
  203. }
  204. }
  205. struct SpriteTiles pdex_arrow_rot_tiles = {pdexArrowRotatedTiles, 256, DEX_ARROW_TAG};
  206. struct SpritePalette pdex_arrow_rot_pal = {pdexArrowRotatedPal, DEX_ARROW_TAG};
  207. struct SpritePalette pdex_arrow_rot_pal_gray = {pdexArrowRotatedPal, DEX_ARROW_TAG_EPAL};
  208. const struct OamData pdex_arrow_rot_oam = {
  209. .affine_mode = 0,
  210. .obj_mode = 0,
  211. .mosaic = false,
  212. .shape = 0,
  213. .size = 1,
  214. };
  215. const struct Template pdex_arrow_rot_template = {
  216. .tiles_tag = DEX_ARROW_TAG,
  217. .pal_tag = DEX_ARROW_TAG,
  218. .oam = &pdex_arrow_rot_oam,
  219. .animation = &anim_image_empty,
  220. .graphics = &pdex_arrow_rot_tiles,
  221. .rotscale = &rotscale_empty,
  222. .callback = dexdetail_oac_arrow,
  223. };
  224. void dexdetail_load_form_arrows(void) {
  225. gpu_tile_obj_decompress_alloc_tag_and_upload(&pdex_arrow_rot_tiles);
  226. u8 normalPal = gpu_pal_obj_alloc_tag_and_apply(&pdex_arrow_rot_pal);
  227. u8 grayPal = gpu_pal_obj_alloc_tag_and_apply(&pdex_arrow_rot_pal_gray);
  228. tint_palette_gray(&palette_bg_unfaded[16 * (16 + grayPal)], 16);
  229. u8 leftArrow = template_instanciate_forward_search(&pdex_arrow_rot_template, 10, 55, 0);
  230. u8 rightArrow = template_instanciate_forward_search(&pdex_arrow_rot_template, 100, 55, 0);
  231. objects[leftArrow].priv[0] = true;
  232. objects[leftArrow].final_oam.h_flip = true;
  233. objects[leftArrow].priv[1] = normalPal;
  234. objects[leftArrow].priv[2] = grayPal;
  235. objects[rightArrow].priv[0] = false;
  236. objects[rightArrow].priv[1] = normalPal;
  237. objects[rightArrow].priv[2] = grayPal;
  238. pokedex_context->detail_arrows_oam[0] = leftArrow;
  239. pokedex_context->detail_arrows_oam[1] = rightArrow;
  240. }
  241. void dexdetail_scroll_update(void) {
  242. /* base of -24576 + (scroll_amount * pixel_length * 14 pixels) */
  243. bgid_mod_y_offset(1, -24576 + (pokedex_context->detail_scroll_amount * 256 * 14), 0);
  244. }
  245. void dexdetail_loop(u8 tid) {
  246. u16 currentIndex = pokedex_context->cursor_position_top + pokedex_context->cursor_position_internal;
  247. switch (pokedex_context->state) {
  248. case 0:
  249. bgid_send_tilemap(2);
  250. dexdetail_load_form_arrows();
  251. dexdetail_load_pokemon(currentIndex, NORMAL);
  252. pokedex_context->detail_form_position = 0;
  253. struct DexFormEntry *forms = dexdetail_get_forms(currentIndex);
  254. if (forms != NULL) {
  255. OBJID_SHOW(pokedex_context->detail_arrows_oam[0]);
  256. OBJID_SHOW(pokedex_context->detail_arrows_oam[1]);
  257. } else {
  258. OBJID_HIDE(pokedex_context->detail_arrows_oam[0]);
  259. OBJID_HIDE(pokedex_context->detail_arrows_oam[1]);
  260. }
  261. pokedex_context->detail_forms = forms;
  262. palette_bg_faded_fill_black();
  263. pokedex_context->state++;
  264. break;
  265. case 1:
  266. gpu_sync_bg_show(0);
  267. gpu_sync_bg_show(1);
  268. gpu_sync_bg_hide(3);
  269. gpu_sync_bg_show(2);
  270. fade_screen(0xFFFFFFFF, PDEX_FADEIN_SPD, 16, 0, 0x0000);
  271. pokedex_context->state++;
  272. break;
  273. case 2:
  274. if (!pal_fade_control.active) {
  275. pokecry_play(pdex_lazy_lookup_entry(currentIndex)->species, 0);
  276. pokedex_context->state++;
  277. }
  278. break;
  279. case 3:
  280. switch (super.buttons_new) {
  281. case KEY_B:
  282. pokedex_context->state = 12;
  283. u16 dexindex = pokedex_context->cursor_position_top + pokedex_context->cursor_position_internal;
  284. if (dexindex <= PDEX_LAST_SHOWN - 7) {
  285. pokedex_context->cursor_position_top = dexindex;
  286. pokedex_context->cursor_position_internal = 0;
  287. } else {
  288. pokedex_context->cursor_position_top = PDEX_LAST_SHOWN - 7;
  289. pokedex_context->cursor_position_internal = (dexindex - pokedex_context->cursor_position_top);
  290. }
  291. m4aSongNumStart(601);
  292. fade_screen(0xFFFFFFFF, PDEX_FADEIN_SPD, 0, 16, 0x0000);
  293. break;
  294. case KEY_LEFT:
  295. if (pokedex_context->detail_form_position != 0) {
  296. pokedex_context->detail_form_position--;
  297. dexdetail_update_form(pokedex_context->detail_form_position);
  298. }
  299. break;
  300. case KEY_RIGHT:
  301. if (pokedex_context->detail_forms[pokedex_context->detail_form_position].type != FORM_END) {
  302. pokedex_context->detail_form_position++;
  303. dexdetail_update_form(pokedex_context->detail_form_position);
  304. }
  305. break;
  306. case KEY_START:
  307. pokecry_play(pdex_lazy_lookup_entry(currentIndex)->species, 0);
  308. break;
  309. case KEY_UP:
  310. if (pokedex_context->detail_scroll_amount > 0) {
  311. pokedex_context->detail_scroll_amount--;
  312. dexdetail_scroll_update();
  313. }
  314. break;
  315. case KEY_DOWN:
  316. if (pokedex_context->detail_scroll_amount < pokedex_context->detail_scroll_max) {
  317. pokedex_context->detail_scroll_amount++;
  318. dexdetail_scroll_update();
  319. }
  320. break;
  321. }
  322. break;
  323. case 12:
  324. if (!pal_fade_control.active) {
  325. task_del(tid);
  326. pdex_vram_free_bgmaps();
  327. set_callback2(pdex_load);
  328. }
  329. break;
  330. default:
  331. break;
  332. }
  333. }
  334. struct SpritePalette dexdetail_type_pal = {&pokemon_type_chart_pal[0], DEX_DETAIL_TYPEPAL};
  335. void dexdetail_load_gfx(void) {
  336. rbox_init_from_templates(&dexdetail_boxes[0]);
  337. lz77UnCompVram(pdexDetailBgTiles, (void *)0x0600C000);
  338. LZ77UnCompWram(pdexDetailBgMap, bgid_get_tilemap(2));
  339. gpu_pal_apply_compressed(pdexDetailBgPal, 0, 32);
  340. gpu_pal_apply(pdex_text_pal, 15 * 16, 32);
  341. gpu_pal_obj_alloc_tag_and_apply(&dexdetail_type_pal);
  342. lcd_io_set(REG_ID_WIN0H, (8 << 8) | (232));
  343. lcd_io_set(REG_ID_WIN0V, ((100 << 8) | (160)));
  344. lcd_io_set(REG_ID_WININ, WIN_BG0 | WIN_BG1 | WIN_BG2 | WIN_BG3 | WIN_OBJ);
  345. lcd_io_set(REG_ID_WINOUT, WIN_BG0 | WIN_BG2 | WIN_BG3 | WIN_OBJ);
  346. bgid_mod_y_offset(1, -24576, 1);
  347. bgid_mark_for_sync(0);
  348. }
  349. void dexdetail_load(void) {
  350. pdex_vram_setup();
  351. dexdetail_load_gfx();
  352. pokedex_context->state = 0;
  353. pokedex_context->detail_pokemon_oam = -1;
  354. pokedex_context->detail_type_oam[0] = -1;
  355. pokedex_context->detail_type_oam[1] = -1;
  356. task_add(dexdetail_loop, 0);
  357. set_callback2(pdex_cb_handler);
  358. }