// BlinkenSisters - Hunt for the Lost Pixels
//     Bringing back the fun of the 80s
//
// (C) 2005-07 Rene Schickbauer, Wolfgang Dautermann
//
// See License.txt for licensing information
//


#include "globals.h"
#include "bsscreen.h"
#include "SDL_rotozoom.h"

Uint32 realRes_X = 0;
Uint32 realRes_Y = 0;
SDL_Surface *realRes_gScreen = 0;
bool realRes_enabled = false;
bool realRes_smoothieZoom = false;

COLOR3D colormode = COLOR3D_NONE;
SDL_Surface *gScreen_Left = 0;
SDL_Surface *gScreen_Right = 0;
SDL_Surface *gScreen_Normal = 0;
bool useColor3D = false;
bool enableColor3D = false;

void BS_SetRealResolution(Uint32 width, Uint32 height, bool smoothieZoom) {
    /* Create a 32-bit surface with the bytes of each pixel in R,G,B,A order,
    as expected by OpenGL for textures */
	Uint32 rmask, gmask, bmask, amask;

	if(width == SCR_WIDTH && height == SCR_HEIGHT) {
		return;
	}
	
	/* SDL interprets each pixel as a 32-bit number, so our masks must depend
		on the endianness (byte order) of the machine */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif

	
    realRes_X = width;
    realRes_Y = height;
    if(realRes_gScreen) {
        SDL_FreeSurface(gScreen);
    }

    SDL_Surface *temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, rmask, gmask, bmask, amask);
    gScreen = SDL_DisplayFormat(temp);
    SDL_FreeSurface(temp);


    realRes_enabled = true;
    realRes_smoothieZoom = smoothieZoom;
}

void BS_Set3DMode(COLOR3D mode) {
	//bool oldState = useColor3D;
	if(mode == COLOR3D_NONE) {
		gScreen = gScreen_Normal;
		useColor3D = false;
	} else if(mode == COLOR3D_LEFT) {
		gScreen = gScreen_Left;
		useColor3D = true;
	} else {
		gScreen = gScreen_Right;
		useColor3D = true;
	}

	/* Don't need this? 
	if(useColor3D == false && oldState == true) {
		BS_ColorSurfacesToScreen();
	}
	*/
}

void BS_ColorSurfacesToScreen() {

    Uint32 pitch_n = gScreen_Normal->pitch / 4;	
    Uint32 pitch_l = gScreen_Left->pitch / 4;	
    Uint32 pitch_r = gScreen_Right->pitch / 4;	
	Uint32 i, j;
	Uint32 pixel_l, pixel_r, pixel_n;

	if (SDL_MUSTLOCK(gScreen_Normal))
		if (SDL_LockSurface(gScreen_Normal) < 0)
			return;
	if (SDL_MUSTLOCK(gScreen_Left))
		if (SDL_LockSurface(gScreen_Left) < 0)
			return;
	if (SDL_MUSTLOCK(gScreen_Right))
		if (SDL_LockSurface(gScreen_Right) < 0)
			return;

	for(i=0; i < SCR_WIDTH; i++) {
		for(j=0; j < SCR_HEIGHT; j++) {
			pixel_l = ((Uint32 *)gScreen_Left->pixels)[j * pitch_l + i];
			pixel_r = ((Uint32 *)gScreen_Right->pixels)[j * pitch_r + i];
			
			pixel_l = ((pixel_l & 0xff) + 
						((pixel_l / 256) & 0xff) +
						((pixel_l / 65536) & 0xff)) / 3;
			if(pixel_l > 255) {
				pixel_l = 255;
			}
			pixel_r = ((pixel_r & 0xff) + 
						((pixel_r / 256) & 0xff) +
						((pixel_r / 65536) & 0xff)) / 3;
			if(pixel_r > 255) {
				pixel_r = 255;
			}

			//pixel_n = pixel_r *  256 + pixel_r + pixel_l * 65536;
			pixel_n = pixel_l *  256 + pixel_l + pixel_r * 65536;

			((Uint32 *)gScreen_Normal->pixels)[j * pitch_n + i] = pixel_n;
		}
	}

	if (SDL_MUSTLOCK(gScreen_Normal))
		SDL_UnlockSurface(gScreen_Normal);
	if (SDL_MUSTLOCK(gScreen_Left))
		SDL_UnlockSurface(gScreen_Left);
	if (SDL_MUSTLOCK(gScreen_Right))
		SDL_UnlockSurface(gScreen_Right);
}

void BS_ColorToGreyscale() {
	
    Uint32 pitch = gScreen->pitch / 4;		
	Uint32 i, j;
	Uint32 pixel;
	
	if (SDL_MUSTLOCK(gScreen))
		if (SDL_LockSurface(gScreen) < 0)
			return;
	
	for(i=0; i < (Uint32)gScreen->w; i++) {
		for(j=0; j < (Uint32)gScreen->h; j++) {
			pixel = ((Uint32 *)gScreen->pixels)[j * pitch + i];
			
			pixel = ((pixel & 0xff) + 
					   ((pixel / 256) & 0xff) +
					   ((pixel / 65536) & 0xff)) / 3;
			if(pixel > 255) {
				pixel = 255;
			}
			
			pixel = pixel + pixel *  256 + pixel * 65536;
			
			((Uint32 *)gScreen->pixels)[j * pitch + i] = pixel;
		}
	}
	
	if (SDL_MUSTLOCK(gScreen))
		SDL_UnlockSurface(gScreen);
}

SDL_Surface* BS_SetVideoMode(Uint32 width, Uint32 height, Uint32 depth, Uint32 flags) {
    /* Create a 32-bit surface with the bytes of each pixel in R,G,B,A order,
    as expected by OpenGL for textures */
	Uint32 rmask, gmask, bmask, amask;
	SDL_Surface *temp;

	/* SDL interprets each pixel as a 32-bit number, so our masks must depend
		on the endianness (byte order) of the machine */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	rmask = 0xff000000;
	gmask = 0x00ff0000;
	bmask = 0x0000ff00;
	amask = 0x000000ff;
#else
	rmask = 0x000000ff;
	gmask = 0x0000ff00;
	bmask = 0x00ff0000;
	amask = 0xff000000;
#endif


    if(!realRes_enabled) {
        gScreen = SDL_SetVideoMode(width, height, depth, flags);
    } else {
        if(realRes_gScreen && gScreen != realRes_gScreen) {
            SDL_FreeSurface(gScreen);
        }
		realRes_gScreen = SDL_SetVideoMode(realRes_X, realRes_Y, depth, flags);
		temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, depth, rmask, gmask, bmask, amask);
		gScreen = SDL_DisplayFormat(temp);
		SDL_FreeSurface(temp);
	}
	
	if(enableColor3D) {
		gScreen_Normal = gScreen;

		if(gScreen_Left) {
			SDL_FreeSurface(gScreen_Left);
		}
		temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, rmask, gmask, bmask, amask);
		gScreen_Left = SDL_DisplayFormat(temp);
		SDL_FreeSurface(temp);

		if(gScreen_Right) {
			SDL_FreeSurface(gScreen_Right);
		}
		temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, rmask, gmask, bmask, amask);
		gScreen_Right = SDL_DisplayFormat(temp);
		SDL_FreeSurface(temp);
	}
   
    return gScreen;


}

void BS_OLPCScreenZoom(SDL_Surface *src, SDL_Surface *dst) {
	if (SDL_MUSTLOCK(src))
		if (SDL_LockSurface(src) < 0)
			return;
	if (SDL_MUSTLOCK(dst))
		if (SDL_LockSurface(dst) < 0)
			return;

	Uint32 srcpitch = src->pitch / 4;
	Uint32 dstpitch = dst->pitch / 4;

	for(Uint32 y = 0; y < SCR_HEIGHT; y++) {
        for(Uint32 x = 0; x < SCR_WIDTH; x++) {
            ((Uint32 *)dst->pixels)[(y * 2) * dstpitch + x * 2] = 
            ((Uint32 *)dst->pixels)[((y * 2) + 1)* dstpitch + x * 2] = 
            ((Uint32 *)dst->pixels)[(y * 2) * dstpitch + x * 2 + 1] = 
            ((Uint32 *)dst->pixels)[((y * 2) + 1)* dstpitch + x * 2 + 1] = 
                ((Uint32 *)src->pixels)[y * srcpitch + x];
        }
	}


	if (SDL_MUSTLOCK(src))
		SDL_UnlockSurface(src);
	if (SDL_MUSTLOCK(dst))
		SDL_UnlockSurface(dst);

}

int BS_Flip(SDL_Surface* myscreen) {
	SDL_Surface *tmpScreen = 0;
    if(!enableColor3D && (!realRes_gScreen || myscreen != gScreen)) {
        return SDL_Flip(myscreen);
    } else {
		if(enableColor3D) {
			if(useColor3D) {
				tmpScreen = gScreen;
				gScreen = gScreen_Normal;
				BS_ColorSurfacesToScreen();
			} else {
				// Make screen Greyscale - if we don't, 
				// the player may see some unwanted and very irritating
				// 3D effects in videos, images und menu
				BS_ColorToGreyscale();
			}
		}
	
		if(realRes_enabled) {
#ifdef OLPCBUILD
            BS_OLPCScreenZoom(gScreen, realRes_gScreen);
#else // NO OLPCBUILD
			if(realRes_smoothieZoom) {
				zoomSurfaceRGBA(gScreen, realRes_gScreen, 0, 0, 1);
			} else {
				zoomSurfaceRGBA(gScreen, realRes_gScreen, 0, 0, 0);
			}
#endif
			SDL_Flip(realRes_gScreen);
		} else {
			SDL_Flip(gScreen);
		}
		if(enableColor3D) {
			if(useColor3D) {
				gScreen = tmpScreen;
			}
		}

        return 0;
        //return SDL_Flip(realRes_gScreen);
    }
}

//BS_SetVideoMode(SCR_WIDTH, SCR_HEIGHT, 32, SDL_SWSURFACE | SDL_FULLSCREEN);
