/********************************
 * Příklad na dvourozměrné vlny *
 * Napsal Bulb roku 1997        *
 ********************************/

/* Tento zdrojový kód byl psán a testován v kompilátoru    *
 * DJGPP v2. Nicméně jsem se snažil napsat jej tak, aby    *
 * neobsahoval žádné systémově či kompilátorově specifické *
 * funkce, takže by mělo být možné jej přeložit libovolným *
 * kompilátorem pod podmínkou, že si pro tento kompilátor  *
 * napíšete vlastní I/O rutiny, jejichž verze pro DJGPP v2 *
 * a TURBO C přikládám ve dvou variantách souboru xmisc.if */

#include<conio.h> /* testování klávesnice pomocí kbhit/getch */

#include"xmisc.if" /* Bulbovy příkladové I/O funkce */

#define IDIM 100 /* 200 / 2 (y) */
#define JDIM 160 /* 320 / 2 (x) */
#define ROWS 200
#define COLS 320
/* pozn: není to izotropní -> bude to vypadat divně */

int main(void)
{
    fixed p[IDIM*JDIM]; /* pole okamžitých výchylek */
    fixed v[IDIM*JDIM]; /* pole rychlostí (1. derivace) */
    long pavg=0, vavg=0; /* proměnné pro průměrování */
#ifndef __GNUC__  /* GNU C podporuje 64-bitové integery */
    long long tmp;
    long long psum=0, vsum=0; /* pomocné proměnné pro průměrování - DJGPP */
#else /* V ostatních případech se použije pomalejší přetypování na double */
    double tmp;
    double psum=0, vsum=0; /* pomocné proměnné pro průměrování - TC/BC */
#endif
    long i=0, j=0, k=0; /* pomocné proměnné */

    for(i = 0; i < IDIM*JDIM; i++) {p[i] = 0; v[i] = 0;};
        /* počáteční podmínky */

    while(kbhit()) getch();

    x_set_mcga(); /* nastav MCGA mode (13h) */

    for(i = 0, j = 32; i < 32; i++, j++)   /* nastav paletu   0 -  31 */
        x_mcga_set_color(i, 0, j, 63);
    for(i = 32, j = 1; i < 95; i++, j++)   /* nastav paletu  32 -  94 */
        x_mcga_set_color(i, j, 63, 63);
    for(i = 95; i < 161; i++)              /* nastav paletu  95 - 160 */
        x_mcga_set_color(i, 31, 31, 31);
    for(i = 161, j = 0; i < 225; i++, j++) /* nastav paletu 161 - 224 */
        x_mcga_set_color(i, 0, 0, j);
    for(i = 225, j = 1; i < 256; i++, j++) /* nastav paletu 225 - 255 */
        x_mcga_set_color(i, 0, j, 63);

    for(k = 0; !kbhit(); k++) { /* začátek výpočetní smyčky */
        vsum = 0; /* nulování sčítacích proměnných */
        psum = 0;

        for(i = JDIM; i < JDIM * (IDIM - 1); i += JDIM) {
            for(j = i + 1; j < i + JDIM - 1; j++) {
                v[j] += ((p[j+1] + p[j-1] + p[j-JDIM] + p[j+JDIM]) >> 2)
                    - p[j] - (v[j] >> 6) - vavg; /* V = 1/4, D = 1/64 */
                vsum += v[j];
            };
        }; /* tady proběhl výpočet rychlosti. Ten cyklus je tak zběsilý,
            * aby se to potom nemuselo násobit */

        tmp = vsum / ((IDIM - 2)*(JDIM - 2)); /* výpočet průměru */
        vavg = tmp; /* z důvodu správného přetypování */

        for(i = JDIM; i < JDIM * (IDIM - 1); i += JDIM) {
            for(j = i + 1; j < i + JDIM - 1; j++) {
                p[j] += v[j] - pavg;
                psum += p[j];
            };
            p[i] = p[i + 1]; /* okrajové prvky */
            p[j] = p[j - 1];
        }; /* stejně zběsilý cyklus pro výpočet výchylek */

        tmp = psum / ((IDIM - 2)*(JDIM - 2)); /* výpočet průměru */
        pavg = tmp; /* z důvodu správného přetypování */

        for(i = 0, j = JDIM * (IDIM - 1); i < JDIM; i++, j++) {
            p[i] = p[i + JDIM]; /* zapsání volných okrajů */
            p[j] = p[j - JDIM];
        };

        if(!(k & 0x3f)) { /* v určitých periodách (64 cyklů) */
            i = (k & 0x80) ? (65*JDIM) : (35*JDIM);
            j = (k & 0x40) ? (105) : (55); /* dopadne do místa i, j */

#define LO 45 /* kapka vody (tohle jsou pomocné konstanty - hloubka) */
#define MD 75
#define MH 90
#define HI 100

            p[i - (3*JDIM) + j - 1] -= LO * 65536; /* a tohle všechno... */
            p[i - (3*JDIM) + j    ] -= LO * 65536;
            p[i - (3*JDIM) + j + 1] -= LO * 65536;
            p[i - (2*JDIM) + j - 2] -= LO * 65536;
            p[i - (2*JDIM) + j - 1] -= MD * 65536;
            p[i - (2*JDIM) + j    ] -= MD * 65536;
            p[i - (2*JDIM) + j + 1] -= MD * 65536;
            p[i - (2*JDIM) + j + 2] -= LO * 65536;
            p[i - (1*JDIM) + j - 3] -= LO * 65536;
            p[i - (1*JDIM) + j - 2] -= MD * 65536;
            p[i - (1*JDIM) + j - 1] -= MH * 65536;
            p[i - (1*JDIM) + j    ] -= HI * 65536;
            p[i - (1*JDIM) + j + 1] -= MH * 65536;
            p[i - (1*JDIM) + j + 2] -= MD * 65536;
            p[i - (1*JDIM) + j + 3] -= LO * 65536;
            p[i            + j - 3] -= LO * 65536;
            p[i            + j - 2] -= MD * 65536;
            p[i            + j - 1] -= HI * 65536;
            p[i            + j    ] -= HI * 65536;
            p[i            + j + 1] -= HI * 65536;
            p[i            + j + 2] -= MD * 65536;
            p[i            + j + 3] -= LO * 65536;
            p[i + (1*JDIM) + j - 3] -= LO * 65536;
            p[i + (1*JDIM) + j - 2] -= MD * 65536;
            p[i + (1*JDIM) + j - 1] -= MH * 65536;
            p[i + (1*JDIM) + j    ] -= HI * 65536;
            p[i + (1*JDIM) + j + 1] -= MH * 65536;
            p[i + (1*JDIM) + j + 2] -= MD * 65536;
            p[i + (1*JDIM) + j + 3] -= LO * 65536;
            p[i + (2*JDIM) + j - 2] -= LO * 65536;
            p[i + (2*JDIM) + j - 1] -= MD * 65536;
            p[i + (2*JDIM) + j    ] -= MD * 65536;
            p[i + (2*JDIM) + j + 1] -= MD * 65536;
            p[i + (2*JDIM) + j + 2] -= LO * 65536;
            p[i + (3*JDIM) + j - 1] -= LO * 65536;
            p[i + (3*JDIM) + j    ] -= LO * 65536;
            p[i + (3*JDIM) + j + 1] -= LO * 65536; /* je její popis */
        };

        /* x_mcga_vsync(); */ /* veritcal retrace synchronizace */
        /* Rozhodl jsem se tady ten příkaz nechat jenom v kometnáři. Když *
         * jsem to totiž odlaďoval, tak to vypadalo následovně: Při turbu *
         * (Pentium 2x66MHz) téměř žádný rozdíl, bez turba (Pentium       *
         * 2x50MHz) to s vsync běželo dvakrát pomalejc, protože to těsně  *
         * nestíhalo za 1 snímek. Mimochodem, velmi paradoxní je, že když *
         * jsem tenhle příklad původně napsal s rozepsaným kódem          *
         * putpixelu, tak to fachalo pomalejc, než když jsem tento kód    *
         * přesunul do __INLINE__ funkce!                                 */

        for(i = 0; i < IDIM*JDIM; i += JDIM) {
            for(j = 0; j < JDIM; j++) {
                x_mcga_put_pixel((i<<2) + (j<<1), x_fixtoi(p[i+j]));
                x_mcga_put_pixel((i<<2) + 2*JDIM + (j<<1),
                    x_fixtoi(p[i+j]));
                x_mcga_put_pixel((i<<2) + (j<<1) + 1, x_fixtoi(p[i+j]));
                x_mcga_put_pixel((i<<2) + 2*JDIM + (j<<1) + 1,
                    x_fixtoi(p[i+j]));
            };
        };
    };

    x_set_normalmode(); /* Nastavení normálního videomódu */

    getch(); /* zrušení stisknuté klávesy ze zásobníku, nezpůsobí čekání,
              * protože kbhit() */

    return 0;
}


            výheň