GBAlatro
A Demake of Balatro for the GBA
Loading...
Searching...
No Matches
card.c
1#include "card.h"
2
3#include "graphic_utils.h"
4#include "item.h"
5#include "util.h"
6
7#include <maxmod.h>
8#include <stdlib.h>
9
10// Audio
11#include "pool.h"
12#include "soundbank.h"
13
14// Card Sprites and Palettes
15#include "deck_big_gfx.h"
16#include "deck_gfx.h"
17#include "decks_face_down_gfx.h"
18#include "high_contrast_deck_pal_gfx.h"
19
20// Card sprites lookup table. First index is the suit, second index is the rank. The value is the
21// tile index.
22const static u16 CARD_SPRITE_LUT[NUM_SUITS][NUM_RANKS] = {
23 {0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192},
24 {208, 224, 240, 256, 272, 288, 304, 320, 336, 352, 368, 384, 400},
25 {416, 432, 448, 464, 480, 496, 512, 528, 544, 560, 576, 592, 608},
26 {624, 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816}
27};
28// Deck sprites lookup table. Index is the deck Id. The value is the tile index.
29const static u16 DECK_SPRITE_LUT[DECK_TYPE_MAX] = {0, 16, 32, 48, 64, 80};
30
31static bool s_high_contrast = DEFAULT_HIGH_CONTRAST;
32static bool s_more_readable = DEFAULT_MORE_READABLE;
33
34void card_init()
35{
36 GRIT_CPY(&pal_obj_mem[DECK_SPRITES_PB * PAL_ROW_LEN], decks_face_down_gfxPal);
37}
38
39void set_cards_high_contrast(bool enable)
40{
41 s_high_contrast = enable;
42 if (s_high_contrast)
43 {
44 GRIT_CPY(&pal_obj_mem[CARD_PB * PAL_ROW_LEN], high_contrast_deck_pal_gfxPal);
45 }
46 else
47 {
48 GRIT_CPY(&pal_obj_mem[CARD_PB * PAL_ROW_LEN], deck_gfxPal);
49 }
50}
51
52void set_cards_more_readable(bool enable)
53{
54 s_more_readable = enable;
55}
56
57bool get_cards_high_contrast(void)
58{
59 return s_high_contrast;
60}
61
62bool get_cards_more_readable(void)
63{
64 return s_more_readable;
65}
66
67// Card methods
68Card* card_new(u8 suit, u8 rank)
69{
70 Card* card = POOL_GET(Card);
71
72 card->suit = suit;
73 card->rank = rank;
74
75 return card;
76}
77
78void card_destroy(Card** card)
79{
80 POOL_FREE(Card, *card);
81 *card = NULL;
82}
83
84u8 card_get_value(Card* card)
85{
86 if (card->rank == JACK || card->rank == QUEEN || card->rank == KING)
87 {
88 return 10; // Face cards are worth 10
89 }
90 else if (card->rank == ACE)
91 {
92 return 11; // Ace is worth 11
93 }
94 else
95 {
96 return card->rank + RANK_OFFSET; // 2-10 are worth their rank + RANK_OFFSET
97 }
98
99 return 0; // Should never reach here, but just in case
100}
101
102// CardObject methods
103CardObject* card_object_new(Card* card)
104{
105 CardObject* card_object = POOL_GET(CardObject);
106 sprite_object_init((SpriteObject*)card_object);
107 card_object->card = card;
108
109 card_object->type = ITEM_TYPE_PLAYING_CARD;
110 card_object->selected = false;
111
112 return card_object;
113}
114
115void card_object_destroy(CardObject** card_object)
116{
117 if (*card_object == NULL)
118 return;
119 sprite_object_destroy((SpriteObject*)(*card_object));
120 POOL_FREE(CardObject, *card_object);
121 *card_object = NULL;
122}
123
124void card_object_set_sprite(CardObject* card_object, s16 layer)
125{
126 int tile_index = CARD_TID + (layer * CARD_SPRITE_OFFSET);
127 const unsigned int* card_tiles = s_more_readable ? deck_big_gfxTiles : deck_gfxTiles;
128 memcpy32(
129 &tile_mem[TILE_MEM_OBJ_CHARBLOCK0_IDX][tile_index],
130 &card_tiles[CARD_SPRITE_LUT[card_object->card->suit][card_object->card->rank] * TILE_SIZE],
131 TILE_SIZE * CARD_SPRITE_OFFSET
132 );
133 Sprite* sprite = sprite_new(
134 ATTR0_SQUARE | ATTR0_4BPP | ATTR0_AFF,
135 ATTR1_SIZE_32,
136 tile_index,
137 CARD_PB,
138 layer + CARD_STARTING_LAYER
139 );
140 sprite_object_set_sprite((SpriteObject*)card_object, sprite);
141}
142
143void card_object_set_sprite_face_down(CardObject* card_object, enum DeckType deck, s16 layer)
144{
145 int tile_index = CARD_TID + (layer * CARD_SPRITE_OFFSET);
146 memcpy32(
147 &tile_mem[TILE_MEM_OBJ_CHARBLOCK0_IDX][tile_index],
148 &decks_face_down_gfxTiles[DECK_SPRITE_LUT[deck] * TILE_SIZE],
149 TILE_SIZE * CARD_SPRITE_OFFSET
150 );
151 Sprite* sprite = sprite_new(
152 ATTR0_SQUARE | ATTR0_4BPP | ATTR0_AFF,
153 ATTR1_SIZE_32,
154 tile_index,
155 DECK_SPRITES_PB,
156 layer + CARD_STARTING_LAYER
157 );
158 sprite_object_set_sprite((SpriteObject*)card_object, sprite);
159}
160
161void card_object_shake(CardObject* card_object, mm_word sound_id)
162{
163 sprite_object_shake((SpriteObject*)card_object, sound_id);
164}
165
166void card_object_set_selected(CardObject* card_object, bool selected)
167{
168 if (card_object == NULL)
169 return;
170 card_object->selected = selected;
171}
172
173bool card_object_is_selected(CardObject* card_object)
174{
175 if (card_object == NULL)
176 return false;
177 return card_object->selected;
178}
179
180Sprite* card_object_get_sprite(CardObject* card_object)
181{
182 if (card_object == NULL)
183 return NULL;
184 return sprite_object_get_sprite((SpriteObject*)card_object);
185}
186
187int card_object_get_buy_price(Item* card_object)
188{
189 GBAL_RETURN_IF_NULL_RET(card_object, UNDEFINED);
190 ITEM_RETURN_IF_UNEXPECTED_TYPE_RET(card_object, ITEM_TYPE_PLAYING_CARD, UNDEFINED);
191
192 return 1;
193}
194
195void card_object_dispose(Item** card_object_item)
196{
197 GBAL_RETURN_IF_NULL_VOID(card_object_item);
198 GBAL_RETURN_IF_NULL_VOID(*card_object_item);
199 ITEM_RETURN_IF_UNEXPECTED_TYPE_VOID(*card_object_item, ITEM_TYPE_PLAYING_CARD);
200
201 CardObject* card_object = (CardObject*)(*card_object_item);
202 card_object_destroy(&card_object);
203 *card_object_item = NULL;
204}
Graphic utility functions.
#define TILE_SIZE
Tile size in pixels, both height and width as tiles are square.
#define TILE_MEM_OBJ_CHARBLOCK0_IDX
The index for the first charblock of the object memory in tonc's tile_mem.
The core structure for items in the shop and inventory. Provides a common API for the shop and invent...
#define ITEM_RETURN_IF_UNEXPECTED_TYPE_RET(item, expected_type, ret_val)
Checks if item is of type expected_type - logs error message and returns otherwise.
Definition item.h:25
#define ITEM_RETURN_IF_UNEXPECTED_TYPE_VOID(item, expected_type)
Checks if item is of type expected_type - logs error message and returns otherwise.
Definition item.h:41
void sprite_object_init(SpriteObject *sprite_object)
Initialize a SpriteObject to a default state. Must be called only once per SpriteObject when it is cr...
Definition sprite.c:186
void sprite_object_destroy(SpriteObject *sprite_object)
Destroy SpriteObject.
Definition sprite.c:197
void sprite_object_set_sprite(SpriteObject *sprite_object, Sprite *sprite)
Register a Sprite to an associated SpriteObject.
Definition sprite.c:205
void sprite_object_shake(SpriteObject *sprite_object, mm_word sound_id)
Shake SpriteObject on screen and play a sound.
Definition sprite.c:350
Sprite * sprite_new(u16 a0, u16 a1, u32 tid, u32 pb, s16 sprite_index)
Allocate and retrieve a pointer to a valid Sprite.
Definition sprite.c:36
Sprite * sprite_object_get_sprite(SpriteObject *sprite_object)
Get a SpriteObject's registered Sprite.
Definition sprite.c:363
Definition card.h:50
A generic interface for all items that can appear in the shop or be in the inventory....
Definition item.h:76
A sprite object is a sprite that is focusable and movable in animation.
Definition sprite.h:61
Sprite struct for GBA hardware specifics.
Definition sprite.h:29
Utilities relating around number string representation and protected arithmatic helper functions.
#define GBAL_RETURN_IF_NULL_RET(param, ret_val)
Checks if param is equal to NULL and prints error message and returns in case it is....
Definition util.h:95
#define GBAL_RETURN_IF_NULL_VOID(param)
Checks if param is NULL and prints error message and returns in case it is. Useful for checking argum...
Definition util.h:76