gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Newbie requires help...

#18873 - cheech - Wed Apr 07, 2004 4:48 pm

Hi,

I'm just trying to code a simple fade to black, fade in from black. The fade TO black works but the fadeIn doesn't. Any ideas?

Here's the code...

Code:
#include "gba.h"
#include "screenmodes.h"
#include "test.h"

u16* theVideoBuffer = (u16*)VideoBuffer;
u16* theScreenPalette = (u16*)BGPaletteMem;
u16* theBackBuffer = (u16*)BackBuffer;
u32  frames = 0;

#define RGB(r,g,b)(r+(g<<5)+(b<<10));
#define VCOUNT (*(volatile u16 *)0x04000006)

void WaitForVsync() { 
  while(VCOUNT != 160) ;
  while(VCOUNT != 161) ;
  frames++;
}

void Flip() {
   if (REG_DISPCNT & BACKBUFFER) {
      REG_DISPCNT &= ~BACKBUFFER;
      theVideoBuffer = theBackBuffer;
   } else {
      REG_DISPCNT |= BACKBUFFER;
      theVideoBuffer = theBackBuffer;
   }
}


void fadePaletteToBlack(void) {
   u16 i, r, g, b, col;
   for (i=0;i<256;i++) {
      col = theScreenPalette[i];
      r = (col & 0x000F);
      g = (col & 0x03E0) >> 5;
      b = (col & 0x7C00) >> 10;
      if (r > 0)
         r--;
      if (g > 0)
         g--;
      if (b > 0)
         b--;
      col = RGB(r, g, b);
      theScreenPalette[i] = col;
   }
}

void blankPalette(void) {
   u16 i;
   for (i=0;i<256;i++) {
      theScreenPalette[i] = 0x00;
   }
}

void fadePaletteIn(void) {
   u16 i, r, g, b, col;
   for (i=0;i<256;i++) {
      col = theScreenPalette[i];
      r = (col & 0x000F);
      g = (col & 0x03E0) >> 5;
      b = (col & 0x7C00) >> 10;

      if (r < (testPalette[i] & 0x000F))
         r++;
      if (g < ((testPalette[i] & 0x03E0) >> 5))
         g++;
      if (b < ((testPalette[i] & 0x7C00) >> 10))
         b++;
      col = RGB(r, g, b);
      theScreenPalette[i] = col;
   }
}

int main() {
   SetMode(SCREENMODE4 | BG2ENABLE);
   u16 i;

   for (i=0;i<256;i++) {
      theScreenPalette[i] = testPalette[i];
   }
   u16* tempData = (u16*)test;
   u16 x, y;

   for (x=0;x<240*160;x++)   {
      theBackBuffer[x] = tempData[x];
   }
   while(1) {
      WaitForVsync();
      if (frames == 1) {
         Flip();
      }
      if (frames > 50) {
         fadePaletteToBlack();
         WaitForVsync();
         WaitForVsync();
      }
      if (frames > 2000) {
         fadePaletteIn();
         WaitForVsync();
         WaitForVsync();
      }
   }
   return 0;
}



Thanks in advance.
Cheech.

#18876 - poslundc - Wed Apr 07, 2004 6:24 pm

Three notes:

1. When masking for the red component of the colour, you need to use 0x001F, not 0x000F. This error would make your image lack saturation in the red channel when fading up.

2. The effect you're creating isn't really a fade in the strictest sense. You should use fixed-point math so that all components of all colours reach either zero (black) or their destination at exactly the same time.

3. How long did you wait for the fade up to begin? If you wait for the frames variable to reach 2000, it will be over 30 seconds before the fade up starts.

It would be much more helpful if you told us what actually happens (ie. what goes wrong) when you try the fade.

Dan.

#18886 - Lupin - Wed Apr 07, 2004 7:38 pm

You can also check out the gba blending, it does a pretty good job on fading from/to black...

Code:

//This will kick the timer
c=0;
FadeOut = true;
REG_BLDMOD = 0xD4;
REG_TM1CNT = (TIMER_ENABLE | FREQUENCY_64 | TIMER_IRQ);

//Use this as timer interrupt handler
void DoFade(void) {
    if(FadeIn) {
        REG_COLEY=c;
        c--;
           
        if(c <= 0) {
            //Deactivate fade
            FadeIn = false; FadeOut = false;
            //Do something after the fade...
            //???
            REG_BLDMOD = BIT10 | 1<<6; //disable fade
            DisableInterrupts(INT_TIMMER1); //disable timer
        }
    } else if(FadeOut) {
        REG_COLEY=c;
        c++;
           
        if(c >= 17) {
            //we finished fading out (now we can load or do other stuff)
            FadeIn = true; FadeOut = false;
        }
    }
    REG_TM1D = 32768;   //make timer faster :)
}

_________________
Team Pokeme
My blog and PM ASM tutorials

#18923 - cheech - Thu Apr 08, 2004 10:17 am

poslundc:

It just never seems to fade back in. I've downed the frames too. It seems as if the palette is fading to is all black or something?

lupin:

Thanks, but could you give me a complete example for this? I can't figure out how this would fit into my existing code?

Thanks!
Cheech.

#18937 - poslundc - Thu Apr 08, 2004 2:18 pm

Well, now that I give your program a second look, anothe problem that stands out is that every frame will execute both fadePaletteToBlack() and fadePaletteIn(), so they will cancel each other out.

Because, you know, if frames > 2000, frames is also > 50.

You should do something about that.

Dan.

#18938 - MayFly - Thu Apr 08, 2004 2:20 pm

Hi Cheech,

It's generally easier to use the gba?s hardware (as has been suggested before by setting up the appropriate registers correctly ? commonly? known as REG_BLMOD and REG_COLY) to implement to fade in/out effects.

You may want to check out this thread too as it touches on your query:

http://forum.gbadev.org/viewtopic.php?t=1654&highlight=

At any rate here?s one way to do the Fade In effect:

/********************************************************************/
/* The background fades from black, the delta parameter specifies */
/* how many frames the REG_COLY will stay at a constant value. */
void FadeIn( u16 delta )
{
/* Setting the Reg for fading effect */
REG_BLDMOD = 0x1FDF;

u16 loop;
u32 fade_out_frame_count = 0;

/* The GBA has 16 levels of darkness/lightness */
for( loop = 17; loop > 0; --loop )
{
fade_out_frame_count = global_frame_count + delta;

REG_COLY = loop;

while( fade_out_frame_count > global_frame_count )
{
/* wait */
}

}
} /* End function FadeIn */

P.S. Remember do not play with your palettes (at least when it comes to wanting to fade in/out an entire screen).

#18943 - poslundc - Thu Apr 08, 2004 2:45 pm

MayFly wrote:
P.S. Remember do not play with your palettes (at least when it comes to wanting to fade in/out an entire screen).


Why not? I do almost all of my fading in/out exclusively with palette effects. It also lets me do things that can't be done with hardware blending, like colour multiplication (so I can, for example, make a scene fade to black except for the red compenent for a really strong fire effect or what have you).

I say unless you don't have any other use for it, save the hardware effects register for cooler alpha-blending stuff.

Dan.

#18946 - cheech - Thu Apr 08, 2004 4:17 pm

Cheers everyone. I've now (finally!) got it sorted using the REG_POSY as mentioned by MayFly.

Thanks again everyone!!!
Cheech

#18951 - MayFly - Thu Apr 08, 2004 4:47 pm

Hi Dan,

Aye! Fair enough. I should clarify my previous post script statement.

If you only want to implement a UNIFORM fade in/out effect on an entire screen I recommend using the hardware to do it.

As you say, if you want to do something more complicated; playing with the palettes is the way to go.

I guess it all depends on how one defines a fade in/out.

MayFly

#18963 - yaustar - Thu Apr 08, 2004 7:34 pm

I did a fade in / out effect on my intro, doing it by hardware is the easiest in my opionion.

Code:
for(int a = 0; a < 480; a++) //fade to black
        {
            WAIT_VSYNC();
            //if(!(*KEYS & KEY_A))
            //{break;}
            //set the transperancy of the first layer
            SET_BLENDING(BLEND_BG0, 0, DARKEN);
            //source BG0, target backdrop, mode fade to black
            REG_COLEY = a >> 4;
        }

        for(int a = 480; a > 0; a--) //fade to normal colour
        {
            WAIT_VSYNC();
            //if(!(*KEYS & KEY_A))
            //{break;}
            //set the transperancy of the first layer
            SET_BLENDING(BLEND_BG0, 0, DARKEN);
            //source BG0, target backdrop, mode fade to black
            REG_COLEY = a >> 4;
        }


And the header file
Code:
#include "gba.h"

#define SOURCE_SHIFT(n) ((n) << 0)
#define TARGET_SHIFT(n) ((n) << 8)

//REG_BLDMOD supplement header file by yaustar 02/10/2003

#define BLEND_BG0 0x1
#define BLEND_BG1 0x2
#define BLEND_BG2 0x4
#define BLEND_BG3 0x8

#define BLEND_SPRITES 0x10
#define BLEND_BACK 0x20

#define ALL_OFF 0x0
#define ALPHA_BLEND 0x40
#define LIGHTEN 0x80
#define DARKEN 0xC0

#define SET_BLENDING(s,t,m) REG_BLDMOD = (SOURCE_SHIFT(s) | TARGET_SHIFT(t) | m)

//REG_COLEV supplement header file by yaustar 02/10/2003
//eg of usage SET_BLENDING(BLEND_BG0, BLEND_BG1, ALPHA_BLEND);

#define SET_COEFF(s,t) REG_COLEV = (SOURCE_SHIFT(s) | TARGET_SHIFT(t))
//s + t MUST equal to 16 or <16 for a darkening effect or >16 for a lighting effect

//key: s = source, t = target, m = mode

_________________
[Blog] [Portfolio]