e7f550ce22
* background * Implement Options button * Update main menu artwork * add options menu tiles * prepare options menu handling * incorporate main menu refactor * toto * add all menu interactions * do not reset selection_x in main_menu * options struct * fix rebase from ricfehr3's repo * Implement high contrast cards * Save/Load options values to SRAM * load options on game_init and validate data within the load_options function * Get changes from ricfehr3's PR * recover fix for glitched ace * clang format * clang format * clang format * Save 500B of image data by using only minimal set of tiles instead of keeping final window in source file * clang format * clang format * Implement Options button * Update main menu artwork * progress, leaving it alone for now until discussion * make game_vars an extern * Move options vars into their own struct * rollback previous commit * Implement save validation. Version check to come * implement data validity + version check for game saves * clang format * Save position in rng sequence for consistent run after load * fix rebase issues * fix rebase issue * remove unused/duplicate define * Oops, made a mistake when testing PR #424 * encode high contrast palette into an image, and load it at game_start * document save.c/h and correct typos * correct alignment * game speed and high contrast buttons working * small cleanup * sliders also work again now * clang format * Moved balatro_version extern declaration to version.h file * removed unsused variable * make showing ROM version a toggle * move ante, round and money to the GameVariables struct * Rename SaveCheckInfo struct to SaveHeader for clarity * Add SaveHeader struct explanation * clang format * Revert unnecessary tileset optimization * SFX now follows the sound volume slider * clang format * Music now follows volume slider * Changed volume slider increment from 5 to 20 to avoid having the music sound too rough under 20% volume * refactor main_menu.c to use SelectionGrid and Button structs * clang format * make a "new" save button so we don't save during the state transition * clang format * Reduced state transition flicker by only changing affine background to a different one * Fix loading game too late in game init sequence * First batch of suggestions from @MeirGavish * Remove unnecessary intermediary buffers for high contrast palette swapping * comment row warp hack for button input * Add some of Copilot's suggestions * rename balatro_version into gbalatro_version for rebranding reasons + version display erase screen fix * remove unnecessary NULL check on `on_selection_changed` method * implement small game speed arrow buttons animation * factorize some code * remove unnecessary data validation in load_game(), since we already checked the header * Implement @MeirGavish 's suggestion regarding splitting the huge `on_update` function * clang format * implement @ricfehr3 's suggestion about keeping last selected button instead of using an obscure `on_boot` boolean * Apply @ricfehr3's suggestions * fix clang-format flags --------- Co-authored-by: MathisMartin31 <mathis.martin31@gmail.com>
150 lines
4.5 KiB
C
150 lines
4.5 KiB
C
#include "affine_background.h"
|
|
|
|
#include "affine_background_gfx.h"
|
|
#include "affine_main_menu_background_gfx.h"
|
|
#include "graphic_utils.h"
|
|
|
|
#define ANIMATION_SPEED_DIVISOR 16
|
|
|
|
// Prepare screen during VBLANK
|
|
// Pre-computes the affine matrices values for each scanline and stores in bgaff_arr. This is to be
|
|
// done in VBLANK so the HBLANK code can just fetch the values quickly.
|
|
static IWRAM_CODE void s_affine_background_prep_bgaff_arr();
|
|
|
|
static BG_AFFINE _bgaff_arr[SCREEN_HEIGHT + 1];
|
|
static AFF_SRC_EX _asx = {0};
|
|
static enum AffineBackgroundID _background = AFFINE_BG_NONE;
|
|
static uint _timer = 0;
|
|
|
|
void affine_background_init()
|
|
{
|
|
affine_background_update();
|
|
|
|
REG_BG_AFFINE[AFFINE_BG_IDX] = bg_aff_default;
|
|
}
|
|
|
|
IWRAM_CODE void affine_background_hblank()
|
|
{
|
|
vu16 vcount = REG_VCOUNT;
|
|
|
|
if ((vcount >= SCREEN_HEIGHT)) // Exit the function if the scanline is outside the screen
|
|
{
|
|
return;
|
|
}
|
|
|
|
// See comment in affine_background_prep_bgaff_arr()
|
|
REG_BG_AFFINE[AFFINE_BG_IDX] = _bgaff_arr[vcount + 1];
|
|
}
|
|
|
|
void affine_background_update()
|
|
{
|
|
if (REG_IE & IRQ_HBLANK) // High quality mode with HBLANK interrupt
|
|
{
|
|
s_affine_background_prep_bgaff_arr();
|
|
}
|
|
else // Low quality mode without HBLANK interrupt
|
|
{
|
|
_asx.scr_x = 0;
|
|
_asx.scr_y = 0;
|
|
_asx.tex_x += 5;
|
|
_asx.tex_y += 12;
|
|
// Scale the sine value to fit in a s16
|
|
_asx.sx = ((lu_sin(_timer * 100)) >> 8) + 256;
|
|
// Scale the sine value to fit in a s16
|
|
_asx.sy = ((lu_sin(_timer * 100 + 0x4000)) >> 8) + 256;
|
|
_asx.alpha = 0;
|
|
|
|
bg_rotscale_ex(&_bgaff_arr[0], &_asx);
|
|
REG_BG_AFFINE[AFFINE_BG_IDX] = _bgaff_arr[0];
|
|
}
|
|
|
|
_timer++;
|
|
}
|
|
|
|
void affine_background_set_color(COLOR color)
|
|
{
|
|
// Reload the palette to reset any previous color scaling
|
|
affine_background_change_background(_background);
|
|
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);
|
|
}
|
|
|
|
void affine_background_change_background(enum AffineBackgroundID new_bg)
|
|
{
|
|
if (_background == new_bg)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_background = new_bg;
|
|
|
|
switch (_background)
|
|
{
|
|
case AFFINE_BG_MAIN_MENU:
|
|
REG_BG2CNT &= ~BG_AFF_32x32;
|
|
REG_BG2CNT |= BG_AFF_16x16;
|
|
REG_IE |= IRQ_HBLANK; // Enable HBLANK
|
|
|
|
memcpy32_tile8_with_palette_offset(
|
|
(u32*)&tile8_mem[AFFINE_BG_CBB],
|
|
(const u32*)affine_main_menu_background_gfxTiles,
|
|
affine_main_menu_background_gfxTilesLen / 4,
|
|
AFFINE_BG_PB
|
|
);
|
|
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_main_menu_background_gfxMap);
|
|
affine_background_load_palette(affine_main_menu_background_gfxPal);
|
|
break;
|
|
case AFFINE_BG_GAME:
|
|
REG_BG2CNT &= ~BG_AFF_16x16;
|
|
REG_BG2CNT |= BG_AFF_32x32;
|
|
REG_IE &= ~IRQ_HBLANK; // Disable HBLANK
|
|
|
|
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);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static IWRAM_CODE void s_affine_background_prep_bgaff_arr()
|
|
{
|
|
for (u16 vcount = 0; vcount < SCREEN_HEIGHT; vcount++)
|
|
{
|
|
const s32 timer_s32 = _timer << 8;
|
|
const s32 vcount_s32 = vcount << 8;
|
|
const s16 vcount_s16 = vcount;
|
|
const s32 vcount_sine = lu_sin(vcount_s32 + timer_s32 / ANIMATION_SPEED_DIVISOR);
|
|
|
|
_asx.scr_x = (SCREEN_WIDTH / 2);
|
|
// scr_y must equal vcount otherwise the background will have no vertical difference
|
|
_asx.scr_y = vcount_s16 - (SCREEN_HEIGHT / 2);
|
|
_asx.tex_x = (1000 * 1000) + (vcount_sine);
|
|
_asx.tex_y = (1000 * 1000);
|
|
_asx.sx = 128;
|
|
_asx.sy = 128;
|
|
_asx.alpha = vcount_sine + (timer_s32 / ANIMATION_SPEED_DIVISOR);
|
|
|
|
bg_rotscale_ex(&_bgaff_arr[vcount], &_asx);
|
|
}
|
|
|
|
/* HBLANK occurs after the scanline so REG_VCOUNT represents the
|
|
* the scanline that just passed, so when it's SCREEN_HEIGHT we will
|
|
* actually be updating the first line
|
|
*/
|
|
_bgaff_arr[SCREEN_HEIGHT] = _bgaff_arr[0];
|
|
}
|