#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

#define ALFANUMERICO 0x03
#define GRAFICO      0x13

void  DIBUJA_BLOQUE_SIN_MASK_CUT(int *, char *, char *);
void  DIBUJA_BLOQUE_CON_MASK_CUT(int *, char *, char *);
void  VUELCA_PANTALLA(int,int, int,int, int,int, char *);
void  pantalla_cine(void);
void  cinta_cine(void);
void  premios(void);
void  premiados(void);
void  espera_pulsar(void);
void  espera_soltar(void);
void  no_hay_raton(void);
void  desactiva_raton(void);
void  activa_raton(void);
void  dibuja_graficos(void);
void  inicializa_raton_texto(void);
void  inicializa_raton_grafico(void);
void  salir_al_dos(void);
void  asigna_modo_video(char);
void  lee_dibujos(char *);
void  descomprime_dibujo(char *);
void  asigna_rgb(char *);
void  asigna_memoria(void);
void  libera_memoria(void);

int   x_raton;
int   y_raton;
int   y_raton_ant;
int   boton_izq;
int   boton_der;
int   pos_playa     [6] = {   0, 0,           0,  0, 320,200 };
int   pos_toalla    [8] = { 188, 0, 188,47, 130,152,  87, 47 };
int   pos_sombrilla [8] = {   0, 0,  94, 0, 175,110,  94, 70 };
int   pos_pelota    [8] = { 275, 0, 275,23, 185,170,  25, 23 };
char  fichero1       [] = { "raton1.pcx" };
char  fichero2       [] = { "raton2.pcx" };
int   dir_raton [32+32] = { 0x3FFF,		       /* m�scara del cursor */
			    0x1FFF,
			    0x0FFF,
			    0x07FF,
			    0x03FF,
			    0x01FF,
			    0x00FF,
			    0x007F,
			    0x003F,
			    0x001F,
			    0x000F,
			    0x0007,
			    0x0007,
			    0xF81F,
			    0xFC0F,
			    0xFE0F,

			    0x0000,		        /* dibujo del cursor */
			    0x4000,
			    0x6000,
			    0x7000,
			    0x7800,
			    0x7C00,
			    0x7E00,
			    0x7F00,
			    0x7F80,
			    0x7FC0,
			    0x7FE0,
			    0x7FF0,
			    0x0780,
			    0x03C0,
			    0x01E0,
			    0x0000 };
char  color_izq=DARKGRAY;
char  color_der=BROWN;
char *dir_carga_dibujos;
char *dir_dibujo1;
char *dir_dibujo2;
char *dir_zona_pantalla;
FILE *handle_dibujos;

/*//////////////////////////////// PROGRAMA ////////////////////////////////*/

void main(void)
{
	 union REGS ent, sal;

        asigna_memoria();

        asigna_modo_video(ALFANUMERICO);
        inicializa_raton_texto();
        desactiva_raton();
        pantalla_cine();
        cinta_cine();
        premios();
	activa_raton();
	while(bioskey(1)!=0) bioskey(0);

        do{
          espera_pulsar();
          desactiva_raton();
          if(boton_izq==1) color_izq=LIGHTGRAY;
          if(boton_der==1) color_der=YELLOW;
          cinta_cine();
          premiados();
          activa_raton();
          espera_soltar();
          desactiva_raton();
          if(boton_izq==0) color_izq=DARKGRAY;
          if(boton_der==0) color_der=BROWN;
          cinta_cine();
          premios();
          activa_raton();
        }while(bioskey(1)==0);

        asigna_modo_video(GRAFICO);
        lee_dibujos(fichero1);
        descomprime_dibujo(dir_dibujo1);
        lee_dibujos(fichero2);
	descomprime_dibujo(dir_dibujo2);

        inicializa_raton_grafico();
        DIBUJA_BLOQUE_SIN_MASK_CUT(pos_playa,     dir_dibujo1, dir_zona_pantalla);
        DIBUJA_BLOQUE_CON_MASK_CUT(pos_toalla,    dir_dibujo2, dir_zona_pantalla);
        DIBUJA_BLOQUE_CON_MASK_CUT(pos_pelota,    dir_dibujo2, dir_zona_pantalla);
        DIBUJA_BLOQUE_CON_MASK_CUT(pos_sombrilla, dir_dibujo2, dir_zona_pantalla);
        desactiva_raton();
        VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
	activa_raton();
	while(bioskey(1)!=0) bioskey(0);

        do{
          ent.x.ax = 3;
          int86(0x33, &ent, &sal);       /* lee posici�n y estados del bot�n */
          boton_izq=sal.x.bx & 1;
          boton_der=(sal.x.bx >> 1) & 1;

          if((boton_izq==1 || boton_der==1) &&
          x_raton>=pos_toalla[4]+(pos_toalla[6]/2)-4 &&
          x_raton<=pos_toalla[4]+(pos_toalla[6]/2)+4 &&
          y_raton>=pos_toalla[5]+(pos_toalla[7]/2)-4 &&
          y_raton<=pos_toalla[5]+(pos_toalla[7]/2)+4) {
            pos_toalla[4]=(sal.x.cx >> 1)-(pos_toalla[6]/2);
            pos_toalla[5]=(sal.x.dx     )-(pos_toalla[7]/2);
            dibuja_graficos();
            desactiva_raton();
            VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
            activa_raton();
          }
          else if((boton_izq==1 || boton_der==1) &&
          x_raton>=pos_pelota[4]+(pos_pelota[6]/2)-4 &&
          x_raton<=pos_pelota[4]+(pos_pelota[6]/2)+4 &&
          y_raton>=pos_pelota[5]+(pos_pelota[7]/2)-4 &&
          y_raton<=pos_pelota[5]+(pos_pelota[7]/2)+4) {
            pos_pelota[4]=(sal.x.cx >> 1)-(pos_pelota[6]/2);
            pos_pelota[5]=(sal.x.dx     )-(pos_pelota[7]/2);
            dibuja_graficos();
            desactiva_raton();
            VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
            activa_raton();
          }
          else if((boton_izq==1 || boton_der==1) &&
          x_raton>=pos_sombrilla[4]+(pos_sombrilla[6]/2)-4 &&
          x_raton<=pos_sombrilla[4]+(pos_sombrilla[6]/2)+4 &&
          y_raton>=pos_sombrilla[5]+(pos_sombrilla[7]/2)-4 &&
          y_raton<=pos_sombrilla[5]+(pos_sombrilla[7]/2)+4) {
            pos_sombrilla[4]=(sal.x.cx >> 1)-(pos_sombrilla[6]/2);
            pos_sombrilla[5]=(sal.x.dx     )-(pos_sombrilla[7]/2);
            dibuja_graficos();
            desactiva_raton();
            VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
            activa_raton();
          }
          x_raton=sal.x.cx >> 1;
          y_raton=sal.x.dx;
        }while(bioskey(1)==0);
        while(bioskey(1)!=0) bioskey(0);

        salir_al_dos();
}

void dibuja_graficos(void)
{
        DIBUJA_BLOQUE_SIN_MASK_CUT(pos_playa,     dir_dibujo1, dir_zona_pantalla);
        DIBUJA_BLOQUE_CON_MASK_CUT(pos_toalla,    dir_dibujo2, dir_zona_pantalla);
        DIBUJA_BLOQUE_CON_MASK_CUT(pos_pelota,    dir_dibujo2, dir_zona_pantalla);
        DIBUJA_BLOQUE_CON_MASK_CUT(pos_sombrilla, dir_dibujo2, dir_zona_pantalla);
}

void inicializa_raton_texto(void)
{
        union REGS ent, sal;

        ent.x.ax =   0;
        int86(0x33, &ent, &sal);          /* averigua si hay rat�n conectado */

        if(sal.x.ax==0) no_hay_raton();

        ent.x.ax =  15;
        ent.x.cx =   8;
        ent.x.dx =  16;
        int86(0x33, &ent, &sal);               /* fija la raz�n mickey/pixel */

        ent.x.ax =   7;
        ent.x.cx =   0;
        ent.x.dx = 639;
        int86(0x33, &ent, &sal);  /* fija la posici�n m�x. y m�n. horizontal */

        ent.x.ax =   8;
        ent.x.cx =   0;
        ent.x.dx = 199;
        int86(0x33, &ent, &sal);    /* fija la posici�n m�x. y m�n. vertical */

        ent.x.ax =   4;
        ent.x.cx = 320;
        ent.x.dx = 100;
        int86(0x33, &ent, &sal);               /* fija la posici�n del rat�n */

        ent.x.ax =   1;
        int86(0x33, &ent, &sal);             /* muestra el puntero del rat�n */
}

void inicializa_raton_grafico(void)
{
        struct SREGS seg;
	union   REGS ent, sal;
	long         dir;

        ent.x.ax =   0;
        int86(0x33, &ent, &sal);          /* averigua si hay rat�n conectado */

        if(sal.x.ax==0) no_hay_raton();

        ent.x.ax =  15;
	ent.x.cx =   5;
        ent.x.dx =  12;
        int86(0x33, &ent, &sal);               /* fija la raz�n mickey/pixel */

        ent.x.ax =   7;
        ent.x.cx =   0;
        ent.x.dx = 639;
        int86(0x33, &ent, &sal);  /* fija la posici�n m�x. y m�n. horizontal */

        ent.x.ax =   8;
        ent.x.cx =   0;
        ent.x.dx = 199;
        int86(0x33, &ent, &sal);    /* fija la posici�n m�x. y m�n. vertical */

	dir      = (long)dir_raton;
        ent.x.ax =   9;
        ent.x.bx =   0;
        ent.x.cx =   0;
	ent.x.dx = (int) dir;
	seg.es   = (int)(dir >> 16);
	int86x(0x33, &ent, &sal, &seg);        /* asigna un cursor diferente */

        ent.x.ax =   4;
        ent.x.cx = 320;
        x_raton=ent.x.cx >> 1;
        ent.x.dx = 100;
        y_raton=ent.x.dx;
        int86(0x33, &ent, &sal);               /* fija la posici�n del rat�n */

        ent.x.ax =   1;
        int86(0x33, &ent, &sal);             /* muestra el puntero del rat�n */
}

void activa_raton(void)
{
        union REGS ent, sal;

        ent.x.ax = 1;
        int86(0x33, &ent, &sal);
}

void desactiva_raton(void)
{
        union REGS ent, sal;

        ent.x.ax = 2;
        int86(0x33, &ent, &sal);
}

void espera_pulsar(void)
{
        union REGS ent, sal;

        do{
          if(bioskey(1)!=0) break;
          ent.x.ax = 3;
          int86(0x33, &ent, &sal);       /* lee posici�n y estados del bot�n */
        }while((sal.x.bx & 3)==0);
        boton_izq=sal.x.bx & 1;
        boton_der=(sal.x.bx >> 1) & 1;
        x_raton=sal.x.cx >> 1;
        y_raton=sal.x.dx;
}

void espera_soltar(void)
{
        union REGS ent, sal;

        do{
          ent.x.ax = 3;
          int86(0x33, &ent, &sal);       /* lee posici�n y estados del bot�n */
        }while((sal.x.bx & 3)!=0);
        boton_izq=sal.x.bx & 1;
        boton_der=(sal.x.bx >> 1) & 1;
        x_raton=sal.x.cx >> 1;
        y_raton=sal.x.dx;
}

void no_hay_raton(void)
{
        asigna_modo_video(ALFANUMERICO);
        libera_memoria();
        gotoxy(1,1); printf("No hay RATON instalado");
        exit(0);
}

void salir_al_dos(void)
{
        asigna_modo_video(ALFANUMERICO);
        libera_memoria();
        exit(0);
}

void asigna_memoria(void)
{
        if((dir_zona_pantalla = malloc (64000))==NULL) {
          printf("No hay suficiente memoria. Libere programas residentes.");
          exit(1);
        }
        if((dir_carga_dibujos = malloc (65000))==NULL) {
          printf("No hay suficiente memoria. Libere programas residentes.");
          exit(1);
        }
        if((dir_dibujo1       = malloc (64000))==NULL) {
          printf("No hay suficiente memoria. Libere programas residentes.");
          exit(1);
        }
        if((dir_dibujo2       = malloc (64000))==NULL) {
          printf("No hay suficiente memoria. Libere programas residentes.");
          exit(1);
        }
}

void libera_memoria(void)
{
        free(dir_zona_pantalla);
        free(dir_carga_dibujos);
        free(dir_dibujo1);
        free(dir_dibujo2);
}

void asigna_modo_video(char modo)   /* asigna el modo de v�deo indicado      */
{                                   /* en la variable "modo"                 */
        union REGS ent, sal;

        ent.h.al = modo;
        ent.h.ah = 0;
        int86(16, &ent, &sal);      /* funci�n para asignar el modo de video */
}

void lee_dibujos(char *fichero)
{
        char *p;

        if((handle_dibujos = fopen(fichero, "rb"))==NULL) {
          printf("No se puede abrir el archivo.");
          exit(1);
        }
        p=dir_carga_dibujos;
        while(!feof(handle_dibujos)) {
          *p++=getc(handle_dibujos);
        }
        if(fclose(handle_dibujos)!=NULL) {
          printf("No se puede cerrar el archivo.");
          exit(1);
        }
}

void descomprime_dibujo(char *dir_escritura)
{
        unsigned char  byte;
                 char *dir_lectura;
                 int   columnas, filas, contador;

        dir_lectura=dir_carga_dibujos+128;   /* inicio del dibujo comprimido */

        for(filas=200; filas>0; filas--) {
          columnas=320;
          dir_escritura-=columnas; dir_escritura+=320;
          while(columnas>0) {
            byte=(unsigned)*dir_lectura++;
            if(byte<=192) { *dir_escritura++=byte; columnas--; }
            else {
              contador=byte&63; byte=*dir_lectura++;
              for(;contador>0;contador--) { *dir_escritura++=byte;columnas--; }
            }
          }
        }
        dir_lectura++;
        asigna_rgb(dir_lectura);       /* remapea los 256 colores del dibujo */
}

void asigna_rgb(char *dir_lectura)
{
        struct   SREGS  seg;
        union     REGS  ent, sal;
        unsigned  int   reg_dx, n;
        long      int   dir;
                  char *dir_col;

        dir_col=dir_lectura;                                /* divide entre  */
        for(n=256*3; n>0; n--) {                            /* 4 los colores */
          *dir_col=*dir_col >> 2; dir_col++;
        }

        reg_dx=(int)dir_lectura;                 /* offset de los colores    */
        dir   =(long)dir_lectura;                /* obtiene el segmento      */
        seg.es=(int)(dir >> 16);                 /* donde estan los colores  */

        ent.h.al =  18;
        ent.h.ah =  16;
        ent.x.bx =   0;
        ent.x.cx = 256;
        ent.x.dx = reg_dx;
        int86x(0x10, &ent, &sal, &seg);  /* funci�n para asignar los colores */
}

void cinta_cine(void)
{
        textcolor(color_izq);
        gotoxy(21, 1); cprintf                    ("�����    �������");
        gotoxy(19, 2); cprintf                  ("���������    ���");
        gotoxy(17, 3); cprintf                (" ������������   ");
        gotoxy(15, 4); cprintf              ("�    �����������");
        gotoxy(13, 5); cprintf            ("�����    �������");
        gotoxy(11, 6); cprintf          ("���������    ���");
        gotoxy( 9, 7); cprintf        (" ������������   ");
        gotoxy( 7, 8); cprintf      ("�    �����������");
        gotoxy( 5, 9); cprintf    ("�����    �������");
        gotoxy( 3,10); cprintf  ("���������    ���");
        gotoxy( 1,11); cprintf(" ������������   ");
        gotoxy( 1,12); cprintf("   �����������");
        gotoxy( 1,13); cprintf("�    �������");
        gotoxy( 1,14); cprintf("���    ���");
        gotoxy( 1,15); cprintf("�����  ");
        gotoxy( 1,16); cprintf("������");
        gotoxy( 1,17); cprintf("����");
        gotoxy( 1,18); cprintf("��");

        textcolor(color_der);
        gotoxy(79,14); cprintf                      ("� ");
        gotoxy(77,15); cprintf                    ("����");
        gotoxy(75,16); cprintf                  ("������");
        gotoxy(73,17); cprintf                (" �������");
        gotoxy(71,18); cprintf              ("�    �����");
        gotoxy(69,19); cprintf            ("�����    ���");
        gotoxy(67,20); cprintf          ("���������    �");
        gotoxy(65,21); cprintf        (" ������������   ");
        gotoxy(63,22); cprintf      ("�    �����������");
        gotoxy(61,23); cprintf    ("�����    �������");
        gotoxy(59,24); cprintf  ("���������    ���");
        gotoxy(57,25); cprintf(" ������������   ");
}

void pantalla_cine(void)
{
        textbackground(BLACK); textcolor(BLACK); clrscr();
        textcolor(BLUE);
        gotoxy( 1, 1); cprintf("                 �                   �");
        gotoxy( 1, 2); cprintf("               �                   �  ");
        gotoxy( 1, 3); cprintf("             �                   �    ");
        gotoxy( 1, 4); cprintf("           �                   �      ");
        gotoxy( 1, 5); cprintf("         �                   �        ");
        gotoxy( 1, 6); cprintf("       �                   �          ");
        gotoxy( 1, 7); cprintf("     �                   �            ");
        gotoxy( 1, 8); cprintf("   �                   �              ");
        gotoxy( 1, 9); cprintf(" �                   �                ");
        gotoxy( 1,10); cprintf("                   �                  ");
        gotoxy( 1,11); cprintf("                 �                    ");
        gotoxy( 1,12); cprintf("               �                      ");
        gotoxy( 1,13); cprintf("             �                        ");
        gotoxy( 1,14); cprintf("           �                          ");
        gotoxy( 1,15); cprintf("         �                            ");
        gotoxy( 1,16); cprintf("       �                              ");
        gotoxy( 1,17); cprintf("     �                                ");
        gotoxy( 1,18); cprintf("   �                                  ");
        gotoxy( 1,19); cprintf(" �                                    ");

        textcolor(BLUE);
        gotoxy(54,12); cprintf("                          �");
        gotoxy(54,13); cprintf("                        �  ");
        gotoxy(54,14); cprintf("                      �    ");
        gotoxy(54,15); cprintf("                    �      ");
        gotoxy(54,16); cprintf("                  �        ");
        gotoxy(54,17); cprintf("                �          ");
        gotoxy(54,18); cprintf("              �            ");
        gotoxy(54,19); cprintf("            �              ");
        gotoxy(54,20); cprintf("          �                ");
        gotoxy(54,21); cprintf("        �                  ");
        gotoxy(54,22); cprintf("      �                   �");
        gotoxy(54,23); cprintf("    �                   �  ");
        gotoxy(54,24); cprintf("  �                   �    ");
        gotoxy(54,25); cprintf("�                   �     ");
}

void premios(void)
{
        textcolor(WHITE);
        gotoxy(49, 1); cprintf("LXVI EDICION DE LOS OSCARS");

        textcolor(YELLOW);
        gotoxy(45, 3); cprintf("MEJOR PELICULA                      ");
        gotoxy(43, 4); cprintf("MEJOR DIRECTOR                        ");
        gotoxy(41, 5); cprintf("MEJOR ACTRIZ                            ");
        gotoxy(39, 6); cprintf("MEJOR ACTOR                               ");
        gotoxy(37, 7); cprintf("MEJOR ACTRIZ SECUNDARIA                     ");
        gotoxy(35, 8); cprintf("MEJOR ACTOR SECUNDARIO                        ");
        gotoxy(33, 9); cprintf("MEJOR PELICULA EXTRANJERA                       ");
        gotoxy(31,10); cprintf("MEJOR GUION ORIGINAL                              ");
        gotoxy(29,11); cprintf("MEJOR GUION ADAPTADO                                ");
        gotoxy(27,12); cprintf("MEJOR DIRECCION ARTISTICA                           ");
        gotoxy(25,13); cprintf("MEJOR SONIDO                                        ");
        gotoxy(23,14); cprintf("MEJOR MONTAJE                                       ");
        gotoxy(21,15); cprintf("MEJOR FOTOGRAFIA                                    ");
        gotoxy(19,16); cprintf("MEJOR EFECTOS DE SONIDO                             ");
        gotoxy(17,17); cprintf("MEJOR MUSICA ORIGINAL                               ");
        gotoxy(15,18); cprintf("MEJOR CANCION                                       ");
        gotoxy(13,19); cprintf("MEJOR VESTUARIO                                     ");
        gotoxy(11,20); cprintf("MEJOR EFECTOS VISUALES                              ");
        gotoxy( 9,21); cprintf("MEJOR MAQUILLAJE                                    ");
        gotoxy( 7,22); cprintf("MEJOR CORTO DE ANIMACION                            ");
        gotoxy( 5,23); cprintf("MEJOR CORTO DE ACCION EN VIVO                       ");
        gotoxy( 3,24); cprintf("MEJOR LARGOMETRAJE DOCUMENTAL                       ");
        gotoxy( 1,25); cprintf("MEJOR CORTO DOCUMENTAL                              ");
}

void premiados(void)
{
        textcolor(WHITE);
        switch(y_raton/8) {
          case  2: gotoxy(45, 3); cprintf("�La lista de Schindler�             "); break;
          case  3: gotoxy(43, 4); cprintf("Spielberg, �La lista de Schindler�    "); break;
          case  4: gotoxy(41, 5); cprintf("Holly Hunter, �El Piano�                "); break;
          case  5: gotoxy(39, 6); cprintf("Tom Hanks, �Philadelphia�                 "); break;
          case  6: gotoxy(37, 7); cprintf("Anna Paquin, �El Piano�                     "); break;
          case  7: gotoxy(35, 8); cprintf("Tommy Lee Jones, �El Fugitivo�                "); break;
	  case  8: gotoxy(33, 9); cprintf("�Belle �poque� (Espa�a), Fernando Trueba        "); break;
          case  9: gotoxy(31,10); cprintf("Jane Campion, �El Piano�                          "); break;
          case 10: gotoxy(29,11); cprintf("Steven Zaillian, �La lista de Schindler�            "); break;
          case 11: gotoxy(27,12); cprintf("Allan Starski y Ewa Braun, �La lista de Schindler�  "); break;
          case 12: gotoxy(25,13); cprintf("�Parque Jur�sico�                                   "); break;
          case 13: gotoxy(23,14); cprintf("Michael Kahn, �La lista de Schindler�               "); break;
          case 14: gotoxy(21,15); cprintf("Janusz Kaminski, �La lista de Schindler�            "); break;
          case 15: gotoxy(19,16); cprintf("�Parque Jur�sico�                                   "); break;
          case 16: gotoxy(17,17); cprintf("John Williams, �La lista de Schindler�              "); break;
          case 17: gotoxy(15,18); cprintf("�Streets of Philadelphia�, Bruce Springsteen        "); break;
          case 18: gotoxy(13,19); cprintf("Gabriella Pescucci, �La edad de la inocencia�       "); break;
          case 19: gotoxy(11,20); cprintf("�Parque Jur�sico�                                   "); break;
          case 20: gotoxy( 9,21); cprintf("�Sra. Doubtfire�                                    "); break;
          case 21: gotoxy( 7,22); cprintf("�The wrong trousers�                                "); break;
          case 22: gotoxy( 5,23); cprintf("�Schwarzfahrer�                                     "); break;
          case 23: gotoxy( 3,24); cprintf("�I am a promise:child. of Stanton Elementary School�"); break;
          case 24: gotoxy( 1,25); cprintf("�Defending our lives�                               "); break;
        }
}