#47631 - Fatnickc - Mon Jul 11, 2005 4:23 pm
I know that there have been heaps of posts asking how to do fading, but I realy can't do it at all. I've tried so many things, and, after looking at CowBite, thought I had it. However, changing the value of REG_BLDMOD or REG_COLEY, turned one pixel black each. I'm using Mode 4, and, I know this is being incredibly lazy, but, can anyone just show me some source which works, so I can understand how and why, and then make my own function for it?
Thanks, Fatnickc.
EDIT : Please, I'm really at a lost end here.
#47690 - Crs - Tue Jul 12, 2005 12:25 pm
Hi,
Perhaps you could just step down/up all your palettes rather than using BLDMOD.. I would think this would help with fading any sprites too.
All I can suggest is check your target and source backgrounds are the right way around, and that you are using the correct blend mode.. I dont have any code to share but if you can post some I may beable to spot why its not functioning correctly.
Also ensure your backgrounds have mosaic enabled.. (never used mode 4 so maybe thats a reason?)
Cheers
Chris
#47696 - Cearn - Tue Jul 12, 2005 1:00 pm
A very simply fade to white for mode 4. You'll have to change the names to whatever you're used to, but I hope it's pretty clear. A fade works on the top layers (REG_BLDCNT{0-5}), not on the bottom layers (REG_BLDCNT{8-D}), maybe that was the problem. Also, you probably need to include the backdrop too, otherwise 0-pixels will shine through, which is probably undesireable.
Code: |
// blend build macro: top layer, source layer, blend mode
#define BLD_BUILD(_top, _bot, _mode) \
( (_top) | (((_mode)&3)<<6) | ((_bot)<<8) )
int main()
{
REG_DISPCNT= DCNT_MODE4 | DCNT_BG2_ON;
// fill the screen with random pixels (replace with image, of course)
int ii;
for(ii=0; ii<256; ii++)
pal_bg_mem[ii]= rand();
for(ii=0; ii<120*160; ii++)
vid_mem[ii]= rand();
// set blend mode:
// top=bg2 and backdrop
// bottom= none
// fade to white (mode=2)
// (REG_BLDCNT == REG_BLDMOD)
REG_BLDCNT = BLD_BUILD((1<<2)|(1<<5), 0, 2);
// ey denotes fade level. (Well, ey denotes 8*fade level,
// because I don't want the fade to be too fast)
u32 ey=0;
while(1)
{
vid_vsync();
REG_BLDY= ey>>3; // REG_BLDY == REG_COLEY (yeah overflow, so what?)
ey++;
}
return 0;
}
|
And like Chris said, modifing the palette itself will work too (mosaic isn't required, though).
#47707 - Fatnickc - Tue Jul 12, 2005 4:10 pm
I don't even have some of those definations, so that'sprobably where I'm going wrong. Perhaps you could provide me with the definations of all the REGs, so I can at least run it?
#47726 - tepples - Tue Jul 12, 2005 8:18 pm
There are all sorts of 'gba.h' files floating around.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#47728 - Fatnickc - Tue Jul 12, 2005 8:30 pm
Yes, and they are all different.
#47729 - tepples - Tue Jul 12, 2005 8:45 pm
They're all different, but they are similar. You can usually resolve naming differences by checking against GBATEK or the CowBite spec. Recent code may be written against the header files that come with libgba, which is available from the same place where you got devkitARM.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#47779 - Fatnickc - Wed Jul 13, 2005 10:38 am
Thank you tepples, and thank you Cearn. When I'm back on the fast computer sometime soon(search around..). I'll add to me header files, as appropriate, and then attempt the above code.
Cearn, is the vid_mem just the bg_mem? So, if you use pcx2gba, it's the first part, right?
Following what CowBite and GBATEK say, the REGs I was stuck on are just the same as some of the other ones. However, this results in 'warning : assignment of read only memory'. I can understand this, but it must be the way I make REG_BLDCNT and REG_BLDY the same as REG_BLDMOD and REG_COLEY respectively. At the moment I just define them as each other, and think this is wrong. However, saying
Code: |
REG_BLDY == REG_COLEY |
doesn't work either, with an error from the compiler. What am I to do?
#47803 - Quirky - Wed Jul 13, 2005 7:48 pm
Code: |
#define REG_COLEY *(volatile u16*)0x4000054
|
That's what my gba.h has, taken many moons ago from the pern project.
#47815 - Fatnickc - Wed Jul 13, 2005 9:17 pm
Urrm.. I wasn't looking for that one though..
#47889 - Fatnickc - Thu Jul 14, 2005 9:17 am
I've just tried another method, which doesn't work either.
I'm going to post my code here, and can you test it to see if it works with you?
Code: |
#include "gba.h"
#include "bg.h"
void SleepQ(int i)
{
int x, y;
int c;
for (y = 0; y < i; y++)
{
for (x = 0; x < 4000; x++)
c = c + 2; // do something to slow things down
}
}
//******************************************************************************
void fadeout( u32 aWait )
{
s8 Phase;
REG_BLDMOD = 0 | 1 | 2 | 4 | 8 | 128 | 64 | 32;
for( Phase = 0; Phase < 17; Phase++ )
{
REG_COLEY = Phase;
SleepQ( aWait );
}
}
//******************************************************************************
void fadein( u32 aWait )
{
s8 Phase;
REG_BLDMOD = 0 | 1 | 2 | 4 | 8 | 128 | 64 | 32;
for( Phase = 0; Phase < 16; Phase++ )
{
REG_COLEY = 16-Phase;
SleepQ ( aWait );
}
}
u16 loop;
int main()
{
SetMode(MODE_4 | BG2_ENABLE | OBJ_ENABLE | OBJ_MAP_1D);
for (loop = 0; loop < 256; loop++) {
BG_PaletteMem[loop]=bgPalette[loop];
}
for (loop = 0; loop < (120*160); loop++) {
FrontBuffer[loop] = bgData[loop] ;
}
fadeout(10);
return 0;
}
|
Is it the way in which I assign my background which is wrong?
What this currently does is turn 2 pixels at the top, to the left of the center black, and then a while later flash back to white, then go black again straight away.
This is similar to what other methods have resulted in, except for now the pixels flash.
I'm fairly sure that I am at fault, and not the methods, as so many have not seemed to work, producing the same results.
#47890 - headspin - Thu Jul 14, 2005 10:10 am
Check out the site in my sig, there is some basic fade-in/out code there. It worked for me! :)
_________________
Warhawk DS | Manic Miner: The Lost Levels | The Detective Game
#47891 - Fatnickc - Thu Jul 14, 2005 10:23 am
Thank you, that works! However, it doesn't fade all the way down to black. I think this may be to do with what I set fade to. What did you set it to?
#47958 - Cearn - Fri Jul 15, 2005 10:51 am
Fatnickc wrote: |
Thank you tepples, and thank you Cearn. When I'm back on the fast computer sometime soon(search around..). I'll add to me header files, as appropriate, and then attempt the above code.
Cearn, is the vid_mem just the bg_mem? So, if you use pcx2gba, it's the first part, right?
|
vid_mem is VRAM pointer is (u16*)0x06000000. I usually use my own headers/library. This includes a page on blending which I've pointed to in other threads as well, so I thought you'd seen it already.
Quote: |
Following what CowBite and GBATEK say, the REGs I was stuck on are just the same as some of the other ones. However, this results in 'warning : assignment of read only memory'. I can understand this, but it must be the way I make REG_BLDCNT and REG_BLDY the same as REG_BLDMOD and REG_COLEY respectively. |
This usually works:
Code: |
#define REG_BLDCNT REG_BLDMOD
#define REG_BLDY REG_COLEY
|
Or the other way around, depending on which ones you have in your own header files.
Quote: |
Code: | void SleepQ(int i)
{
int x, y;
int c;
for (y = 0; y < i; y++)
{
for (x = 0; x < 4000; x++)
c = c + 2; // do something to slow things down
}
} |
|
If you have any level of optimisation on, this probably won't work at all. Since variable c isn't used anywhere else, c= c+2 (commonly referred to as c+=2), will be optimised out. Since the x loop doesn't do anything then either, it is optimised out as well. Since the y loop will be empty at that point as well, it too will go and the function will be a complete no-op. If you want to wait a while, use a vsync or a timer or something like that.
Quote: |
Code: | void fadein( u32 aWait )
{
s8 Phase;
REG_BLDMOD = 0 | 1 | 2 | 4 | 8 | 128 | 64 | 32;
for( Phase = 0; Phase < 16; Phase++ )
{
REG_COLEY = 16-Phase;
SleepQ ( aWait );
}
} |
|
The fade out seems ok, but at the end of fade in REG_COLEY will be set to 1. The loop ends at 15 after all. Oh, and don't use non-word types as local variables.
If you're now using headspin's fade out:
Code: |
void fade_out()
{
while (fade != (16<<1))
{
fade++;
FadeIn((fade>>2));
WaitVBlank();
}
}
|
Note that the maximum value of fade is 31. The maximum value passed to FadeIn is fade/4 = 7, which is about half a fade. Also, note that in neither fade_in nor fade_out the fade variable ever gets a value, is this supposed to be a global variable? (Hmm, since it's not even declared there, probably)
And @headspin, why use Code: |
u16 *reg_BLDMOD = (u16 *)0x4000050;
reg_BLDMOD[0]= ...;
|
when Code: |
#define REG_BLDMOD (*(volatile u16*)0x04000050)
REG_BLDMOD= ...;
|
is easier for users, doesn't create an extra variable for the register and is possibly safer due to the volatile?
#47962 - Fatnickc - Fri Jul 15, 2005 11:58 am
Yes, I already had it as a global variable, I was just wondering what to set it as..
Anyway, with a few tweaks I got headspin's method down to going all the way down to black. Also, at the same time, I worked out how to do a fairly simple wipe from the top, which works nicely. Thanks headspin for the method, and thanks cearn for the insight ;).
Now, I'd like to know about lightening the image. I assumed that if you changed the fade_in function to continue for longer than until it was back to normal, you would have a fade to white, but this doesn't work, instead changing to black as soon as it has reached normal and tries to proceed.
What changes could one make to the fade_in (or indeed fade_out) to make it go to white?
#48132 - Quirky - Sun Jul 17, 2005 12:34 pm
For fading and "whiting" I use the following:
Code: |
void screen_fade(int level)
{
if (level > 16)
level = 16;
if (level < 0)
level = 0;
REG_BLDMOD = BLDMOD_FIRST_BG1 | BLDMOD_FIRST_BG0 | BLDMOD_FIRST_BG2|
BLDMOD_FIRST_OBJ | BLDMOD_SECOND_BD | BLDMOD_MODE(3);
REG_COLEY = level;
}
void screen_fade_out()
{
int loop;
for (loop = 0; loop < 17; loop++) {
wait_vsync_int();
screen_fade(loop);
}
}
void screen_fade_in()
{
int loop;
for (loop = 0; loop < 17; loop++) {
wait_vsync_int();
screen_fade(16-loop);
}
}
void screen_white(int level)
{
if (level > 16)
level = 16;
if (level < 0)
level = 0;
REG_BLDMOD = BLDMOD_FIRST_BD
| BLDMOD_MODE(2);
REG_COLEY = level;
}
void screen_white_out()
{
int loop;
for (loop = 0; loop < 17; loop++) {
wait_vsync_int();
screen_white(loop);
}
}
void screen_white_in()
{
int loop;
for (loop = 0; loop < 17; loop++) {
wait_vsync_int();
screen_white(16-loop);
}
}
|
All the details of which bits you should set, in case you don't have the defines, are here:
Cowbite effects registers descriptions