#15285 - qw3rty - Tue Jan 20, 2004 1:14 pm
I have a little problem with the speed of my code.
I try to do a raster-scrolling-effect (scroll the even lines to the left, the odd`s to the right)
My code is fast enough, but as soon I put it into an "if" - statement, like this :
if (bg0)
{
(scroll-code for BG0)
}
if (bg1)
{
(scroll-code for BG1)
}
.
.
.
the code doesn`t run fast enough to switch the scroll-pos depending on the line (the lines scroll randomly to the left/right).
I don`t get it why this if-statement slows things down (it should have NOTHING to do with my code inside the if ?!)
This isn`t a real problem though - enabling compiler optimization (-Os is enough) makes it fast enough - but I am curious how to optimize this switch.
#15286 - MumblyJoe - Tue Jan 20, 2004 1:24 pm
I have two suggestions...
If your test conditions are constants or numbers (not variables) use a switch/case statement instead, I have never really looked into the difference in generated code but I have heard that good compilers can optimise them better.
Also you could try an if/else instead of an if/if, once again I havent examined the code output but i can imagine if you are only testing two conditions that this would be better.
could you post what code you use entirely so we could see if there is anything else that may be the cause?
_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!
#15288 - qw3rty - Tue Jan 20, 2004 1:42 pm
I already tried a switch instead of if`s....in fact i replaced the switch with the if`s, cause a friend of mine suggested to try this to speed things up...
Code: |
void scroll_BG_EXT2(TILE_Bg* text1, u8 bg_n) //scrolls BG_n 256pixels left/right (to next screen)
{
s16 x_scroll;
u8 i;
s16 x_scroll_old = text1[0].x_scroll;
if (bg_n == 0)
{
if (x_scroll_old == 0)
{
for (i = 0; i smaller 256/8;i++)
{
while (REG_VCOUNT != 160)
{
while ((*DISPSTAT & BIT1) == 0);
{
if ((REG_VCOUNT & BIT0) !=0) //even line
{
x_scroll=(i sh_left 3);
}
else //odd line
{
x_scroll=-(i sh_left 3);
}
}
REG_BG0HOFS = x_scroll;
}
if (REG_VCOUNT == 160)
{
updateSpritesAnim();
}
}
}
else //screen 2 / x_scroll_old = 256
{
for (i = 256/8; i greater 0;i--)
{
while (REG_VCOUNT != 160)
{
while ((*DISPSTAT & BIT1) == 0);
{
if ((REG_VCOUNT & BIT0) !=0) //even line
{
x_scroll=-(i sh_left 3);
}
else //odd line
{
x_scroll=+(i sh_left 3);
}
}
REG_BG0HOFS = x_scroll;
}
if (REG_VCOUNT == 160)
{
updateSpritesAnim();
}
}
}
} //if bg_n == 0 end
.
.
.
}
|
err...don`t be to confused about the "smaller" and "sh_left" stuff - the "> / <" keys aren`t working on my keyboard ;)
I have 3 more if-statements, that are activated for bg1...bg3 with the exact same code (only the REG_BGxOFFSET's are replaced with the proper ones)
I think I could disable the "if (x_scroll_old == 0)" statement ...[/code]
#15289 - qw3rty - Tue Jan 20, 2004 1:59 pm
I ereased the if "(x_scroll_old == 0)" switch - resulting in non-functional, STILL to slow code....
#15291 - ampz - Tue Jan 20, 2004 2:29 pm
Why the "if (bg_n == 0), if (bg_n == 1), if (bg_n == 2), if (bg_n == 3)" ?
As far as I can see, this code only scrolls one background at a time.
Are thoose if statements just there for added flexibility?
Your problem is in the scroll code... You wait for HBlank, but you never check that you have left HBlank before you calculate the next scroll value.
Also, you may want a check to make sure you start scrolling at the beginning of a frame.
I'd suggest something like this: (untested code)
Code: |
for (i = 0; i smaller 256/8;i++) {
while (REG_VCOUNT != 227); //Wait for the start of a frame.
while (REG_VCOUNT != 160) {
while ((*DISPSTAT & BIT1) == 1); //Wait until we have left HBlank
//Precalculate next scroll value while the current line is drawn
if ((REG_VCOUNT & BIT0) !=0) //Even line
x_scroll=(i sh_left 3);
else //Odd line
x_scroll=-(i sh_left 3);
while ((*DISPSTAT & BIT1) != 1); //Wait for HBlank
REG_BG0HOFS = x_scroll;
}
updateSpritesAnim();
}
|
#15292 - qw3rty - Tue Jan 20, 2004 3:14 pm
You`re right, the "if`s" are only for added flexibility...in fact I only use this function to scroll one particular BG (always BG1).
Now I see the problem :
I was doing all the work in HBLANK, but could have done the calculation of the offset outside the HBLANK.
Actually my code even attempted to scroll the BG multiple times in ONE hblank-phase ;)
Thanks for the advice :D
#15294 - qw3rty - Tue Jan 20, 2004 3:31 pm
It`s working now :D
Code: |
void scroll_BG_EXT2(TILE_Bg* text1, u8 bg_n) //scrolls BG_n 256pixels left/right (to next screen)
{
s16 x_scroll;
u8 i;
s16 x_scroll_old = text1[0].x_scroll;
if (bg_n == 0)
{
for (i = 0; i smaller 256/8;i++)
{
while (REG_VCOUNT != 160)
{
while ((*DISPSTAT & BIT1) == 0) // <---removed semicolon (D'OH !)
{ //<--- are these two {}'s ignored with the semicolon ?
if ((REG_VCOUNT & BIT0) !=0) //even line
{
x_scroll=(i sh_left 3);
}
else //odd line
{
x_scroll=-(i sh_left 3);
}
while ((*DISPSTAT & BIT1) ==0); // <---added
} //<--- are these two {}'s ignored with the semicolon ?
REG_BG0HOFS = x_scroll;
while ((*DISPSTAT & BIT1) != 0); // <---added
}
if (REG_VCOUNT == 160)
{
updateSpritesAnim();
}
}
} //if bg_n == 0 end
.
.
.
}
|
I removed a semicolon (I think the {...} were ignored, correct me if I`m wrong ;)) and added two waits - one for the HBLANK to occur another for the finish of HBLANK ;)
#15307 - ampz - Tue Jan 20, 2004 7:29 pm
Yeah, now you messed it up real good :-)
If you look at my code... first I wait until we have left HBlank. Then I do the calculation, wait for Hblank, enter the new scroll value, and then I go back waiting for the GBA to leave HBlank.
You have one "while" more than you need. And the {} should not be there at all.
#15359 - qw3rty - Wed Jan 21, 2004 11:48 am
Thanks for the help ampz :D
I think every unnecessary "while" is cut out now...