From 9f9b55714315bc119c8cb050036975e42433f3fa Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sat, 2 Aug 2025 18:56:10 +0300 Subject: [PATCH 1/9] Refactor - extracted game_shop_intro() from game_shop() --- source/game.c | 64 +++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/source/game.c b/source/game.c index 6f3d8deb..edb7b9c8 100644 --- a/source/game.c +++ b/source/game.c @@ -2135,6 +2135,39 @@ void game_round_end() } } +void game_shop_intro(JokerObject* shop_jokers[]) +{ + main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP); + + if (timer == 1) + { + game_shop_create_items(shop_jokers, true); + } + + if (timer >= 7) // Shift the shop icon + { + int timer_offset = timer - 6; + + // TODO: Extract to generic function? + for (int y = 0; y < timer_offset; y++) + { + int y_from = 26 + y - timer_offset; + int y_to = 0 + y; + + Rect from = { 0, y_from, 8, y_from }; + BG_POINT to = { 0, y_to }; + + main_bg_se_copy_rect(from, to); + } + } + + if (timer == 12) + { + state = 1; + timer = 0; // Reset the timer + } +} + void game_shop() { change_background(BG_ID_SHOP); @@ -2183,36 +2216,7 @@ void game_shop() { case 0: // Intro sequence (menu and shop icon coming into frame) { - main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP); - - if (timer == 1) - { - game_shop_create_items(shop_jokers, true); - } - - if (timer >= 7) // Shift the shop icon - { - int timer_offset = timer - 6; - - // TODO: Extract to generic function? - for (int y = 0; y < timer_offset; y++) - { - int y_from = 26 + y - timer_offset; - int y_to = 0 + y; - - Rect from = {0, y_from, 8, y_from}; - BG_POINT to = {0, y_to}; - - main_bg_se_copy_rect(from, to); - } - } - - if (timer == 12) - { - state = 1; - timer = 0; // Reset the timer - } - + game_shop_intro(shop_jokers); break; } case 1: // Shop menu input and selection From a8f429eca35ad73ba4028606ac5055b063668de0 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sun, 3 Aug 2025 16:08:41 +0300 Subject: [PATCH 2/9] Moved the price of shop items below the item so it is not obstructed when the card is raised on highlight --- include/sprite.h | 2 ++ source/game.c | 2 +- source/sprite.c | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/sprite.h b/include/sprite.h index 0cd9840a..d76f2b5b 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -4,6 +4,8 @@ #include #include +#define CARD_SPRITE_SIZE 32 + typedef struct { OBJ_ATTR *obj; diff --git a/source/game.c b/source/game.c index 6f3d8deb..db684b03 100644 --- a/source/game.c +++ b/source/game.c @@ -1821,7 +1821,7 @@ static void game_shop_create_items(JokerObject *shop_jokers[], bool first_time) shop_jokers[i]->sprite_object->ty = int2fx(71); int x = fx2int(shop_jokers[i]->sprite_object->tx) + TILE_SIZE - (get_digits_even(shop_jokers[i]->joker->value) - 1) * TILE_SIZE; - int y = fx2int(shop_jokers[i]->sprite_object->ty); + int y = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE; tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, shop_jokers[i]->joker->value); if (first_time == false) diff --git a/source/sprite.c b/source/sprite.c index 5e3edf69..ebb2e378 100644 --- a/source/sprite.c +++ b/source/sprite.c @@ -1,5 +1,6 @@ #include "sprite.h" #include "util.h" +#include "audio_utils.h" #include #include @@ -206,8 +207,7 @@ void sprite_object_shake(SpriteObject* sprite_object, mm_word sound_id) if (sound_id == UNDEFINED) return; // If no sound ID is provided, do nothing - mm_sound_effect sfx_select = { {sound_id}, 1024, 0, 255, 128, }; - mmEffectEx(&sfx_select); + play_sfx(sound_id, MM_BASE_PITCH_RATE); } void sprite_object_set_selected(SpriteObject* sprite_object, bool selected) From bbefff2eb955c9476c8866c9571bfafd0ac41069 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sun, 3 Aug 2025 16:51:16 +0300 Subject: [PATCH 3/9] Fixed bug where shop price would continue displaying after the item was purchased --- source/game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/game.c b/source/game.c index dae247b3..af14d73b 100644 --- a/source/game.c +++ b/source/game.c @@ -2325,7 +2325,7 @@ void game_shop() Rect joker_price_rect; joker_price_rect.left = fx2int(shop_jokers[i]->sprite_object->tx); - joker_price_rect.top = fx2int(shop_jokers[i]->sprite_object->ty) + TILE_SIZE; + joker_price_rect.top = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + 2*TILE_SIZE; joker_price_rect.right = joker_price_rect.left + TILE_SIZE * 3; joker_price_rect.bottom = joker_price_rect.top + TILE_SIZE; From ec2aaf245dc6e717a54b8b4519e21aa9031f49a9 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sun, 3 Aug 2025 18:15:28 +0300 Subject: [PATCH 4/9] Added clarification comment --- source/game.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/game.c b/source/game.c index af14d73b..1f4fd5cc 100644 --- a/source/game.c +++ b/source/game.c @@ -2325,6 +2325,7 @@ void game_shop() Rect joker_price_rect; joker_price_rect.left = fx2int(shop_jokers[i]->sprite_object->tx); + // 2*TILE_SIZE because the item is highlighted and raised by 1 additional tile joker_price_rect.top = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + 2*TILE_SIZE; joker_price_rect.right = joker_price_rect.left + TILE_SIZE * 3; joker_price_rect.bottom = joker_price_rect.top + TILE_SIZE; From de672572b15689708e708e4a5f12b08631585025 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sat, 2 Aug 2025 18:57:50 +0300 Subject: [PATCH 5/9] Updated joker palette swapping system to reuse palettes when jokers are removed --- include/joker.h | 8 +++++- include/sprite.h | 2 +- source/game.c | 2 +- source/joker.c | 69 ++++++++++++++++++++++++++++++++++-------------- source/sprite.c | 9 +++++++ 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/include/joker.h b/include/joker.h index a869ed51..37b9712f 100644 --- a/include/joker.h +++ b/include/joker.h @@ -6,10 +6,16 @@ #include "sprite.h" #include "card.h" #include "game.h" +#include "graphic_utils.h" #define JOKER_TID (MAX_HAND_SIZE + MAX_SELECTION_SIZE) * JOKER_SPRITE_OFFSET // Tile ID for the starting index in the tile memory #define JOKER_SPRITE_OFFSET 16 // Offset for the joker sprites -#define JOKER_BASE_PB 4 // Palette bank for the default jokers +#define JOKER_BASE_PB 4 // The starting palette index for the jokers +#define JOKER_LAST_PB (NUM_PALETTES - 1) +// 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 +// such as planet cards etc. + #define JOKER_STARTING_LAYER 27 #define BASE_EDITION 0 diff --git a/include/sprite.h b/include/sprite.h index 0cd9840a..09a1a281 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -8,7 +8,6 @@ typedef struct { OBJ_ATTR *obj; OBJ_AFFINE *aff; - u32 tid, pb; POINT pos; } Sprite; @@ -44,6 +43,7 @@ INLINE void sprite_position(Sprite *sprite, int x, int y) // Sprite functions void sprite_init(); void sprite_draw(); +int sprite_get_pb(const Sprite* sprite); // SpriteObject methods SpriteObject *sprite_object_new(); diff --git a/source/game.c b/source/game.c index edb7b9c8..1fd9377b 100644 --- a/source/game.c +++ b/source/game.c @@ -29,7 +29,7 @@ static uint timer = 0; // This might already exist in libtonc but idk so i'm jus static int game_speed = 1; static int background = 0; -static enum GameState game_state = GAME_BLIND_SELECT; // The current game state, this is used to determine what the game is doing at any given time +static enum GameState game_state = GAME_SHOP; // The current game state, this is used to determine what the game is doing at any given time static enum HandState hand_state = HAND_DRAW; static enum PlayState play_state = PLAY_PLAYING; static int state = 0; // General state variable, used for switch statements in each game state related function diff --git a/source/joker.c b/source/joker.c index 02febc5a..2d960a93 100644 --- a/source/joker.c +++ b/source/joker.c @@ -39,16 +39,52 @@ static bool used_layers[MAX_JOKER_OBJECTS] = {false}; // Track used layers for j // Maps the spritesheet index to the palette bank index allocated to it. // Spritesheets that were not allocated are static int* joker_spritesheet_pb_map; +static int joker_pb_num_sprite_users[JOKER_LAST_PB - JOKER_BASE_PB + 1] = { 0 }; static int get_num_spritesheets() { return (get_joker_registry_size() + NUM_JOKERS_PER_SPRITESHEET - 1) / NUM_JOKERS_PER_SPRITESHEET; } +static int joker_get_spritesheet_idx(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_id / NUM_JOKERS_PER_SPRITESHEET; + int joker_spritesheet_idx = joker_get_spritesheet_idx(joker_id); int joker_pb = joker_spritesheet_pb_map[joker_spritesheet_idx]; if (joker_pb != UNDEFINED) { @@ -57,23 +93,9 @@ static int allocate_pb_if_needed(u8 joker_id) } // Allocate a new palette - joker_pb = int_arr_max(joker_spritesheet_pb_map, get_num_spritesheets()); + joker_pb = get_unused_joker_pb(); if (joker_pb == UNDEFINED) - { - // This is the first palette loaded - joker_pb = JOKER_BASE_PB; - } - else - { - // The new palette bank is a 1 increment of the last allocated one - /* TODO: This doesn't account for removal, we need to address that, - * track sprite usage and remove palettes for unused sprites - */ - joker_pb = joker_pb + 1; - } - - if (joker_pb == NUM_PALETTES) { // Ran out of palettes, default to base and pray joker_pb = JOKER_BASE_PB; @@ -129,7 +151,7 @@ Joker *joker_new(u8 id) joker->id = id; joker->modifier = BASE_EDITION; // TODO: Make this a parameter - joker->value = jinfo->base_value + edition_price_lut[joker->modifier]; // Base value + edition price + joker->value = jinfo->base_value + edition_price_lut[joker->modifier]; joker->rarity = jinfo->rarity; joker->processed = false; @@ -172,12 +194,13 @@ JokerObject *joker_object_new(Joker *joker) int tile_index = JOKER_TID + (layer * JOKER_SPRITE_OFFSET); - int joker_spritesheet_idx = joker->id / NUM_JOKERS_PER_SPRITESHEET; + int joker_spritesheet_idx = joker_get_spritesheet_idx(joker->id); int joker_idx = joker->id % NUM_JOKERS_PER_SPRITESHEET; int joker_pb = allocate_pb_if_needed(joker->id); + 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); - + sprite_object_set_sprite ( joker_object->sprite_object, @@ -198,10 +221,16 @@ JokerObject *joker_object_new(Joker *joker) void joker_object_destroy(JokerObject **joker_object) { - if (*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; used_layers[layer] = false; + 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) + { + joker_spritesheet_pb_map[joker_get_spritesheet_idx((*joker_object)->joker->id)] = UNDEFINED; + } + sprite_object_destroy(&(*joker_object)->sprite_object); // Destroy the sprite joker_destroy(&(*joker_object)->joker); // Destroy the joker free(*joker_object); diff --git a/source/sprite.c b/source/sprite.c index 5e3edf69..376018a3 100644 --- a/source/sprite.c +++ b/source/sprite.c @@ -100,6 +100,15 @@ void sprite_draw() oam_copy(oam_mem, obj_buffer, MAX_SPRITES); } +int sprite_get_pb(const Sprite *sprite) +{ + if (sprite == NULL) + { + return UNDEFINED; + } + return (sprite->obj->attr2 & ATTR2_PALBANK_MASK) >> ATTR2_PALBANK_SHIFT; +} + // SpriteObject methods SpriteObject* sprite_object_new() { From 7c6aa7371fc7a69af15765c62c198ee2da3ba5e2 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Mon, 4 Aug 2025 10:20:49 +0300 Subject: [PATCH 6/9] Added -g compile flag to allow debug symbols for IDE debugging --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 55f4d213..9bee64fe 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ GRAPHICS := graphics #--------------------------------------------------------------------------------- ARCH := -mthumb -mthumb-interwork -CFLAGS := -O3 -Wall -Werror\ +CFLAGS := -g -O3 -Wall -Werror\ -mcpu=arm7tdmi -mtune=arm7tdmi \ -ffast-math -fomit-frame-pointer -funroll-loops \ $(ARCH) From 607a17542627ff33213b589753207ed71c784420 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Mon, 4 Aug 2025 18:56:38 +0300 Subject: [PATCH 7/9] Update README.md Reworded the readme and added links to the official version of Balatro on all platforms --- README.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0270f470..1e8f8686 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,26 @@ # Balatro GBA This is an attempt to recreate the game 'Balatro' as accurately as possible, including all of the visual effects that make Balatro feel satisfying to play. -This port is strictly limited to the content that was available in the January 2024 Balatro Steam demo. -### **Disclaimer: This project is NOT endorsed or supported by Playstack or LocalThunk** -#### This project is solely aimed to recreate Balatro's old demo on the Game Boy Advance and is not meant to infringe or draw sales away from the full game's release or any of the established works by Playstack and LocalThunk. All rights are reserved to their respective holders. +This port is strictly limited in content to a minimal version of Balatro and will not recreate the full game. +### **Disclaimer: This project is NOT endorsed by or affiliated with Playstack or LocalThunk** +#### This is a non-profit community fan project solely aimed to recreate a minimal version of Balatro on the Game Boy Advance as a tribute to the full Balatro and is not meant to infringe or draw sales away from the full game's release or any of the established works by Playstack and LocalThunk. +#### All rights are reserved to their respective holders. +This version is meant for people who already own and know the official full game. + +Buy the official full version + +[Balatro on Steam](https://store.steampowered.com/app/2379780/Balatro/) + +[Balatro on Google Play](https://play.google.com/store/apps/details?id=com.playstack.balatro.android) + +[Balatro on Apple App Store](https://apps.apple.com/us/app/balatro/id6502453075) + +[Balatro on Switch](https://www.nintendo.com/us/store/products/balatro-switch/) + +[Balatro on PlayStation Store](https://store.playstation.com/en-us/concept/10010334) + +[Balatro on Xbox](https://www.xbox.com/games/store/balatro/9PK087LNGJC5) + ![Example](https://github.com/cellos51/balatro-gba/blob/main/example.gif) # **Build Instructions:** @@ -22,7 +39,7 @@ Example: `cd '/home/user/OneDrive/Documents/balatro-gba` or something like this. 9. After it completes, navigate through the `build` directory in the project folder and look for `balatro-gba.gba` and load it on an emulator or flashcart. ## **-Linux-** -[Not Available] +[No Instructions Available] ### **Common Issues:** 1. **When I drag the folder into the window and press enter, it doesn't work!** @@ -36,5 +53,3 @@ Example: `cd '/home/user/OneDrive/Documents/balatro-gba` or something like this. 5. **It says I don't have `Git` or `Make` installed!** -Use `pacman -S git` or `pacman -S make` although it should already be installed if you followed the instructions correctly. -#### Purchasing the official game is highly recommended and almost mandatory in order for this project to have a chance of staying up due to copyright issues and potential legal action. -**Purchase the Steam Version here: https://store.steampowered.com/app/2379780/Balatro/** From 742114792d821d2903cfd086048c9b51258d35a0 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Mon, 4 Aug 2025 20:27:03 +0300 Subject: [PATCH 8/9] Fixed game starting at shop --- source/game.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/game.c b/source/game.c index 03dad5a9..6fbb685e 100644 --- a/source/game.c +++ b/source/game.c @@ -29,7 +29,7 @@ static uint timer = 0; // This might already exist in libtonc but idk so i'm jus static int game_speed = 1; static int background = 0; -static enum GameState game_state = GAME_SHOP; // The current game state, this is used to determine what the game is doing at any given time +static enum GameState game_state = GAME_BLIND_SELECT; // The current game state, this is used to determine what the game is doing at any given time static enum HandState hand_state = HAND_DRAW; static enum PlayState play_state = PLAY_PLAYING; static int state = 0; // General state variable, used for switch statements in each game state related function From fe4b8e081d22845122224373f56c975a2fa7f1ae Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 5 Aug 2025 22:03:54 +0300 Subject: [PATCH 9/9] Changed clubs symbol to improve card readability --- graphics/deck_gfx.png | Bin 10399 -> 10459 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/deck_gfx.png b/graphics/deck_gfx.png index 1b775262a558bb430cf6532fbc7ceee2393f3780..98c61d96f7bc567ebede4b89e31436c396a93c16 100644 GIT binary patch literal 10459 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