Clang format joker files and def files (#257)
* Clang format joker files and def files * Fix blind usage of GBLA_UNUSED macro * Add final files for clang-format (main.c and selection_grid.h) --------- Co-authored-by: MeirGavish <meir.gavish@gmail.com>
This commit is contained in:
@@ -17,21 +17,4 @@ jobs:
|
|||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Run clang-format
|
- name: Run clang-format
|
||||||
run: >
|
run: clang-format --dry-run -Werror include/*.h source/*.c
|
||||||
clang-format --dry-run -Werror
|
|
||||||
include/bitset.h source/bitset.c
|
|
||||||
include/affine_background.h source/affine_background.c
|
|
||||||
include/audio_utils.h source/audio_utils.c
|
|
||||||
include/graphic_utils.h source/graphic_utils.c
|
|
||||||
include/util.h source/util.c
|
|
||||||
include/pool.h source/pool.c
|
|
||||||
include/card.h source/card.c
|
|
||||||
include/game.h source/game.c
|
|
||||||
include/hand_analysis.h source/hand_analysis.c
|
|
||||||
include/list.h source/list.c
|
|
||||||
include/sprite.h source/sprite.c
|
|
||||||
include/splash_screen.h source/splash_screen.c
|
|
||||||
include/blind.h source/blind.c
|
|
||||||
# Currently contains only the code that has been formatted to conform
|
|
||||||
# When all existing code conforms, change to this:
|
|
||||||
# run: clang-format --dry-run -Werror include/*.h source/*.c
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "sprite.h"
|
|
||||||
#include "joker.h"
|
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
|
#include "joker.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "sprite.h"
|
||||||
|
|
||||||
POOL_ENTRY(Sprite, MAX_SPRITES);
|
POOL_ENTRY(Sprite, MAX_SPRITES);
|
||||||
POOL_ENTRY(SpriteObject, MAX_SPRITE_OBJECTS);
|
POOL_ENTRY(SpriteObject, MAX_SPRITE_OBJECTS);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// clang-format off
|
||||||
// (stateEnum, on_init, on_update, on_exit)
|
// (stateEnum, on_init, on_update, on_exit)
|
||||||
DEF_STATE_INFO(GAME_STATE_SPLASH_SCREEN, splash_screen_on_init, splash_screen_on_update, splash_screen_on_exit)
|
DEF_STATE_INFO(GAME_STATE_SPLASH_SCREEN, splash_screen_on_init, splash_screen_on_update, splash_screen_on_exit)
|
||||||
DEF_STATE_INFO(GAME_STATE_MAIN_MENU, game_main_menu_on_init, game_main_menu_on_update, noop)
|
DEF_STATE_INFO(GAME_STATE_MAIN_MENU, game_main_menu_on_init, game_main_menu_on_update, noop)
|
||||||
@@ -7,3 +8,4 @@ DEF_STATE_INFO(GAME_STATE_SHOP, noop, game_shop_on_update, game_shop_on_exit)
|
|||||||
DEF_STATE_INFO(GAME_STATE_BLIND_SELECT, noop, game_blind_select_on_update, game_blind_select_on_exit)
|
DEF_STATE_INFO(GAME_STATE_BLIND_SELECT, noop, game_blind_select_on_update, game_blind_select_on_exit)
|
||||||
DEF_STATE_INFO(GAME_STATE_LOSE, game_lose_on_init, game_lose_on_update, game_over_on_exit)
|
DEF_STATE_INFO(GAME_STATE_LOSE, game_lose_on_init, game_lose_on_update, game_over_on_exit)
|
||||||
DEF_STATE_INFO(GAME_STATE_WIN, game_win_on_init, game_win_on_update, game_over_on_exit)
|
DEF_STATE_INFO(GAME_STATE_WIN, game_win_on_init, game_win_on_update, game_over_on_exit)
|
||||||
|
// clang-format on
|
||||||
|
|||||||
+83
-53
@@ -1,12 +1,12 @@
|
|||||||
#ifndef JOKER_H
|
#ifndef JOKER_H
|
||||||
#define JOKER_H
|
#define JOKER_H
|
||||||
|
|
||||||
#include <maxmod.h>
|
|
||||||
|
|
||||||
#include "sprite.h"
|
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "graphic_utils.h"
|
#include "graphic_utils.h"
|
||||||
|
#include "sprite.h"
|
||||||
|
|
||||||
|
#include <maxmod.h>
|
||||||
|
|
||||||
// This won't be more than the number of jokers in your current deck
|
// This won't be more than the number of jokers in your current deck
|
||||||
// plus the amount that can fit in the shop, 8 should be fine. For now...
|
// plus the amount that can fit in the shop, 8 should be fine. For now...
|
||||||
@@ -14,51 +14,59 @@
|
|||||||
|
|
||||||
#define MAX_DEFINABLE_JOKERS 150
|
#define MAX_DEFINABLE_JOKERS 150
|
||||||
|
|
||||||
#define JOKER_TID (MAX_HAND_SIZE + MAX_SELECTION_SIZE) * JOKER_SPRITE_OFFSET // Tile ID for the starting index in the tile memory
|
// Tile ID for the starting index in the tile memory
|
||||||
|
#define JOKER_TID (MAX_HAND_SIZE + MAX_SELECTION_SIZE) * JOKER_SPRITE_OFFSET
|
||||||
#define JOKER_SPRITE_OFFSET 16 // Offset for the joker sprites
|
#define JOKER_SPRITE_OFFSET 16 // Offset for the joker sprites
|
||||||
#define JOKER_BASE_PB 4 // The starting palette index for the jokers
|
#define JOKER_BASE_PB 4 // The starting palette index for the jokers
|
||||||
#define JOKER_LAST_PB (NUM_PALETTES - 1)
|
#define JOKER_LAST_PB (NUM_PALETTES - 1)
|
||||||
// Currently allocating the rest of the palettes for the jokers.
|
// Currently allocating the rest of the palettes for the jokers.
|
||||||
// This number needs to be decreased once we need to allocated palettes for other sprites
|
// This number needs to be decreased once we need to allocated palettes for other sprites
|
||||||
// such as planet cards etc.
|
// such as planet cards etc.
|
||||||
|
|
||||||
#define JOKER_STARTING_LAYER 27
|
#define JOKER_STARTING_LAYER 27
|
||||||
|
|
||||||
#define BASE_EDITION 0
|
#define BASE_EDITION 0
|
||||||
#define FOIL_EDITION 1
|
#define FOIL_EDITION 1
|
||||||
#define HOLO_EDITION 2
|
#define HOLO_EDITION 2
|
||||||
#define POLY_EDITION 3
|
#define POLY_EDITION 3
|
||||||
#define NEGATIVE_EDITION 4
|
#define NEGATIVE_EDITION 4
|
||||||
|
|
||||||
#define MAX_EDITIONS 5
|
#define MAX_EDITIONS 5
|
||||||
|
|
||||||
#define COMMON_JOKER 0
|
#define COMMON_JOKER 0
|
||||||
#define UNCOMMON_JOKER 1
|
#define UNCOMMON_JOKER 1
|
||||||
#define RARE_JOKER 2
|
#define RARE_JOKER 2
|
||||||
#define LEGENDARY_JOKER 3
|
#define LEGENDARY_JOKER 3
|
||||||
|
|
||||||
// Percent chance to get a joker of each rarity
|
// Percent chance to get a joker of each rarity
|
||||||
// Note that this deviates slightly from the Balatro wiki to allow legendary
|
// Note that this deviates slightly from the Balatro wiki to allow legendary
|
||||||
// jokers to appear without spectral cards implemented
|
// jokers to appear without spectral cards implemented
|
||||||
#define COMMON_JOKER_CHANCE 70
|
#define COMMON_JOKER_CHANCE 70
|
||||||
#define UNCOMMON_JOKER_CHANCE 25
|
#define UNCOMMON_JOKER_CHANCE 25
|
||||||
#define RARE_JOKER_CHANCE 5
|
#define RARE_JOKER_CHANCE 5
|
||||||
#define LEGENDARY_JOKER_CHANCE 0
|
#define LEGENDARY_JOKER_CHANCE 0
|
||||||
|
|
||||||
// These are the common Joker Events. Special Joker behaviour will be checked on a
|
// These are the common Joker Events. Special Joker behaviour will be checked on a
|
||||||
// Joker per Joker basis (see if it's there, then do something, e.g. Pareidolia, Baseball Card)
|
// Joker per Joker basis (see if it's there, then do something, e.g. Pareidolia, Baseball Card)
|
||||||
enum JokerEvent
|
enum JokerEvent
|
||||||
{
|
{
|
||||||
JOKER_EVENT_ON_JOKER_CREATED, // Triggers only once when the Joker is created, mainly used for data initialization
|
JOKER_EVENT_ON_JOKER_CREATED, // Triggers only once when the Joker is created, mainly used for
|
||||||
JOKER_EVENT_ON_HAND_PLAYED, // Triggers only once when the hand is played and before the cards are scored
|
// data initialization
|
||||||
JOKER_EVENT_ON_CARD_SCORED, // Triggers when a played card scores (e.g. Walkie Talkie, Fibonnacci...)
|
JOKER_EVENT_ON_HAND_PLAYED, // Triggers only once when the hand is played and before the cards
|
||||||
JOKER_EVENT_ON_CARD_SCORED_END, // Triggers after the card has finishd scoring (e.g. retrigger Jokers)
|
// are scored
|
||||||
|
JOKER_EVENT_ON_CARD_SCORED, // Triggers when a played card scores (e.g. Walkie Talkie,
|
||||||
|
// Fibonnacci...)
|
||||||
|
JOKER_EVENT_ON_CARD_SCORED_END, // Triggers after the card has finishd scoring (e.g. retrigger
|
||||||
|
// Jokers)
|
||||||
JOKER_EVENT_ON_CARD_HELD, // Triggers when going through held cards
|
JOKER_EVENT_ON_CARD_HELD, // Triggers when going through held cards
|
||||||
JOKER_EVENT_INDEPENDENT, // Joker will trigger normally, when Jokers are scored (e.g. base Joker)
|
JOKER_EVENT_INDEPENDENT, // Joker will trigger normally, when Jokers are scored (e.g. base
|
||||||
JOKER_EVENT_ON_HAND_SCORED_END, // Triggers when entire hand has finished scoring (e.g. food Jokers)
|
// Joker)
|
||||||
|
JOKER_EVENT_ON_HAND_SCORED_END, // Triggers when entire hand has finished scoring (e.g. food
|
||||||
|
// Jokers)
|
||||||
JOKER_EVENT_ON_HAND_DISCARDED, // Triggers when discarding a hand
|
JOKER_EVENT_ON_HAND_DISCARDED, // Triggers when discarding a hand
|
||||||
JOKER_EVENT_ON_ROUND_END, // Triggers at the end of the round (e.g. Rocket)
|
JOKER_EVENT_ON_ROUND_END, // Triggers at the end of the round (e.g. Rocket)
|
||||||
JOKER_EVENT_ON_BLIND_SELECTED, // Triggers when selecting a blind (e.g. Dagger, Riff Raff, Madness..)
|
JOKER_EVENT_ON_BLIND_SELECTED, // Triggers when selecting a blind (e.g. Dagger, Riff Raff,
|
||||||
|
// Madness..)
|
||||||
};
|
};
|
||||||
|
|
||||||
// These are flags that can be combined into a single u32 and returned by
|
// These are flags that can be combined into a single u32 and returned by
|
||||||
@@ -76,49 +84,59 @@ enum JokerEvent
|
|||||||
#define MAX_JOKER_OBJECTS 32 // The maximum number of joker objects that can be created at once
|
#define MAX_JOKER_OBJECTS 32 // The maximum number of joker objects that can be created at once
|
||||||
|
|
||||||
// Jokers in the game
|
// Jokers in the game
|
||||||
#define DEFAULT_JOKER_ID 0
|
#define DEFAULT_JOKER_ID 0
|
||||||
#define GREEDY_JOKER_ID 1
|
#define GREEDY_JOKER_ID 1
|
||||||
#define STENCIL_JOKER_ID 16
|
#define STENCIL_JOKER_ID 16
|
||||||
#define SHORTCUT_JOKER_ID 26
|
#define SHORTCUT_JOKER_ID 26
|
||||||
#define PAREIDOLIA_JOKER_ID 30
|
#define PAREIDOLIA_JOKER_ID 30
|
||||||
#define BLUEPRINT_JOKER_ID 39
|
#define BLUEPRINT_JOKER_ID 39
|
||||||
#define BRAINSTORM_JOKER_ID 40
|
#define BRAINSTORM_JOKER_ID 40
|
||||||
#define FOUR_FINGERS_JOKER_ID 48
|
#define FOUR_FINGERS_JOKER_ID 48
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 id; // Unique ID for the joker, used to identify different jokers
|
u8 id; // Unique ID for the joker, used to identify different jokers
|
||||||
u8 modifier; // base, foil, holo, poly, negative
|
u8 modifier; // base, foil, holo, poly, negative
|
||||||
u8 value;
|
u8 value;
|
||||||
u8 rarity;
|
u8 rarity;
|
||||||
|
|
||||||
// General purpose values that are interpreted differently for each Joker (scaling, last retriggered card, etc...)
|
// General purpose values that are interpreted differently for each Joker (scaling, last
|
||||||
|
// retriggered card, etc...)
|
||||||
s32 scoring_state;
|
s32 scoring_state;
|
||||||
s32 persistent_state;
|
s32 persistent_state;
|
||||||
} Joker;
|
} Joker;
|
||||||
|
|
||||||
typedef struct JokerObject
|
typedef struct JokerObject
|
||||||
{
|
{
|
||||||
Joker *joker;
|
Joker* joker;
|
||||||
SpriteObject* sprite_object;
|
SpriteObject* sprite_object;
|
||||||
} JokerObject;
|
} JokerObject;
|
||||||
|
|
||||||
typedef struct // These jokers are triggered after the played hand has finished scoring.
|
typedef struct // These jokers are triggered after the played hand has finished scoring.
|
||||||
{
|
{
|
||||||
u32 chips;
|
u32 chips;
|
||||||
u32 mult;
|
u32 mult;
|
||||||
u32 xmult;
|
u32 xmult;
|
||||||
int money;
|
int money;
|
||||||
bool retrigger; // Retrigger played hand (e.g. "Dusk" joker, even though on the wiki it says "On Scored" it makes more sense to have it here)
|
bool retrigger; // Retrigger played hand (e.g. "Dusk" joker, even though on the wiki it says "On
|
||||||
bool expire; // Will make the Joker expire/destry itself if true (i.e. Bananas and fully consumed Food Jokers)
|
// Scored" it makes more sense to have it here)
|
||||||
char* message; // Used to send custom messages e.g. "Extinct!" or "Again!"
|
bool expire; // Will make the Joker expire/destry itself if true (i.e. Bananas and fully
|
||||||
|
// consumed Food Jokers)
|
||||||
|
char* message; // Used to send custom messages e.g. "Extinct!" or "Again!"
|
||||||
} JokerEffect;
|
} JokerEffect;
|
||||||
|
|
||||||
// JokerEffectFuncs take in a joker that will be scored, a scored_card that is not NULL when related to the given joker_event, and output a joker_effect storing the effects of the scored joker
|
// JokerEffectFuncs take in a joker that will be scored, a scored_card that is not NULL when related
|
||||||
// They return a set of flags indicating what fields of the joker_effect are valid to access
|
// to the given joker_event, and output a joker_effect storing the effects of the scored joker They
|
||||||
typedef u32 (*JokerEffectFunc)(Joker *joker, Card *scored_card, enum JokerEvent joker_event, JokerEffect **joker_effect);
|
// return a set of flags indicating what fields of the joker_effect are valid to access
|
||||||
|
typedef u32 (*JokerEffectFunc)(
|
||||||
|
Joker* joker,
|
||||||
|
Card* scored_card,
|
||||||
|
enum JokerEvent joker_event,
|
||||||
|
JokerEffect** joker_effect
|
||||||
|
);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
u8 rarity;
|
u8 rarity;
|
||||||
u8 base_value;
|
u8 base_value;
|
||||||
JokerEffectFunc joker_effect_func;
|
JokerEffectFunc joker_effect_func;
|
||||||
@@ -128,23 +146,35 @@ size_t get_joker_registry_size(void);
|
|||||||
|
|
||||||
void joker_init();
|
void joker_init();
|
||||||
|
|
||||||
Joker *joker_new(u8 id);
|
Joker* joker_new(u8 id);
|
||||||
void joker_destroy(Joker **joker);
|
void joker_destroy(Joker** joker);
|
||||||
|
|
||||||
// Unique effects like "Four Fingers" or "Credit Card" will be hard coded into game.c with a conditional check for the joker ID from the players owned jokers
|
// Unique effects like "Four Fingers" or "Credit Card" will be hard coded into game.c with a
|
||||||
// game.c should probably be restructured so most of the variables in it are moved to some sort of global variable header file so they can be easily accessed and modified for the jokers
|
// conditional check for the joker ID from the players owned jokers game.c should probably be
|
||||||
u32 joker_get_score_effect(Joker *joker, Card *scored_card, enum JokerEvent joker_event, JokerEffect **joker_effect);
|
// restructured so most of the variables in it are moved to some sort of global variable header file
|
||||||
|
// so they can be easily accessed and modified for the jokers
|
||||||
|
u32 joker_get_score_effect(
|
||||||
|
Joker* joker,
|
||||||
|
Card* scored_card,
|
||||||
|
enum JokerEvent joker_event,
|
||||||
|
JokerEffect** joker_effect
|
||||||
|
);
|
||||||
int joker_get_sell_value(const Joker* joker);
|
int joker_get_sell_value(const Joker* joker);
|
||||||
|
|
||||||
JokerObject *joker_object_new(Joker *joker);
|
JokerObject* joker_object_new(Joker* joker);
|
||||||
void joker_object_destroy(JokerObject **joker_object);
|
void joker_object_destroy(JokerObject** joker_object);
|
||||||
void joker_object_update(JokerObject *joker_object);
|
void joker_object_update(JokerObject* joker_object);
|
||||||
// This doesn't actually score anything, it just performs an animation and plays a sound effect
|
// This doesn't actually score anything, it just performs an animation and plays a sound effect
|
||||||
void joker_object_shake(JokerObject *joker_object, mm_word sound_id);
|
void joker_object_shake(JokerObject* joker_object, mm_word sound_id);
|
||||||
// This scores the joker and returns true if it was scored successfully
|
// This scores the joker and returns true if it was scored successfully
|
||||||
// card_object = NULL means the joker_event does not concern a particular Card, i.e. Independend or On_Blind_Selected
|
// card_object = NULL means the joker_event does not concern a particular Card, i.e. Independend or
|
||||||
// as opposed to events that concern a particular card, i.e. On_Card_Scored or On_Card_Held
|
// On_Blind_Selected as opposed to events that concern a particular card, i.e. On_Card_Scored or
|
||||||
bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum JokerEvent joker_event);
|
// On_Card_Held
|
||||||
|
bool joker_object_score(
|
||||||
|
JokerObject* joker_object,
|
||||||
|
CardObject* card_object,
|
||||||
|
enum JokerEvent joker_event
|
||||||
|
);
|
||||||
|
|
||||||
void joker_object_set_selected(JokerObject* joker_object, bool selected);
|
void joker_object_set_selected(JokerObject* joker_object, bool selected);
|
||||||
bool joker_object_is_selected(JokerObject* joker_object);
|
bool joker_object_is_selected(JokerObject* joker_object);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// clang-format off
|
||||||
#ifndef JOKER_GFX_H
|
#ifndef JOKER_GFX_H
|
||||||
#define JOKER_GFX_H
|
#define JOKER_GFX_H
|
||||||
|
|
||||||
@@ -29,3 +30,4 @@
|
|||||||
#include "joker_gfx25.h"
|
#include "joker_gfx25.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|||||||
@@ -10,11 +10,18 @@ typedef struct SelectionGridRow SelectionGridRow;
|
|||||||
typedef struct SelectionGrid SelectionGrid;
|
typedef struct SelectionGrid SelectionGrid;
|
||||||
|
|
||||||
// Called whenever there is a change in the selection cursor
|
// Called whenever there is a change in the selection cursor
|
||||||
// row_idx is the index of the row whose function is invoked - can be used to identify whether it is the previous or new selection row.
|
// row_idx is the index of the row whose function is invoked - can be used to identify whether it is
|
||||||
typedef void (*RowOnSelectionChangedFunc)(SelectionGrid* selection_grid, int row_idx, const Selection* prev_selection, const Selection* new_selection);
|
// the previous or new selection row.
|
||||||
|
typedef void (*RowOnSelectionChangedFunc)(
|
||||||
|
SelectionGrid* selection_grid,
|
||||||
|
int row_idx,
|
||||||
|
const Selection* prev_selection,
|
||||||
|
const Selection* new_selection
|
||||||
|
);
|
||||||
typedef int (*RowGetSizeFunc)();
|
typedef int (*RowGetSizeFunc)();
|
||||||
// Called for any non-directional key hit
|
// Called for any non-directional key hit
|
||||||
// The key will not be passed, the function will have to check key_hit() etc. for the key it wants to check
|
// The key will not be passed, the function will have to check key_hit() etc. for the key it wants
|
||||||
|
// to check
|
||||||
typedef void (*RowOnKeyTransitFunc)(SelectionGrid* selection_grid, Selection* selection);
|
typedef void (*RowOnKeyTransitFunc)(SelectionGrid* selection_grid, Selection* selection);
|
||||||
|
|
||||||
struct SelectionGridRow
|
struct SelectionGridRow
|
||||||
@@ -30,8 +37,7 @@ struct SelectionGrid
|
|||||||
const SelectionGridRow* rows;
|
const SelectionGridRow* rows;
|
||||||
const int num_rows;
|
const int num_rows;
|
||||||
Selection selection;
|
Selection selection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void selection_grid_process_input(SelectionGrid* selection_grid);
|
void selection_grid_process_input(SelectionGrid* selection_grid);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -45,7 +45,8 @@ static Blind _blind_type_map[BLIND_TYPE_MAX] = {
|
|||||||
|
|
||||||
static void s_blind_gfx_init(enum BlindType type);
|
static void s_blind_gfx_init(enum BlindType type);
|
||||||
|
|
||||||
GBLA_UNUSED void blind_set_boss_graphics(const unsigned int* tiles, const u16* palette)
|
GBLA_UNUSED
|
||||||
|
void blind_set_boss_graphics(const unsigned int* tiles, const u16* palette)
|
||||||
{
|
{
|
||||||
// TODO: This function is unused and not fully fleshed out.
|
// TODO: This function is unused and not fully fleshed out.
|
||||||
// We need to support more boss blind graphics in the future.
|
// We need to support more boss blind graphics in the future.
|
||||||
|
|||||||
+158
-134
@@ -1,38 +1,35 @@
|
|||||||
#include <tonc.h>
|
|
||||||
|
|
||||||
#include "joker.h"
|
#include "joker.h"
|
||||||
#include "joker_gfx.h"
|
|
||||||
#include "graphic_utils.h"
|
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
|
#include "graphic_utils.h"
|
||||||
|
#include "joker_gfx.h"
|
||||||
|
#include "pool.h"
|
||||||
#include "soundbank.h"
|
#include "soundbank.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include <maxmod.h>
|
#include <maxmod.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <tonc.h>
|
||||||
|
|
||||||
#include "pool.h"
|
#define JOKER_SCORE_TEXT_Y 48
|
||||||
|
#define HELD_CARD_SCORE_TEXT_Y 108
|
||||||
#define JOKER_SCORE_TEXT_Y 48
|
#define MAX_CARD_SCORE_STR_LEN 2
|
||||||
#define HELD_CARD_SCORE_TEXT_Y 108
|
|
||||||
#define MAX_CARD_SCORE_STR_LEN 2
|
|
||||||
#define NUM_JOKERS_PER_SPRITESHEET 2
|
#define NUM_JOKERS_PER_SPRITESHEET 2
|
||||||
|
|
||||||
static const unsigned int *joker_gfxTiles[] =
|
static const unsigned int* joker_gfxTiles[] = {
|
||||||
{
|
|
||||||
#define DEF_JOKER_GFX(idx) joker_gfx##idx##Tiles,
|
#define DEF_JOKER_GFX(idx) joker_gfx##idx##Tiles,
|
||||||
#include "../include/def_joker_gfx_table.h"
|
#include "../include/def_joker_gfx_table.h"
|
||||||
#undef DEF_JOKER_GFX
|
#undef DEF_JOKER_GFX
|
||||||
};
|
};
|
||||||
static const unsigned short *joker_gfxPal[] =
|
|
||||||
{
|
static const unsigned short* joker_gfxPal[] = {
|
||||||
#define DEF_JOKER_GFX(idx) joker_gfx##idx##Pal,
|
#define DEF_JOKER_GFX(idx) joker_gfx##idx##Pal,
|
||||||
#include "../include/def_joker_gfx_table.h"
|
#include "def_joker_gfx_table.h"
|
||||||
#undef DEF_JOKER_GFX
|
#undef DEF_JOKER_GFX
|
||||||
};
|
};
|
||||||
|
|
||||||
const static u8 edition_price_lut[MAX_EDITIONS] =
|
const static u8 edition_price_lut[MAX_EDITIONS] = {
|
||||||
{
|
|
||||||
0, // BASE_EDITION
|
0, // BASE_EDITION
|
||||||
2, // FOIL_EDITION
|
2, // FOIL_EDITION
|
||||||
3, // HOLO_EDITION
|
3, // HOLO_EDITION
|
||||||
@@ -42,104 +39,45 @@ const static u8 edition_price_lut[MAX_EDITIONS] =
|
|||||||
|
|
||||||
/* So for the card objects, I needed them to be properly sorted
|
/* So for the card objects, I needed them to be properly sorted
|
||||||
which is why they let you specify the layer index when creating a new card object.
|
which is why they let you specify the layer index when creating a new card object.
|
||||||
Since the cards would overlap a lot in your hand, If they weren't sorted properly, it would look like a mess.
|
Since the cards would overlap a lot in your hand, If they weren't sorted properly, it would look
|
||||||
The joker objects are functionally identical to card objects, so they use the same logic.
|
like a mess. The joker objects are functionally identical to card objects, so they use the same
|
||||||
But I'm going to use a simpler approach for the joker objects
|
logic. But I'm going to use a simpler approach for the joker objects since I'm lazy and sorting
|
||||||
since I'm lazy and sorting them wouldn't look good enough to warrant the effort.
|
them wouldn't look good enough to warrant the effort.
|
||||||
*/
|
*/
|
||||||
static bool used_layers[MAX_JOKER_OBJECTS] = {false}; // Track used layers for joker sprites
|
static bool _used_layers[MAX_JOKER_OBJECTS] = {false}; // Track used layers for joker sprites
|
||||||
// TODO: Refactor sorting into SpriteObject?
|
// TODO: Refactor sorting into SpriteObject?
|
||||||
|
|
||||||
// Maps the spritesheet index to the palette bank index allocated to it.
|
// Maps the spritesheet index to the palette bank index allocated to it.
|
||||||
// Spritesheets that were not allocated are
|
// Spritesheets that were not allocated are
|
||||||
static int joker_spritesheet_pb_map[(MAX_DEFINABLE_JOKERS + 1) / NUM_JOKERS_PER_SPRITESHEET];
|
static int _joker_spritesheet_pb_map[(MAX_DEFINABLE_JOKERS + 1) / NUM_JOKERS_PER_SPRITESHEET];
|
||||||
static int joker_pb_num_sprite_users[JOKER_LAST_PB - JOKER_BASE_PB + 1] = { 0 };
|
static int _joker_pb_num_sprite_users[JOKER_LAST_PB - JOKER_BASE_PB + 1] = {0};
|
||||||
|
|
||||||
static int get_num_spritesheets()
|
static int s_get_num_spritesheets(void);
|
||||||
{
|
static int s_joker_get_spritesheet_idx(u8 joker_id);
|
||||||
return (get_joker_registry_size() + NUM_JOKERS_PER_SPRITESHEET - 1) / NUM_JOKERS_PER_SPRITESHEET;
|
static void s_joker_pb_add_sprite_user(int pb);
|
||||||
}
|
static void s_joker_pb_remove_sprite_user(int pb);
|
||||||
|
static int s_joker_pb_get_num_sprite_users(int joker_pb);
|
||||||
static int joker_get_spritesheet_idx(u8 joker_id)
|
static int s_get_unused_joker_pb(void);
|
||||||
|
static int s_allocate_pb_if_needed(u8 joker_id);
|
||||||
{
|
|
||||||
return joker_id / NUM_JOKERS_PER_SPRITESHEET;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This should be generalized so any sprite can have dynamic swapping
|
|
||||||
static void joker_pb_add_sprite_user(int pb)
|
|
||||||
{
|
|
||||||
joker_pb_num_sprite_users[pb - JOKER_BASE_PB]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void joker_pb_remove_sprite_user(int pb)
|
|
||||||
{
|
|
||||||
int num_sprite_users = joker_pb_num_sprite_users[pb - JOKER_BASE_PB];
|
|
||||||
joker_pb_num_sprite_users[pb - JOKER_BASE_PB] = max(0, num_sprite_users - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int joker_pb_get_num_sprite_users(int joker_pb)
|
|
||||||
{
|
|
||||||
return joker_pb_num_sprite_users[joker_pb - JOKER_BASE_PB];
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_unused_joker_pb()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NUM_ELEM_IN_ARR(joker_pb_num_sprite_users); i++)
|
|
||||||
{
|
|
||||||
if (joker_pb_num_sprite_users[i] == 0)
|
|
||||||
{
|
|
||||||
return (i + JOKER_BASE_PB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int allocate_pb_if_needed(u8 joker_id)
|
|
||||||
{
|
|
||||||
int joker_spritesheet_idx = joker_get_spritesheet_idx(joker_id);
|
|
||||||
int joker_pb = joker_spritesheet_pb_map[joker_spritesheet_idx];
|
|
||||||
if (joker_pb != UNDEFINED)
|
|
||||||
{
|
|
||||||
// Already allocated
|
|
||||||
return joker_pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a new palette
|
|
||||||
joker_pb = get_unused_joker_pb();
|
|
||||||
|
|
||||||
if (joker_pb == UNDEFINED)
|
|
||||||
{
|
|
||||||
// Ran out of palettes, default to base and pray
|
|
||||||
joker_pb = JOKER_BASE_PB;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
joker_spritesheet_pb_map[joker_spritesheet_idx] = joker_pb;
|
|
||||||
memcpy16(&pal_obj_mem[PAL_ROW_LEN * joker_pb], joker_gfxPal[joker_spritesheet_idx], NUM_ELEM_IN_ARR(joker_gfx0Pal));
|
|
||||||
}
|
|
||||||
|
|
||||||
return joker_pb;
|
|
||||||
}
|
|
||||||
|
|
||||||
void joker_init()
|
void joker_init()
|
||||||
{
|
{
|
||||||
// This should init once only so no need to free
|
// This should init once only so no need to free
|
||||||
int num_spritesheets = get_num_spritesheets();
|
int num_spritesheets = s_get_num_spritesheets();
|
||||||
|
|
||||||
for (int i = 0; i < num_spritesheets; i++)
|
for (int i = 0; i < num_spritesheets; i++)
|
||||||
{
|
{
|
||||||
joker_spritesheet_pb_map[i] = UNDEFINED;
|
_joker_spritesheet_pb_map[i] = UNDEFINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Joker *joker_new(u8 id)
|
Joker* joker_new(u8 id)
|
||||||
{
|
{
|
||||||
if (id >= get_joker_registry_size()) return NULL;
|
if (id >= get_joker_registry_size())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
Joker *joker = POOL_GET(Joker);
|
Joker* joker = POOL_GET(Joker);
|
||||||
const JokerInfo *jinfo = get_joker_registry_entry(id);
|
const JokerInfo* jinfo = get_joker_registry_entry(id);
|
||||||
|
|
||||||
joker->id = id;
|
joker->id = id;
|
||||||
joker->modifier = BASE_EDITION; // TODO: Make this a parameter
|
joker->modifier = BASE_EDITION; // TODO: Make this a parameter
|
||||||
@@ -149,22 +87,28 @@ Joker *joker_new(u8 id)
|
|||||||
joker->persistent_state = 0;
|
joker->persistent_state = 0;
|
||||||
|
|
||||||
// initialize persistent Joker data if needed
|
// initialize persistent Joker data if needed
|
||||||
JokerEffect *joker_effect = NULL;
|
JokerEffect* joker_effect = NULL;
|
||||||
jinfo->joker_effect_func(joker, NULL, JOKER_EVENT_ON_JOKER_CREATED, &joker_effect);
|
jinfo->joker_effect_func(joker, NULL, JOKER_EVENT_ON_JOKER_CREATED, &joker_effect);
|
||||||
|
|
||||||
return joker;
|
return joker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void joker_destroy(Joker **joker)
|
void joker_destroy(Joker** joker)
|
||||||
{
|
{
|
||||||
POOL_FREE(Joker, *joker);
|
POOL_FREE(Joker, *joker);
|
||||||
*joker = NULL;
|
*joker = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 joker_get_score_effect(Joker *joker, Card *scored_card, enum JokerEvent joker_event, JokerEffect **joker_effect)
|
u32 joker_get_score_effect(
|
||||||
|
Joker* joker,
|
||||||
|
Card* scored_card,
|
||||||
|
enum JokerEvent joker_event,
|
||||||
|
JokerEffect** joker_effect
|
||||||
|
)
|
||||||
{
|
{
|
||||||
const JokerInfo *jinfo = get_joker_registry_entry(joker->id);
|
const JokerInfo* jinfo = get_joker_registry_entry(joker->id);
|
||||||
if (!jinfo) return JOKER_EFFECT_FLAG_NONE;
|
if (!jinfo)
|
||||||
|
return JOKER_EFFECT_FLAG_NONE;
|
||||||
|
|
||||||
return jinfo->joker_effect_func(joker, scored_card, joker_event, joker_effect);
|
return jinfo->joker_effect_func(joker, scored_card, joker_event, joker_effect);
|
||||||
}
|
}
|
||||||
@@ -176,21 +120,21 @@ int joker_get_sell_value(const Joker* joker)
|
|||||||
return UNDEFINED;
|
return UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return joker->value/2;
|
return joker->value / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JokerObject methods
|
// JokerObject methods
|
||||||
JokerObject *joker_object_new(Joker *joker)
|
JokerObject* joker_object_new(Joker* joker)
|
||||||
{
|
{
|
||||||
JokerObject *joker_object = POOL_GET(JokerObject);
|
JokerObject* joker_object = POOL_GET(JokerObject);
|
||||||
|
|
||||||
int layer = 0;
|
int layer = 0;
|
||||||
for (int i = 0; i < MAX_JOKER_OBJECTS; i++)
|
for (int i = 0; i < MAX_JOKER_OBJECTS; i++)
|
||||||
{
|
{
|
||||||
if (!used_layers[i])
|
if (!_used_layers[i])
|
||||||
{
|
{
|
||||||
layer = i;
|
layer = i;
|
||||||
used_layers[i] = true; // Mark this layer as used
|
_used_layers[i] = true; // Mark this layer as used
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,18 +144,20 @@ JokerObject *joker_object_new(Joker *joker)
|
|||||||
|
|
||||||
int tile_index = JOKER_TID + (layer * JOKER_SPRITE_OFFSET);
|
int tile_index = JOKER_TID + (layer * JOKER_SPRITE_OFFSET);
|
||||||
|
|
||||||
int joker_spritesheet_idx = joker_get_spritesheet_idx(joker->id);
|
int joker_spritesheet_idx = s_joker_get_spritesheet_idx(joker->id);
|
||||||
int joker_idx = joker->id % NUM_JOKERS_PER_SPRITESHEET;
|
int joker_idx = joker->id % NUM_JOKERS_PER_SPRITESHEET;
|
||||||
int joker_pb = allocate_pb_if_needed(joker->id);
|
int joker_pb = s_allocate_pb_if_needed(joker->id);
|
||||||
joker_pb_add_sprite_user(joker_pb);
|
s_joker_pb_add_sprite_user(joker_pb);
|
||||||
|
|
||||||
memcpy32(&tile_mem[4][tile_index], &joker_gfxTiles[joker_spritesheet_idx][joker_idx * TILE_SIZE * JOKER_SPRITE_OFFSET], TILE_SIZE * JOKER_SPRITE_OFFSET);
|
memcpy32(
|
||||||
|
&tile_mem[4][tile_index],
|
||||||
|
&joker_gfxTiles[joker_spritesheet_idx][joker_idx * TILE_SIZE * JOKER_SPRITE_OFFSET],
|
||||||
|
TILE_SIZE * JOKER_SPRITE_OFFSET
|
||||||
|
);
|
||||||
|
|
||||||
sprite_object_set_sprite
|
sprite_object_set_sprite(
|
||||||
(
|
|
||||||
joker_object->sprite_object,
|
joker_object->sprite_object,
|
||||||
sprite_new
|
sprite_new(
|
||||||
(
|
|
||||||
ATTR0_SQUARE | ATTR0_4BPP | ATTR0_AFF,
|
ATTR0_SQUARE | ATTR0_4BPP | ATTR0_AFF,
|
||||||
ATTR1_SIZE_32,
|
ATTR1_SIZE_32,
|
||||||
tile_index,
|
tile_index,
|
||||||
@@ -220,36 +166,37 @@ JokerObject *joker_object_new(Joker *joker)
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return joker_object;
|
return joker_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
void joker_object_destroy(JokerObject **joker_object)
|
void joker_object_destroy(JokerObject** joker_object)
|
||||||
{
|
{
|
||||||
if (joker_object == NULL || *joker_object == NULL) return;
|
if (joker_object == NULL || *joker_object == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
int layer = sprite_get_layer(joker_object_get_sprite(*joker_object)) - JOKER_STARTING_LAYER;
|
int layer = sprite_get_layer(joker_object_get_sprite(*joker_object)) - JOKER_STARTING_LAYER;
|
||||||
used_layers[layer] = false;
|
_used_layers[layer] = false;
|
||||||
joker_pb_remove_sprite_user(sprite_get_pb(joker_object_get_sprite(*joker_object)));
|
s_joker_pb_remove_sprite_user(sprite_get_pb(joker_object_get_sprite(*joker_object)));
|
||||||
if (joker_pb_get_num_sprite_users((sprite_get_pb(joker_object_get_sprite(*joker_object)))) == 0)
|
if (s_joker_pb_get_num_sprite_users((sprite_get_pb(joker_object_get_sprite(*joker_object)))) ==
|
||||||
|
0)
|
||||||
{
|
{
|
||||||
joker_spritesheet_pb_map[joker_get_spritesheet_idx((*joker_object)->joker->id)] = UNDEFINED;
|
_joker_spritesheet_pb_map[s_joker_get_spritesheet_idx((*joker_object)->joker->id)] =
|
||||||
|
UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite_object_destroy(&(*joker_object)->sprite_object); // Destroy the sprite
|
sprite_object_destroy(&(*joker_object)->sprite_object); // Destroy the sprite
|
||||||
joker_destroy(&(*joker_object)->joker); // Destroy the joker
|
joker_destroy(&(*joker_object)->joker); // Destroy the joker
|
||||||
POOL_FREE(JokerObject, *joker_object);
|
POOL_FREE(JokerObject, *joker_object);
|
||||||
*joker_object = NULL;
|
*joker_object = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void joker_object_update(JokerObject *joker_object)
|
void joker_object_update(JokerObject* joker_object)
|
||||||
{
|
{
|
||||||
CardObject *card_object = (CardObject *)joker_object;
|
CardObject* card_object = (CardObject*)joker_object;
|
||||||
card_object_update(card_object);
|
card_object_update(card_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void joker_object_shake(JokerObject *joker_object, mm_word sound_id)
|
void joker_object_shake(JokerObject* joker_object, mm_word sound_id)
|
||||||
{
|
{
|
||||||
sprite_object_shake(joker_object->sprite_object, sound_id);
|
sprite_object_shake(joker_object->sprite_object, sound_id);
|
||||||
}
|
}
|
||||||
@@ -265,7 +212,11 @@ void set_and_shift_text(char* str, int* cursor_pos_x, int* cursor_pos_y, int col
|
|||||||
*cursor_pos_x += joker_score_display_offset_px;
|
*cursor_pos_x += joker_score_display_offset_px;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum JokerEvent joker_event)
|
bool joker_object_score(
|
||||||
|
JokerObject* joker_object,
|
||||||
|
CardObject* card_object,
|
||||||
|
enum JokerEvent joker_event
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (joker_object == NULL)
|
if (joker_object == NULL)
|
||||||
{
|
{
|
||||||
@@ -273,16 +224,17 @@ bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum
|
|||||||
}
|
}
|
||||||
|
|
||||||
JokerEffect* joker_effect = NULL;
|
JokerEffect* joker_effect = NULL;
|
||||||
u32 effect_flags_ret = joker_get_score_effect(joker_object->joker, card_object->card, joker_event, &joker_effect);
|
u32 effect_flags_ret =
|
||||||
|
joker_get_score_effect(joker_object->joker, card_object->card, joker_event, &joker_effect);
|
||||||
|
|
||||||
if (effect_flags_ret == JOKER_EFFECT_FLAG_NONE)
|
if (effect_flags_ret == JOKER_EFFECT_FLAG_NONE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 chips = get_chips();
|
u32 chips = get_chips();
|
||||||
u32 mult = get_mult();
|
u32 mult = get_mult();
|
||||||
int money = get_money();
|
int money = get_money();
|
||||||
|
|
||||||
if (effect_flags_ret & JOKER_EFFECT_FLAG_RETRIGGER)
|
if (effect_flags_ret & JOKER_EFFECT_FLAG_RETRIGGER)
|
||||||
{
|
{
|
||||||
@@ -317,7 +269,7 @@ bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum
|
|||||||
}
|
}
|
||||||
if (effect_flags_ret & JOKER_EFFECT_FLAG_MULT)
|
if (effect_flags_ret & JOKER_EFFECT_FLAG_MULT)
|
||||||
{
|
{
|
||||||
mult = u32_protected_add(mult, joker_effect->mult);
|
mult = u32_protected_add(mult, joker_effect->mult);
|
||||||
char score_buffer[INT_MAX_DIGITS + 2];
|
char score_buffer[INT_MAX_DIGITS + 2];
|
||||||
snprintf(score_buffer, sizeof(score_buffer), "+%lu", joker_effect->mult);
|
snprintf(score_buffer, sizeof(score_buffer), "+%lu", joker_effect->mult);
|
||||||
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_RED_PB);
|
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_RED_PB);
|
||||||
@@ -326,7 +278,7 @@ bool joker_object_score(JokerObject *joker_object, CardObject* card_object, enum
|
|||||||
// if xmult is zero, DO NOT multiply by it
|
// if xmult is zero, DO NOT multiply by it
|
||||||
if (effect_flags_ret & JOKER_EFFECT_FLAG_XMULT && joker_effect->xmult > 0)
|
if (effect_flags_ret & JOKER_EFFECT_FLAG_XMULT && joker_effect->xmult > 0)
|
||||||
{
|
{
|
||||||
mult = u32_protected_mult(mult, joker_effect->xmult);
|
mult = u32_protected_mult(mult, joker_effect->xmult);
|
||||||
char score_buffer[INT_MAX_DIGITS + 2];
|
char score_buffer[INT_MAX_DIGITS + 2];
|
||||||
snprintf(score_buffer, sizeof(score_buffer), "X%lu", joker_effect->xmult);
|
snprintf(score_buffer, sizeof(score_buffer), "X%lu", joker_effect->xmult);
|
||||||
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_RED_PB);
|
set_and_shift_text(score_buffer, &cursorPosX, &cursorPosY, TTE_RED_PB);
|
||||||
@@ -405,10 +357,82 @@ int joker_get_random_rarity()
|
|||||||
{
|
{
|
||||||
joker_rarity = RARE_JOKER;
|
joker_rarity = RARE_JOKER;
|
||||||
}
|
}
|
||||||
else if (rarity_roll < COMMON_JOKER_CHANCE + UNCOMMON_JOKER_CHANCE + RARE_JOKER_CHANCE + LEGENDARY_JOKER_CHANCE)
|
else if (rarity_roll < COMMON_JOKER_CHANCE + UNCOMMON_JOKER_CHANCE + RARE_JOKER_CHANCE +
|
||||||
|
LEGENDARY_JOKER_CHANCE)
|
||||||
{
|
{
|
||||||
joker_rarity = LEGENDARY_JOKER;
|
joker_rarity = LEGENDARY_JOKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return joker_rarity;
|
return joker_rarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int s_get_num_spritesheets()
|
||||||
|
{
|
||||||
|
return (get_joker_registry_size() + NUM_JOKERS_PER_SPRITESHEET - 1) /
|
||||||
|
NUM_JOKERS_PER_SPRITESHEET;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_joker_get_spritesheet_idx(u8 joker_id)
|
||||||
|
{
|
||||||
|
return joker_id / NUM_JOKERS_PER_SPRITESHEET;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void s_joker_pb_add_sprite_user(int pb)
|
||||||
|
{
|
||||||
|
_joker_pb_num_sprite_users[pb - JOKER_BASE_PB]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void s_joker_pb_remove_sprite_user(int pb)
|
||||||
|
{
|
||||||
|
int num_sprite_users = _joker_pb_num_sprite_users[pb - JOKER_BASE_PB];
|
||||||
|
_joker_pb_num_sprite_users[pb - JOKER_BASE_PB] = max(0, num_sprite_users - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_joker_pb_get_num_sprite_users(int joker_pb)
|
||||||
|
{
|
||||||
|
return _joker_pb_num_sprite_users[joker_pb - JOKER_BASE_PB];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_get_unused_joker_pb()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_ELEM_IN_ARR(_joker_pb_num_sprite_users); i++)
|
||||||
|
{
|
||||||
|
if (_joker_pb_num_sprite_users[i] == 0)
|
||||||
|
{
|
||||||
|
return (i + JOKER_BASE_PB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_allocate_pb_if_needed(u8 joker_id)
|
||||||
|
{
|
||||||
|
int joker_spritesheet_idx = s_joker_get_spritesheet_idx(joker_id);
|
||||||
|
int joker_pb = _joker_spritesheet_pb_map[joker_spritesheet_idx];
|
||||||
|
if (joker_pb != UNDEFINED)
|
||||||
|
{
|
||||||
|
// Already allocated
|
||||||
|
return joker_pb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a new palette
|
||||||
|
joker_pb = s_get_unused_joker_pb();
|
||||||
|
|
||||||
|
if (joker_pb == UNDEFINED)
|
||||||
|
{
|
||||||
|
// Ran out of palettes, default to base and pray
|
||||||
|
joker_pb = JOKER_BASE_PB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_joker_spritesheet_pb_map[joker_spritesheet_idx] = joker_pb;
|
||||||
|
memcpy16(
|
||||||
|
&pal_obj_mem[PAL_ROW_LEN * joker_pb],
|
||||||
|
joker_gfxPal[joker_spritesheet_idx],
|
||||||
|
NUM_ELEM_IN_ARR(joker_gfx0Pal)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return joker_pb;
|
||||||
|
}
|
||||||
|
|||||||
+1706
-1153
File diff suppressed because it is too large
Load Diff
+30
-21
@@ -1,18 +1,18 @@
|
|||||||
#include <tonc.h>
|
#include "affine_background.h"
|
||||||
#include <maxmod.h>
|
#include "blind.h"
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "sprite.h"
|
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "blind.h"
|
|
||||||
#include "joker.h"
|
|
||||||
#include "affine_background.h"
|
|
||||||
#include "graphic_utils.h"
|
#include "graphic_utils.h"
|
||||||
|
#include "joker.h"
|
||||||
|
#include "sprite.h"
|
||||||
|
|
||||||
|
#include <maxmod.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <tonc.h>
|
||||||
|
|
||||||
// Graphics
|
// Graphics
|
||||||
#include "background_gfx.h"
|
|
||||||
#include "affine_background_gfx.h"
|
#include "affine_background_gfx.h"
|
||||||
|
#include "background_gfx.h"
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
#include "soundbank.h"
|
#include "soundbank.h"
|
||||||
@@ -25,7 +25,15 @@ void init()
|
|||||||
irq_add(II_HBLANK, affine_background_hblank);
|
irq_add(II_HBLANK, affine_background_hblank);
|
||||||
|
|
||||||
// Initialize text engine
|
// Initialize text engine
|
||||||
tte_init_se(0, BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB), 0, CLR_WHITE, TTE_BIT_UNPACK_OFFSET, NULL, NULL);
|
tte_init_se(
|
||||||
|
0,
|
||||||
|
BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB),
|
||||||
|
0,
|
||||||
|
CLR_WHITE,
|
||||||
|
TTE_BIT_UNPACK_OFFSET,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
tte_erase_screen();
|
tte_erase_screen();
|
||||||
tte_init_con();
|
tte_init_con();
|
||||||
|
|
||||||
@@ -40,7 +48,7 @@ void init()
|
|||||||
REG_BG0CNT = BG_PRIO(0) | BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB) | BG_4BPP;
|
REG_BG0CNT = BG_PRIO(0) | BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB) | BG_4BPP;
|
||||||
// BG1 is the main background layer
|
// BG1 is the main background layer
|
||||||
REG_BG1CNT = BG_PRIO(1) | BG_CBB(MAIN_BG_CBB) | BG_SBB(MAIN_BG_SBB) | BG_8BPP;
|
REG_BG1CNT = BG_PRIO(1) | BG_CBB(MAIN_BG_CBB) | BG_SBB(MAIN_BG_SBB) | BG_8BPP;
|
||||||
// BG2 is the affine background layer
|
// BG2 is the affine background layer
|
||||||
REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_SBB) | BG_8BPP | BG_WRAP;
|
REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_SBB) | BG_8BPP | BG_WRAP;
|
||||||
|
|
||||||
int win1_left = 72;
|
int win1_left = 72;
|
||||||
@@ -53,20 +61,21 @@ void init()
|
|||||||
int win2_right = 232;
|
int win2_right = 232;
|
||||||
int win2_bottom = 44;
|
int win2_bottom = 44;
|
||||||
|
|
||||||
REG_WIN0H = win1_left<<8 | win1_right;
|
REG_WIN0H = win1_left << 8 | win1_right;
|
||||||
REG_WIN0V = win1_top<<8 | win1_bottom;
|
REG_WIN0V = win1_top << 8 | win1_bottom;
|
||||||
REG_WIN0CNT = WIN_ALL | WIN_BLD;
|
REG_WIN0CNT = WIN_ALL | WIN_BLD;
|
||||||
REG_WINOUTCNT = WIN_ALL;
|
REG_WINOUTCNT = WIN_ALL;
|
||||||
|
|
||||||
REG_WIN1H = win2_left<<8 | win2_right;
|
REG_WIN1H = win2_left << 8 | win2_right;
|
||||||
REG_WIN1V = win2_top<<8 | win2_bottom;
|
REG_WIN1V = win2_top << 8 | win2_bottom;
|
||||||
REG_WIN1CNT = WIN_ALL | WIN_BLD;
|
REG_WIN1CNT = WIN_ALL | WIN_BLD;
|
||||||
|
|
||||||
REG_BLDCNT = BLD_BUILD(BLD_BG1, BLD_BG2, 1);
|
REG_BLDCNT = BLD_BUILD(BLD_BG1, BLD_BG2, 1);
|
||||||
|
|
||||||
REG_BLDALPHA = BLDA_BUILD(0, 13);
|
REG_BLDALPHA = BLDA_BUILD(0, 13);
|
||||||
|
|
||||||
REG_DISPCNT = DCNT_MODE1 | DCNT_OBJ_1D | DCNT_BG0 | DCNT_BG1 | DCNT_BG2 | DCNT_OBJ | DCNT_WIN0 | DCNT_WIN1;
|
REG_DISPCNT = DCNT_MODE1 | DCNT_OBJ_1D | DCNT_BG0 | DCNT_BG1 | DCNT_BG2 | DCNT_OBJ | DCNT_WIN0 |
|
||||||
|
DCNT_WIN1;
|
||||||
|
|
||||||
// Initialize subsystems
|
// Initialize subsystems
|
||||||
mmInitDefault((mm_addr)soundbank_bin, 12);
|
mmInitDefault((mm_addr)soundbank_bin, 12);
|
||||||
@@ -94,14 +103,14 @@ int main()
|
|||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
while(true)
|
while (true)
|
||||||
{
|
{
|
||||||
VBlankIntrWait();
|
VBlankIntrWait();
|
||||||
mmFrame();
|
mmFrame();
|
||||||
key_poll();
|
key_poll();
|
||||||
update();
|
update();
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -6,4 +6,5 @@
|
|||||||
#define GIT_DIRTY "-dirty"
|
#define GIT_DIRTY "-dirty"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__attribute__((section(".version"), used)) const char balatro_version[] = "GBALATRO_VERSION:" GIT_HASH GIT_DIRTY;
|
__attribute__((section(".version"), used)) const char balatro_version[] =
|
||||||
|
"GBALATRO_VERSION:" GIT_HASH GIT_DIRTY;
|
||||||
|
|||||||
Reference in New Issue
Block a user