Skip to content

Commit

Permalink
Simplified / improved a bit palette fading process to avoid palette t…
Browse files Browse the repository at this point in the history
…ransfer outside vblank
  • Loading branch information
Stephane-D committed Oct 2, 2024
1 parent 7564554 commit 8ab25b2
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 98 deletions.
Binary file modified lib/libmd.a
Binary file not shown.
136 changes: 39 additions & 97 deletions src/pal.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,6 @@ static u16 fadeSize;
static s16 fadeCounter;


// forward
static void setFadePalette(u16 ind, const u16 *src, u16 len, bool forceWaitVBlank);
static bool doFadeStepInternal(bool forceWaitVBlank);


u16 PAL_getColor(u16 index)
{
const u16 addr = index * 2;
Expand Down Expand Up @@ -292,44 +287,6 @@ void PAL_setPalette(u16 numPal, const u16* pal, TransferMethod tm)
}


static void setFadePalette(u16 ind, const u16 *src, u16 len, bool forceWaitVBlank)
{
// be sure that we are during vblank
if (forceWaitVBlank) SYS_doVBlankProcess();

// use DMA for long transfer
PAL_setColors(ind, src, len, (len > 16)?DMA:CPU);
}

//static void setFadePalette(u16 ind, const u16 *src, u16 len)
//{
// static u32 lastVTimer = 0;
//
// // we are inside VInt callback --> just set palette colors immediately
// if (SYS_isInVIntCallback())
// {
// // use DMA for long transfer
// if (len > 16) DMA_doDma(DMA_CRAM, (u32) src, ind * 2, len, 2);
// else PAL_setColors(ind, src, len);
// }
// else
// {
// // be sure to wait at least 1 frame between set fade palette call
// if (lastVTimer == vtimer) VDP_waitVSync();
//
// // disable interrupts to not conflict with VInt accesses
// SYS_disableInts();
// // use DMA for long transfer
// if (len > 16) DMA_doDma(DMA_CRAM, (u32) src, ind * 2, len, 2);
// else PAL_setColors(ind, src, len);
// SYS_enableInts();
//
// // keep track of last update
// lastVTimer = vtimer;
// }
//}


bool NO_INLINE PAL_initFade(u16 fromCol, u16 toCol, const u16* palSrc, const u16* palDst, u16 numFrame)
{
// can't do a fade on 0 frame !
Expand Down Expand Up @@ -376,66 +333,51 @@ bool NO_INLINE PAL_initFade(u16 fromCol, u16 toCol, const u16* palSrc, const u16
*stepB++ = divs(BD - BS, numFrame);
}

// set current palette on next vblank
PAL_setColors(fadeInd, fadeCurrentPal, fadeSize, DMA_QUEUE);

return TRUE;
}

static bool NO_INLINE doFadeStepInternal(bool forceWaitVBlank)
bool NO_INLINE PAL_doFadeStep(void)
{
// not yet done ?
if (--fadeCounter >= 0)
// prepare fade palette for next frame
s16* palR = fadeR;
s16* palG = fadeG;
s16* palB = fadeB;
s16* stepR = fadeSR;
s16* stepG = fadeSG;
s16* stepB = fadeSB;
u16* dst = fadeCurrentPal;

// compute the next fade palette
u16 i = fadeSize;
while(i--)
{
// set current fade palette
setFadePalette(fadeInd, fadeCurrentPal, fadeSize, forceWaitVBlank);

// then prepare fade palette for next frame
s16* palR = fadeR;
s16* palG = fadeG;
s16* palB = fadeB;
s16* stepR = fadeSR;
s16* stepG = fadeSG;
s16* stepB = fadeSB;
u16* dst = fadeCurrentPal;

// compute the next fade palette
u16 i = fadeSize;
while(i--)
{
u16 col;

const u16 R = *palR + *stepR++;
const u16 G = *palG + *stepG++;
const u16 B = *palB + *stepB++;
u16 col;

*palR++ = R;
*palG++ = G;
*palB++ = B;
const u16 R = *palR + *stepR++;
const u16 G = *palG + *stepG++;
const u16 B = *palB + *stepB++;

col = ((R >> PALETTEFADE_FRACBITS) << VDPPALETTE_REDSFT) & VDPPALETTE_REDMASK;
col |= ((G >> PALETTEFADE_FRACBITS) << VDPPALETTE_GREENSFT) & VDPPALETTE_GREENMASK;
col |= ((B >> PALETTEFADE_FRACBITS) << VDPPALETTE_BLUESFT) & VDPPALETTE_BLUEMASK;
*palR++ = R;
*palG++ = G;
*palB++ = B;

*dst++ = col;
}
col = ((R >> PALETTEFADE_FRACBITS) << VDPPALETTE_REDSFT) & VDPPALETTE_REDMASK;
col |= ((G >> PALETTEFADE_FRACBITS) << VDPPALETTE_GREENSFT) & VDPPALETTE_GREENMASK;
col |= ((B >> PALETTEFADE_FRACBITS) << VDPPALETTE_BLUESFT) & VDPPALETTE_BLUEMASK;

// not yet done
return TRUE;
*dst++ = col;
}
else
{
// last step --> we can just set the final fade palette
setFadePalette(fadeInd, fadeEndPal, fadeSize, forceWaitVBlank);

// done
return FALSE;
}
}
// schedule palette transfer on next vblank
PAL_setColors(fadeInd, fadeCurrentPal, fadeSize, DMA_QUEUE);

bool PAL_doFadeStep()
{
return doFadeStepInternal(FALSE);
return (--fadeCounter > 0);
}

void PAL_interruptFade()
void PAL_interruptFade(void)
{
VBlankProcess &= ~PROCESS_PALETTE_FADING;
}
Expand All @@ -449,8 +391,12 @@ void PAL_fade(u16 fromCol, u16 toCol, const u16* palSrc, const u16* palDst, u16
if (async) VBlankProcess |= PROCESS_PALETTE_FADING;
else
{
// process fading immediatly with forced VBlank wait
while (doFadeStepInternal(TRUE));
// process fading immediately
do
{
SYS_doVBlankProcess();
}
while (PAL_doFadeStep());
}
}

Expand Down Expand Up @@ -525,10 +471,6 @@ bool PAL_isDoingFade()

void PAL_waitFadeCompletion()
{
if (PAL_isDoingFade())
{
// need to do VBlank process otherwise we can wait a long time for completion ^^
while (VBlankProcess & PROCESS_PALETTE_FADING)
SYS_doVBlankProcess();
}
// need to do VBlank process otherwise we can wait a long time for completion ^^
while (PAL_isDoingFade()) SYS_doVBlankProcess();
}
4 changes: 3 additions & 1 deletion src/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,10 +529,12 @@ void NO_INLINE _start_entry()
BMP_drawBitmapScaled(logo, 128 - (w >> 1), 80 - (w >> 1), w, w, FALSE);
// flip to screen
BMP_flip(FALSE);
// so palette fade is done
DMA_flushQueue();
}

// while fade not completed
while(PAL_doFadeStep());
PAL_waitFadeCompletion();
}

// wait 1 second
Expand Down

3 comments on commit 8ab25b2

@D0NM
Copy link
Contributor

@D0NM D0NM commented on 8ab25b2 Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops... i got a glitch at my side. (wrong palette during fading to 4 pals)
i'll report more later

@Stephane-D
Copy link
Owner Author

@Stephane-D Stephane-D commented on 8ab25b2 Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only difference I could see compared to old implementation is that it brings back CRAM dot at the beginning of the vblank area. It's a bit annoying but you only see these borders on old CRT (and not all of them).
If you meet an issue with it then don't hesitate to report with a small reproducible case if possible, thanks !

@werton
Copy link
Contributor

@werton werton commented on 8ab25b2 Oct 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stef, the behavior of the PAL_doFadeStep() function has changed. The body code of the PAL_doFadeStep() function is now always executed, even if PAL_doFadeStep() == FALSE and the colors accordingly continue to change, jumping over the target values.

Please sign in to comment.