#5592 - Link - Fri May 02, 2003 2:54 pm
I'm proving the .bin file of tutorial33.zip of pernproject...
(i'm learning how show sprite on GBA and move)
But moving the sprite in that .bin example i can see a bad blur of image:
When i move the image it became blurry, in the movement i see it not correctly (like bleary)...
Instead if i try commercial game it don't happen..
What does depend it by?
#5610 - pollier - Sat May 03, 2003 4:10 am
Make sure your emulator is running at full speed, and maybe turn on V-Sync if you're using, say, VBA. Or does this problem occur on hardware? If so, the code isn't waiting for the V-Blank to update the position. Be sure to update your OAM after scanlines have finished to avoid shearing.
_________________
(Works for me!)
#5612 - Link - Sat May 03, 2003 8:47 am
Quote: |
Make sure your emulator is running at full speed, and maybe turn on V-Sync if you're using, say, VBA. |
i don't think it depend by that, because i have the some configuration of emu with commercial rom, and blurry don't happen with them.
can u explain? What is V-blank?
Update? i do see you the code:
Code: |
/********************************************************
*
*
* by devoto
*
*
********************************************************/
#include<math.h>
#include"gba.h"
#include"screenmode.h"
#include"keypad.h"
#include"sprite.h"
#include"sprite1.h"
#define FIXED s32
#define PI 3.14159
#define RADIAN(n) (((float)n)/(float)180*PI)
///declare our functions so the c compiler knows what we are talking about
void InitializeSprites(void);
void WaitForVsync(void);
void CopyOAM(void);
void GetInput(void);
void MoveSprite(OAMEntry* sp, int x, int y);
void RotateSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale);
///these are global so i do not have to pass them to GetInput
s16 x = 10;
s16 y = 10;
u16 char_number = 0;
FIXED angle = 0;
FIXED zoom = 1<<8;
FIXED SIN[360];
FIXED COS[360];
///main entry point from the boot.asm startup file
int main(void)
{
int index = 0; //some looping variables for loops :)
u16 loop;
for(loop = 0; loop < 360; loop++)
{
SIN[loop] = (FIXED)(sin(RADIAN(loop)) * 256); //sin and cos are computed and cast to //fixed
COS[loop] = (FIXED)(cos(RADIAN(loop)) * 256);
}
SetMode(MODE_2 | OBJ_ENABLE | OBJ_MAP_1D); //set mode 2 and enable sprites and 2d mapping
for(loop = 0; loop < 256; loop++)
OBJPaletteMem[loop] = sprite1Palette[loop]; //loop through and store the palette from your pict
//palette into obj palette mem OBJPaletteMem is
//defined in gba.h. sprite1Palette is from
//pcx2gba tool sprite1.h.
InitializeSprites(); //set all 128 sprites to offscreen
//this is were we define our sprite atributes for the first sprite
//256 color 64x64 sprite that starts at character 0. Character 0 is
//the first sprite data memory location.
sprites[0].attribute0 = COLOR_256 | SQUARE| ROTATION_FLAG | y;
sprites[0].attribute1 = SIZE_64 |ROTDATA(0)|x;
sprites[0].attribute2 = char_number;
//allright now to copy in the sprites bitmap. The data in sprite1Data is allready striped
//so we just copy it in one row of tiles at a time. The only difference between this and a
//2D sprite is that we would need to keep in mind the fact that the tiles are not all in a row.
//We could just use one big for loop. There are 8 rows (64x64 = 8x8 tiles) so we loop through
//all 8. There is 512 bytes per row (8 tiles * 8x8 = 512) but since we copy 2 bytes at a
//time that equals 256. The width of char memory is 32 * 8x8 = 1024 (512 double bytes).
//
for(index = 0; index < 256*8; index++)
{
OAMData[index] = sprite1Data[index];
}//end index loop
///Main Game loop
while(1)
{
GetInput(); //get input changes the x and y based on input
MoveSprite(&sprites[0],x,y); //changes sprite atributes based on new x,y
RotateSprite(0,angle,zoom,zoom);
WaitForVsync(); //waits for the screen to stop drawing
CopyOAM(); //Copies our sprite array into OAM.
}
}
////Set sprites to off screen
void InitializeSprites(void)
{
int loop;
for(loop = 0; loop < 128; loop++)
{
sprites[loop].attribute0 = 160; //y to > 159
sprites[loop].attribute1 = 240; //x to > 239
}
}
//wait for the screen to stop drawing
void WaitForVsync(void)
{
//lets get rid of htat inline asm we used in arm
/*
__asm
{
mov r0, #0x4000006 //0x4000006 is vertical trace counter; when it hits 160 //160 the vblanc starts
scanline_wait: //the vertical blank period has begun. done in asm just
//because:)
ldrh r1, [r0]
cmp r1, #160
bne scanline_wait
}
*/
while(REG_VCOUNT<160);
}
///Copy our sprite array to OAM
void CopyOAM(void)
{
u16 loop;
u16* temp;
temp = (u16*)sprites;
for(loop = 0; loop < 128*4; loop++)
{
OAM[loop] = temp[loop];
}
}
///Test for key presses
void GetInput(void)
{
if(!(*KEYS & KEY_UP))
{
y--;
}
if(!(*KEYS & KEY_DOWN))
{
y++;
}
if(!(*KEYS & KEY_LEFT))
{
x--;
}
if(!(*KEYS & KEY_RIGHT))
{
x++;
}
if(!(*KEYS & KEY_L))
{
angle--;
if(angle<0)
angle = 359;
}
if(!(*KEYS & KEY_R))
{
angle++;
if(angle > 359)
angle = 0;
}
if(!(*KEYS & KEY_A))
{
zoom--;
}
if(!(*KEYS & KEY_B))
{
zoom++;
}
if(!(*KEYS & KEY_START))
{
if(!(sprites[0].attribute0 & SIZE_DOUBLE))//set or clear size double
{ //needs if to keep from holding down the start
sprites[0].attribute0 |= SIZE_DOUBLE;
x-=32; //size double shifts the sprite center by half the width and height this just
y-=32; //adjusts for it.
}
}
if(!(*KEYS & KEY_SELECT))
{
if((sprites[0].attribute0 & SIZE_DOUBLE))
{
sprites[0].attribute0 &= ~SIZE_DOUBLE;
x+=32;
y+=32;
}
}
}
//move the sprite
void MoveSprite(OAMEntry* sp, int x, int y)
{
if(x < 0) //if it is off the left corect
x = 512 + x;
if(y < 0) //if off the top corect
y = 256 + y;
sp->attribute1 = sp->attribute1 & 0xFE00; //clear the old x value
sp->attribute1 = sp->attribute1 | x;
sp->attribute0 = sp->attribute0 & 0xFF00; //clear the old y value
sp->attribute0 = sp->attribute0 | y;
}
void RotateSprite(int rotDataIndex, int angle, FIXED x_scale,FIXED y_scale)
{
FIXED pa,pb,pc,pd;
pa = ((x_scale) * COS[angle])>>8; //(do my fixed point multiplies and shift back down)
pb = ((y_scale) * SIN[angle])>>8;
pc = ((x_scale) * -SIN[angle])>>8;
pd = ((y_scale) * COS[angle])>>8;
rotData[rotDataIndex].pa = pa; //put them in my data struct
rotData[rotDataIndex].pb = pb;
rotData[rotDataIndex].pc = pc;
rotData[rotDataIndex].pd = pd;
} |
#5617 - Malefactor - Sat May 03, 2003 3:02 pm
if you are using VBA, make sure you have the motion blur filter turned off.
_________________
[Images not permitted - Click here to view it]
#5620 - pollier - Sat May 03, 2003 9:17 pm
Code: |
//wait for the screen to stop drawing
void WaitForVsync(void)
{
//lets get rid of htat inline asm we used in arm
/*
__asm
{
mov r0, #0x4000006 //0x4000006 is vertical trace counter; when it hits 160 //160 the vblanc starts
scanline_wait: //the vertical blank period has begun. done in asm just
//because:)
ldrh r1, [r0]
cmp r1, #160
bne scanline_wait
}
*/
while(REG_VCOUNT<160);
} |
This is interesting... It should work fine, but you might want to watch out for skipping frames. I don't think that would be the cause of the blurring, however.
V-Blank is the period in which it's safe to do anything to the display registers/memory without getting things like shearing on the LCD because the GBA is finished drawing scanlines for this frame.
If we're talking about a real 'blur' then it's definitely your emulator, but if the image is choppy or sheared then it might be either the emulator or the code.
_________________
(Works for me!)
#5625 - Link - Sun May 04, 2003 1:06 am
what exactly do this??: Code: |
//wait for the screen to stop drawing
void WaitForVsync(void)
{
//lets get rid of htat inline asm we used in arm
/*
__asm
{
mov r0, #0x4000006 //0x4000006 is vertical trace counter; when it hits 160 //160 the vblanc starts
scanline_wait: //the vertical blank period has begun. done in asm just
//because:)
ldrh r1, [r0]
cmp r1, #160
bne scanline_wait
}
*/
while(REG_VCOUNT<160);
} |
however the motion blur is disabled, and i usa VBA with parameters default.
In the game (commercials) the blur don't appear but in my test yes!
#5632 - antysix - Sun May 04, 2003 2:19 pm
It waits for the screen to finish drawing.
_________________
Currently playing: NGC: Metroid Prime
GBA: Golden Sun: The Lost Age
Currently developping: Project ~ [ Phail ]
#5633 - Link - Sun May 04, 2003 2:27 pm
how do u do?
Thanx for help! ;)
#5634 - Touchstone - Sun May 04, 2003 2:51 pm
A more proper wait-vsync is this:
Code: |
void WaitForVsync(void)
{
while(REG_VCOUNT == 160);
while(REG_VCOUNT != 160);
} |
This is safer to use if your processing-time of a frame is shorter than the vblank period.
_________________
You can't beat our meat
#5635 - Link - Sun May 04, 2003 3:09 pm
Tnx much