#19019 - Pinski - Sat Apr 10, 2004 7:44 am
Now I hate to enter the community asking a question that has been answered many times before. However, I've spent a whole day trying to get this to work, searched this forum and the internet many times and read all the relevant posts, and read the Day 4 tutorial on The Pern Project website several times and I can not get fading to work. I've tried all of the versions of the fading code I have found on this site and others and haven't gotten it to work so I figured maybe someone would help me out.
I just want to have BG0 in Mode 0 fade out to black, so I can then load a new screen in BG0, and then fade in to the new screen.
I've been trying to use REG_BLDMOD and REG_COLEY to do this, however I can't get them to work. I could post some code, however I've attempted about five different ways of doing this and none of them have worked. I haven't even tried fading in yet because I can't get the fade out to work, I leave the registers as they are yet the screen is not faded out. I see no difference in the screen at all, it doesn't darken or anything. This is the first thing I have done on the GBA where I am completely lost and can not get anything to work at all. If anyone could post some full code that just fades BG0 in Mode 0 to black I'd greatly appreciate it. Please help!
#19020 - sgeos - Sat Apr 10, 2004 8:05 am
You could do a palette fade effect instead. I'd store a "master" palette in WRAM and have a function copy a darker and darker version of the "master" palette into VRAM each frame.
When the screen is all black, you are free to chage the screen data and the master palette and the execute the fade in effect- starting from black, copy a lighter and lighter version of the palette in each frame until you have the proper palette in RAM.
If you don't want a copy of your palette in WRAM all the time, you could copy the palette from VRAM to a local array at the start of a fade out routine.
-Brendan
#19025 - delbogun - Sat Apr 10, 2004 1:09 pm
I like the palette fade better than the hardware fade because with palette fade you can specify exactly which palettes you want to fade. But which fading technique is actually better to use if you want to consume less power and maybe do the fading faster?
#19028 - poslundc - Sat Apr 10, 2004 1:23 pm
| delbogun wrote: |
| I like the palette fade better than the hardware fade because with palette fade you can specify exactly which palettes you want to fade. But which fading technique is actually better to use if you want to consume less power and maybe do the fading faster? |
Hardware fading is much less CPU-intensive since it's done by the graphics coprocessor.
But, you've only got one alpha-effects register, so if you'd like to use it for other stuff then palette fading is the way to go.
If not, it doesn't hurt to use the effects register for it.
Pinski: People have been posting code to this thread. As for your stuff, you're going to have to post some code if you expect us to tell you what's wrong with it.
Dan.
#19055 - Pinski - Sat Apr 10, 2004 8:33 pm
As I said, I've read all those threads, including the one you linked to poslundc, and tried every solution in them. However, I know I'm a newb and I hate when people claim to do that stuff in my other community and they haven't. I want to use the built in fader because it's quicker and I'm fading sprites too. I know I didn't mention that in my original post because I thought I could figure that part out myself. However after the first post I realized it was important and I shouldn't have left it out.
Here's one of my solutions of code:
| Code: |
REG_BLDMOD = BIT00 | BIT04 | BIT06 | BIT07 | BIT13;
for( loop = 0; loop < 17; ++loop )
{
REG_COLEY = loop;
UpdateBackground(&bg0); //makes any changes to the bg struct get copied in to the apropriate registers
WaitForVsync();
} |
I can post other ways I've tried, but this one seems like it's the closest to being correct. I just want BG0 and sprites to fade to black in Mode 0.
#19062 - poslundc - Sat Apr 10, 2004 9:04 pm
Well, first of all, you don't need to set bit 13 in REG_BLDMOD, although I don't think that would affect your results.
Second of all, realize that your effect is lasting approximately 0.27 seconds before fading entirely to black, so it's entirely possible that it's happening faster than you can really notice.
Third of all, it is unclear what happens once you exit your for loop. What happens next? If that's the end of your program, it'll reset and keep resetting.
Fourth of all, it would be much more helpful if you told us what happens when you try running the code. If none of the above help, I'd advise being more specific in your query.
Good luck,
Dan.
#19076 - yaustar - Sat Apr 10, 2004 10:40 pm
my post in poslundc linked thread has a snipnet of code for both fading in and out which is taken out of our (me and a friend) demo. If it is not working for you then there is something else wrong within your code. If in doubt, post the entire main() procedure.
_________________
[Blog] [Portfolio]
#19078 - Pinski - Sat Apr 10, 2004 10:47 pm
I know I'm a newb and this is a commonly asked question. I'm sorry if I'm not being specific enough, but this seems to be a simple problem and I thought maybe just something was faulty in my code. I'll answer your suggestions as you posed them.
1) Turned off Bit 13 and it didn't effect anything.
2) I know my effect is lasting only for a short time. I put something in the code before like
| Code: |
for(x=0; x<30000; x++)
{} |
for a delay, but it doesn't matter how long the effect is. It still does nothing.
3) This happens within my getinput function. When the user presses up on the directional pad and goes to a new screen this code occurs and then another screen is loaded in the background. Here's the code:
| Code: |
if(!(*KEYS & KEY_UP))
{
if(screenY-2 >= 0)
{
//do some move sprite stuff omitted for length
}
else if(spriteY-2 >= 0)
{
if(spriteY-2 < 2 && currentMap > 2)
{
REG_BLDMOD = BIT00 | BIT04 | BIT06 | BIT07;
for( loop = 0; loop < 17; ++loop )
{
REG_COLEY = loop;
UpdateBackground(&bg0);
for(x=0; x<30000; x++)
{}
WaitForVsync();
}
if(currentMap==3)//currentMap is a variable that tells which Map the user is on
{
for(loop = 0; loop < 32*32; loop++) //32x32 tiles
bg0.mapData[loop] = UpLeftScreen[loop];
CreateCMap(UpLeftScreen); //creates the collision map for the new screen
if(NPC_Active==1)//check for computer sprites being active
{
sprites[1].attribute2 |= BIT10; //turns off computer sprites displayed
NPC_Active=0; //sets computer sprites to inactive
}
}
//check for other currentMap states
//change sprite, currentMap, and screen scroll variables and then return to the main game loop
}
|
4) I thought I mentioned what happens when I run this code. Absolutely nothing happens when this code is run, which is why I'm at a loss of what to do. Normally when the code is run without this, the sprite goes to the border of the screen, then the screen jumps to the top of the next screen as it loads, then the sprite appears in it's proper place at the bottom of the new screen. This all happens within a span of less than a second, however it's noticable to the naked eye.
With the code in place (with the delay timer in effect) the sprite moves to the top of the old screen, sits in place as the timer ticks down (all the while nothing happens on the screen, no fading in either direction of background or sprites, nothing), then the screen jumps to the top of the next screen as it loads, then the sprite appears in it's proper place at the bottom of the new screen. The only difference with the code and without the code is the length of time it takes.
I'm running the emulation on VisualBoy and have opened up the Memory and I/O viewers and have watched the registers change correctly. I have turned down my monitor refresh rate to 60Hz in order to see if it was a refresh problem, that didn't work. I have even loaded this onto the GBA to see if it was an emulation problem as talked about in other posts, and the effect doesn't work on the GBA either.
I'm totally at a loss of what to do next. The registers are changing in memory but no effect takes place on the screen.
If you need more details or more code I'd be happy to supply them. Thank you for your patients and your help.
#19081 - Pinski - Sat Apr 10, 2004 11:05 pm
yaustar: I tried your code again and changed it to be my specific functions and to eliminate the macros:
| Code: |
for(x = 0; x < 480; x++) //fade to black
{
WaitForVsync();
//if(!(*KEYS & KEY_A))
//{break;}
//set the transperancy of the first layer
REG_BLDMOD = (0x1 | 0 | 0xC0);
//source BG0, target backdrop, mode fade to black
REG_COLEY = x >> 4;
} |
Nothing happened. It worked the same as my code posted, however the delay was shorter.
My main function is kind of long, here's my declration of BG0 and of my main game function:
| Code: |
int main(void)
{
int index = 0; //some looping variables for loops :)
int move = 0;
int NPC_Check = 0;
u16 loop;
u16* temp;
SetMode(MODE_0 | OBJ_ENABLE | OBJ_MAP_1D | WIN1_ENABLE | BG1_ENABLE); //set mode 0
//omitted for length declaration of BG1 which is a background that is only displayed in a window for text purposes, window is always off unless talking to a computer controlled sprite
//omitted for length declaration of sprite[0] and sprite [1], sprite [0] is the player's sprite, sprite[1] is a computer controlled sprite
//Let us set up the backgroud two structure and enable the background
bg0.number = 0; //background number 0-3
bg0.charBaseBlock = 0;
bg0.screenBaseBlock = 31;
bg0.colorMode = BG_COLOR_256;
bg0.size = TEXTBG_SIZE_256x256;
bg0.mosiac = 0;
bg0.x_scroll = screenX;
bg0.y_scroll = screenY;
//This call enables the background with the suplied attributes and when it returns
//bg0.mapdata and tiledata will be valid pointers to the correct place
//for the map and tile data in VRAM
EnableBackground(&bg0);
//Now let us copy in the background tile palette
for(loop = 0; loop < 256; loop++)
BGPaletteMem[loop] = MapTilesPalette[loop];
//now for the actual tile graphics created by pcx2sprite
for(loop = 0; loop < (MapTiles_WIDTH*MapTiles_HEIGHT)/2 ; loop++)
bg0.tileData[loop] = MapTilesData[loop];
for(loop = 0; loop < 32*32; loop++) //32x32 tiles
bg0.mapData[loop] = LeftScreen[loop];
//Set current character position
charX = spriteX + screenX;
charY = spriteY + screenY;
char2X = sprite2X + screen2X;
char2Y = sprite2Y + screen2Y;
CreateCMap(LeftScreen);
while(1) //main game loop
{
GetInput(); //get input changes the x and y based on input
Lower_Left_NPC = (char2X/8)+(((char2Y+23)/8)+1)*32;
Lower_Right_NPC = ((char2X+15)/8)+(((char2Y+23)/8)+1)*32;
Upper_Left_NPC = (char2X/8)+(((char2Y+15)/8)+1)*32;
Upper_Right_NPC = ((char2X+15)/8)+(((char2Y+15)/8)+1)*32;
Lower_Left = (charX/8)+(((charY+23)/8)+1)*32;
Lower_Right = ((charX+15)/8)+(((charY+23)/8)+1)*32;
Upper_Left = (charX/8)+(((charY+15)/8)+1)*32;
Upper_Right = ((charX+15)/8)+(((charY+15)/8)+1)*32;
SquareCollision(); //detects collisions with background
MoveSprite(&sprites[0],spriteX,spriteY); //changes sprite atributes based on new x,y
MoveSprite(&sprites[1],sprite2X,sprite2Y);
if(NPC_Check>=150 && NPC_Active==1)
{
move=rand()%4;
if(move==0)
{
sprite2X += 8;
char2X += 8;
}
else if(move==1)
{
sprite2X -= 8;
char2X -= 8;
}
else if(move==2)
{
sprite2Y += 8;
char2Y += 8;
}
else if(move==3)
{
sprite2Y -= 8;
char2Y -= 8;
}
NPC_Collision();
MoveSprite(&sprites[1],sprite2X,sprite2Y);
NPC_Check=0;
}
else
NPC_Check++;
UpdateBackground(&bg0); //makes any changes to the bg struct get copied into the apropriate registers
WaitForVsync(); //waits for the screen to stop drawing
CopyOAM(); //Copies our sprite array into OAM.
}
} |
I hope I'm not overloading you guys with too much. I was trying to keep the code posts simple, however it doesn't seem to be going to well that way. Most of this stuff is code I learned from the Pern Project.
#19082 - poslundc - Sat Apr 10, 2004 11:21 pm
I couldn't tell where, in your main loop, the fading code gets executed.
Dan.
#19085 - Cearn - Sat Apr 10, 2004 11:44 pm
I had a similar problem where I could see the registers change, but nothing happened.
In the VBA menu, under Options/Video there is an option named "Disable SFX". If this is checked, mosaic/transparency and windowing will be disabled. Took me a while to figure that one out.
#19087 - yaustar - Sat Apr 10, 2004 11:48 pm
It be in GetInput then this code executes:
| Code: |
if(!(*KEYS & KEY_UP))
{
if(screenY-2 >= 0)
{
//do some move sprite stuff omitted for length
}
else if(spriteY-2 >= 0)
{
if(spriteY-2 < 2 && currentMap > 2)
{
REG_BLDMOD = BIT00 | BIT04 | BIT06 | BIT07;
for( loop = 0; loop < 17; ++loop )
{
REG_COLEY = loop;
UpdateBackground(&bg0);
for(x=0; x<30000; x++)
{}
WaitForVsync();
}
if(currentMap==3)//currentMap is a variable that tells which Map the user is on
{
for(loop = 0; loop < 32*32; loop++) //32x32 tiles
bg0.mapData[loop] = UpLeftScreen[loop];
CreateCMap(UpLeftScreen); //creates the collision map for the new screen
if(NPC_Active==1)//check for computer sprites being active
{
sprites[1].attribute2 |= BIT10; //turns off computer sprites displayed
NPC_Active=0; //sets computer sprites to inactive
}
}
//check for other currentMap states
//change sprite, currentMap, and screen scroll variables and then return to the main game loop
} |
_________________
[Blog] [Portfolio]
#19088 - poslundc - Sun Apr 11, 2004 12:11 am
If it's not what Cearn pointed out about the settings in VBA, I would recommend testing it without all of the conditional statements (just replace them with "if (1)" and comment out the current conditions) because those could easily be your problem.
Dan.
#19094 - Pinski - Sun Apr 11, 2004 2:07 am
I checked the "Disable SFX" option and it was turned off. I didn't think this would be the problem because I've loaded both of these examples up on the GBA and they didn't run either.
I tried both my original implementation and the one I posted of yaustar's modified code with the conditionals changed just like poslundc stated, however that didn't change anything either. The conditionals are just a big else if statement to check which screen you are currently in so it can adjust the next screen accordingly.
I'm completly stumped and have no idea where to go next.
Thanks for all the help and patients any way.
#19096 - bats - Sun Apr 11, 2004 4:36 am
Just some suggestions:
Check in VBA to see if the Registers are being changed (under I/O viewer).
Do some tests to see that the code is being executed (using debug printf, or just change a palette entry that you know will be observable)
Check your REG_BLDMOD and REG_COLEY definitions (or whatever you call them) they shoud be something like:
| Code: |
#define REG_BLDMOD *(vu16 *)(0x04000050)
#define REG_COLEY *(vu16 *)(0x04000054)
|
#19101 - Pinski - Sun Apr 11, 2004 6:57 am
Both registers are defined correctly and the changes in the registers occur when the code is run in both Memory Viewer and I/O viewer as I've said before. Thanks any way.
#19102 - Pinski - Sun Apr 11, 2004 8:39 am
I got it to work in a simpler demo. Now I just have to translate it over. Cross your fingers.
#19103 - Pinski - Sun Apr 11, 2004 9:14 am
Ok, I finally figured it out. For some reason, when you declare a window, it messes with the fading. It's not the actual window code, because the fade works with that. It's the actual setting of the window in the REG_DISPCNT register. So what I did is subtracted the value of windows enable, fade, and then add the windows enable.
I can't believe that was the problem. Well thanks for all of the help and sorry to cause such a headache as a newb. Thanks again and here's my final fade code that works:
| Code: |
REG_BLDMOD = BIT00 | BIT04 | BIT06 | BIT07;
REG_DISPCNT -= 0x2000;
for(y = 0; y < 17; ++y)
{
REG_COLEY = y;
for(z=0; z<30000; z++)
{}
WaitForVsync();
}
REG_DISPCNT += 0x2000; |
#19105 - bats - Sun Apr 11, 2004 12:03 pm
Hmm... sorry, missed you mention the I/O stuff. Good to see you figured it out.
Just to save you some headaches...
In general you don't want to subtract from bitfields. If, for example, REG_DISPCNT does not have bit 13 set (0x2000) subtracting 0x2000 will change other bits -- probably not what you want.
Instead use: | Code: |
REG_DISPCNT &= ~0x2000; // this clears bit 13
|
and | Code: |
REG_DISPCNT |= 0x2000; // this sets bit 13
|
if you know that window 0 is always going to be on when you execute this code, you can leave it as subtract -- but you might as well get into the habit of using | and & when modifying bitfields.
#19106 - Cearn - Sun Apr 11, 2004 12:35 pm
You could also try this:
Bits 1<<5 and 1<<13 of the REG_WIN_IN and REG_WIN_OUT registers regulare the blending in the windows. If you set those blending will occur as usual.
I always wondered what those did.
#19132 - Pinski - Sun Apr 11, 2004 8:39 pm
The window blending did the trick. Not only does my fading work now, but it cleared up another glitch I had. Thanks!
Final Fade Out Code:
| Code: |
REG_BLDMOD = BIT00 | BIT04 | BIT06 | BIT07;
for(y = 0; y < 17; ++y)
{
REG_COLEY = y;
for(z=0; z<5000; z++)
{}
WaitForVsync();
} |
Final Fade In Code:
| Code: |
REG_BLDMOD = BIT00 | BIT04 | BIT06 | BIT07;
for(y = 16; y >= 0; --y)
{
REG_COLEY = y;
for(z=0; z<30000; z++)
{}
WaitForVsync();
} |
Window setting code:
| Code: |
REG_WININ = WIN0_BG0 | WIN0_SPRITES | WIN0_BLENDS;
REG_WINOUT = WINOUT_BG0 | WINOUT_SPRITES | WINOUT_BLENDS; |
I only have one window active as of now.
Thanks to everyone that helped.