
#include <i86.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <math.h>

// -----------------------

void VGA_WaitForRetrace(void) {
    while ((inp(0x3DA) & 8) == 0);
}

void VGA_WaitForDisplay(void) {
    while ((inp(0x3DA) & 8) == 8);
}

void VGA_VSync(void) {
    VGA_WaitForDisplay();
    VGA_WaitForRetrace();
}

// -----------------------
                  
void PAL_Fade(char *inicial, char *final)
{
int n,distintos;
char *dest,*tmp;
char temppal[768];
memcpy(temppal,inicial,768);
distintos=1;
while(distintos && !kbhit()){
        distintos=0;
        dest=final; 
        tmp=temppal;
        for(n=0;n<768;n++){
            if(*tmp!=*dest){
                distintos=1;
                if(*tmp<*dest)
                        (*tmp)++;
                else    
                        (*tmp)--;
            }
            tmp++;
            dest++;
        }
        VGA_VSync();
        PAL_SetPal(temppal);
    }
}

void VuelcaPal(char *pal, int n);
#pragma aux VuelcaPal parm [ESI] [ECX] modify [EDX] = \
    "MOV EDX,0x3C9" \
    "lp:"           \
    "OUTSB"         \
    "OUTSB"         \
    "OUTSB"         \
    "SUB    ECX,3"  \
    "JA lp"

void PAL_SetPal(char *paleta)
{
    if (paleta == NULL) return;    

    outp(0x3c8, 0x0); // Set to first color
    VuelcaPal(paleta, 768);
/*
    for (i= 0; i<768; i++)
    {

        outp(0x3c9, paleta[i]); };
*/
}

// -----------------------

#pragma aux memcpy parm [EDI] [ESI] [ECX] = \
    "MOV    EAX,ECX" \
    "SHR    ECX,2"   \
    "REP MOVSD"      \
    "AND    EAX,3"   \
    "MOV    ECX,EAX" \
    "REP MOVSB"


typedef unsigned char  bool;
typedef unsigned char  byte;
typedef unsigned short word;
typedef unsigned long  dword;

typedef signed char  sbyte;
typedef signed short sword;
typedef signed long  sdword;

#define PUBLIC  extern
#define PRIVATE static

enum {
    FALSE,
    TRUE
};

union REGS regs;
struct SREGS sregs;

typedef byte TScr[200][320];
typedef byte (*PScr)[320];
TScr scr;
#define vgascr ((PScr)0xA0000UL)

struct {
    byte head[32];
    byte pal[768];
    TScr scr;
} cel;

void DumpScr(void) {
    static int cont;
    int i, j;
    byte *p = vgascr;
    byte *s;
    int w1, w2;

    p += 320 *(cont&1)+ ((cont & 2)>>1);
    w1 = 321 - (cont&2);
    w2 = 319 + (cont&2);

    cont++;

    for(i=0;i<100;i+=2){
        s=scr[i];
        for(j=0;j<160;j++){
                *p++=*s;
                s++;
                p++;
                }
        p+=w1;
        s=scr[i+1];
        for(j=0;j<160;j++){
                *p++=*s;
                s++;
                p++;
                }
        p+=w2;
        }

}

#define LONGX 160
#define LONGY 100

char pal1[768], pal2[1152], pal3[768];
int CambPal = 0;

int CosTab[2048];


dword tdist1[2*LONGY+1][2*LONGX+1];
dword tdist2[2*LONGY+1][2*LONGX+1];
dword tdist3[2*LONGY+1][2*LONGX+1];
dword tdist4[2*LONGY+1][2*LONGX+1];
dword tdist5[2*LONGY+1][2*LONGX+1];

typedef struct {
    int x, y, px, py, vx, vy;
} TCenter;

TCenter
    g1 = {65, 55}
   ,g2 = {75, 135}
   ,g3 = {145, 60}
//    g1 = {130, 10}
//   ,g2 = {150, 70}
//   ,g3 = {50, 90}
;

#define wt1 31 //123
#define wt2 13 //35
#define wt3 7  //67

#define beta1 5
#define beta2 25
#define beta3 15

void InitCenter(TCenter  *c) {
    c->px = (c->px * LONGX) / 100;
    c->py = (c->py * LONGY) / 100;
    c->px = c->x << 8;
    c->py = c->y << 8;
    c->vx = 0;
    c->vy = 0;
}

#define VEL 16

void MoveCenter(TCenter  *c) {
    if (c->py < (LONGY << 8))
        c->vy += VEL;
    else if (c->py > (LONGY << 8))
        c->vy -= VEL;
    if (c->px < (LONGX << 8))
        c->vx += VEL;
    else if (c->px > (LONGX << 8))
        c->vx -= VEL;
    c->px += c->vx;
    c->py += c->vy;
    c->x = c->px >> 8;
    c->y = c->py >> 8;
}

void main() {
    int i, j;
    char *p;
    byte *s;

    int time;

    int *ct1, *ct2, *ct3;
    int fase1 = 134, fase2 = 345, fase3 = 234;

    printf("If you don't own a 486 with coprocessor you better not\n"
           "run this. Look at the code to find out why...\n"
           );

    {
        FILE *f;
        f = fopen("poslogo.cel", "rb");
        fread(&cel, 64800, 1, f);
        fclose(f);
    }

    for (i=0; i< 2048; i++)
    {   CosTab[i] = 256.0*cos(i*3.149648/512.0);
    }

    for (i = 0; i < 2*LONGY+1; i++)
        for (j = 0; j < 2*LONGX+1; j++)
        {    tdist1[i][j] = (beta1 *(int) sqrt((j-LONGX)*(j-LONGX) +
            (i-LONGY)*(i-LONGY))) %  1024;
           tdist2[i][j] = (beta2*(int) sqrt((j-LONGX)*(j-LONGX) +
            (i-LONGY)*(i-LONGY))) %  1024;
            tdist3[i][j] = (beta3 *(int) sqrt((j-LONGX)*(j-LONGX) +
            (i-LONGY)*(i-LONGY))) %  1024;
        }
    for (i = 0; i < 2*LONGY+1; i++)
        for (j = 0; j < 2*LONGX+1; j++)
            tdist4[i][j] = 1024/(1+sqrt((j-LONGX)*(j-LONGX) + (i-LONGY)*(i-LONGY)));

    for (i = 0; i < 2*LONGY+1; i++)
        for (j = 0; j < 2*LONGX+1; j++)
            tdist5[i][j] = (int) sqrt((j-LONGX)*(j-LONGX) + (i-LONGY)*(i-LONGY)) %
            1024;
    memset(pal3, 0, 768);

    p = pal1;
    for (i = 0; i < 64; i++) {
        *p++ = 0;
        *p++ = i;
        *p++ = i;
    }
    for (i = 0; i < 64; i++) {
        *p++ = i;
        *p++ = 63-i;
        *p++ = 63;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 63;
        *p++ = i;
        *p++ = 63-i;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 63-i;
        *p++ = 63-i;
        *p++ = 0;
    }

    p = pal2;
    for (i = 0; i < 64; i++) {
        *p++ = i;
        *p++ = 0;
        *p++ = 0;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 63-i;
        *p++ = 0;
        *p++ = 0;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 0;
        *p++ = 0;
        *p++ = i;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 0;
        *p++ = 0;
        *p++ = 63-i;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 0;
        *p++ = i;
        *p++ = 0;
    }
    for (i = 0; i < 64; i++) {
        *p++ = 0;
        *p++ = 63-i;
        *p++ = 0;
    }


    InitCenter(&g1);
    InitCenter(&g2);
    InitCenter(&g3);

    regs.w.ax = 0x13;
    int386(0x10, &regs, &regs);

otra:

    VGA_VSync();
    PAL_SetPal(pal3);

//    outp(0x3D4, 9);
//  outp(0x3D5, (inp(0x3D5) & 0xE0) + 1);

    memcpy(vgascr, cel.scr, 64000);

    VGA_VSync();
    PAL_Fade(pal3,cel.pal);

    for (time = 0; time < 70*5 && !kbhit(); time++) VGA_VSync();
//    getch();


    PAL_SetPal(pal1);

  //  outp(0x3D4, 9);
    //outp(0x3D5, (inp(0x3D5) & 0xE0) + 3);

    memset(vgascr, 0, 64000);
    time = 0;
    while (time < 20*10 && !kbhit()) {
        for (i = LONGY/2; i < LONGY+LONGY/2; i++) {
            s = scr[i-LONGY/2];
            for (j = LONGX/2; j < LONGX+LONGX/2; j++)
                *s++ = (
                            tdist4[LONGY+i-g1.y][LONGX+j-g1.x]
                           -tdist4[LONGY+i-g2.y][LONGX+j-g2.x]
                           +tdist4[LONGY+i-g3.y][LONGX+j-g3.x]
                           ) / 2;
        }
        time++;
        VGA_VSync();
        DumpScr();

        MoveCenter(&g1);
        MoveCenter(&g2);
        MoveCenter(&g3);
    }
//    getch();
    
    fase1 = 134, fase2 = 345, fase3 = 234;

    ct1 = CosTab + (fase1 += wt1) % 1024;
    ct2 = CosTab + (fase2 += wt2) % 1024;
    ct3 = CosTab + (fase3 += wt3) % 1024;
    time = 0;
    while (time < 20*10 && !kbhit()) {

/*
        ct1 = CosTab + (fase1 += wt1) % 1024;
        ct2 = CosTab + (fase2 += wt2) % 1024;
        ct3 = CosTab + (fase3 += wt3) % 1024;
*/
        for (i = LONGY/2; i < LONGY+LONGY/2; i++) {
            s = scr[i-LONGY/2];
            for (j = LONGX/2; j < LONGX+LONGX/2; j++)
                *s++ = (
                           ( ct1[tdist5[LONGY+i-g1.y][LONGX+j-g1.x]]
                           +ct2[tdist5[LONGY+i-g2.y][LONGX+j-g2.x]]
                           -ct3[tdist5[LONGY+i-g3.y][LONGX+j-g3.x]]
                           ) /1);
        }
        VGA_VSync();
        time++;
        DumpScr();

        MoveCenter(&g1);
        MoveCenter(&g2);
        MoveCenter(&g3);

    }
//    getch();


    time = 0;
    PAL_SetPal(pal2+(3*128)*CambPal);
    CambPal = (CambPal)? 0:1;

    while (time < 20*10 && !kbhit()) {

        ct1 = CosTab + (fase1 += wt1) % 1024;
        ct2 = CosTab + (fase2 += wt2) % 1024;
        ct3 = CosTab + (fase3 += wt3) % 1024;


        for (i = LONGY/2; i < LONGY+LONGY/2; i++) {
            s = scr[i-LONGY/2];
            for (j = LONGX/2; j < LONGX+LONGX/2; j++)
                *s++ =
                           ( ct1[tdist1[LONGY+i-g1.y][LONGX+j-g1.x]]
                           +ct2[tdist2[LONGY+i-g2.y][LONGX+j-g2.x]]
                           +ct3[tdist3[LONGY+i-g3.y][LONGX+j-g3.x]]
                           ) /4;
        }
        VGA_VSync();
        time++;
        DumpScr();

        MoveCenter(&g1);
        MoveCenter(&g2);
        MoveCenter(&g3);

    }

    if (!kbhit())
        goto otra;

    getch();

    regs.w.ax = 0x3;
    int386(0x10, &regs, &regs);

    puts(
"Intro coded during the Posadas Amiga Party in 1995.\n"
"   Original idea by OLS/Iguana.\n"
"   Additional code by Jare/Iguana and Zhorlack/W.A.H.T.\n"
"   PMODE/W 1.16 by Tran & Daredevil.\n"
"\n"
"Only tools available were Watcom C 10.0a, QEdit, Boxer and Animator 1.0.\n"
"Only machine available was a !portable! Dell 486-75.\n"
"\n"
"Greetings to all PC dudes, and also to all Amiga dudes that own a PC and\n"
"don't dare confess it. :)\n"
"Also to all participants in the party, the organizers, the three babes\n"
"dressed in black last night, and the swimming pool watchman.\n"
"\n"
"See you soon at the Euskal Party! (12-15 October, 1995, Tolosa, Spain).\n"
"For more info get the Invitation: EUINVTRO.ZIP at the usual sites.\n"
"\n"
"That's all, folks!\n"
);
}
