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 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. for (uint8_t i = 0; i < SPRITE_COUNT; i++) {
  40. uint8_t bank = metasprites[i].bank;
  41. if (metasprites[i].pa == power_palettes) {
  42. bank = BANK(power_palettes);
  43. }
  44. START_ROM_BANK(bank);
  45. if ((metasprites[i].pa != NULL) && ((metasprites[i].pa_i & PALETTE_ALL_FLAGS) == PALETTE_PRELOAD)) {
  46. set_sprite_palette(metasprites[i].pa_i, metasprites[i].pa_n, metasprites[i].pa);
  47. }
  48. END_ROM_BANK();
  49. }
  50. }
  51. void spr_draw(enum SPRITES sprite, enum SPRITE_FLIP flip,
  52. int8_t x_off, int8_t y_off, uint8_t frame,
  53. uint8_t *hiwater) NONBANKED {
  54. START_ROM_BANK(metasprites[sprite].bank);
  55. if (frame >= metasprites[sprite].ms_n) {
  56. frame = 0;
  57. }
  58. uint8_t pa_off = 0;
  59. if ((metasprites[sprite].pa_i & PALETTE_ALL_FLAGS) == PALETTE_DYNAMIC_LOAD) {
  60. uint8_t pa_i = frame;
  61. if (pa_i >= metasprites[sprite].pa_n) {
  62. pa_i = 0;
  63. }
  64. set_sprite_palette((metasprites[sprite].pa_i & PALETTE_NO_FLAGS) + pa_i, 1, metasprites[sprite].pa + (pa_i * 4));
  65. } else if ((metasprites[sprite].pa_i & PALETTE_ALL_FLAGS) == PALETTE_DYNAMIC_LOAD_IP) {
  66. pa_off = frame;
  67. if (pa_off >= metasprites[sprite].pa_n) {
  68. pa_off = 0;
  69. }
  70. set_sprite_palette((metasprites[sprite].pa_i & PALETTE_NO_FLAGS), 1, metasprites[sprite].pa + (pa_off * 4));
  71. }
  72. switch (flip) {
  73. case FLIP_Y:
  74. *hiwater += move_metasprite_flipy(
  75. metasprites[sprite].ms[frame], metasprites[sprite].off,
  76. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  77. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  78. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  79. break;
  80. case FLIP_XY:
  81. *hiwater += move_metasprite_flipxy(
  82. metasprites[sprite].ms[frame], metasprites[sprite].off,
  83. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  84. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  85. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  86. break;
  87. case FLIP_X:
  88. *hiwater += move_metasprite_flipx(
  89. metasprites[sprite].ms[frame], metasprites[sprite].off,
  90. (metasprites[sprite].pa_i - pa_off) & PALETTE_NO_FLAGS, *hiwater,
  91. DEVICE_SPRITE_PX_OFFSET_X + (DEVICE_SCREEN_PX_WIDTH / 2) + x_off,
  92. DEVICE_SPRITE_PX_OFFSET_Y + (DEVICE_SCREEN_PX_HEIGHT / 2) + y_off);
  93. break;
  94. case FLIP_NONE:
  95. default:
  96. *hiwater += move_metasprite_ex(
  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. }
  103. END_ROM_BANK();
  104. }
  105. void spr_ship(enum SPRITE_ROT rot, uint8_t moving, uint8_t *hiwater) NONBANKED {
  106. switch (rot) {
  107. case ROT_0:
  108. spr_draw(SPR_SHIP, FLIP_NONE, -1, 4, moving ? 1 : 0, hiwater);
  109. break;
  110. case ROT_45:
  111. spr_draw(SPR_SHIP, FLIP_NONE, -6, 0, moving ? 3 : 2, hiwater);
  112. break;
  113. case ROT_90:
  114. spr_draw(SPR_SHIP, FLIP_NONE, -4, -1, moving ? 5 : 4, hiwater);
  115. break;
  116. case ROT_135:
  117. spr_draw(SPR_SHIP, FLIP_Y, -6, 0, moving ? 3 : 2, hiwater);
  118. break;
  119. case ROT_180:
  120. spr_draw(SPR_SHIP, FLIP_Y, 0, -4, moving ? 1 : 0, hiwater);
  121. break;
  122. case ROT_225:
  123. spr_draw(SPR_SHIP, FLIP_XY, 6, 0, moving ? 3 : 2, hiwater);
  124. break;
  125. case ROT_270:
  126. spr_draw(SPR_SHIP, FLIP_X, 4, 0, moving ? 5 : 4, hiwater);
  127. break;
  128. case ROT_315:
  129. spr_draw(SPR_SHIP, FLIP_X, 6, 0, moving ? 3 : 2, hiwater);
  130. break;
  131. default:
  132. break;
  133. }
  134. }