/*
 Once upon a Time in the East (Huulikorppuhastaja)
 - Marq
*/

#include <math.h>
#include <SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "render.h"
#include "cool_mzx/cool_mzx.h"
#include "noise.h"
#include "halftone.h"
#include "png_wrap.h"
#include "partikle.h"
#include "heart.h"
#include "overlay.h"
#include "feissi.h"
#include "globals.h"

#ifndef DATADIR
#define DATADIR "data/"
#endif

#ifdef WIN32
int putenv(char *);
#endif

#ifdef GP2X
#include <SDL_joystick.h>
#include <SDL_gp2x.h>
#include "gp2x.h"
#endif

#ifndef TIMING_TEST

// These defines enable individual effects.
#define TOWERS
#define PARTICLES
#define CIRCLES
#define GUN
#define HEART
#define FEISSI

#else

#endif

// From png's RGBA to SDL's ARGB
void fixrgba(PNG *s,char to16)
{
    int i;
    unsigned *u,col;

    u=(unsigned *)s->data;
    for(i=0;i<s->x*s->y;i++)
    {
        col=(s->data[i*4+3]<<24)+(s->data[i*4+0]<<16)+
        (s->data[i*4+1]<<8)+(s->data[i*4+2]<<0);
        u[i]=col;
    }

#ifdef HICOLOR
    buftype *d=(buftype *)s->data;
    u=(unsigned *)s->data;

    if(to16)
        for(i=0;i<s->x*s->y;i++)
        {
            if(u[i]>0xf8000000)
                d[i]=0x20+
                     ((u[i]>>8)&0xf800)+
                     ((u[i]>>5)&0x7c0)+
                     ((u[i]>>3)&0x1f);
            else
                d[i]=((u[i]>>8)&0xf800)+
                     ((u[i]>>5)&0x7c0)+
                     ((u[i]>>3)&0x1f);

            // "Dither" == noise to remove the ugly banding
            if(to16!=2 && !(random()&3))
            {
                if((d[i]&0xf800)!=0xf800 &&
                   (d[i]&0x07c0)!=0x7c0 &&
                   (d[i]&0x1f)!=0x1f)
                    d[i]+=0x0841;
            }
        }

#endif
}

/* LSB <-> MSB 32-bit */
void swap(int *d,int units)
{
    int n;
    unsigned char *p=(unsigned char *)d,c;

    for(n=0;n<units;n++,p+=4)
    {
        c=p[0]; p[0]=p[3]; p[3]=c;
        c=p[1]; p[1]=p[2]; p[2]=c;
    }
}

int main(int argc,char *argv[])
{
    SDL_Event e;
    buftype *scr,*t;

#ifdef HICOLOR
    int everyeit=0;
    SDL_Surface *gpscreen;
#else
    SDL_Surface *s;
    int fukkidrgba=0;
  #ifdef FUKKIDRGBA
    fukkidrgba=1;
  #endif
#endif

#ifdef GP2X
    SDL_Surface *s;
    int lvolo,rvolo;
#endif

    int fast_forward=0; // pikakelaus
    int fast_forward_prevticks=0; // nopeuden rajoitusta varten

    int quit=0,n,m,i,x,y,fullscreen=SDL_FULLSCREEN,
        feistart=-1,feidistart=-1;
    unsigned tid=0;
    int now_ticks=0;

    static unsigned buf[XRES*YRES],buf2[XRES*YRES],blakkis[XRES*YRES];

    static int gun[10000/4];

    static unsigned char biisi[1000000];

#ifdef DOUBLEPIX
    static unsigned buf3[XRES*YRES];
#endif

    FILE *f;

    PNG c1,c2,hart,reesnevi,klintti,leenini,houses,flagga,gringos,once,
        vainio,bullet,greet,noize,whitenoize,flagga2;

    // Names and pointers for loading the images in one go
    char *picnames[]={  "circle32.png","circle34.png",
        "heart.png","brezgun.png",
        "karvaclint.png","leninhunt.png",
        "towers.png","stara.png",
        "gringot.png","ouaTITe.png",
        "jussivainiomummo.png","luot1.png",
        "greetz.png","noise.png",
        "whitenoise.png","stara.png",
        NULL
    };

    PNG *piccy[]={     
        &c1,&c2, 
        &hart,&reesnevi,
        &klintti,&leenini, 
        &houses,&flagga,
        &gringos,&once, 
        &vainio,&bullet,
        &greet,&noize, 
        &whitenoize,&flagga2
    };

    char to16[]={2,2,1,1, // Which pics to convert to 16-bit if relevant
                 1,1,1,0,
                 1,1,1,1,
                 1,2,1,2};

#define PART_INTRO (0)
#define PART_LENIN (300)
#define PART_CLINT (500)
#define PART_FACE (700)
#define PART_WAYNE (1000)
#define PART_BRESHNEV (1200)

    // Start pos, fade time, counter, the same for fade out, pic
    OVERLAY ovl[]={{PART_INTRO+100,200,0, PART_INTRO+148,1500,0, &gringos, 0,53, 319,183},
        {PART_INTRO+200,200,0, PART_INTRO+248,1500,0, &once, 0,42, 319,196},
        {PART_INTRO+260,500,0, PART_INTRO+300,1,0, &whitenoize, 0,0, 319,239},
        {PART_LENIN,200,0, PART_LENIN+148,1500,0, &leenini, 0,83, 93,239},
        {PART_LENIN+152,2000,0, PART_LENIN+200,500,0, &noize, 0,0, 319,239},
        {PART_CLINT,1500,0, PART_CLINT+200,1,0, &klintti, 215,18, 319,239},
        {PART_CLINT+152,2000,0, PART_CLINT+200,500,0, &noize, 0,0, 319,239},
        {PART_WAYNE,1500,0, PART_WAYNE+60,500,0, &vainio, 0,8, 133,239},
        {PART_WAYNE+100,500,0, PART_WAYNE+132,1500,0, &vainio, 0,8, 133,239},
        {PART_BRESHNEV,200,0, PART_BRESHNEV+140,1,0, &reesnevi, 208,70, 319,239},
        {PART_BRESHNEV+124,800,0, PART_BRESHNEV+140,1,0, &whitenoize, 0,0, 319,239},
        {PART_BRESHNEV+144,4400,0, PART_BRESHNEV+200,1,0, &noize, 0,0, 319,239},
        {0,0,0,0,0,0,NULL, 0,0, 319,239}};

    // Locations of the greetings
    int grtx[][3]={
        {123,61, PART_CLINT+100},
        {15,17, PART_CLINT+102},
        {15,127, PART_CLINT+103},
        {15,61, PART_CLINT+104},
        {123,17, PART_CLINT+106},
        {15,149, PART_CLINT+109},
        {123,127, PART_CLINT+110},

        {123,39, PART_CLINT+116},
        {123,149, PART_CLINT+117},
        {123,83, PART_CLINT+120},
        {15,83, PART_CLINT+130},
        {15,39, PART_CLINT+131},
        {123,105, PART_CLINT+132},
        {15,105, PART_CLINT+133},

        {15,193, PART_CLINT+135}
    };

    int trigged=0;

    char namn[100]="";

    // Read pix and convert colors
    for(n=0;picnames[n];n++)
    {
        strcpy(namn,DATADIR);
        strcat(namn,picnames[n]);

        if(read_png(namn,piccy[n]))
        {
            printf("Couldn't open pic: %s",picnames[n]);
            return(1);
        }
        fixrgba(piccy[n],to16[n]);
    }

    // 3D Model
    f=fopen(DATADIR "gun.bare","rb");
    if(f==NULL)
        return(1);
    i=fread(gun,1,10000,f);
    fclose(f);

#ifndef MSB // The format was originally designed for Amiga
    swap(gun,50000/4);
#endif

    halftone_init(XRES,YRES);
    feissi_init();

    // Load & init mzx
#ifdef TIMING_TEST
    f=fopen(DATADIR "timingtest.mod","rb");
#else
    f=fopen(DATADIR "luckystalin_4.mod","rb");
#endif
    if(f==NULL)
        return(1);
    i=fread(biisi,1,1000000,f);
    fclose(f);

    for(n=1;n<argc;n++)
    {
        if(!strcmp(argv[n],"-w"))
            fullscreen=0;
#ifdef WIN32
        if(!strcmp(argv[n],"-d"))
            putenv("SDL_AUDIODRIVER=dsound");
#endif
    }

    // For Mac purposes the windowed version has a name ending in 'w'
    if(argv[0][strlen(argv[0])-1]=='w')
        fullscreen=0;

#ifdef GP2X
    set_FCLK(230);
    SDL_Init(SDL_INIT_VIDEO+SDL_INIT_TIMER+SDL_INIT_AUDIO+SDL_INIT_JOYSTICK);
#else
    SDL_Init(SDL_INIT_VIDEO+SDL_INIT_TIMER+SDL_INIT_AUDIO);
#endif

#ifdef DOUBLEPIX
    s=SDL_SetVideoMode(XRES*2,YRES*2,32,SDL_SWSURFACE+fullscreen);
#else

  #ifdef HICOLOR
    #ifdef VIDEO
    s=SDL_SetVideoMode(XRES*2,YRES*2,16,SDL_HWSURFACE+fullscreen);
    gpscreen=SDL_CreateRGBSurface(0,XRES,YRES,16,0,0,0,0);

    SDL_LockSurface(s);
    memset(s->pixels,0,XRES*YRES*4*2);
    SDL_UnlockSurface(s);

    SDL_Rect rektaali={150,100,368,290};

    SDL_GP2X_Display(&rektaali);
    #else
    gpscreen=SDL_SetVideoMode(XRES,YRES,16,SDL_SWSURFACE+fullscreen);
    #endif

  #else
    s=SDL_SetVideoMode(XRES,YRES,32,SDL_HWSURFACE+SDL_DOUBLEBUF+fullscreen);
  #endif

#endif

    // Try to detect if the buffer is not in ARGB order
#ifndef HICOLOR
    if(s->format->Rmask!=0xff0000)
        fukkidrgba=1;
#endif

    SDL_ShowCursor(0);
    SDL_WM_SetCaption("Once upon a Time in the East",NULL);

#ifdef GP2X
    SDL_JoystickOpen(0);

    lvolo=gp2x_getvol()&0xff;
    rvolo=gp2x_getvol()>>8;

  #ifdef F200
    // Or you will suffer on F200
    rvolo=3;
    lvolo=3;

    gp2x_setvol(lvolo,rvolo);
  #endif
#endif

#ifdef TIMING_TEST
//    while (now_ticks < 10000) ;
    fprintf(stdout, "now_ticks at mzx_init(): %d\n", now_ticks);
#endif

    mzx_init(44100,BLKSIZE);
    mzx_get(biisi);

    memcpy(buf,whitenoize.data,XRES*YRES*4);
    memcpy(buf2,whitenoize.data,XRES*YRES*4);
    memset(blakkis,0,XRES*YRES*4);

#ifdef TIMING_TEST
    fprintf(stdout, "now_ticks at mzx_start(): %d\n", now_ticks);
#endif
    mzx_start(50);
    mzx_update_position();
    while(mzx_position()<0 || mzx_position()>100) // Skip a bug...
        mzx_update_position();

#ifdef TIMING_TEST
    fprintf(stdout, "now_ticks after waiting for music to start: %d\n", now_ticks);
#endif

    while(!quit) // *************************** MAIN LOOP **************************
    {
        mzx_update_position(); // <-- this is a new thing to do with cool_mzx versions after 2012-08-19! 
        now_ticks = SDL_GetTicks();

#ifdef HICOLOR
        SDL_LockSurface(gpscreen);
        scr=gpscreen->pixels;
#else
        SDL_LockSurface(s);
  #ifdef DOUBLEPIX
        scr=buf3;
  #else
        scr=s->pixels;
  #endif
#endif

        if (0) ;
        // Tower blocks
#ifdef TOWERS
        else if(mzx_position()<PART_INTRO+300)
        {
            t=(buftype *)houses.data;
            i=1000000-now_ticks/30;
            for(n=0;n<YRES;n++) // Scroll the parts
            {
                memcpy(&scr[n*XRES],&t[(n+i)%YRES*XRES],100*sizeof(buftype));
                memcpy(&scr[n*XRES+220],&t[(n+i)%YRES*XRES+220],100*sizeof(buftype));

                memcpy(&scr[n*XRES+100],&t[(n+i/2)%YRES*XRES+100],50*sizeof(buftype));
                memcpy(&scr[n*XRES+170],&t[(n+i/2)%YRES*XRES+170],50*sizeof(buftype));

                memcpy(&scr[n*XRES+150],&t[(n+i/4)%YRES*XRES+150],20*sizeof(buftype));
            }
        }
#endif

        // Charged particles
#ifdef PARTICLES
        else if(mzx_position()>=PART_LENIN && mzx_position()<PART_LENIN+200)
        {
  #ifdef NOCAP
            if(1)
  #else
            if(now_ticks-tid>=1000/60) // Retrig particles
  #endif
            {
                i=0;
                tid=now_ticks;

                if((mzx_position()%100&31)==0 && !trigged)
                {
                    trigged=1;
                    i++;
                }
                else
                    trigged=0;

  #ifdef HICOLOR
                everyeit++;
                if(everyeit==8)
                    everyeit=0;

                // Need to fade slower
                if(trigged)
                    bang((buftype *)buf,(unsigned char *)whitenoize.data,PARTS,i);
                else
                {
                    if(!everyeit)
                        bang((buftype *)buf,(unsigned char *)whitenoize.data,PARTS,i);
                    else
                        bang((buftype *)buf,(unsigned char *)whitenoize.data,PARTS,-1);
                }
  #else
                bang(buf,(unsigned char *)whitenoize.data,PARTS,i);
  #endif
            }

            memcpy(scr,buf,XRES*YRES*sizeof(buftype));

            // Bullet holez
            if(mzx_position()>=PART_LENIN+4)
                overlaypart((buftype *)scr,(buftype *)bullet.data,224,173,74,68);
            if(mzx_position()>=PART_LENIN+36)
                overlaypart((buftype *)scr,(buftype *)bullet.data,136,12,74,68);
            if(mzx_position()>=PART_LENIN+104)
                overlaypart((buftype *)scr,(buftype *)bullet.data,128,167,74,68);
            if(mzx_position()>=PART_LENIN+136)
                overlaypart((buftype *)scr,(buftype *)bullet.data,237,73,74,68);
        }
#endif

        // Interferenz circles or something
#ifdef CIRCLES
        else if(mzx_position()>=PART_CLINT && mzx_position()<PART_CLINT+200)
        {
            x=(int)(1000+sinf(now_ticks/1400.0f)*42.0f)%32;
            y=(int)(1000+cosf(now_ticks/1500.0f)*32.0f)%32;

            buftype *t=(buftype *)c1.data;
            for(n=0;n<YRES;n++)
                memcpy(&scr[n*XRES],&t[(y+n)*c1.x+x],XRES*sizeof(buftype));

            x=(int)(1000+sinf((500+now_ticks
                   +cosf(now_ticks/2000.0)*500)
                   /1500.0f)*40.0f)%34;
            y=(int)(1000+cosf((500+now_ticks
                   -sinf(now_ticks/2000.0)*500)
                   /1400.0f)*30.0f)%34;

            t=(buftype *)c2.data;
            for(n=0;n<YRES;n++)
            {
                for(m=0;m<XRES;m++)
                    scr[n*XRES+m]&=t[(y+n)*c2.x+x+m];
            }

            // Greets
            for(i=0;i<15;i++)
            {
                if(mzx_position()>=grtx[i][2])
                {
                    if(i!=14)
                        overlaypart((buftype *)scr,(buftype *)greet.data,grtx[i][0],grtx[i][1],105,22);
                    else
                        overlaypart((buftype *)scr,(buftype *)greet.data,grtx[i][0],grtx[i][1],160,22);
                }
            }
        }
#endif

        // Appearing face
#ifdef FEISSI
        else if(mzx_position()>=PART_FACE && mzx_position()<PART_FACE+200)
        {
            if(feistart==-1)
            {
                feistart=now_ticks;
            }
            int roll;
            roll = 0;
            if (now_ticks >= mzx_time_of_position(PART_FACE+132))
                roll = (now_ticks - mzx_time_of_position(PART_FACE+132)) / 10;

            feissi(scr,(buftype *)blakkis,now_ticks-feistart,roll);
        }

        // Face goes away.
        else if(mzx_position()>=PART_FACE+200 && mzx_position()<PART_WAYNE)
        {
#ifdef HICOLOR
            buftype *a=(buftype *)blakkis,
                    *b=(buftype *)flagga2.data;
#else
            unsigned char *a=(unsigned char *)blakkis,
                          *b=(unsigned char *)flagga2.data;
#endif

            if(feidistart==-1)
            {
                feissi_convert_from_8bit((buftype *)buf,(unsigned char *)blakkis,0);
                memcpy(blakkis,buf,XRES*YRES*sizeof(buftype));

                feidistart=now_ticks;
            }

            if(now_ticks-feidistart>1000/22)
            {
  #ifdef HICOLOR
                everyeit++;
                if(everyeit>7)
                    everyeit=0;

                // Need to fade every 2nd frame and every 4th pixel
                if(everyeit&1)
                {
                    int xp,yp;
                    switch(everyeit)
                    {
                        case 1: xp=0;yp=0;break;
                        case 3: xp=1;yp=0;break;
                        case 5: xp=1;yp=1;break;
                        case 7: xp=0;yp=1;break;
                        default: xp=0;yp=0;break;
                    }

                    a+=xp+XRES*yp;
                    y+=xp+XRES*yp;
                    for(m=0;m<YRES;m+=2)
                    {
                        for(n=0;n<XRES;n+=2,a+=2,b+=2)
                        {
                            if(*a!=*b)
                            {
                                if((*a & 0xf800) < (*b & 0xf800))
                                    (*a)+=0x800;
                                else
                                    if((*a & 0xf800) > (*b & 0xf800))
                                        (*a)-=0x800;

                                if((*a & 0x7c0) < (*b & 0x7c0))
                                    (*a)+=0x40;
                                else
                                    if((*a & 0x7c0) > (*b & 0x7c0))
                                        (*a)-=0x40;

                                if((*a & 0x1f) < (*b & 0x1f))
                                    (*a)++;
                                else
                                    if((*a & 0x1f) > (*b & 0x1f))
                                        (*a)--;
                            }
                        }
                        a+=XRES;
                        b+=XRES;
                    }
                }
  #else
                for(n=0;n<XRES*YRES*sizeof(buftype);n++,a++,b++)
                {
                    if(*a<*b)
                        (*a)++;
                    else
                        if(*a>*b)
                            (*a)--;
                }
  #endif
                feidistart=now_ticks;
            }

            memcpy(scr,blakkis,XRES*YRES*sizeof(buftype));
        }
#endif
        // <---- FEISSI

        // TEH Gun!
#ifdef GUN
        else if(mzx_position()>=PART_WAYNE && mzx_position()<PART_WAYNE+200)
        {
            memcpy(buf,flagga.data,XRES*YRES*4);
            memset(scr,0,XRES*YRES*sizeof(buftype));
            bare_loadidentity();

            // Move the gun when the time is right
            if(mzx_position()<PART_WAYNE+32)
            {
                i=(now_ticks-mzx_time_of_position(PART_WAYNE));
                if(i>1000)
                    i=1000;

                bare_translate(1.5,-0.3-(1000-i)/100.0,-20);
            }
            else
            {
                if(mzx_position()>=PART_WAYNE+148)
                    bare_translate(1.5,-0.3-(now_ticks-mzx_time_of_position(PART_WAYNE+148))/100.0,-7-(now_ticks-mzx_time_of_position(PART_WAYNE+100))/500.0);
                else
                {
                    // Swing da gun a bit at this point
                    if(mzx_position()>=PART_WAYNE+100)
                    {
                        float mulli=(now_ticks-mzx_time_of_position(PART_WAYNE+100))/1000.0f+1;
                        mulli=4.0f/(mulli*mulli*mulli*mulli)-0.05;
                        if(mulli<0)
                            mulli=0;
                        bare_translate(1.5,-0.3+sinf((now_ticks-mzx_time_of_position(PART_WAYNE+100))/50.0)*mulli,-20);
                    }
                    else
                        bare_translate(1.5,-0.3,-20);

/*                    if(mzx_position()>=PART_WAYNE+100)
                        bare_translate(1.5,-0.3,-7-(now_ticks-mzx_time_of_position(PART_WAYNE+100))/500.0);
                    else
                        bare_translate(1.5,-0.3,-20);*/
                }
            }

            if(mzx_position()>=PART_WAYNE+148)
            {
                bare_rotatey(now_ticks/1000.0f);
                bare_rotatez((now_ticks-mzx_time_of_position(PART_WAYNE+148))/200.0f);
            }
            else
            {
                bare_rotatey(now_ticks/1000.0f);
            }

            bare_render(gun,buf,NULL);

            if(mzx_position()>=PART_WAYNE+100)
                halftone(scr,buf,130+cosf((now_ticks-mzx_time_of_position(PART_WAYNE))/500.0f)*120.0f);
            else
                halftone(scr,buf,130+cosf((now_ticks-mzx_time_of_position(PART_WAYNE))/500.0f)*100.0f);

            if(mzx_position()>=PART_WAYNE+148) // You call THAT a fade?
            {
                i=(now_ticks-mzx_time_of_position(PART_WAYNE+148))/5;
                if(i>XRES)
                    i=XRES;
                for(n=0;n<YRES;n++)
                    memcpy(&scr[n*XRES],&whitenoize.data[(n*XRES+XRES-i)*sizeof(buftype)],i*sizeof(buftype));
            }
        }
#endif
// <---- GUN

        // Heart L-system
#ifdef HEART
        if(mzx_position()>=PART_BRESHNEV)
        {
            // Limit speed
            if(now_ticks-tid>=1000/38)
            {
                tid=now_ticks;
                heart((buftype *)buf2,&hart);
            }

            if(mzx_position()>=PART_BRESHNEV+140)
            {
                memcpy(scr,noize.data,XRES*YRES*sizeof(buftype));
                halftone(scr,(unsigned *)flagga.data,130+cosf((now_ticks-mzx_time_of_position(PART_BRESHNEV+140))/1000.0f)*130.0f);
            }
            else
                memcpy(scr,buf2,XRES*YRES*sizeof(buftype));
        }
#endif

        if(mzx_position()>=PART_BRESHNEV+163)
            quit=1;

        if (fast_forward)
        {
            if ((now_ticks / 10) - fast_forward_prevticks)
            {
                mix_newhand(NULL, NULL, 44100);
                fast_forward_prevticks = now_ticks / 10;
            }
        }

        while(SDL_PollEvent(&e))
        {
            //if(e.type==SDL_MOUSEBUTTONDOWN)
            //    quit=1;
            if(e.type==SDL_KEYDOWN)
            {
                if(e.key.keysym.sym==SDLK_SPACE)
                    fast_forward = 1;
                else if(e.key.keysym.sym==SDLK_ESCAPE)
                    quit=1;
            }
            if(e.type==SDL_KEYUP)
                if(e.key.keysym.sym==SDLK_SPACE)
                    fast_forward = 0;

#ifdef GP2X
            if(e.type==SDL_JOYBUTTONDOWN)
            {
                switch(e.jbutton.button)
                {
                    case GP2X_BUTTON_X: quit++;
                        break;
                    case GP2X_BUTTON_B: quit++;
                        break;
                    case GP2X_BUTTON_VOLUP:
                        rvolo+=3; if(rvolo>99) rvolo=99;
                        lvolo+=3; if(lvolo>99) lvolo=99; break;
                    case GP2X_BUTTON_VOLDOWN:
                        rvolo-=3; if(rvolo<0) rvolo=0;
                        lvolo-=3; if(lvolo<0) lvolo=0; break;
                }

                gp2x_setvol(lvolo,rvolo);
            }
#endif
        }

#ifdef TIMING_TEST

        int nowpos, noworderpos, nowrow, beatpos, timefrombeat;
        memset(scr,0xFF,XRES*YRES*sizeof(buftype));
        bare_loadidentity();

        nowpos = mzx_position();
        noworderpos = nowpos / 100;
        nowrow = nowpos % 100;

        beatpos = (noworderpos * 64 + nowrow) & (0xFFFF-3);
        beatpos = (beatpos / 64) * 100 + (beatpos % 64);
        timefrombeat = now_ticks - mzx_time_of_position(beatpos);

        bare_translate(0.0,-0.3,-22);

        bare_rotatez(timefrombeat / 1000.0f);

        bare_render(gun,scr,NULL);
#endif
// <---------------------------------- TIMING_TEST
        
#ifndef HICOLOR // If hicolor, do the overlay etc. after 16-bit conversion
        overlay(scr,ovl);
        noise(scr, now_ticks/20);
#endif

    // Fix wrong RGB byteorder (maybe)
#ifndef HICOLOR
    if(fukkidrgba)
    {
        unsigned char tnp,*pt=s->pixels;
  #ifdef DOUBLEPIX
        pt=(unsigned char *)buf3;
  #endif
        for(n=0;n<XRES*YRES*4;n+=4)
        {
            tnp=pt[n+0];
            pt[n+0]=pt[n+3];
            pt[n+3]=tnp;
            tnp=pt[n+1];
            pt[n+1]=pt[n+2];
            pt[n+2]=tnp;
        }
    }
#endif

        // Slowly double the pixels if 320x240 is not natively supported
#ifdef DOUBLEPIX
        buftype *dst=s->pixels;
        unsigned offi;

        for(y=i=0;y<YRES;y++)
        {
            offi=y*XRES*4;
            for(x=0;x<XRES;x++,i++,offi+=2)
            {
                dst[offi]=
                dst[offi+1]=
                dst[offi+XRES*2]=
                dst[offi+XRES*2+1]=
                buf3[i];
            }
        }
#endif

#ifdef HICOLOR
        overlay((buftype *)gpscreen->pixels,ovl);
        noise((buftype *)gpscreen->pixels, now_ticks/20);

  #ifdef VIDEO
        SDL_LockSurface(s);

        for(n=0;n<YRES;n++)
            memcpy(&((unsigned short *)s->pixels)[(n+120)*XRES*2+160],&scr[n*XRES],XRES*sizeof(buftype));

        SDL_UnlockSurface(gpscreen);
        SDL_UnlockSurface(s);
        SDL_Flip(s);
  #else
        SDL_UnlockSurface(gpscreen);
        SDL_Flip(gpscreen);
  #endif

#else
        SDL_UnlockSurface(s);
        SDL_Flip(s);
#endif
    }

    SDL_Quit();

#ifdef GP2X
    gp2x_menu();
#endif

    return(0);
}
