/*
    Parameters:
    
    game
        structure that holds game data, including the Graphics structure which contains data needed to write to the screen
    image
        image to draw to the screen
    texPitch
        number of pixels in a single row for the image.  This is given in the form 2^n where texPitch = n
    sourceX, sourceY, sourceWidth, sourceHeight
        portion of image to copy.  
        sourceWidth is given in the form 2^n where sourceWidth = n 
        sourceHeight is given in the form 2^n where sourceHeight = n
    destX,destY,destWidth,destHeight
        portion of screen to copy image to
    depth
        distance from the image to the camera in world space
*/

void drawImage(Game *game, byte *image, int texPitch, int sourceX, int sourceY, int sourceWidth, int sourceHeight, int destX, int destY, int destWidth, int destHeight, fixed depth)
{
    Graphics *g = (Graphics*)game->graphics;
    fixed sampleSizeX = FP16DIV( ITOFP16(1<<sourceWidth) , ITOFP16(destWidth) );
    fixed sampleSizeY = FP16DIV( ITOFP16(1<<sourceHeight) , ITOFP16(destHeight) );
    fixed samplePosX = 0;
    fixed initSamplePosY = 0;
    fixed *depthBuffer = g->depthBuffer;

    /* screen space coordinates of destination image */
    int startX = destX;        
    int startY = destY;
    int endX = startX+destWidth;
    int endY = startY+destHeight;

    /* used to clip sampling coordinates so that they do not go out of bounds of the image */
    int modX = (1<<sourceWidth)-1;
    int modY = (1<<sourceHeight)-1;

    /* stores current screen coordinate of destination image */
    int x = 0;
    int y = 0;

    /* necessary data for writing to the screen */
    IDIB *backBuffer = g->backBuffer;
    int pitch = backBuffer->nPitch;

    /* used to store current screen position of destination image */
    byte *screen = NULL;
    
    /* clip to screen and update sampling positions */
    if(startX < 0)
    {
        samplePosX = FP16MUL(ITOFP16(-startX) , sampleSizeX);
        startX = 0;
    }

    if(startY < 0)
    {
        initSamplePosY = FP16MUL(ITOFP16(-startY) , sampleSizeY );
        startY = 0;
    }

    if(endX > game->DeviceInfo.cxScreen)
        endX = game->DeviceInfo.cxScreen;

    if(endY > game->DeviceInfo.cyScreen)
        endY = game->DeviceInfo.cyScreen;

    /* grab the screen starting position of the destination image */
    screen = backBuffer->pBmp + startX+(startY*pitch);
    
    for(x = startX; x < endX; ++x)
    {
        byte *screenPos = screen;
        fixed samplePosY = initSamplePosY;

        /* if depth is less than depth of slice in depth buffer */
        if( depth <= depthBuffer[x] )
        {
            for(y = startY; y < endY; ++y)
            {
                /* grab image pixel coordinates */
                int px = (FP16TOI(samplePosX) & modX) + sourceX;
                int py = (FP16TOI(samplePosY) & modY) + sourceY;

                /* grab image pixel */
                byte pixel = image[px+(py<<texPitch)];
                
                /* if that pixel is not transparent, write it to the screen */
                if(pixel != 255)
                    *screenPos = pixel;

                screenPos += pitch;
                samplePosY += sampleSizeY;
            }
        }

        ++screen;
        samplePosX += sampleSizeX;
    }
}