Merge branch 'main' into joker_pooling

This commit is contained in:
MeirGavish
2025-08-09 06:19:16 +03:00
25 changed files with 268 additions and 67 deletions
+46
View File
@@ -0,0 +1,46 @@
#include "affine_background.h"
#include "affine_background_gfx.h"
#include "graphic_utils.h"
BG_AFFINE bgaff;
AFF_SRC_EX asx = {32<<8, 64<<8, 120, 80, 0x0100, 0x0100, 0};
void affine_background_init()
{
memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_background_gfxTiles, affine_background_gfxTilesLen/4, AFFINE_BG_PB);
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap);
affine_background_load_palette(affine_background_gfxPal);
bgaff = bg_aff_default;
}
void affine_background_update()
{
static uint timer = 0;
timer++;
// These values are not permament, just the current configuration for the affine background
asx.tex_x += 5;
asx.tex_y += 12;
asx.sx = (lu_sin(timer * 100)) >> 8; // Scale the sine value to fit in a s16
asx.sx += 256; // Add 256 to the sine value to make it positive
asx.sy = (lu_sin(timer * 100 + 0x4000)) >> 8; // Scale the sine value to fit in a s16
asx.sy += 256; // Add 256 to the sine value to make it positive
bg_rotscale_ex(&bgaff, &asx);
REG_BG_AFFINE[2] = bgaff;
}
void affine_background_set_color(COLOR color)
{
memcpy16(&pal_bg_mem[AFFINE_BG_PB], affine_background_gfxPal, AFFINE_BG_PAL_LEN);
for (int i = 0; i < AFFINE_BG_PAL_LEN; i++)
{
clr_rgbscale(&pal_bg_mem[AFFINE_BG_PB] + i, &pal_bg_mem[AFFINE_BG_PB] + i, 1, color);
}
}
void affine_background_load_palette(const u16 *src)
{
memcpy16(&pal_bg_mem[AFFINE_BG_PB], src, AFFINE_BG_PAL_LEN);
}
+15 -6
View File
@@ -11,6 +11,7 @@
#include "hand_analysis.h"
#include "blind.h"
#include "joker.h"
#include "affine_background.h"
#include "graphic_utils.h"
#include "tonc_video.h"
#include "audio_utils.h"
@@ -18,6 +19,7 @@
#include "background_gfx.h"
#include "background_shop_gfx.h"
#include "background_blind_select_gfx.h"
#include "affine_background_gfx.h"
#include "soundbank.h"
@@ -148,6 +150,11 @@ int get_hand_top(void) {
return hand_top;
}
int hand_get_size(void)
{
return hand_top + 1;
}
CardObject **get_played_array(void) {
return played;
}
@@ -239,6 +246,10 @@ static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFI
#define PITCH_STEP_UNDISCARD_SFX 2*PITCH_STEP_DRAW_SFX
// Naming the stage where cards return from the discard pile to the deck "undiscard"
int get_num_discards_remaining(void) {
return discards;
}
// General functions
void set_seed(int seed)
{
@@ -428,6 +439,8 @@ void change_background(int id)
else if (current_blind == BOSS_BLIND)
{
main_bg_se_copy_rect(BOSS_BLIND_TITLE_SRC_RECT, TOP_LEFT_BLIND_TITLE_POINT);
affine_background_set_color(blind_get_color(BOSS_BLIND, BLIND_SHADOW_COLOR_INDEX));
}
bg_copy_current_item_to_top_left_panel();
@@ -849,11 +862,6 @@ void hand_change_sort()
sort_cards();
}
int hand_get_size()
{
return hand_top + 1;
}
int hand_get_max_size()
{
return hand_size;
@@ -1615,7 +1623,7 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
tte_set_special(0xD000); // Set text color to blue from background memory
// Write the score to a character buffer variable
char score_buffer[5]; // Assuming the maximum score is 99, we need 4 characters (2 digits + null terminator)
char score_buffer[INT_MAX_DIGITS + 2]; // for '+' and null terminator
snprintf(score_buffer, sizeof(score_buffer), "+%d", card_get_value(played[j]->card));
tte_write(score_buffer);
@@ -1986,6 +1994,7 @@ void game_round_end()
tte_erase_rect_wrapper(BLIND_REWARD_RECT);
tte_erase_rect_wrapper(BLIND_REQ_TEXT_RECT);
obj_hide(playing_blind_token->obj);
affine_background_load_palette(affine_background_gfxPal);
state = 5;
timer = 0;
}
+19
View File
@@ -168,3 +168,22 @@ void update_text_rect_to_right_align_num(Rect* rect, int num, int overflow_direc
}
}
void memcpy16_tile8_with_palette_offset(u16* dst, const u16* src, uint hwcount, u8 palette_offset)
{
const u16 offset = (((palette_offset) << 8) | (palette_offset));
for (int i = 0; i < hwcount; i++)
{
// Copying u8 data twice across u16 data
dst[i] = src[i] + offset;
}
}
void memcpy32_tile8_with_palette_offset(u32* dst, const u32* src, uint wcount, u8 palette_offset)
{
const u32 offset = (palette_offset << 24) | (palette_offset << 16) | (palette_offset << 8) | palette_offset;
for (int i = 0; i < wcount; i++)
{
// Copying u8 data 4 times across u32 data
dst[i] = src[i] + offset;
}
}
+28 -8
View File
@@ -127,6 +127,9 @@ void joker_init()
joker_gfxTiles[6] = joker_gfx6Tiles;
joker_gfxTiles[7] = joker_gfx7Tiles;
joker_gfxTiles[8] = joker_gfx8Tiles;
joker_gfxTiles[9] = joker_gfx9Tiles;
joker_gfxTiles[10] = joker_gfx10Tiles;
joker_gfxTiles[11] = joker_gfx11Tiles;
joker_gfxPal[0] = joker_gfx0Pal;
joker_gfxPal[1] = joker_gfx1Pal;
@@ -137,6 +140,9 @@ void joker_init()
joker_gfxPal[6] = joker_gfx6Pal;
joker_gfxPal[7] = joker_gfx7Pal;
joker_gfxPal[8] = joker_gfx8Pal;
joker_gfxPal[9] = joker_gfx9Pal;
joker_gfxPal[10] = joker_gfx10Pal;
joker_gfxPal[11] = joker_gfx11Pal;
for (int i = 0; i < num_spritesheets; i++)
{
@@ -264,33 +270,47 @@ bool joker_object_score(JokerObject *joker_object, Card* scored_card, int *chips
*money += joker_effect.money;
// TODO: Retrigger
tte_set_pos(fx2int(joker_object->sprite_object->x) + 8, JOKER_SCORE_TEXT_Y); // Offset of 16 pixels to center the text on the card
char score_buffer[12];
const int joker_score_display_offset_px = (MAX_CARD_SCORE_STR_LEN + 1)*TTE_CHAR_SIZE;
// + 1 For space
int cursorPosX = fx2int(joker_object->sprite_object->x) + 8; // Offset of 16 pixels to center the text on the card
if (joker_effect.chips > 0)
{
char score_buffer[INT_MAX_DIGITS + 2]; // For '+' and null terminator
tte_set_pos(cursorPosX, JOKER_SCORE_TEXT_Y);
tte_set_special(0xD000); // Blue
snprintf(score_buffer, sizeof(score_buffer), "+%d", joker_effect.chips);
tte_write(score_buffer);
cursorPosX += joker_score_display_offset_px;
}
else if (joker_effect.mult > 0)
if (joker_effect.mult > 0)
{
char score_buffer[INT_MAX_DIGITS + 2];
tte_set_pos(cursorPosX, JOKER_SCORE_TEXT_Y);
tte_set_special(0xE000); // Red
snprintf(score_buffer, sizeof(score_buffer), "+%d", joker_effect.mult);
tte_write(score_buffer);
cursorPosX += joker_score_display_offset_px;
}
else if (joker_effect.xmult > 0)
if (joker_effect.xmult > 0)
{
char score_buffer[INT_MAX_DIGITS + 2];
tte_set_pos(cursorPosX, JOKER_SCORE_TEXT_Y);
tte_set_special(0xE000); // Red
snprintf(score_buffer, sizeof(score_buffer), "X%d", joker_effect.xmult);
tte_write(score_buffer);
cursorPosX += joker_score_display_offset_px;
}
else if (joker_effect.money > 0)
if (joker_effect.money > 0)
{
char score_buffer[INT_MAX_DIGITS + 2];
tte_set_pos(cursorPosX, JOKER_SCORE_TEXT_Y);
tte_set_special(0xC000); // Yellow
snprintf(score_buffer, sizeof(score_buffer), "+%d", joker_effect.money);
tte_write(score_buffer);
cursorPosX += joker_score_display_offset_px;
}
tte_write(score_buffer);
joker_object->joker->processed = true; // Mark the joker as processed
joker_object_shake(joker_object, SFX_CARD_SELECT); // TODO: Add a sound effect for scoring the joker
+84 -4
View File
@@ -1,3 +1,4 @@
#include "game.h"
#include "joker.h"
#include "util.h"
#include "hand_analysis.h"
@@ -178,7 +179,8 @@ static JokerEffect half_joker_effect(Joker *joker, Card *scored_card) {
if (scored_card != NULL)
return effect; // if card != null, we are not at the end-phase of scoring yet
if (get_played_top() + 1 <= 3) // game.c has hand_get_size() but it's not accesible here
int played_size = get_played_top() + 1;
if (played_size <= 3)
effect.mult = 20;
return effect;
@@ -190,12 +192,13 @@ static JokerEffect joker_stencil_effect(Joker *joker, Card *scored_card) {
return effect; // if card != null, we are not at the end-phase of scoring yet
// +1 xmult per empty joker slot...
int jokers_top = get_jokers_top();
effect.xmult = (MAX_JOKERS_HELD_SIZE-1) - jokers_top;
int num_jokers = get_jokers_top() + 1;
effect.xmult = (MAX_JOKERS_HELD_SIZE) - num_jokers;
// ...and also each stencil_joker adds +1 xmult
JokerObject** jokers = get_jokers();
for (int i = 0; i < jokers_top; i++ )
for (int i = 0; i < num_jokers; i++ )
{
if (jokers[i]->joker->id == JOKER_STENCIL_ID)
effect.xmult++;
@@ -215,6 +218,78 @@ static JokerEffect misprint_joker_effect(Joker *joker, Card *scored_card) {
return effect;
}
static JokerEffect walkie_talkie_joker_effect(Joker *joker, Card *scored_card) {
JokerEffect effect = {0};
if (scored_card == NULL)
return effect;
if (scored_card->rank == TEN || scored_card->rank == FOUR) {
effect.chips = 10;
effect.mult = 4;
}
return effect;
}
static JokerEffect fibonnaci_joker_effect(Joker *joker, Card *scored_card) {
JokerEffect effect = {0};
if (scored_card == NULL)
return effect;
switch (scored_card->rank) {
case ACE: case TWO: case THREE: case FIVE: case EIGHT:
effect.mult = 8;
default:
break;
}
return effect;
}
static JokerEffect banner_joker_effect(Joker *joker, Card *scored_card) {
JokerEffect effect = {0};
if (scored_card != NULL)
return effect; // if card != null, we are not at the end-phase of scoring yet
effect.chips = 30 * get_num_discards_remaining();
return effect;
}
static JokerEffect mystic_summit_joker_effect(Joker *joker, Card *scored_card) {
JokerEffect effect = {0};
if (scored_card != NULL)
return effect; // if card != null, we are not at the end-phase of scoring yet
if (get_num_discards_remaining() == 0)
effect.mult = 15;
return effect;
}
static JokerEffect blackboard_joker_effect(Joker *joker, Card *scored_card) {
JokerEffect effect = {0};
if (scored_card != NULL)
return effect; // if card != null, we are not at the end-phase of scoring yet
bool all_cards_are_spades_or_clubs = true;
CardObject** hand = get_hand_array();
int hand_size = hand_get_size();
for (int i = 0; i < hand_size; i++ )
{
u8 suit = hand[i]->card->suit;
if (suit == HEARTS || suit == DIAMONDS) {
all_cards_are_spades_or_clubs = false;
break;
}
}
if (all_cards_are_spades_or_clubs)
effect.xmult = 3;
return effect;
}
const JokerInfo joker_registry[] = {
{ COMMON_JOKER, 2, default_joker_effect }, // DEFAULT_JOKER_ID = 0
{ COMMON_JOKER, 5, greedy_joker_effect }, // GREEDY_JOKER_ID = 1
@@ -233,6 +308,11 @@ const JokerInfo joker_registry[] = {
{ COMMON_JOKER, 4, crafty_joker_effect },
{ COMMON_JOKER, 5, half_joker_effect },
{ UNCOMMON_JOKER, 8, joker_stencil_effect },
{ COMMON_JOKER, 5, banner_joker_effect },
{ COMMON_JOKER, 4, walkie_talkie_joker_effect },
{ UNCOMMON_JOKER, 8, fibonnaci_joker_effect },
{ UNCOMMON_JOKER, 6, blackboard_joker_effect },
{ COMMON_JOKER, 5, mystic_summit_joker_effect },
{ COMMON_JOKER, 4, misprint_joker_effect },
};
+3 -42
View File
@@ -7,6 +7,7 @@
#include "game.h"
#include "blind.h"
#include "joker.h"
#include "affine_background.h"
#include "graphic_utils.h"
// Graphics
@@ -17,29 +18,6 @@
#include "soundbank.h"
#include "soundbank_bin.h"
#define MAP_AFF_SIZE 0x0100
BG_AFFINE bgaff;
AFF_SRC_EX asx = {32<<8, 64<<8, 120, 80, 0x0100, 0x0100, 0};
void init_map() // Temp function derived from libtonc example
{
// Grit is fucking garbage and doesn't allow you to have a palette offset, they all get loaded at 0x0000. I have to manually change each tile's palette bank
unsigned int correctedTiles[affine_background_gfxTilesLen / 4];
for (int i = 0; i < affine_background_gfxTilesLen / 4; i++)
{
correctedTiles[i] = affine_background_gfxTiles[i] | 0xF0F0F0F0; // I brute forced this. I have no idea how this would and does work, but it does. We'll just leave this here for now.
// Actually for future reference, each number seems to equate to an XY on the palette, so 0xF0F0F0F0 would just push everything down 15 colors, since the second number isn't set.
}
memcpy(&tile8_mem[AFFINE_BG_CBB], correctedTiles, affine_background_gfxTilesLen);
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap);
memcpy16(&pal_bg_mem[16 * 15], affine_background_gfxPal, 5);
bgaff = bg_aff_default;
}
void init()
{
irq_init(NULL);
@@ -93,9 +71,8 @@ void init()
REG_DISPCNT = DCNT_MODE1 | DCNT_OBJ_1D | DCNT_BG0 | DCNT_BG1 | DCNT_BG2 | DCNT_OBJ | DCNT_WIN0 | DCNT_WIN1;
init_map(); // Initialize the map for the background
// Initialize subsystems
affine_background_init();
sprite_init();
card_init();
blind_init();
@@ -103,24 +80,9 @@ void init()
game_init();
}
void background_update() // This needs to be called before update() and draw() because setting REG_BG_AFFINE during an HBlank can cause issues
{
static uint timer = 0;
timer++;
// These values are not permament, just the current configuration for the affine background
asx.tex_x += 5;
asx.tex_y += 12;
asx.sx = (lu_sin(timer * 100)) >> 8; // Scale the sine value to fit in a s16
asx.sx += 256; // Add 256 to the sine value to make it positive
asx.sy = (lu_sin(timer * 100 + 0x4000)) >> 8; // Scale the sine value to fit in a s16
asx.sy += 256; // Add 256 to the sine value to make it positive
bg_rotscale_ex(&bgaff, &asx);
REG_BG_AFFINE[2]= bgaff;
}
void update()
{
affine_background_update();
game_update();
}
@@ -138,7 +100,6 @@ int main()
VBlankIntrWait();
mmFrame();
key_poll();
background_update();
update();
draw();
}