/*
　画面に色々なエフェクトと同時に作画を行うプログラム
　　　　ＧＣＣ　ＴＢＩＯＳアクセス関数のチェック用。

  使用言語 ＧＣＣ1.36　使用機種　ＦＭ−ＴＯＷＮＳ　２Ｍ　ＭＥＭＯＲＹ．

 1 st // program written by s.k Mon.,Apr.30,'91
 2 nd // arrenged by s.k Tus.,June 27,'91
         変更内容 縦横ラフタースクロール設立
 3 rd // arrenged by s.k Mon.,Aug 12,'91
         変更内容 TOWNS-OS L30から画面を読み込むように

　冗談の塊ですからあてにしないように。

*/


#include <stdio.h>
#include <tbios.h>

void main ()
{
    int i,j;

    setsumei ();                /* 説明表示 */
    CRTC_init ();
    EGB_displaypage (0,3);
    EGB_vramstart (0,255);
    EGB_gprint (0,0,"奇妙なグラフィックロード･デモ");
    EGB_gprint (0,20,"               programed by s.k");
    EGB_gprint (0,60,"L30 SYSTEM のCDをセットしてから");
    EGB_gprint (0,80,"TOWNS-PADのAボタンを");
    EGB_gprint (0,100,"               押してください。");
    for (i=0;i<256;i++)
    {
        EGB_vramstart (0,255-i);
    }
    while ((SND_pad (0) & 0x10)!=0)
    {
            break_check ();
    }
    EGB_gprint (0,160,"それでは、開始します。");
/* no.1 */
    load_image ("q:/fj/photo/cat1.tif");
    mosic ();
    sprite_initilize ();
    define_sprite_from_scrn ();
    sprite_galaxy_hello ();
/* no.2 */
    load_image ("q:/fj/photo/cat2.tif");
    define_sprite_from_scrn ();
    sprite_galaxy_hello ();
/* no.3 */
    load_image ("q:/fj/photo/palm.tif");
    define_sprite_from_scrn ();
    sprite_galaxy_hello ();
/* no.4 */
    load_image ("q:/fj/photo/pool.tif");
    define_sprite_from_scrn ();
    for (i=0;i<=255;i++)        /* scroll right to left. */
    {
        SPR_display (2,0);
        SPR_offset (255-i,0);
        break_check ();
    }
/* no.5 */
    load_image ("q:/fj/photo/penguin.tif");
    define_sprite_from_scrn ();
    sprite_galaxy_hello ();
/* etc */
    EGB_wait (180);
    sprite_downto_bye ();

    sprite_upto_hello ();
    EGB_wait (180);

    sprite_smallto_bye ();
    sprite_bigto_hello ();
    EGB_wait (180);
    EGB_displaypage (1,2);        /* ぼろの出ないように */
    sprite_rot ();                /* 傾く */
    sprite_rot ();
    sprite_rot ();
    EGB_displaypage (1,3);        /* もどす */
    EGB_wait (180);
    sprite_mozic_bye ();
    raf_2 ();
    EGB_displaypage (0,0);
    vram_erase ();
    EGB_displaypage (0,3);
    SPR_display (0,1024);
    EGC_puts ("fin.\n");
}

CRTC_init ()
{
    EGB_init ();
    EGB_screen (1,6);
    EGB_screen (0,6);
    EGB_displaypage (1,2);
    EGB_writepage (1);
    EGB_zoom (2,2);
    EGB_displaystart (32,0);
    EGB_view (255,240);
    EGB_backcolor (0x8000);
    EGB_vramstart (0,0);
    EGB_cls ();
    EGB_writepage (0);
    EGB_zoom (2,2);
    EGB_view (255,240);
    EGB_displaystart (32,0);
    EGB_backcolor (0x8000);
    EGB_cls ();
    EGB_writecolor (0x7fff);
}

load_image (char *fname)
{
    FILE *fopen (),*fp;
    char scrn[320*240*2],buff[1024];
    uint x,y,i;

    fp=fopen (fname,"rb");
    if (fp==NULL)
    {
        EGB_writepage (0);
        EGB_displaypage (0,3);
        EGB_writecolor (0x7fff);
        EGC_puts ("can not find file.\n");
        exit (1);
    }
    fread (scrn,1,512,fp);
    fread (scrn,1,320*240*2,fp);
    fclose (fp);
    EGB_displaypage (1,2);
    for (y=0;y<200;y++)
    {
        for (x=0;x<255;x++)
        {
            buff[x*2]=scrn[640*3+32+x*2+y*320*2];
            buff[x*2+1]=scrn[640*3+32+x*2+1+y*320*2];
        }
        EGB_put (0,y,255,y,buff);
    }
}

define_sprite_from_scrn ()
{
    char buff[1024];
    char spr[16*16*2*208];
    uint x,y,i;
    uint pat=0,num=0;

    SPR_display (1,208);
    EGB_displaypage (1,2);
    for (y=0;y<13;y++)
    {
        for (x=0;x<16;x++)
        {
            EGB_get (x*16,y*16,x*16+15,y*16+15,buff);
            for (i=0;i<(16*16*2);i++)
                spr[num++]=buff[i];
        }
    }
    SPR_display (0,208);
    for (i=0;i<255;i++)
    {
        EGB_writepage (1);
        EGB_get (0,i,255,i,buff);
        EGB_writepage (0);
        EGB_put (0,i,255,i,buff);
    }
    EGB_displaypage (0,1);    
    num=0;
    for (y=0;y<13;y++)
    {
        for (x=0;x<16;x++)
        {
            SPR_set (1,128+4*(pat++),1,1,&spr[num]);
            num+=512;
        }
    }
    SPR_offset (256,256);
    EGB_writepage (0);
    EGB_writecolor (0);
    EGB_line (0,0,255,0);
    EGB_line (0,1,255,1);
    EGB_displaypage (1,3);
    SPR_display (1,208);
}

sprite_initilize ()
{
    uint x,y;

    SPR_init ();
    SPR_display (0,1);
    for (x=0;x<16;x++)
    {
        for (y=0;y<13;y++)
        {
            SPR_attribute (1023-(x+y*16),1,1,128+(x+y*16)*4+0x8000,0);
            SPR_setposition (0,1023-(x+y*16),1,1,x*16,y*16);
        }
    }
    SPR_offset (256,256);
    SPR_display (1,208);
}

sprite_downto_bye ()
{
    uint x,y,i,j;
    uint yd[208];

    for (i=0;i<208;i++)
    {
        yd[i]=240+rand () % 400;
    }
    for (j=0;j<256;j+=2)
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(i % 16)*16;
            y=(i/16)*16+(yd[i]*j)/256;
            if (y>300) y=300;
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
}

sprite_upto_hello ()
{
    int x,y,i,j;
    int yd[208];

    for (i=0;i<208;i++)
    {
        yd[i]=240+rand () % 400;
    }
    for (j=256;j>=0;j-=2)
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(i % 16)*16;
            y=(i/16)*16+(yd[i]*j)/256;
            if (y>300) y=300;
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
}

sprite_mozic_bye ()
{
    int i,j,k,l;
    int num[208];

    for (i=0;i<208;i++)
    {
        num[i]=i;
    }
    for (i=0;i<208;i++)
    {
        k=rand () % 208;
        l=rand () % 208;
        j=num[k];
        num[k]=num[l];
        num[l]=j;
    }
    for (i=0;i<208;i++)
    {
        SPR_display (2,0);
        SPR_setposition (0,1023-num[i],1,1,480,480);
    }
}

sprite_galaxy_hello ()
{
    int i;

    for (i=255;i>=0;i=i-(256-i)/28-1)
    {
        SPR_display (2,0);
        SPR_offset (-i,-i);
        break_check ();
    }
    SPR_offset (0,0);
}

sprite_bigto_hello ()
{
    int x,y,i,j;

    for (j=0;j<=64;j++)
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(((i % 16)*16)-128)*(j)/64+128;
            y=(((i/16)*16)-100)*(j)/64+100;
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
}

sprite_smallto_bye ()
{
    int x,y,i,j;

    for (j=64;j>=0;j--)
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(((i % 16)*16)-128)*(j)/64+128;
            y=(((i/16)*16)-100)*(j)/64+100;
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
}

sprite_rot ()        /* 傾く */
{
    int s,x,y,i,j;

    s=256;
    for (j=0;j<=16;j++)                /* 右上がり */
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(i % 16)*16;
            y=(i/16)*16+((104-(i % 16)*16)*j/s);
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
    for (j=16;j>-16;j--)            /* 左下がり */
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(i % 16)*16;
            y=(i/16)*16+((104-(i % 16)*16)*j/s);
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
    for (j=-16;j<=0;j++)            /* 元に戻る */
    {
        break_check ();
        SPR_display (2,0);
        for (i=0;i<208;i++)
        {
            x=(i % 16)*16;
            y=(i/16)*16+((104-(i % 16)*16)*j/s);
            SPR_setposition (0,1023-i,1,1,x,y);
        }
    }
}

setsumei ()
{
    VGA400_init ();

    EGB_displaypage (0,0);
    EGB_gprint (0,0,"このプログラムは、単純に、次々と画面をロードした後に");
    EGB_gprint (0,20,"表示するだけの物です。");
    EGB_gprint (0,40,"これは、自分の作ったライブラリの動作を確認する為に");
    EGB_gprint (0,60,"制作したもので、最後まで三十秒もないものです。");
    EGB_gprint (0,80,"しかしながら、ちょっとした奇妙なアイディアを用いて");
    EGB_gprint (0,100,"色々なエフェクト処理を行っています。");
    EGB_gprint (0,120,"Ｃ言語＋ＴＢＩＯＳでもこの位はできるということなので");
    EGB_gprint (0,140,"す（ＶＲＡＭやＣＲＴＣは直接触っていません）。");
    EGB_gprint (0,160,"尚、最後はループ");
    EGB_gprint (0,180,"しますので、パッドのＡボタンを押してください。");
    EGB_gprint (0,210,"本プログラムの最後では、かなり重たい処理をします。");
    EGB_gprint (0,230,"ですから、低ウエイトモードの方が見やすいでしょう。");
    EGB_gprint (0,250,"         (こんなんばっかり)");
    EGB_displaypage (0,1);
    EGB_gprint (0,300,"パッドのＡボタンを押すことによって開始します。");
    while ((SND_pad (0) & 0x10)!=0)
    {
            break_check ();
    }
}

/*
ラフタースクロールルーチン
　ここからは８０３８６、ＴＢＩＯＳの限界に挑戦します。瀬古技を使っているにせよ
　ＴＢＩＯＳのみでこのようなことが出来るのです！！
  パソコン業界初　縦横同時ラフタースクロール！！（超誇大広告だ）
　冗談ですよ、冗談。
*/
raf_2 ()
{
    unsigned short int p[256*200*12];
    unsigned short int q[256*200];
    unsigned short int s[200];
    int r[12]={0,1,3,5,6,7,7,6,5,3,1,0};
    int i,j,y;

    SPR_display (0,1024);            /* スプライト機能停止 */
    EGB_displaypage (0,1);
    EGB_writepage (0);
    EGB_get (0,0,255,199,&q[0]);    /* 元の画面 */
    EGB_writepage (1);
    EGB_backcolor (0xffff);
    EGB_cls ();
    EGB_displaypage (0,1);

    for (j=0;j<12;j++)
    {
        for (i=0;i<256;i++)
        {
            y=r[(i+j) % 12];
            EGB_writepage (0);
            EGB_get (i,0,i,199,&s[0]);
            EGB_writepage (1);
            EGB_put (i,y,i,y+199,&s[0]);
        }
        EGB_get (0,0,255,199,&p[256*200*j]);
        EGB_cls ();
    }
    EGB_displaypage (1,2);
    EGB_cls ();
    EGB_writecolor (0x7fff);
    EGB_gprint (20,100,"８０３８６パワー全開！");
    EGB_gprint (20,50,"ＴＢＩＯＳの限界に挑戦");
    EGB_gprint (30,170,"終了はＰＡＤ−Ａボタン");
    waite (400);
    i=0;
    while ((SND_pad (0) & 0x10)!=0)
    {
        /* 縦ラフター */
        for (i=0;((i<200)&&((SND_pad (0) & 0x10)!=0));i++)
        {
            EGC_vsync_wait ();
            EGB_put (0,0,255,199,&p[256*200*(i % 12)]);
            break_check ();
        }
        /* 縦ラフターに横振動を加える */
        for (i=0;((i<200)&&((SND_pad (0) & 0x10)!=0));i++)
        {
            EGC_vsync_wait ();
            for (j=0;j<200;j++)
                EGB_put (r[i%12],j,r[i%12]+255,j,&p[256*200*(i % 12)+j*256]);
            break_check ();
        }
        /* 横ラフター */        
        for (i=0;((i<200)&&((SND_pad (0) & 0x10)!=0));i++)
        {
            EGC_vsync_wait ();
            for (j=0;j<200;j++)
            {
                y=(i+j) % 12;
                EGB_put (r[y],j,r[y]+255,j,&q[j*256]);
            }
            break_check ();
        }        
        /* 縦横同時ラフター！！ 80386 パワー全開！！ */        
        for (i=0;((i<200)&&((SND_pad (0) & 0x10)!=0));i++)
        {
            EGC_vsync_wait ();
            for (j=0;j<200;j++)
            {
                y=(i+j) % 12;
                EGB_put (r[y],j,r[y]+255,j,&p[256*200*(i % 12)+j*256]);
            }
            break_check ();
        }        
    }
}

/*
    ゆっくりとモザイクの掛かった絵が戻る。スーパー？ァミコンでよくやる
    こと。
*/
mosic ()        /* モザイク処理 */
{
    uint x,y;
    uint v,i,s,ye=0,j;
    uint s1=0,s2=1;
    unsigned short int f[258*240];    /* VRAM バッファ */
    unsigned short int g[258*240];

    EGB_displaypage (0,3);
    EGB_writepage (0);
    EGB_get (0,0,255,239,&g[0]);
    EGB_cls ();
    EGB_displaystart (32,0);
    EGB_writepage (1);
    EGB_cls ();
    EGB_displaystart (32,0);
        
    for (v=16;v>=3;v--)
    {
        i=0;
        for (y=0;y<(479/v);y++)
        {
            s=256*(240*y/(479/v));
            for (x=0;x<(511/v);x++)
                f[i++]=g[s+256*x/(511/v)];
        }
        waite (v);
        EGB_writepage (s1);
        EGB_displaypage (s2,3);
        x=s1; s1=s2; s2=x;
        EGB_put (0,0,511/v-1,479/v-1,&f[0]);
        EGB_zoom (v,v);
        ye=ye+240/v;
        break_check ();
    }
    waite (40);
    EGB_displaypage (s2,3);
    EGB_writepage (s2);
    waite (40);
    EGB_writepage (0);
    EGB_put (0,0,255,239,&g[0]);    /* VRAM 0 は元の画面に戻る */
    EGB_zoom (2,2);
    EGB_writepage (1);
    EGB_put (0,0,255,239,&g[0]);    /* VRAM 1 はVRAM 0と同じ */
    EGB_zoom (2,2);
    EGB_displaypage (0,3);
    EGB_writepage (0);
    EGB_cls ();
    waite (170);
}
