Optimized affine background HBLANK effect - improved but still not good enough

This commit is contained in:
MeirGavish
2025-08-12 00:06:04 +03:00
parent af2358f487
commit b043b82d3f
2 changed files with 43 additions and 27 deletions
+3 -2
View File
@@ -7,10 +7,11 @@
#define AFFINE_BG_PAL_LEN 5
#define AFFINE_BG_PB (PAL_ROW_LEN * 15) // This isn't really a palette bank, just the starting index of the palette
#define AFFINE_BG_IDX 2 // The index of BGCNT register etc.
void affine_background_init();
void affine_background_hblank();
void affine_background_update();
IWRAM_CODE void affine_background_hblank();
IWRAM_CODE void affine_background_update();
void affine_background_set_color(COLOR color);
// Must be called with an array of size at least AFFINE_BG_PAL_LEN
void affine_background_load_palette(const u16 *src);
+32 -17
View File
@@ -3,11 +3,10 @@
#include "graphic_utils.h"
BG_AFFINE bgaff;
AFF_SRC_EX asx = {32<<8, 64<<8, 120, 80, 0x0100, 0x0100, 0};
BG_AFFINE bgaff_arr[SCREEN_HEIGHT + 1];
static uint timer = 0;
#define TOP_SCANLINE_OFFSET 228
#define ANIMATION_SPEED_DIVISOR 16
@@ -17,22 +16,18 @@ void affine_background_init()
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap);
affine_background_load_palette(affine_background_gfxPal);
bgaff = bg_aff_default;
REG_BG_AFFINE[AFFINE_BG_IDX] = bg_aff_default;
}
void affine_background_hblank()
// 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.
IWRAM_CODE void affine_background_prep_bgaff_arr()
{
vu16 vcount = REG_VCOUNT;
if ((vcount > 160 && vcount < 225) || vcount > TOP_SCANLINE_OFFSET) // Exit the function if the scanline is outside the valid range
for (u16 vcount = 0; vcount < SCREEN_HEIGHT; vcount++)
{
return;
}
else if (vcount > TOP_SCANLINE_OFFSET - 3) // This fixes a visual issue where the top 3 pixels of the scanline are out of sync
{
vcount -= TOP_SCANLINE_OFFSET;
}
AFF_SRC_EX asx = {32<<8, 64<<8, 120, 80, 0x0100, 0x0100, 0};
const s32 timer_s32 = timer << 8;
const s32 vcount_s32 = vcount << 8;
const s16 vcount_s16 = vcount;
@@ -46,12 +41,32 @@ void affine_background_hblank()
asx.sy = vcount_sine / 16;
asx.alpha = vcount_sine + (timer_s32 / ANIMATION_SPEED_DIVISOR);
bg_rotscale_ex(&bgaff, &asx);
REG_BG_AFFINE[2] = bgaff;
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];
}
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()
{
affine_background_prep_bgaff_arr();
timer++;
}