Hi,
My graphics routines do exactly that. They use Mr.Mirkos routines, and my own 'canvas' structure rather than a simple framebuffer pointer, but its not hard to change.
The calculate an offset into thje framebuffer, and an offset into the sprite data, and then copy a column at once using memcopy. If you do it right, use the optimised ASM memcopy from my site, which is WAY faster than standard memcpy (
snippet: unknown author - Fast assembler memcpy routine).
A guide to understanding this function:
destination->data :the framebuffer pointer.
destination->width: 320
destination->height: 240
source->data: the sprite data (16bpp, prerotated)
source->width: width of sprite (BEFORE rotation)
source->height: height of sprite (BEFORE rotation)
coff: offset into framebuffer (canvas offset)
doff: offset into sprite (data offset)
vw: length of each 'column' in pixels (in 16bpp, each pixel is two bytes, hence the *2 in the memcpy routine)
frame: Just ignore this (pretend it is 0 - it is used for multiple frame sprite animation)
Code:
void gp_canvasPaste( tGP_canvas *destination, tGP_canvas *source, short x, short y, unsigned char frame ){
unsigned short xx,yy;
unsigned short vw,vh;
unsigned long doff;
unsigned long coff;
unsigned short px,py;
short tx,ty;
// If rect is off the screen, exit
if ((x>=destination->width) || (y>=destination->height)){ return; }
tx = x+source->width; ty = y+source->height;
if ((tx<0) || (ty<0)){ return; }
if (frame>source->frames){ return; }
// Determine frame to render
if (frame<1){ frame=1; }
frame-=1;
// The rest of the coordinates are calculated based on a screen rotation
// of 90 degrees clockwise.
ty = y;
y = x;
x = destination->height - ty - source->height;
tx = x+source->height; ty = y+source->width;
// Positional offsets
px = max( 0, x );
py = max( 0, y );
// Visible height
if (y<0){
vh = min( ty, destination->width );
}else{
if (ty>destination->width){
vh = source->width - (ty-destination->width);
}else{
vh = source->width;
}
}
// Visible width
if (x<0){
vw = min( tx, destination->height );
}else{
if (tx>destination->height){
vw = source->height - (tx-destination->height);
}else{
vw = source->height;
}
}
// Data offset (including frame offset)
doff = ( source->height * max( 0, -y ) ) + max( 0, -x ) + (frame*source->width*source->height);
// Canvas data offset
coff = py*destination->height + px;
// Draw visible pixels only
for ( yy=0; yy<vh; yy++ ){
memcpy( (unsigned short*)&destination->data[coff], (unsigned short*)&source->data[doff], vw*2 );
doff += source->height;
coff += destination->height;
}
// Set flag to indicate that canvas has been drawn to
destination->redraw=1;
}
EDIT: This routine handles all cases:
1) Sprite fits entirely in the screen
2) Sprite overlaps one or more borders (e.g. is only half on screen)
3) Sprite is larger than the screen, and two or more sides of the sprite are 'cropped'. e.g. a 640x480 sprite moving around, and you can only see part of it.