/***************************************************************************
    Windows CE GDI Video Routine
 ***************************************************************************/
#include <windows.h>
#ifdef WIN32_PLATFORM_PSPC
#include "gx.h"
#endif

#include "ce.h"
#include "CEvideo_GDI.h"
#include "CEvideo_GAPI.h"
#include "system.h"
#include "ppp_stdio.h"

/** Various variables ****************************************/
char *  g_vram;
char *  g_vbuf;
int g_width;
int g_height;
int g_screen_width;
int g_screen_height;
int g_screen_x;
int g_screen_y;
int videomode=0;
int scanline=0;
int scanlineflip = 0;

void Simple1x(u8 *, u32 , u8 * , u8 *, u32 , int , int );
void SimpleHalf(u8 *,u32, u8 * , u8 *, u32 , int , int );
void SimpleInterless(u8 *,u32, u8 * , u8 *, u32 , int , int );
void Simple2x(u8 *, u32 , u8 * , u8 *, u32 , int , int );
void Half2x(u8 *,u32, u8 * , u8 *, u32 , int , int );
void Interless2x(u8 *,u32, u8 * , u8 *, u32 , int , int );

void  (*filterFunction)(u8*,u32,u8*,u8*,u32,int,int);
int   (*CEVideo_Init)(int,int);
void  (*CEVideo_Trash)(void);
char* (*CEVideo_GetBufferPtrLine)(int line);
char* (*CEVideo_GetBufferPtr)(void);
void  (*CEVideo_CleanBuffer)(void);
void  (*CEVideo_FreeBufferPtr)(void);

void (*systemDrawScreen)();

/*************************************************************/
/*************************************************************/
void CEVideo_SetVideoMode(void)
{
    switch( videomode ){
        case 0:
            CEVideo_Init         = CEVideo_Init_GDI;
            CEVideo_Trash        = CEVideo_Trash_GDI;
            CEVideo_GetBufferPtr = CEVideo_GetBufferPtr_GDI_NOBUF ;
            CEVideo_CleanBuffer  = CEVideo_CleanBuffer_GDI_NOBUF  ;
            CEVideo_FreeBufferPtr= CEVideo_FreeBufferPtr_GDI_NOBUF;
            systemDrawScreen     = systemDrawScreen_GDI_NOBUF;
            switch( scanline ){
               case 0 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_NOBUF; break;
               case 1 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_HALF_GDI_NOBUF; break;
               case 2 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_INTERLESS_GDI_NOBUF; break;
               case 3 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_NOBUF; break;
               case 4 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_NOBUF; break;
               case 5 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_NOBUF; break;
            }
            break;
        case 1:
            CEVideo_Init         = CEVideo_Init_GDI;
            CEVideo_Trash        = CEVideo_Trash_GDI;
            CEVideo_GetBufferPtr = CEVideo_GetBufferPtr_GDI_USEBUF ;
            CEVideo_CleanBuffer  = CEVideo_CleanBuffer_GDI_USEBUF  ;
            CEVideo_FreeBufferPtr= CEVideo_FreeBufferPtr_GDI_USEBUF;
            systemDrawScreen     = systemDrawScreen_GDI_USEBUF;
            switch( scanline ){
               case 0 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_USEBUF; break;
               case 1 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_HALF_GDI_USEBUF; break;
               case 2 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_INTERLESS_GDI_USEBUF; break;
               case 3 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_USEBUF; break;
               case 4 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_USEBUF; break;
               case 5 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GDI_USEBUF; break;
            }
            break;
#ifdef WIN32_PLATFORM_PSPC
        case 2:
            CEVideo_Init         = CEVideo_Init_GAPI;
            CEVideo_Trash        = CEVideo_Trash_GAPI;
            CEVideo_GetBufferPtr = CEVideo_GetBufferPtr_GAPI_NOBUF ;
            CEVideo_CleanBuffer  = CEVideo_CleanBuffer_GAPI_NOBUF  ;
            CEVideo_FreeBufferPtr= CEVideo_FreeBufferPtr_GAPI_NOBUF;
            systemDrawScreen     = systemDrawScreen_GAPI_NOBUF;
            switch( scanline ){
               case 0 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GAPI_NOBUF; break;
               case 1 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_HALF_GAPI_NOBUF; break;
               case 2 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_INTERLESS_GAPI_NOBUF; break;
               case 3 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GAPI_NOBUF; break;
               case 4 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_HALF_GAPI_NOBUF; break;
               case 5 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_INTERLESS_GAPI_NOBUF; break;
            }
            break;
        case 3:
            CEVideo_Init         = CEVideo_Init_GAPI;
            CEVideo_Trash        = CEVideo_Trash_GAPI;
            CEVideo_GetBufferPtr = CEVideo_GetBufferPtr_GAPI_USEBUF ;
            CEVideo_CleanBuffer  = CEVideo_CleanBuffer_GAPI_USEBUF  ;
            CEVideo_FreeBufferPtr= CEVideo_FreeBufferPtr_GAPI_USEBUF;
            systemDrawScreen     = systemDrawScreen_GAPI_USEBUF;
            switch( scanline ){
               case 0 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GAPI_USEBUF; break;
               case 1 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_HALF_GAPI_USEBUF; break;
               case 2 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_INTERLESS_GAPI_USEBUF; break;
               case 3 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_FULL_GAPI_USEBUF; break;
               case 4 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_HALF_GAPI_USEBUF; break;
               case 5 : CEVideo_GetBufferPtrLine = CEVideo_GetBufferPtrLine_INTERLESS_GAPI_USEBUF; break;
            }
            break;
#endif
    }

    switch( scanline ){
       case 0:     filterFunction = Simple1x;         break;
       case 1:     filterFunction = SimpleHalf;       break;
       case 2:     filterFunction = SimpleInterless;  break;
	   case 3:     filterFunction = Simple2x;		  break;
	   case 4:     filterFunction = Half2x;           break;
	   case 5:     filterFunction = Interless2x;      break;
    }

}

/*************************************************************/
/*************************************************************/
void Simple1x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
              u8 *dstPtr, u32 dstPitch, int srcWidth, int srcHeight)
{
  do {
    u16 *bP = (u16 *)srcPtr;
    u16 *dP = (u16 *)dstPtr;
    u16 *finish = bP + srcWidth;

    do {
      *dP++ = *bP++;
    } while (bP < finish);
    
    srcPtr   += srcPitch;
    dstPtr   += dstPitch;
  }
  while (--srcHeight);
}

/*************************************************************/
/*************************************************************/
void Simple2x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
              u8 *dstPtr, u32 dstPitch, int srcWidth, int srcHeight)
{
 
  do {
    u16 *bP = (u16 *)srcPtr;
    u16 *dP = (u16 *)dstPtr;
	u16 *dP2= (u16 *)(dstPtr + dstPitch);

    u16 *finish = bP + srcWidth;

    do {
      *dP++ = *dP2++ = *bP;
      *dP++ = *dP2++ = *bP++;
    } while (bP < finish);
    dstPtr   += dstPitch * 2;
	srcPtr   += srcPitch;

  }
  while (--srcHeight);
}

/*************************************************************/
/*************************************************************/
void SimpleHalf(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
                u8 *dstPtr, u32 dstPitch, int srcWidth, int srcHeight)
{
  u16 *finish;
 
  do {
    u16 *bP = (u16 *)srcPtr;
    u16 *dP = (u16 *)dstPtr;
    
    finish = bP + srcWidth;

    do {
      *dP++ = *bP++;
    } while (bP < finish);
    
    srcPtr   += srcPitch*2;
    dstPtr   += dstPitch*2;
    srcHeight -= 2;
  }
  while (srcHeight>0);
}

/*************************************************************/
/*************************************************************/
void Half2x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
              u8 *dstPtr, u32 dstPitch, int srcWidth, int srcHeight)
{
  u16 *finish;
 
  do {
    u16 *bP = (u16 *)srcPtr;
    u16 *dP = (u16 *)dstPtr;
    
    finish = bP + srcWidth;

    do {
      *dP++ = *bP;
      *dP++ = *bP++;
    } while (bP < finish);
    
    srcPtr   += srcPitch;
    dstPtr   += dstPitch * 2;
  }
  while (--srcHeight);
}

/*************************************************************/
/*************************************************************/
void SimpleInterless(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
                     u8 *dstPtr, u32 dstPitch, int srcWidth, int srcHeight)
{
  u16 *finish;
 
  if( scanlineflip ){
	srcPtr   += srcPitch;
	dstPtr   += dstPitch;
    srcHeight--;
  }
 
  do {
    u16 *bP = (u16 *)srcPtr;
    u16 *dP = (u16 *)dstPtr;
    
    finish = bP + srcWidth;

    do {
      *dP++ = *bP++;
    } while (bP < finish);
    
    srcPtr   += srcPitch * 2;
    dstPtr   += dstPitch * 2;
    srcHeight -= 2;
  }
  while (srcHeight>0);
}

void Interless2x(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
                     u8 *dstPtr, u32 dstPitch, int srcWidth, int srcHeight)
{
  u16 *finish;
 
  if( scanlineflip ){
    dstPtr   += dstPitch;
  }
 
  do {
    u16 *bP = (u16 *)srcPtr;
    u16 *dP = (u16 *)dstPtr;
    
    finish = bP + srcWidth;

    do {
      *dP++ = *bP;
      *dP++ = *bP++;
    } while (bP < finish);
    
    srcPtr   += srcPitch;
    dstPtr   += dstPitch * 2;
    srcHeight--;
  }
  while (srcHeight>0);
}

void systemScreenCapture(int a)
{
/*
    char buffer[2048];

  if(captureFormat) {
    sprintf(buffer, "%s%02d.bmp", "capture", a);
    emuWriteBMP(buffer);
  } else {
    sprintf(buffer, "%s%02d.png", "capture", a);
    emuWritePNG(buffer);
  }
  systemScreenMessage("Screen capture");
*/
}
