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.

C/C++ > blit

#49665 - NighTiger - Mon Aug 01, 2005 12:36 pm

Hi guys,
I have a little problem.
I have a sprite like SPRW = 2, SPRH = 2 in the position
Xpos = 2, Ypos = 2.
The screen is SCRW = 10, SCRH = 8.

To obtain the best performance I would like to use the memcpy function:

for (y=0; y<SPRW*SPRH; y++)
memcpy(&pScrn[((y+Ypos)*SCRW)+Xpos], (pSprt+y), sizeof(pSprt[0]));

but the result is wrong.
What is the correct way?

#49671 - Cearn - Mon Aug 01, 2005 2:54 pm

??? What exactly are you trying to do here? What kind of data have you got? What system are we talking about?
Code:
for (y=0; y<SPRW*SPRH; y++)
   memcpy(&pScrn[((y+Ypos)*SCRW)+Xpos], (pSprt+y), sizeof(pSprt[0]));

Lesseee, what can go wrong here.
  • You're looping over all pixels (SprW*SprH), rather than over all scanlines, which is more traditional when it comes to blitting.
  • What's the bitdepth of the screen? Different bitdepths require different copying styles.
  • What's the pitch of the screen (i.e., the width in bytes, not in pixels)? It doesn't necessarily have to be the same as the screen width (see also the bitdepth question)
  • sizeof(pSprt[0]) gives the size of one pSprt element. What's it's type? Does that correspond to the bitdepth? And even if it does, why use memcpy for a single value, where a simple assignment ('=') would do the same thing (only much, much, much quicker)?
In most cases you'd do something like this.
Code:

BYTE *src= start of source rectangle;
BYTE *dst= start of destination rectangle;
int src_pitch, dst_pitch, nn; // src pitch, dst pitch, # bytes to copy from src

// take care of all nasty assignments and safety checks

while(height--)  // loop over scanlines to copy
{   
    memcpy(dst, src, nn);  // copy by scanline, not by single pixels
    dst += dst_pitch;
    src += src_pitch;
}

A general blit-function for all occasions can be quite nasty due to possibilities with in-byte starts (bpp<8) and alignment problems (like 4byte boundaries for BMPs, etc), care to narrow the cases down a bit?

#49685 - Miked0801 - Mon Aug 01, 2005 6:43 pm

Quote:
Code:

for (y=0; y<SPRW*SPRH; y++)
   memcpy(&pScrn[((y+Ypos)*SCRW)+Xpos], (pSprt+y), sizeof(pSprt[0]));


You are so fired for writing a piece of code that looks like that. :)

1. SPRW == ????
2. SPRH == ????
3. SCRW == ???
...
you get the picture. I can guess you mean sprite width/height and screen width/height - but the numbers you are giving me for those values don't make any sense at all.

I must admit, I have almost no idea what you are trying to accomplish with that line of, well, whatever that is...

#49754 - NighTiger - Tue Aug 02, 2005 7:38 am

I did make a solution

for (y=0; y<SPRH; y++)
memcpy(&FrontBuffer[((y+Ypos)*SCRW)+Xpos], (pSprt+y*SPRW), sizeof(pSprt[0])*SPRW);

where
SPRH = sprite height
Ypos = sprite y position
Xpos = sprite x position
SCRW = screen width

pSprt = pointer to sprite

#49960 - Miked0801 - Thu Aug 04, 2005 12:09 am

Good luck when you come back and look at that code a year from now and try to figure out what it's doing. Please, use descriptive names and comments to save yourself from future doom :)

#50276 - NighTiger - Sun Aug 07, 2005 1:25 pm

excuse me guys,
have memcpy function something wrong?
I use it in my code to make a horizontal line or a fill rect and the color is alway wrong

#50303 - sajiimori - Sun Aug 07, 2005 11:03 pm

Memcpy might be copying a byte at a time, which does not work if you're writing to VRAM. I suggest writing your own 16 or 32 bit version.

#50333 - NighTiger - Mon Aug 08, 2005 8:05 am

like, for example:

memcpy(FrontBuffer, imageData, sizeof(u32));

???

#50336 - Cearn - Mon Aug 08, 2005 8:36 am

memcpy.
(yeah it's the Visual Studio page, but that doesn't matter in this case)

The third parameter is the number of bytes to copy. sizeof(u32) gives the number of bytes used by the type 'u32', which is 4, which most likely has nothing to do with the amount of bytes of the bitmap's scanline.
In principle, memcpy copies in bytes, but in practice it's often optimised to copy in word-sized chunks (u32 in ARM's case) if the occasion allows for it. This is so when there's more than 16 bytes to copy and when both source and destination are word aligned.

What sajimori is referring to is writing your own memcpy function that copies in (half)word chunks, rather than bytes. Something like this for example:
Code:

// dstv: destination pointer
// srcv: source pointer
// len: number of halfwords to copy
//   (not # of bytes, but the switch is easily made)
void memcpy16(const void *dstv, void *srcv, u32 len)
{
    u16 *dst= (u16*)dstv, *src= (u16*)srcv;
    while(len--)
        *dst++ = *src++;
}

Various optimisations are possible of course, but this is the basic form. If you must have optimised versions you 're welcome to try mine, but they're in assembly so you might want to wait with that.