GameBoy (Color) port of the GTA San Andreas arcade game Duality
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sprites.c 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * sprites.c
  3. * Duality
  4. *
  5. * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
  6. *
  7. * Based on examples from gbdk-2020:
  8. * https://github.com/gbdk-2020/gbdk-2020/blob/develop/gbdk-lib/examples/cross-platform/metasprites/src/metasprites.c
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * See <http://www.gnu.org/licenses/>.
  21. */
  22. #include "banks.h"
  23. #include "sprite_data.h"
  24. void spr_init(void) NONBANKED {
  25. uint8_t off = TILE_NUM_START;
  26. for (uint8_t i = 0; i < SPRITE_COUNT; i++) {
  27. START_ROM_BANK(metasprites[i].bank) {
  28. if (metasprites[i].off == TILE_NUM_START) {
  29. metasprites[i].off = off;
  30. off += metasprites[i].cnt;
  31. set_sprite_data(metasprites[i].off, metasprites[i].cnt, metasprites[i].ti);
  32. } else {
  33. metasprites[i].off = metasprites[metasprites[i].off].off;
  34. }
  35. } END_ROM_BANK
  36. }
  37. }
  38. void spr_init_pal(void) NONBANKED {
  39. if (_cpu != CGB_TYPE) {
  40. return;
  41. }
  42. for (uint8_t i = 0; i < SPRITE_COUNT; i++) {
  43. uint8_t bank = metasprites[i].bank;
  44. if (metasprites[i].pa == power_palettes) {
  45. bank = BANK(sprite_data);
  46. }
  47. START_ROM_BANK(bank) {
  48. if ((metasprites[i].pa != NULL) && ((metasprites[i].pa_i & PALETTE_ALL_FLAGS) == PALETTE_PRELOAD)) {
  49. set_sprite_palette(metasprites[i].pa_i, metasprites[i].pa_n, metasprites[i].pa);
  50. }
  51. } END_ROM_BANK
  52. }
  53. }
  54. void spr_draw(enum SPRITES sprite, enum SPRITE_FLIP flip,
  55. int8_t x_off, int8_t y_off, uint8_t frame,
  56. uint8_t *hiwater) NONBANKED {
  57. if (sprite >= SPRITE_COUNT) {
  58. return;
  59. }
  60. START_ROM_BANK(metasprites[sprite].bank) {
  61. if (frame >= metasprites[sprite].ms_n) {
  62. frame = 0;
  63. }
  64. uint8_t pa_off = 0;
  65. if (_cpu == CGB_TYPE) {
  66. if ((metasprites[sprite].pa_i & PALETTE_ALL_FLAGS) == PALETTE_DYNAMIC_LOAD) {
  67. uint8_t pa_i = frame;
  68. if (pa_i >= metasprites[sprite].pa_n) {
  69. pa_i = 0;
  70. }
  71. set_sprite_palette((metasprites[sprite].pa_i & PALETTE_NO_FLAGS) + pa_i, 1, metasprites[sprite].pa + (pa_i * 4));
  72. } else if ((metasprites[sprite].pa_i & PALETTE_ALL_FLAGS) == PALETTE_DYNAMIC_LOAD_IP) {
  73. pa_off = frame;
  74. if (pa_off >= metasprites[sprite].pa_n) {
  75. pa_off = 0;
  76. }
  77. set_sprite_palette((metasprites[sprite].pa_i & PALETTE_NO_FLAGS), 1, metasprites[sprite].pa + (pa_off * 4));
  78. }
  79. }
  80. switch (flip) {
  81. case FLIP_Y:
  82. *hiwater += move_metasprite_flipy(
  83. metasprites[sprite].ms[frame], metasprites[sprite].off,
  84. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  85. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  86. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  87. break;
  88. case FLIP_XY:
  89. *hiwater += move_metasprite_flipxy(
  90. metasprites[sprite].ms[frame], metasprites[sprite].off,
  91. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  92. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  93. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  94. break;
  95. case FLIP_X:
  96. *hiwater += move_metasprite_flipx(
  97. metasprites[sprite].ms[frame], metasprites[sprite].off,
  98. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  99. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  100. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  101. break;
  102. case FLIP_NONE:
  103. default:
  104. *hiwater += move_metasprite_ex(
  105. metasprites[sprite].ms[frame], metasprites[sprite].off,
  106. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  107. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  108. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  109. break;
  110. }
  111. } END_ROM_BANK
  112. }
  113. void spr_ship(enum SPRITE_ROT rot, uint8_t moving, uint8_t *hiwater) NONBANKED {
  114. switch (rot) {
  115. case ROT_0:
  116. spr_draw(SPR_SHIP, FLIP_NONE, -1, 4, moving ? 1 : 0, hiwater);
  117. break;
  118. case ROT_22_5:
  119. spr_draw(SPR_SHIP, FLIP_NONE, -4, 2, moving ? 7 : 6, hiwater);
  120. break;
  121. case ROT_45:
  122. spr_draw(SPR_SHIP, FLIP_NONE, 1, -1, moving ? 3 : 2, hiwater);
  123. break;
  124. case ROT_67_5:
  125. spr_draw(SPR_SHIP, FLIP_NONE, -2, -4, moving ? 9 : 8, hiwater);
  126. break;
  127. // ------------------------------
  128. case ROT_90:
  129. spr_draw(SPR_SHIP, FLIP_NONE, -4, -1, moving ? 5 : 4, hiwater);
  130. break;
  131. case ROT_112_5:
  132. spr_draw(SPR_SHIP, FLIP_Y, -2, 4, moving ? 9 : 8, hiwater);
  133. break;
  134. case ROT_135:
  135. spr_draw(SPR_SHIP, FLIP_Y, 1, 1, moving ? 3 : 2, hiwater);
  136. break;
  137. case ROT_157_5:
  138. spr_draw(SPR_SHIP, FLIP_Y, -2, -2, moving ? 7 : 6, hiwater);
  139. break;
  140. // ------------------------------
  141. // ------------------------------
  142. case ROT_180:
  143. spr_draw(SPR_SHIP, FLIP_Y, 0, -4, moving ? 1 : 0, hiwater);
  144. break;
  145. case ROT_202_5:
  146. spr_draw(SPR_SHIP, FLIP_XY, 3, -2, moving ? 7 : 6, hiwater);
  147. break;
  148. case ROT_225:
  149. spr_draw(SPR_SHIP, FLIP_XY, -1, 1, moving ? 3 : 2, hiwater);
  150. break;
  151. case ROT_247_5:
  152. spr_draw(SPR_SHIP, FLIP_XY, 2, 4, moving ? 9 : 8, hiwater);
  153. break;
  154. // ------------------------------
  155. case ROT_270:
  156. spr_draw(SPR_SHIP, FLIP_X, 4, 0, moving ? 5 : 4, hiwater);
  157. break;
  158. case ROT_292_5:
  159. spr_draw(SPR_SHIP, FLIP_X, 2, -4, moving ? 9 : 8, hiwater);
  160. break;
  161. case ROT_315:
  162. spr_draw(SPR_SHIP, FLIP_X, -1, -1, moving ? 3 : 2, hiwater);
  163. break;
  164. case ROT_337_5:
  165. spr_draw(SPR_SHIP, FLIP_X, 2, 2, moving ? 7 : 6, hiwater);
  166. break;
  167. default:
  168. break;
  169. }
  170. }