home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / games / wcoltris / source / coltris.c < prev    next >
C/C++ Source or Header  |  1994-12-31  |  39KB  |  1,752 lines

  1. #include <gem.h>
  2. #include <vdi.h>
  3. #include <tos.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <linea.h>
  8.  
  9. #include <vaproto.h>
  10. int ap_id,av_id=-1;
  11. int av_state;
  12.  
  13. #include "cltr.h"
  14.  
  15. #include "coltris.rsh"
  16.  
  17. #define min(a,b)    (a)<(b)?(a):(b)
  18. #define max(a,b)    (a)>(b)?(a):(b)
  19.  
  20. OBJECT *menue,*options,*info,*user_keys;
  21. OBJECT *score,*stat;
  22. OBJECT *hi_name,*hiscore;
  23. POSITION *pos;
  24. int handle;
  25.  
  26. typedef struct {
  27.     int entry;
  28.     int key;
  29.     int state;
  30. } KEY_COMMAND;
  31.  
  32. KEY_COMMAND commands[]={
  33. M_START        ,0x13,    K_CTRL,    /* r */
  34. M_START        ,0x13,    0,        /* r */
  35. M_START        ,0x1c,    0,        /* return */
  36. M_START        ,0x72,    0,        /* enter */
  37. M_HISCORE    ,0x23,    K_CTRL,    /* h */
  38. M_HISCORE    ,0x23,    0,        /* h */
  39. M_SAVE        ,0x1f,    K_CTRL,    /* s */
  40. M_QUIT        ,0x10,    K_CTRL,    /* q */
  41. M_TETRIS     ,0x14,    K_CTRL,    /* t */
  42. M_TETRIS     ,0x14,    0,        /* t */
  43. M_COLUMNS    ,0x2e,    K_CTRL,    /* c */
  44. M_COLUMNS    ,0x2e,    0,        /* c */
  45. M_SCORE        ,0x17,    K_CTRL,    /* i */
  46. M_SCORE        ,0x17,    0,        /* i */
  47. M_PREVIEW    ,0x31,    K_CTRL,    /* n */
  48. M_PREVIEW    ,0x31,    0,        /* n */
  49. M_STATISTIC    ,0x30,    K_CTRL,    /* b */
  50. M_STATISTIC    ,0x30,    0,        /* b */
  51. M_OPTS        ,0x18,    K_CTRL,    /* o */
  52. M_OPTS        ,0x18,    0,        /* o */
  53. };
  54.  
  55. char set_file[128]="COLTRIS.SET";
  56.  
  57. OPTS opts={
  58.     PM_TETRIS,{0},1,0,0,1,0,0,0,0,
  59.     {"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0},
  60.     {"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0,"---",0,0},
  61.     {7,0,1,0,0},{7,0,1,0,0},
  62. };
  63. POSITION *pos;
  64.  
  65. static uint last_score;
  66.  
  67. int columns_vdi,tetris_vdi;        /* -1 -> disabled */
  68.                                 /*  0 -> qcopy möglich */
  69.                                 /*  1 -> vdi only */
  70.  
  71. int score_flag,preview_flag,stat_flag;
  72. int end_flag=0;
  73.  
  74. long screen_addr;
  75. long buffer_addr;
  76. long buffer_size;
  77. int buffer_width,buffer_height;        /* width in byte */
  78. int screen_width;                    /* in byte */
  79. int screen_w,screen_h,planes;
  80. int quick_flag;                        /* copy in screen mit ass-routine erlaubt */
  81. static int x_off,y_off,width;
  82.  
  83. MFDB screen,buffer;
  84.  
  85. void redraw_play(int *message);
  86. void close_window(void);
  87. void set_score(void);
  88. void redraw_score(int *message);
  89. void set_preview(void);
  90. void redraw_preview(int *message);
  91. void set_statistic(void);
  92. void redraw_statistic(int *message);
  93.  
  94. #define WIND_ANZ    4
  95. typedef enum {
  96.     W_PLAY,
  97.     W_SCORE,
  98.     W_PREVIEW,
  99.     W_STATISTIC,
  100. } WINDOWS;
  101. typedef struct {
  102.     int handle;
  103.     void (*redraw)(int *message);
  104.     void (*close)(void);
  105. } WINDOW;
  106. WINDOW wind[WIND_ANZ]={-1,redraw_play,close_window,
  107.                        -1,redraw_score,set_score,
  108.                        -1,redraw_preview,set_preview,
  109.                        -1,redraw_statistic,set_statistic};
  110.  
  111.  
  112. /*
  113.     zufallsgenerator nach knuth
  114. */
  115. #define MBIG    1000000000l
  116. #define MSEED    161803398l
  117. #define FAC    1e-9
  118.  
  119. long xrandom(void)
  120. {
  121. /*    return Random();*/
  122. static int first=0;
  123. static long ma[55],inext,inextp;
  124. long mj,mk;
  125. int i,ii,k;
  126.  
  127.     if ( !first ) {
  128.         first=1;
  129.         mj=MSEED-Random();        /* -> bios zufallszahl für init */
  130.         mj=labs(mj%MBIG);
  131.  
  132.         ma[54]=mj;
  133.         mk=1;
  134.         for ( i=0; i<54; i++ ) {
  135.             ii=(21*i+21)%55-1;
  136.             ma[ii]=mk;
  137.             mk=mj-mk;
  138.             if ( mk<0 )
  139.                 mk+=MBIG;
  140.             mj=ma[ii];
  141.         }
  142.         for ( k=0; k<4; k++ ) {
  143.             for ( i=0; i<55; i++ ) {
  144.                 ma[i]=ma[i]-ma[(i+31)%55];
  145.                 if ( ma[i]<0 )
  146.                     ma[i]+=MBIG;
  147.             }
  148.         }
  149.         inext=-1;
  150.         inextp=30;
  151.     }
  152.  
  153.     inext++;
  154.     if ( inext==55 )
  155.         inext=0;
  156.     inextp++;
  157.     if ( inextp==55 )
  158.         inextp=0;
  159.     mj=ma[inext]-ma[inextp];
  160.     if ( mj<0 )
  161.         mj+=MBIG;
  162.     ma[inext]=mj;
  163.     return mj;
  164. }
  165.  
  166. long gettime()
  167. {
  168. long stack;
  169. long time;
  170.  
  171.     stack=Super(0L);
  172.     time=*(long*)0x4BA;
  173.     Super((void*)stack);
  174.     return(time);
  175. }
  176.  
  177. static long time;
  178. void init_wait(void)
  179. {
  180.     time=gettime();
  181. }
  182. void do_wait(int ms)
  183. {
  184.     while ( gettime()<time+ms )
  185.         ;
  186. }
  187.  
  188. uint calc_delay(uint level)
  189. {
  190.     return 55-level*5;
  191. }
  192.  
  193. KEY get_key(void)
  194. {
  195. int key;
  196. EVENT evnt;
  197.  
  198.     evnt.ev_mflags=MU_KEYBD|MU_TIMER;
  199.     evnt.ev_mtlocount=1;
  200.     evnt.ev_mthicount=0;
  201.     if ( EvntMulti(&evnt)==MU_TIMER )
  202.         return NO_KEY;
  203.     key=*(char*)&evnt.ev_mkreturn;
  204.  
  205.         /* user-keys first */
  206.     if ( key==opts.left )
  207.         return K_LEFT;
  208.     if ( key==opts.right )
  209.         return K_RIGHT;
  210.     if ( key==opts.rotate )
  211.         return K_ROTATE;
  212.     if ( key==opts.drop )
  213.         return K_DROP;
  214.  
  215.     if ( key==0x67 )                /* 7z */
  216.         return K_LEFT;
  217.     if ( key==0x69 )                /* 9z */
  218.         return K_RIGHT;
  219.     if ( key==0x68 )                /* 8z */
  220.         return K_ROTATE;
  221.     if ( key==0x39 || key==0x6A )    /* space, 4z */
  222.         return K_DROP;
  223.     if ( key==0x01 || key==0x10 )    /* esc, q */
  224.         return K_QUIT;
  225.     if ( key==0x17 )                /* i */
  226.         return K_INFO;
  227.     if ( key==0x31 )                /* n */
  228.         return K_NEXT;
  229.     if ( key==0x30 )                /* b */
  230.         return K_STAT;
  231.     if ( key==0x1F )                /* s */
  232.         return K_STOP;
  233.     if ( key==0x66 || key==0x26 )    /* *z l */
  234.         return K_LEVEL;
  235.  
  236.     return NO_KEY;
  237. }
  238.  
  239. void clr_keys(void)
  240. {
  241. EVENT evnt;
  242.  
  243.     evnt.ev_mflags=MU_KEYBD|MU_TIMER;
  244.     evnt.ev_mtlocount=1;
  245.     evnt.ev_mthicount=0;
  246.     while ( EvntMulti(&evnt)&MU_KEYBD )
  247.         ;
  248. }
  249.  
  250. int xget_key(void)
  251. {
  252. int key;
  253.     key=evnt_keybd();
  254.     return *(char*)&key;
  255. }
  256.  
  257. void clr_feld(void)
  258. {
  259.     memset((char*)buffer_addr,0,buffer_size);
  260.     redraw_play(0l);
  261.     last_score=0;
  262. }
  263.  
  264. void inv_feld(void)
  265. {
  266. int *d;
  267. long i;
  268.  
  269.     init_wait();
  270.     for ( i=0,d=(int*)buffer_addr; i<buffer_size/2; i++ )
  271.         *d++^=-1;
  272.     redraw_play(0l);
  273.     do_wait(50);
  274.     for ( i=0,d=(int*)buffer_addr; i<buffer_size/2; i++ )
  275.         *d++^=-1;
  276.     redraw_play(0l);
  277. }
  278.  
  279. /*------------------------------------------------------------------------------
  280.  
  281.     quick-copy: schnelle kopierroutinen (nur standard ST-high artige auflösungen)
  282.  
  283. ------------------------------------------------------------------------------*/
  284.     /* variable für ass-routinen */
  285.  
  286. void copy_tet(char *dest,char *source,int lines);
  287. void copy_col(char *dest,char *source,int lines);
  288. void (*qcopy)(char *dest,char *source,int lines);
  289. int copy_max,copy_min;
  290. Copy_Out copy_out;
  291.  
  292. static void qcopy_out(void)
  293. {
  294. char *source,*dest;
  295.  
  296.     if ( copy_min<copy_max ) {
  297.         source=(char*)buffer_addr+(long)copy_min*buffer_width;
  298.         dest=(char*)screen_addr+(long)(copy_min+y_off)*screen_width+x_off/8;
  299.         qcopy(dest,source,copy_max-copy_min);
  300.         copy_min=buffer_height;
  301.         copy_max=0;
  302.     }
  303. }
  304.  
  305. static void vcopy_out(void)
  306. {
  307. int xy[8];
  308.  
  309.     if ( copy_min<copy_max ) {
  310.         xy[0]=0;
  311.         xy[1]=copy_min;
  312.         xy[2]=width-1;
  313.         xy[3]=copy_max;
  314.         xy[4]=x_off;
  315.         xy[5]=y_off+copy_min;
  316.         xy[6]=x_off+width-1;
  317.         xy[7]=y_off+copy_max;
  318.         vro_cpyfm(handle,S_ONLY,xy,&buffer,&screen);
  319.         copy_min=buffer_height;
  320.         copy_max=0;
  321.     }
  322. }
  323.  
  324. static void mcopy_out(void)
  325. {
  326. int xy[8];
  327. void do_ctrl(int flag);
  328.  
  329.     if ( copy_min<copy_max ) {
  330.         xy[3]=wind[W_PLAY].handle;
  331.         xy[4]=x_off;
  332.         xy[5]=y_off+copy_min;
  333.         xy[6]=x_off+width-1;
  334.         xy[7]=y_off+copy_max;
  335.         redraw_play(xy);
  336.         copy_min=buffer_height;
  337.         copy_max=0;
  338.     }
  339.     do_ctrl(1);
  340. }
  341.  
  342. void init_quickcopy(void)
  343. {
  344.     linea_init();
  345.     screen_addr=(long)Logbase();
  346.     screen_width=Linea->v_lin_wr;
  347. }
  348.  
  349. static void init_copy_out(void)
  350. {
  351.     if ( !opts.graph && !((opts.play_mode==PM_TETRIS && tetris_vdi) || (opts.play_mode==PM_COLUMNS && columns_vdi)) ) {
  352.         quick_flag=1;
  353.         if ( !screen_addr )
  354.             init_quickcopy();
  355.         if ( opts.play_mode==PM_TETRIS )
  356.             qcopy=copy_tet;
  357.         else
  358.             qcopy=copy_col;
  359.     }
  360.     else {
  361.         quick_flag=0;
  362.     }
  363.  
  364.     if ( opts.multi )
  365.         copy_out=mcopy_out;
  366.     else if ( quick_flag )
  367.         copy_out=qcopy_out;
  368.     else
  369.         copy_out=vcopy_out;
  370.  
  371.     copy_min=buffer_height;
  372.     copy_max=0;
  373. }
  374.  
  375. /*------------------------------------------------------------------------------
  376.  
  377.     hiscore
  378.  
  379. ------------------------------------------------------------------------------*/
  380. void do_score(uint score,HI_SCORE *hi)
  381. {
  382. int i,j;
  383. int x,y,w,h;
  384.  
  385.     last_score=score;
  386.  
  387.     for ( i=0; i<10; i++ ) {
  388.         if ( score>hi[i].score ) {
  389.             wind_update(BEG_UPDATE);
  390.             form_center(hi_name,&x,&y,&w,&h);
  391.             form_dial(FMD_START,x,y,w,h,x,y,w,h);
  392.             objc_draw(hi_name,0,10,x,y,w,h);
  393.             form_do(hi_name,HI_NAME);
  394.             form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  395.             wind_update(END_UPDATE);
  396.  
  397.             objc_unselect(hi_name,HI_NAME);
  398.             for ( j=9; j>i; j-- )
  399.                 hi[j]=hi[j-1];
  400.             strcpy(hi[i].name,objc_tedstr(hi_name,HI_NAME));
  401.             hi[i].score=score;
  402.             hi[i].date=Tgetdate();
  403.             return;
  404.         }
  405.     }
  406. }
  407.  
  408. void show_hiscore(void)
  409. {
  410. HI_SCORE *hi;
  411. int i,ret,x,y,w,h;
  412. uint date;
  413.  
  414.     if ( opts.play_mode==PM_TETRIS ) {
  415.         hi=opts.tet_hi;
  416.         objc_spec(hiscore,HI_TITEL)="Tetris Hiscore";
  417.     }
  418.     else {
  419.         hi=opts.col_hi;
  420.         objc_spec(hiscore,HI_TITEL)="Columns Hiscore";
  421.     }
  422.  
  423.     objc_hide(hiscore,HI_MARKE);
  424.     for ( i=0; i<10; i++ ) {
  425.         if ( hi[i].score!=0 ) {
  426.             strcpy(objc_spec(hiscore,HISCORE1+i+i+i),hi[i].name);
  427.             date=hi[i].date;
  428.             sprintf(objc_spec(hiscore,HISCORE1+1+i+i+i),"%2d.%2d.%4d",date&31,(date>>5)&15,(date>>9)+1980);
  429.             sprintf(objc_spec(hiscore,HISCORE1+2+i+i+i),"%5d",hi[i].score);
  430.             if ( hi[i].score==last_score ) {
  431.                 objc_unhide(hiscore,HI_MARKE);
  432.                 hiscore[HI_MARKE].ob_y=hiscore[HISCORE1+i+i+i].ob_y;
  433.             }
  434.         }
  435.         else {
  436.             *objc_spec(hiscore,HISCORE1+i+i+i)=0;
  437.             *objc_spec(hiscore,HISCORE1+1+i+i+i)=0;
  438.             *objc_spec(hiscore,HISCORE1+2+i+i+i)=0;
  439.         }
  440.  
  441.     }
  442.  
  443.     form_center(hiscore,&x,&y,&w,&h);
  444.     wind_update(BEG_UPDATE);
  445.     form_dial(FMD_START,x,y,w,h,x,y,w,h);
  446.     objc_draw(hiscore,0,10,x,y,w,h);
  447.     ret=form_do(hiscore,0)&0x7FFF;
  448.     objc_unselect(hiscore,ret);
  449.     form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  450.     wind_update(END_UPDATE);
  451.     if ( ret==CLR_HI ) {
  452.         for ( i=0; i<10; i++ ) {
  453.             strcpy(hi[i].name,"");
  454.             hi[i].score=0;
  455.             hi[i].date=0;
  456.         }
  457.     }
  458. }
  459.  
  460. /*------------------------------------------------------------------------------
  461.  
  462.     schreibe optionen in / lese optionen aus  dialogbox
  463.  
  464. ------------------------------------------------------------------------------*/
  465. void set_opts(void)
  466. {
  467. GAME_OPTS *go;
  468. int i;
  469.  
  470.     if ( opts.play_mode==PM_COLUMNS ) {
  471.         objc_select(options,O_COLUMNS);
  472.         objc_unselect(options,O_TETRIS);
  473.         go=&opts.columns;
  474.     }
  475.     else {
  476.         objc_select(options,O_TETRIS);
  477.         objc_unselect(options,O_COLUMNS);
  478.         go=&opts.tetris;
  479.     }
  480.     for ( i=LEVEL0; i<=LEVEL9; i++ ) {
  481.         objc_unselect(options,i);
  482.     }
  483.     if ( go->start_level<9 )
  484.         objc_select(options,LEVEL0+go->start_level);
  485.  
  486.     for ( i=RANDOM0; i<=RANDOM14; i++ ) {
  487.         objc_unselect(options,i);
  488.     }
  489.     if ( go->random<14 )
  490.         objc_select(options,RANDOM0+go->random);
  491.  
  492.     objc_unselect(options,GRAPH_ST);
  493.     objc_unselect(options,GRAPH_VDI);
  494.     if ( opts.graph )
  495.         objc_select(options,GRAPH_VDI);
  496.     else
  497.         objc_select(options,GRAPH_ST);
  498.  
  499.     objc_unselect(options,SINGLE);
  500.     objc_unselect(options,MULTI);
  501.     if ( opts.multi )
  502.         objc_select(options,MULTI);
  503.     else
  504.         objc_select(options,SINGLE);
  505.  
  506.     objc_unselect(options,CYCLENONE);
  507.     objc_unselect(options,CYCLEPLAY);
  508.     objc_unselect(options,CYCLEALL);
  509.     if ( opts.cycle==0 )
  510.         objc_select(options,CYCLENONE);
  511.     else if ( opts.cycle==1 )
  512.         objc_select(options,CYCLEPLAY);
  513.     else
  514.         objc_select(options,CYCLEALL);
  515.  
  516.     if ( opts.top )
  517.         objc_select(options,TOP_ALL);
  518.     else
  519.         objc_unselect(options,TOP_ALL);
  520. }
  521.  
  522. void get_opts(void)
  523. {
  524. GAME_OPTS *go;
  525. int i;
  526.  
  527.     if ( opts.play_mode==PM_COLUMNS )
  528.         go=&opts.columns;
  529.     else
  530.         go=&opts.tetris;
  531.  
  532.     for ( i=LEVEL0; i<=LEVEL9; i++ ) {
  533.         if ( objc_selected(options,i) )
  534.             { go->start_level=i-LEVEL0; break; }
  535.     }
  536.  
  537.     for ( i=RANDOM0; i<=RANDOM14; i++ ) {
  538.         if ( objc_selected(options,i) )
  539.             { go->random=i-RANDOM0; break; }
  540.     }
  541.  
  542.     if ( objc_selected(options,GRAPH_VDI) )
  543.         opts.graph=1;
  544.     else
  545.         opts.graph=0;
  546.  
  547.     if ( objc_selected(options,MULTI) )
  548.         opts.multi=1;
  549.     else
  550.         opts.multi=0;
  551.  
  552.     if ( objc_selected(options,CYCLENONE) )
  553.         opts.cycle=0;
  554.     else if ( objc_selected(options,CYCLEPLAY) )
  555.         opts.cycle=1;
  556.     else 
  557.         opts.cycle=2;
  558.  
  559.     if ( objc_selected(options,TOP_ALL) )
  560.         opts.top=1;
  561.     else
  562.         opts.top=0;
  563. }
  564.  
  565. void get_user_keys(void)
  566. {
  567. int x,y,w,h;
  568.  
  569.     wind_update(BEG_MCTRL);
  570.     wind_update(BEG_UPDATE);
  571.  
  572.     strcpy(objc_spec(user_keys,KEYS_TXT),"Left");
  573.     form_center(user_keys,&x,&y,&w,&h);
  574.     objc_draw(user_keys,0,10,x,y,w,h);
  575.     opts.left=xget_key();
  576.  
  577.     strcpy(objc_spec(user_keys,KEYS_TXT),"Right");
  578.     form_center(user_keys,&x,&y,&w,&h);
  579.     objc_draw(user_keys,0,10,x,y,w,h);
  580.     opts.right=xget_key();
  581.  
  582.     strcpy(objc_spec(user_keys,KEYS_TXT),"Rotate");
  583.     form_center(user_keys,&x,&y,&w,&h);
  584.     objc_draw(user_keys,0,10,x,y,w,h);
  585.     opts.rotate=xget_key();
  586.  
  587.     strcpy(objc_spec(user_keys,KEYS_TXT),"Drop");
  588.     form_center(user_keys,&x,&y,&w,&h);
  589.     objc_draw(user_keys,0,10,x,y,w,h);
  590.     opts.drop=xget_key();
  591.  
  592.     wind_update(END_MCTRL);
  593.     wind_update(END_UPDATE);
  594. }
  595.  
  596. void do_options(void)
  597. {
  598. int x,y,w,h,r;
  599.  
  600.     wind_update(BEG_UPDATE);
  601.     form_center(options,&x,&y,&w,&h);
  602.     form_dial(FMD_START,x,y,w,h,x,y,w,h);
  603.  
  604.     set_opts();
  605.  
  606.     do {
  607.         objc_draw(options,0,10,x,y,w,h);
  608.         r=form_do(options,0)&0x7FFF;
  609.         objc_unselect(options,r);
  610.         if ( r==USER_KEY ) {
  611.             get_user_keys();
  612.         }
  613.     } while ( r!=OK && r!=ABBR );
  614.  
  615.     if ( r==OK ) {
  616.         get_opts();
  617.         init_copy_out();
  618.     }
  619.  
  620.     form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  621.     wind_update(END_UPDATE);
  622. }
  623.  
  624. void save_options(void)
  625. {
  626. int f_id;
  627.  
  628.     f_id=Fcreate(set_file,0);
  629.     if ( f_id>0 ) {
  630.         Fwrite(f_id,sizeof(opts),&opts);
  631.         Fclose(f_id);
  632.     }
  633. }
  634.  
  635. /*------------------------------------------------------------------------------
  636.  
  637.     sende für av_protokol
  638.  
  639. ------------------------------------------------------------------------------*/
  640. char *get_send_puffer(void)
  641. {
  642. static char *send_puffer=0l;
  643.  
  644.     if ( !send_puffer ) {
  645.         send_puffer=Mxalloc(128,0x0022);
  646.         if ( send_puffer==(char*)-32 )
  647.             send_puffer=Malloc(128);
  648.     }
  649.     return send_puffer;
  650. }
  651.  
  652. void av_send(int msg_typ,int d1,int d2,char *str)
  653. {
  654. int msg[8];
  655. char *puf;
  656.  
  657.     if ( av_id<0 || (msg_typ==AV_SENDKEY && !(av_state&1)) ||
  658.          (msg_typ==AV_OPENWIND && !(av_state&16)) ||
  659.          ((msg_typ==AV_ACCWINDOPEN || msg_typ==AV_ACCWINDCLOSED) && !(av_state&64)) ||
  660.          ((msg_typ==AV_PATH_UPDATE|| msg_typ==AV_WHAT_IZIT) && !(av_state&16)) ||
  661.          (msg_typ==AV_EXIT && !(av_state&1024))
  662.         )    return;
  663.  
  664.     if ( str ) {
  665.         puf=get_send_puffer();
  666.         if ( !puf )
  667.             return;
  668.         strcpy(puf,str);
  669.     }
  670.  
  671.     msg[0]=msg_typ;
  672.     msg[1]=ap_id;
  673.     msg[2]=0;
  674.     if ( str ) {
  675.         *(char**)&msg[3]=puf;
  676.     }
  677.     else {
  678.         msg[3]=d1;
  679.         msg[4]=d2;
  680.     }
  681.     msg[5]=msg[6]=msg[7]=0;
  682.     if ( msg_typ==AV_PROTOKOLL )
  683.         *(char**)&msg[6]="COLTRIS ";
  684.     appl_write(av_id,16,msg);
  685. }
  686.  
  687. void av_init(void)
  688. {
  689. char *av,_av[32];
  690.  
  691.         /* av/va kommunikationspartner einstellen */
  692.     av=getenv("AVSERVER");
  693.     if ( av!=0l ) {
  694.         strncpy(_av,av,16);
  695.         _av[16]=0;
  696.         strcat(_av,"        ");
  697.         _av[8]=0;
  698.         av_id=appl_find(_av);
  699.     }
  700.     if ( av_id<0 ) {
  701.         av_id=appl_find("GEMINI  ");
  702.         if ( av_id<0 ) {
  703.             av_id=appl_find("EASE    ");
  704.             if ( av_id<0 ) {
  705.                 av_id=appl_find("AVSERVER");
  706.             }
  707.         }
  708.     }
  709.     av_send(AV_PROTOKOLL,2,0,0l);
  710. }
  711.  
  712. void av_getproto(void)
  713. {
  714. int evnt;
  715. EVENT event;
  716.  
  717.     do {
  718.         memset(&event,0,sizeof(event));
  719.         event.ev_mflags=MU_MESAG|MU_TIMER;
  720.         event.ev_mtlocount=10;
  721.         /*event.ev_mthicount=0;*/
  722.         evnt=EvntMulti(&event);
  723.         if ( evnt&MU_MESAG && event.ev_mmgpbuf[0]==VA_PROTOSTATUS )
  724.             av_state=event.ev_mmgpbuf[3];
  725.     } while ( evnt&MU_MESAG );
  726. }
  727.  
  728. /*------------------------------------------------------------------------------
  729.  
  730.     init/exit, main
  731.  
  732. ------------------------------------------------------------------------------*/
  733. void get_tetris_size(int *w,int *h);
  734. void get_columns_size(int *w,int *h);
  735.  
  736. void init_buffer(int width,int height)
  737. {
  738. int xwidth;
  739.  
  740.     if ( buffer_addr )
  741.         free((void*)buffer_addr);
  742.  
  743.     xwidth=(width+15)&~15;
  744.  
  745.     buffer_size=(long)xwidth*(long)height*(long)planes/8l;
  746.     buffer_addr=(long)malloc(buffer_size);
  747.     if ( !buffer_addr )
  748.         exit(1);
  749.     memset((void*)buffer_addr,0,buffer_size);
  750.     buffer.fd_addr=(void*)buffer_addr;
  751.     buffer.fd_w=xwidth;
  752.     buffer.fd_h=height;
  753.     buffer.fd_wdwidth=xwidth/16;
  754.     buffer.fd_nplanes=planes;
  755.     buffer.fd_stand=0;
  756.     buffer.fd_r1=buffer.fd_r2=buffer.fd_r3=0;
  757.  
  758.     buffer_width=xwidth/8;
  759.     buffer_height=height;
  760. }
  761.  
  762. void check_windpos(int *x,int *y)
  763. {
  764.     if ( *x<pos->desk_x )
  765.         *x=pos->desk_x;
  766.     else if ( *x>pos->desk_x+pos->desk_w-32 )
  767.         *x=pos->desk_x+pos->desk_w-32;
  768.     if ( *y<pos->desk_y )
  769.         *y=pos->desk_y;
  770.     else if ( *y>pos->desk_y+pos->desk_h-32 )
  771.         *y=pos->desk_y+pos->desk_h-32;
  772. }
  773.  
  774. void init_window(int *x_x,int *y_y,int *w_w,int *h_h)
  775. {
  776. int x,y,w,h,xx,yy,ww,hh;
  777. int height;
  778.  
  779.     if ( objc_state(menue,M_TETRIS)&CHECKED )
  780.         get_tetris_size(&width,&height);
  781.     else
  782.         get_columns_size(&width,&height);
  783.  
  784.     wind_calc(WC_BORDER,NAME|MOVER|CLOSER,pos->wind_pos[W_PLAY].x,pos->wind_pos[W_PLAY].y,width,height,&x,&y,&w,&h);
  785.     check_windpos(&x,&y);
  786.     wind_calc(WC_WORK,NAME|MOVER|CLOSER,x,y,w,h,&xx,&yy,&ww,&hh);
  787.     xx&=~15;
  788.     wind_calc(WC_BORDER,NAME|MOVER|CLOSER,xx,yy,ww,hh,&x,&y,&w,&h);
  789.     *x_x=x;
  790.     *y_y=y;
  791.     *w_w=w;
  792.     *h_h=h;
  793.  
  794.     init_buffer(width,height);
  795.     init_copy_out();
  796. }
  797.  
  798. void open_window(void)
  799. {
  800. int x,y,w,h,dummy;
  801.  
  802.     wind[W_PLAY].handle=wind_create(NAME|MOVER|CLOSER,0,0,screen_w,screen_h);
  803.     init_window(&x,&y,&w,&h);
  804.     if ( opts.play_mode==PM_COLUMNS )
  805.         wind_set(wind[W_PLAY].handle,WF_NAME," Columns ");
  806.     else
  807.         wind_set(wind[W_PLAY].handle,WF_NAME," Tetris ");
  808.     wind_open(wind[W_PLAY].handle,x,y,w,h);
  809.     if ( opts.cycle )
  810.         av_send(AV_ACCWINDOPEN,wind[W_PLAY].handle,0,0l);
  811.     wind_get(wind[W_PLAY].handle,WF_WORKXYWH,&pos->wind_pos[W_PLAY].x,&pos->wind_pos[W_PLAY].y,&dummy,&dummy);
  812. }
  813.  
  814. void close_window(void)
  815. {
  816.     wind_close(wind[W_PLAY].handle);
  817.     wind_delete(wind[W_PLAY].handle);
  818.     av_send(AV_ACCWINDCLOSED,wind[W_PLAY].handle,0,0l);
  819. }
  820.  
  821. #define ABSTAND    24
  822. void xhide(int *hide,int x,int y,int w,int h)
  823. {
  824. int mx,my,dummy;
  825.  
  826.     if ( *hide )
  827.         return;        /* maus ist hidden */
  828.     graf_mkstate(&mx,&my,&dummy,&dummy);
  829.     if ( mx>x-ABSTAND && mx<=x+w+ABSTAND && my>y-ABSTAND && my<=y+h+ABSTAND ) {
  830.         *hide=1;
  831.         v_hide_c(handle);
  832.     }
  833. }
  834.  
  835. int check_recs(int x,int y,int w,int h,int *x1,int *y1,int *w1,int *h1)
  836. {
  837. int hx1,hy1,hx2,hy2;
  838.  
  839.     hx2=min(x+w,*x1+*w1);
  840.     hy2=min(y+h,*y1+*h1);
  841.     hx1=max(x,*x1);
  842.     hy1=max(y,*y1);
  843.     *x1=hx1; *y1=hy1;
  844.     *w1=hx2-hx1; *h1=hy2-hy1;
  845.     return( (hx2>hx1)&&(hy2>hy1) );
  846. }
  847.  
  848. void redraw_play(int *message)
  849. {
  850. int m[8];
  851. int xy[8];
  852. int x,y,w,h,_w;
  853. int xo,yo,ww,hh;
  854. int hide=0;
  855.  
  856.     if ( !message ) {
  857.         m[3]=wind[W_PLAY].handle;
  858.         m[4]=m[5]=0;
  859.         m[6]=screen_w;
  860.         m[7]=screen_h;
  861.         message=m;
  862.     }
  863.     wind_update(BEG_UPDATE);
  864.     wind_get(message[3],WF_WORKXYWH,&xo,&yo,&ww,&hh);
  865.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  866.     while ( w!=0 ) {
  867.         _w=w;
  868.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  869.             if ( _w==ww && quick_flag ) {
  870.               char *source,*dest;
  871.                 xhide(&hide,xo,y,_w,h);
  872.                 source=(char*)buffer_addr+(long)(y-yo)*buffer_width;
  873.                 dest=(char*)screen_addr+(long)y*screen_width+xo/8;
  874.                 qcopy(dest,source,h-1);
  875.             }
  876.             else {
  877.                 xhide(&hide,x,y,w,h);
  878.                 xy[0]=x-xo;
  879.                 xy[1]=y-yo;
  880.                 xy[2]=x-xo+w-1;
  881.                 xy[3]=y-yo+h-1;
  882.                 xy[4]=x;
  883.                 xy[5]=y;
  884.                 xy[6]=x+w-1;
  885.                 xy[7]=y+h-1;
  886.                 vro_cpyfm(handle,S_ONLY,xy,&buffer,&screen);
  887.             }
  888.         }
  889.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  890.     }
  891.     if ( hide )
  892.         v_show_c(handle,1);
  893.     wind_update(END_UPDATE);
  894. }
  895.  
  896. #define OFFSET        11
  897. void do_endgame(void)
  898. {
  899. /************
  900. int i,j;
  901. char *source,*dest;
  902.  
  903.     end_flag=1;
  904.     dest=(char*)buffer_addr+buffer_size/2-sizeof(tet_ende);
  905.     if ( opts.play_mode==PM_TETRIS )
  906.         source=(char*)tet_ende;
  907.     else
  908.         source=(char*)col_ende;
  909.     init_wait();
  910.     for ( i=0,j=0; j<(int)sizeof(tet_ende); i+=OFFSET,j++ ) {
  911.         if ( i>=(int)sizeof(tet_ende) ) {
  912.             i-=(int)sizeof(tet_ende);
  913.             redraw_play(0l);
  914.             do_wait(2);
  915.             init_wait();
  916.         }
  917.         dest[i]=source[i];
  918.     }
  919. /********
  920.     init_wait();
  921.     for ( i=0; i<7; i++ ) {
  922.         if ( i&1 ) {
  923.             for ( j=0; j<(int)sizeof(tet_ende); j++ )
  924.                 dest[j]=~source[j];
  925.         }
  926.         else {
  927.             for ( j=0; j<(int)sizeof(tet_ende); j++ )
  928.                 dest[j]=source[j];
  929.         }
  930.         redraw_play(0l);
  931.         do_wait(125);
  932.         init_wait();
  933.     }
  934. ********/
  935.     redraw_play(0l);
  936. ********/
  937. }
  938.  
  939. void set_tetris(void)
  940. {
  941. int x,y,w,h;
  942.  
  943.     if ( opts.play_mode==PM_TETRIS )
  944.         return;
  945.  
  946.     opts.play_mode=PM_TETRIS;
  947.     menu_icheck(menue,M_TETRIS,1);
  948.     menu_icheck(menue,M_COLUMNS,0);
  949.  
  950.     init_window(&x,&y,&w,&h);
  951.     wind_set(wind[W_PLAY].handle,WF_CURRXYWH,x,y,w,h);
  952.     wind_set(wind[W_PLAY].handle,WF_NAME," Tetris ");
  953.     clr_feld();
  954.  
  955.     objc_hide(stat,C_STAT);
  956.     objc_unhide(stat,TSTAT);
  957.  
  958.     if ( opts.tetris.score!=score_flag )
  959.         set_score();
  960.     if ( opts.tetris.preview!=preview_flag )
  961.         set_preview();
  962.     if ( opts.tetris.statistic!=stat_flag )
  963.         set_statistic();
  964.     else if ( stat_flag )
  965.         redraw_statistic(0l);
  966. }
  967.  
  968. void set_columns(void)
  969. {
  970. int x,y,w,h;
  971.  
  972.     if ( opts.play_mode==PM_COLUMNS )
  973.         return;
  974.  
  975.     opts.play_mode=PM_COLUMNS;
  976.     menu_icheck(menue,M_COLUMNS,1);
  977.     menu_icheck(menue,M_TETRIS,0);
  978.  
  979.     init_window(&x,&y,&w,&h);
  980.     wind_set(wind[W_PLAY].handle,WF_CURRXYWH,x,y,w,h);
  981.     wind_set(wind[W_PLAY].handle,WF_NAME," Columns ");
  982.     clr_feld();
  983.  
  984.     objc_unhide(stat,C_STAT);
  985.     objc_hide(stat,TSTAT);
  986.  
  987.     if ( opts.columns.score!=score_flag )
  988.         set_score();
  989.     if ( opts.columns.preview!=preview_flag )
  990.         set_preview();
  991.     if ( opts.columns.statistic!=stat_flag )
  992.         set_statistic();
  993.     else if ( stat_flag )
  994.         redraw_statistic(0l);
  995. }
  996.  
  997. static uint xlevel,xlines,xstones,xscore;
  998.  
  999. void dr_score(uint level,uint lines,uint stones,uint sc)
  1000. {
  1001. static int _level=-1,_lines=-1;
  1002. int le,li;
  1003. int x,y,w,h;
  1004. int hide=0;
  1005.  
  1006.     xlevel=level;
  1007.     xlines=lines;
  1008.     xstones=stones;
  1009.     xscore=sc;
  1010.  
  1011.     if ( !score_flag )
  1012.         return;
  1013.  
  1014.     le=li=0;
  1015.     if ( _level!=level ) {
  1016.         _level=level;
  1017.         sprintf(objc_tedstr(score,LEVEL),"%d",level);
  1018.         le=1;
  1019.     }
  1020.     if ( _lines!=lines ) {
  1021.         _lines=lines;
  1022.         sprintf(objc_tedstr(score,LINES),"%5d",lines);
  1023.         li=1;
  1024.     }
  1025.     sprintf(objc_tedstr(score,STONES),"%5d",stones);
  1026.     sprintf(objc_tedstr(score,SCORE),"%5d",sc);
  1027.  
  1028.     wind_get(wind[W_SCORE].handle,WF_WORKXYWH,&x,&y,&w,&h);
  1029.     score->ob_x=x;
  1030.     score->ob_y=y;
  1031.  
  1032.     wind_update(BEG_UPDATE);
  1033.     wind_get(wind[W_SCORE].handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  1034.     while ( w ) {
  1035.         xhide(&hide,x,y,w,h);
  1036.         if ( le )
  1037.             objc_draw(score,LEVEL,0,x,y,w,h);
  1038.         if ( li )
  1039.             objc_draw(score,LINES,0,x,y,w,h);
  1040.         objc_draw(score,STONES,0,x,y,w,h);
  1041.         objc_draw(score,SCORE,0,x,y,w,h);
  1042.         wind_get(wind[W_SCORE].handle,WF_NEXTXYWH,&x,&y,&w,&h);
  1043.     }
  1044.     if ( hide )
  1045.         v_show_c(handle,1);
  1046.     wind_update(END_UPDATE);
  1047. }
  1048.  
  1049. void redraw_score(int *message)
  1050. {
  1051. int m[8];
  1052. int dummy;
  1053. int x,y,w,h;
  1054. int hide=0;
  1055.  
  1056.     if ( !message ) {
  1057.         m[3]=wind[W_SCORE].handle;
  1058.         m[4]=m[5]=0;
  1059.         m[6]=screen_w;
  1060.         m[7]=screen_h;
  1061.         message=m;
  1062.     }
  1063.  
  1064.     wind_get(wind[W_SCORE].handle,WF_WORKXYWH,&x,&y,&dummy,&dummy);
  1065.     score->ob_x=x;
  1066.     score->ob_y=y;
  1067.  
  1068.     wind_update(BEG_UPDATE);
  1069.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  1070.     while ( w!=0 ) {
  1071.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  1072.             xhide(&hide,x,y,w,h);
  1073.             objc_draw(score,0,MAX_DEPTH,x,y,w,h);
  1074.         }
  1075.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1076.     }
  1077.     if ( hide )
  1078.         v_show_c(handle,1);
  1079.     wind_update(END_UPDATE);
  1080. }
  1081.  
  1082. void open_score(void)
  1083. {
  1084. int x,y,w,h,dummy;
  1085.  
  1086.     wind[W_SCORE].handle=wind_create(NAME|MOVER|CLOSER,0,0,screen_w,screen_h);
  1087.     wind_calc(WC_BORDER,NAME|MOVER|CLOSER,pos->wind_pos[W_SCORE].x,pos->wind_pos[W_SCORE].y,score->ob_width,score->ob_height,&x,&y,&w,&h);
  1088.     check_windpos(&x,&y);
  1089.     wind_set(wind[W_SCORE].handle,WF_NAME," Score ");
  1090.     dr_score(xlevel,xlines,xstones,xscore);
  1091.     wind_open(wind[W_SCORE].handle,x,y,w,h);
  1092.     if ( opts.cycle==2 )
  1093.         av_send(AV_ACCWINDOPEN,wind[W_SCORE].handle,0,0l);
  1094.     wind_get(wind[W_SCORE].handle,WF_WORKXYWH,&pos->wind_pos[W_SCORE].x,&pos->wind_pos[W_SCORE].y,&dummy,&dummy);
  1095.     redraw_score(0l);
  1096.     if ( wind[W_PLAY].handle ) {
  1097.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1098.         redraw_play(0l);
  1099.     }
  1100. }
  1101.  
  1102.  
  1103. void set_score(void)
  1104. {
  1105.     score_flag=1-score_flag;
  1106.     if ( opts.play_mode==PM_TETRIS )
  1107.         opts.tetris.score=score_flag;
  1108.     else
  1109.         opts.columns.score=score_flag;
  1110.     menu_icheck(menue,M_SCORE,score_flag);
  1111.     if ( !score_flag ) {
  1112.         wind_close(wind[W_SCORE].handle);
  1113.         wind_delete(wind[W_SCORE].handle);
  1114.         av_send(AV_ACCWINDCLOSED,wind[W_SCORE].handle,0,0l);
  1115.         wind[W_SCORE].handle=-1;
  1116.     }
  1117.     else {
  1118.         open_score();
  1119.     }
  1120. }
  1121.  
  1122. int prev_x,prev_y,prev_w,prev_h;
  1123.  
  1124. void redraw_preview(int *message)
  1125. {
  1126. int xy[4];
  1127. int m[8];
  1128. int x,y,w,h;
  1129. int hide=0;
  1130.  
  1131.     if ( !message ) {
  1132.         m[3]=wind[W_PREVIEW].handle;
  1133.         m[4]=m[5]=0;
  1134.         m[6]=screen_w;
  1135.         m[7]=screen_h;
  1136.         message=m;
  1137.     }
  1138.  
  1139.     vsf_style(handle,8);
  1140.     vsf_color(handle,0);
  1141.  
  1142.     wind_update(BEG_UPDATE);
  1143.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  1144.     while ( w!=0 ) {
  1145.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  1146.             xhide(&hide,x,y,w,h);
  1147.             xy[0]=x;
  1148.             xy[1]=y;
  1149.             xy[2]=x+w-1;
  1150.             xy[3]=y+h-1;
  1151.             v_bar(handle,xy);
  1152.         }
  1153.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1154.     }
  1155.     if ( hide )
  1156.         v_show_c(handle,1);
  1157.     wind_update(END_UPDATE);
  1158. }
  1159.  
  1160. void draw_preview(Draw_Funct draw,void *data)
  1161. {
  1162. int xy[4];
  1163. int x,y,w,h;
  1164. int hide=0;
  1165.  
  1166.     wind_update(BEG_UPDATE);
  1167.     wind_get(wind[W_PREVIEW].handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  1168.     while ( w!=0 ) {
  1169.         xhide(&hide,x,y,w,h);
  1170.         xy[0]=x;
  1171.         xy[1]=y;
  1172.         xy[2]=x+w-1;
  1173.         xy[3]=y+h-1;
  1174.         vs_clip(handle,1,xy);
  1175.         draw(data,x,y,w,h);
  1176.         wind_get(wind[W_PREVIEW].handle,WF_NEXTXYWH,&x,&y,&w,&h);
  1177.     }
  1178.     vs_clip(handle,0,xy);
  1179.     if ( hide )
  1180.         v_show_c(handle,1);
  1181.     wind_update(END_UPDATE);
  1182. }
  1183.  
  1184. void open_preview(void)
  1185. {
  1186. int x,y,w,h;
  1187. int cw,ch,tw,th,width,height;
  1188. void get_columns_prev(int *w,int *h);
  1189. void get_tetris_prev(int *w,int *h);
  1190.  
  1191.     get_columns_prev(&cw,&ch);
  1192.     get_tetris_prev(&tw,&th);
  1193.  
  1194.     width=max(cw,tw);
  1195.     height=max(ch,th);
  1196.  
  1197.     wind[W_PREVIEW].handle=wind_create(NAME|MOVER|CLOSER,0,0,screen_w,screen_h);
  1198.     wind_calc(WC_BORDER,NAME|MOVER|CLOSER,pos->wind_pos[W_PREVIEW].x,pos->wind_pos[W_PREVIEW].y,width,height,&x,&y,&w,&h);
  1199.     check_windpos(&x,&y);
  1200.     wind_set(wind[W_PREVIEW].handle,WF_NAME," Next ");
  1201.     wind_open(wind[W_PREVIEW].handle,x,y,w,h);
  1202.     if ( opts.cycle==2 )
  1203.         av_send(AV_ACCWINDOPEN,wind[W_PREVIEW].handle,0,0l);
  1204.     wind_get(wind[W_PREVIEW].handle,WF_WORKXYWH,&prev_x,&prev_y,&prev_w,&prev_h);
  1205.     pos->wind_pos[W_PREVIEW].x=prev_x;
  1206.     pos->wind_pos[W_PREVIEW].y=prev_y;
  1207.     redraw_preview(0l);
  1208.     if ( wind[W_PLAY].handle ) {
  1209.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1210.         redraw_play(0l);
  1211.     }
  1212. }
  1213.  
  1214. void set_preview(void)
  1215. {
  1216.     preview_flag=1-preview_flag;
  1217.     if ( opts.play_mode==PM_TETRIS )
  1218.         opts.tetris.preview=preview_flag;
  1219.     else
  1220.         opts.columns.preview=preview_flag;
  1221.     menu_icheck(menue,M_PREVIEW,preview_flag);
  1222.     if ( !preview_flag ) {
  1223.         wind_close(wind[W_PREVIEW].handle);
  1224.         wind_delete(wind[W_PREVIEW].handle);
  1225.         av_send(AV_ACCWINDCLOSED,wind[W_PREVIEW].handle,0,0l);
  1226.         wind[W_PREVIEW].handle=-1;
  1227.     }
  1228.     else {
  1229.         open_preview();
  1230.     }
  1231. }
  1232.  
  1233. void redraw_statistic(int *message)
  1234. {
  1235. int m[8];
  1236. int dummy;
  1237. int x,y,w,h,xy[4];
  1238. int st_x,st_y,st_dy;
  1239. int hide=0;
  1240. void dr_tstat(int x,int y,int dy);
  1241. void dr_cstat(int x,int y,int dy);
  1242.  
  1243.     if ( !message ) {
  1244.         m[3]=wind[W_STATISTIC].handle;
  1245.         m[4]=m[5]=0;
  1246.         m[6]=screen_w;
  1247.         m[7]=screen_h;
  1248.         message=m;
  1249.     }
  1250.  
  1251.     wind_get(wind[W_STATISTIC].handle,WF_WORKXYWH,&x,&y,&dummy,&dummy);
  1252.     stat->ob_x=x;
  1253.     stat->ob_y=y;
  1254.  
  1255.     st_x=x;
  1256.     if ( opts.play_mode==PM_TETRIS ) {
  1257.         objc_offset(stat,TSTAT0,&h,&st_y);
  1258.         y=st_y+stat[TSTAT0].ob_height/2;
  1259.         objc_offset(stat,TSTAT0+1,&w,&h);
  1260.         h+=stat[TSTAT0+1].ob_height/2;
  1261.     }
  1262.     else {
  1263.         objc_offset(stat,CSTAT0,&h,&st_y);
  1264.         y=st_y+stat[CSTAT0].ob_height/2;
  1265.         objc_offset(stat,CSTAT0+1,&w,&h);
  1266.         h+=stat[CSTAT0+1].ob_height/2;
  1267.     }
  1268.     st_dy=h-y;
  1269.  
  1270.     wind_update(BEG_UPDATE);
  1271.     wind_get(message[3],WF_FIRSTXYWH,&x,&y,&w,&h);
  1272.     while ( w!=0 ) {
  1273.         if ( check_recs(message[4],message[5],message[6],message[7],&x,&y,&w,&h) ) {
  1274.             xhide(&hide,x,y,w,h);
  1275.             objc_draw(stat,0,MAX_DEPTH,x,y,w,h);
  1276.             xy[0]=x;
  1277.             xy[1]=y;
  1278.             xy[2]=x+w-1;
  1279.             xy[3]=y+h-1;
  1280.             vs_clip(handle,1,xy);
  1281.             if ( opts.play_mode==PM_TETRIS )
  1282.                 dr_tstat(st_x,st_y,st_dy);
  1283.             else
  1284.                 dr_cstat(st_x,st_y,st_dy);
  1285.             vs_clip(handle,0,xy);
  1286.         }
  1287.         wind_get(message[3],WF_NEXTXYWH,&x,&y,&w,&h);
  1288.     }
  1289.     if ( hide )
  1290.         v_show_c(handle,1);
  1291.     wind_update(END_UPDATE);
  1292. }
  1293.  
  1294. int _stat[10];
  1295.  
  1296. void dr_stat(uint *nstat)
  1297. {
  1298. int x,y,w,h;
  1299. int i,ii,o;
  1300.  
  1301.     if ( opts.play_mode==PM_TETRIS ) {
  1302.         ii=7;
  1303.         o=TSTAT0;
  1304.     }
  1305.     else {
  1306.         ii=6;
  1307.         o=CSTAT0;
  1308.     }
  1309.     for ( i=0; i<ii; i++,o++ ) {
  1310.       int hide=0;
  1311.         if ( nstat[i]!=_stat[i] ) {
  1312.             _stat[i]=nstat[i];
  1313.             sprintf(objc_tedstr(stat,o),"%3d",nstat[i]);
  1314.             wind_get(wind[W_STATISTIC].handle,WF_WORKXYWH,&x,&y,&w,&h);
  1315.             stat->ob_x=x;
  1316.             stat->ob_y=y;
  1317.  
  1318.             wind_update(BEG_UPDATE);
  1319.             wind_get(wind[W_STATISTIC].handle,WF_FIRSTXYWH,&x,&y,&w,&h);
  1320.             while ( w ) {
  1321.                 xhide(&hide,x,y,w,h);
  1322.                 objc_draw(stat,o,0,x,y,w,h);
  1323.                 wind_get(wind[W_STATISTIC].handle,WF_NEXTXYWH,&x,&y,&w,&h);
  1324.             }
  1325.             if ( hide )
  1326.                 v_show_c(handle,1);
  1327.             wind_update(END_UPDATE);
  1328.         }
  1329.     }
  1330. }
  1331.  
  1332. void open_stat(void)
  1333. {
  1334. int x,y,w,h,dummy;
  1335.  
  1336.     wind[W_STATISTIC].handle=wind_create(NAME|MOVER|CLOSER,0,0,screen_w,screen_h);
  1337.     wind_calc(WC_BORDER,NAME|MOVER|CLOSER,pos->wind_pos[W_STATISTIC].x,pos->wind_pos[W_STATISTIC].y,stat->ob_width,stat->ob_height,&x,&y,&w,&h);
  1338.     check_windpos(&x,&y);
  1339.     wind_set(wind[W_STATISTIC].handle,WF_NAME," Statistic ");
  1340.     wind_open(wind[W_STATISTIC].handle,x,y,w,h);
  1341.     if ( opts.cycle==2 )
  1342.         av_send(AV_ACCWINDOPEN,wind[W_STATISTIC].handle,0,0l);
  1343.     wind_get(wind[W_STATISTIC].handle,WF_WORKXYWH,&pos->wind_pos[W_STATISTIC].x,&pos->wind_pos[W_STATISTIC].y,&dummy,&dummy);
  1344.     redraw_statistic(0l);
  1345.     if ( wind[W_PLAY].handle ) {
  1346.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1347.         redraw_play(0l);
  1348.     }
  1349. }
  1350.  
  1351. void set_statistic(void)
  1352. {
  1353.     stat_flag=1-stat_flag;
  1354.     if ( opts.play_mode==PM_TETRIS )
  1355.         opts.tetris.statistic=stat_flag;
  1356.     else
  1357.         opts.columns.statistic=stat_flag;
  1358.     menu_icheck(menue,M_STATISTIC,stat_flag);
  1359.     if ( !stat_flag ) {
  1360.         wind_close(wind[W_STATISTIC].handle);
  1361.         wind_delete(wind[W_STATISTIC].handle);
  1362.         av_send(AV_ACCWINDCLOSED,wind[W_STATISTIC].handle,0,0l);
  1363.         wind[W_STATISTIC].handle=-1;
  1364.     }
  1365.     else {
  1366.         open_stat();
  1367.     }
  1368. }
  1369.  
  1370. void do_play(void)
  1371. {
  1372. int dummy,gret;
  1373. int preview,score,statistic;
  1374. int message[8];
  1375. WINDOWS w;
  1376.  
  1377. int columns(void);
  1378. int tetris(void);
  1379.  
  1380.     if ( opts.multi ) {
  1381.         menu_tnormal(menue,MT_FILE,1);
  1382.         menu_ienable(menue,M_QUIT,0);
  1383.         menu_ienable(menue,M_START,0);
  1384.         menu_ienable(menue,M_TETRIS,0);
  1385.         menu_ienable(menue,M_COLUMNS,0);
  1386.         menu_ienable(menue,M_OPTS,0);
  1387.     }
  1388.     else {
  1389.         v_hide_c(handle);
  1390.         wind_update(BEG_MCTRL);
  1391.         wind_update(BEG_UPDATE);
  1392.     }
  1393.  
  1394.     if ( opts.top ) {
  1395.         for ( w=WIND_ANZ-1; w>=0; w-- ) {
  1396.             wind_set(wind[w].handle,WF_TOP);
  1397.             wind[w].redraw(0l);
  1398.         }
  1399.     }
  1400.     else {
  1401.         wind_set(wind[W_PLAY].handle,WF_TOP);
  1402.     }
  1403.     preview=preview_flag;
  1404.     score=score_flag;
  1405.     statistic=stat_flag;
  1406.  
  1407.     end_flag=0;
  1408.     clr_feld();
  1409.  
  1410.     if ( preview_flag )
  1411.         wind_get(wind[W_PREVIEW].handle,WF_WORKXYWH,&prev_x,&prev_y,&prev_w,&prev_h);
  1412.     wind_get(wind[W_PLAY].handle,WF_WORKXYWH,&x_off,&y_off,&dummy,&dummy);
  1413.  
  1414.     init_copy_out();
  1415.  
  1416.     if ( opts.play_mode==PM_COLUMNS )
  1417.         gret=columns();
  1418.     else
  1419.         gret=tetris();
  1420.  
  1421.     if ( !gret )    /* spielabbruch -> loesche spielfeld */
  1422.         clr_feld();
  1423.     else {
  1424.         do_endgame();
  1425.     }
  1426.     if ( preview!=preview_flag )
  1427.         set_preview();
  1428.     else if ( preview_flag ) {
  1429.         message[3]=wind[W_PREVIEW].handle;
  1430.         message[4]=0;
  1431.         message[5]=0;
  1432.         message[6]=screen_w;
  1433.         message[7]=screen_h;
  1434.         redraw_preview(message);
  1435.     }
  1436.     if ( score!=score_flag )
  1437.         set_score();
  1438.     if ( statistic!=stat_flag )
  1439.         set_statistic();
  1440.  
  1441.     if ( opts.multi ) {
  1442.         menu_ienable(menue,M_QUIT,1);
  1443.         menu_ienable(menue,M_START,1);
  1444.         if ( tetris_vdi!=-1 )
  1445.             menu_ienable(menue,M_TETRIS,1);
  1446.         if ( columns_vdi!=-1 )
  1447.             menu_ienable(menue,M_COLUMNS,1);
  1448.         menu_ienable(menue,M_OPTS,1);
  1449.     }
  1450.     else {
  1451.         wind_update(END_MCTRL);
  1452.         wind_update(END_UPDATE);
  1453.         v_show_c(handle,1);
  1454.     }
  1455. }
  1456.  
  1457. void prog_info(void)
  1458. {
  1459. int x,y,w,h,r;
  1460.  
  1461.     form_center(info,&x,&y,&w,&h);
  1462.     wind_update(BEG_UPDATE);
  1463.     form_dial(FMD_START,x,y,w,h,x,y,w,h);
  1464.     objc_draw(info,0,10,x,y,w,h);
  1465.     r=form_do(info,0)&0x7FFF;
  1466.     form_dial(FMD_FINISH,x,y,w,h,x,y,w,h);
  1467.     wind_update(END_UPDATE);
  1468.     objc_unselect(info,r);
  1469. }
  1470.  
  1471. int do_menue(int titel,int entry)
  1472. {
  1473.     if ( objc_state(menue,entry)&DISABLED )
  1474.         return 0;
  1475.  
  1476.     switch ( entry ) {
  1477.       case M_INFO:          prog_info();      break;
  1478.       case M_START:          do_play();          break;
  1479.       case M_HISCORE:    show_hiscore();      break;
  1480.       case M_QUIT:          return 1;
  1481.       case M_TETRIS:      set_tetris();      break;
  1482.       case M_COLUMNS:      set_columns();      break;
  1483.       case M_SCORE:          set_score();      break;
  1484.       case M_PREVIEW:      set_preview();      break;
  1485.       case M_STATISTIC:    set_statistic();  break;
  1486.       case M_OPTS:          do_options();      break;
  1487.       case M_SAVE:          save_options();      break;
  1488.     }
  1489.     if ( titel )
  1490.         menu_tnormal(menue,titel,1);
  1491.     return 0;
  1492. }
  1493.  
  1494. void do_ctrl(int flag)
  1495. {
  1496. int dummy;
  1497. WINDOWS w;
  1498. EVENT event;
  1499. int evnt,i;
  1500. int key;
  1501.  
  1502.     if ( !flag ) {
  1503.         event.ev_mflags=MU_MESAG|MU_KEYBD;
  1504.     }
  1505.     else {
  1506.         event.ev_mflags=MU_MESAG|MU_TIMER;
  1507.         event.ev_mtlocount=1;
  1508.         event.ev_mthicount=0;
  1509.     }
  1510.  
  1511.     while ( 1 ) {
  1512.         evnt=EvntMulti(&event);
  1513.  
  1514.         if ( evnt==MU_TIMER )
  1515.             return;
  1516.  
  1517.         if ( evnt&MU_KEYBD ) {
  1518.             key=*(char*)&event.ev_mkreturn;
  1519.             event.ev_mmokstate&=~(K_LSHIFT|K_RSHIFT);
  1520.             for ( i=0; i<(int)(sizeof(commands)/sizeof(commands[0])); i++ ) {
  1521.                 if ( key==commands[i].key && event.ev_mmokstate==commands[i].state ) {
  1522.                     if ( do_menue(0,commands[i].entry) )
  1523.                         return;
  1524.                     break;
  1525.                 }
  1526.             }
  1527.             if ( i==(int)(sizeof(commands)/sizeof(commands[0])) )
  1528.                 av_send(AV_SENDKEY,event.ev_mmokstate,event.ev_mkreturn,0l);
  1529.         }
  1530.         else if ( evnt&MU_MESAG ) {
  1531.             switch ( event.ev_mmgpbuf[0] ) {
  1532.               case MN_SELECTED:
  1533.                   if( do_menue(event.ev_mmgpbuf[3],event.ev_mmgpbuf[4]) )
  1534.                       return;
  1535.               break;
  1536.               case WM_REDRAW:
  1537.                 for ( w=0; w<WIND_ANZ; w++ ) {
  1538.                     if ( event.ev_mmgpbuf[3]==wind[w].handle ) {
  1539.                         wind[w].redraw(event.ev_mmgpbuf);
  1540.                         break;
  1541.                     }
  1542.                 }
  1543.               break;
  1544.               case WM_TOPPED:
  1545.                   wind_set(event.ev_mmgpbuf[3],WF_TOP);
  1546.               break;
  1547.               case WM_MOVED:
  1548.                   if ( event.ev_mmgpbuf[3]==wind[W_PLAY].handle ) {
  1549.                   int x,y,w,h;
  1550.                       wind_calc(WC_WORK,NAME|MOVER|CLOSER,event.ev_mmgpbuf[4],event.ev_mmgpbuf[5],event.ev_mmgpbuf[6],event.ev_mmgpbuf[7],&x,&y,&w,&h);
  1551.                       x&=~15;
  1552.                       wind_calc(WC_BORDER,NAME|MOVER|CLOSER,x,y,w,h,event.ev_mmgpbuf+4,event.ev_mmgpbuf+5,event.ev_mmgpbuf+6,event.ev_mmgpbuf+7);
  1553.                 }
  1554.                 wind_set(event.ev_mmgpbuf[3],WF_CURRXYWH,event.ev_mmgpbuf[4],event.ev_mmgpbuf[5],event.ev_mmgpbuf[6],event.ev_mmgpbuf[7]);
  1555.                 for ( w=0; w<WIND_ANZ; w++ ) {
  1556.                     if ( event.ev_mmgpbuf[3]==wind[w].handle ) {
  1557.                         wind_get(event.ev_mmgpbuf[3],WF_WORKXYWH,&pos->wind_pos[w].x,&pos->wind_pos[w].y,&dummy,&dummy);
  1558.                         break;
  1559.                     }
  1560.                 }
  1561.               break;
  1562.               case WM_CLOSED:
  1563.                 for ( w=0; w<WIND_ANZ; w++ ) {
  1564.                     if ( event.ev_mmgpbuf[3]==wind[w].handle ) {
  1565.                           wind[w].close();
  1566.                         break;
  1567.                     }
  1568.                 }
  1569.                 if ( w==0 )
  1570.                     return;
  1571.               break;
  1572.             }
  1573.         }
  1574.     }
  1575. }
  1576.  
  1577. void scale_tree(OBJECT *tree)
  1578. {
  1579. int i=0;
  1580.  
  1581.     do {
  1582.         rsrc_obfix(tree,i);
  1583.     } while ( !(tree[i++].ob_flags&LASTOB) );
  1584. }
  1585.  
  1586. void do_init(void)
  1587. {
  1588. int i,f_id;
  1589. int dummy,work_in[11],work_out[57];
  1590. int desk_x,desk_y,desk_w,desk_h;
  1591. long h;
  1592. WINDOWS w;
  1593.  
  1594.         /* init */
  1595.     ap_id=appl_init();
  1596.  
  1597.     av_init();
  1598.  
  1599.         /* init resources */
  1600.     menue=rs_trindex[MENUE];
  1601.     scale_tree(menue);
  1602.     score=rs_trindex[XSCORE];
  1603.     scale_tree(score);
  1604.     stat=rs_trindex[STATISTIC];
  1605.     scale_tree(stat);
  1606.     options=rs_trindex[OPTSBOX];
  1607.     scale_tree(options);
  1608.     info=rs_trindex[INFOBOX];
  1609.     scale_tree(info);
  1610.     user_keys=rs_trindex[KEYS];
  1611.     scale_tree(user_keys);
  1612.     hiscore=rs_trindex[HISCORE];
  1613.     scale_tree(hiscore);
  1614.     hi_name=rs_trindex[NEWHI];
  1615.     scale_tree(hi_name);
  1616.     *objc_tedstr(hi_name,HI_NAME)=0;
  1617.  
  1618.         /* lese voreinstellung */
  1619.       set_file[0]=Dgetdrv()+'A';
  1620.       set_file[1]=':';
  1621.       Dgetpath(set_file+2,0);
  1622.     strcat(set_file,"\\COLTRIS.SET");
  1623.     f_id=Fopen(set_file,0);
  1624.     if ( f_id>0 ) {
  1625.         Fread(f_id,sizeof(opts),&opts);
  1626.         Fclose(f_id);
  1627.     }
  1628.  
  1629.     wind_get(0,WF_WORKXYWH,&desk_x,&desk_y,&desk_w,&desk_h);
  1630.  
  1631.     for ( i=0; i<8; i++ ) {
  1632.         pos=&opts.pos[i];
  1633.         if ( pos->desk_x==desk_x && pos->desk_y==desk_y && pos->desk_w==desk_w && pos->desk_h==desk_h )
  1634.             break;
  1635.     }
  1636.     if ( i==8 ) {
  1637.         for ( i=7; i>0; i-- )
  1638.             opts.pos[i]=opts.pos[i-1];
  1639.         pos=&opts.pos[0];
  1640.         for ( w=0; w<WIND_ANZ; w++ ) {
  1641.             h=(long)(pos->wind_pos[w].x-pos->desk_x)*desk_w;
  1642.             pos->wind_pos[w].x=(int)(h/pos->desk_w)+desk_x;
  1643.             h=(long)(pos->wind_pos[w].y-pos->desk_y)*desk_h;
  1644.             pos->wind_pos[w].y=(int)(h/pos->desk_h)+desk_y;
  1645.         }
  1646.         pos->desk_x=desk_x;
  1647.         pos->desk_y=desk_y;
  1648.         pos->desk_w=desk_w;
  1649.         pos->desk_h=desk_h;
  1650.     }
  1651.  
  1652.         /* init vdi */
  1653.     handle=graf_handle(&dummy,&dummy,&dummy,&dummy);
  1654.     for ( i=0; i<10; i++ )
  1655.         work_in[i]=1;
  1656.     work_in[10]=2;
  1657.     v_opnvwk(work_in,&handle,work_out);
  1658.     graf_mouse(0,0);
  1659.  
  1660.     screen_w=work_out[0]+1;
  1661.     screen_h=work_out[1]+1;
  1662.  
  1663.     vq_extnd(handle,1,work_out);
  1664.     planes=work_out[4];
  1665.  
  1666.  
  1667.     vswr_mode(handle,MD_REPLACE);
  1668.     vsf_interior(handle,FIS_PATTERN);
  1669.     vsf_perimeter(handle,0);
  1670.  
  1671.     vst_color(handle,0);
  1672.     vst_height(handle,20,&dummy,&dummy,&dummy,&dummy);
  1673.     /*vst_effects(handle,16);*/
  1674.     vst_alignment(handle,1,1,&dummy,&dummy);
  1675.  
  1676.     av_getproto();
  1677. }
  1678.  
  1679. void do_exit(int ret)
  1680. {
  1681. WINDOWS w;
  1682.  
  1683.     if ( ret==1 ) {
  1684.         form_error(8);
  1685.     }
  1686.     else if ( ret==2 ) {
  1687.         form_alert(1,"[1][ | Missing or incorrect | | Image-Files! | ][ Exit ]");
  1688.     }
  1689.     else if ( ret!=0 ) {
  1690.         form_alert(1,"[1][ | Something went wrong! | ][ Exit ]");
  1691.     }
  1692.     for ( w=0; w<WIND_ANZ; w++ ) {
  1693.         if ( wind[w].handle ) {
  1694.             wind_close(wind[w].handle);
  1695.             wind_delete(wind[w].handle);
  1696.             av_send(AV_ACCWINDCLOSED,wind[w].handle,0,0l);
  1697.         }
  1698.     }
  1699.     v_clsvwk(handle);
  1700.     av_send(AV_EXIT,0,0,0l);
  1701.     appl_exit();
  1702.     if ( buffer_addr )
  1703.         free((void*)buffer_addr);
  1704.     exit(ret);
  1705. }
  1706.  
  1707.  
  1708. void main(void)
  1709. {
  1710. int init_columns(void);
  1711. int init_tetris(void);
  1712.  
  1713.     do_init();
  1714.  
  1715.     if ( !init_columns() )
  1716.         menu_ienable(menue,M_COLUMNS,0);
  1717.     if ( !init_tetris() )
  1718.         menu_ienable(menue,M_TETRIS,0);
  1719.     if ( objc_state(menue,M_COLUMNS)&DISABLED && objc_state(menue,M_TETRIS)&DISABLED )
  1720.         do_exit(2);
  1721.  
  1722.     if ( opts.play_mode==PM_COLUMNS && !(objc_state(menue,M_COLUMNS)&DISABLED) ) {
  1723.         menu_icheck(menue,M_COLUMNS,1);
  1724.         objc_unhide(stat,C_STAT);
  1725.         objc_hide(stat,TSTAT);
  1726.     }
  1727.     else {
  1728.         menu_icheck(menue,M_TETRIS,1);
  1729.         objc_hide(stat,C_STAT);
  1730.         objc_unhide(stat,TSTAT);
  1731.         opts.play_mode=PM_TETRIS;
  1732.     }
  1733.  
  1734.     menu_bar(menue,1);
  1735.  
  1736.     if ( (opts.play_mode==PM_COLUMNS && opts.columns.score) ||
  1737.             (opts.play_mode==PM_TETRIS && opts.tetris.score) )
  1738.         set_score();
  1739.     if ( (opts.play_mode==PM_COLUMNS && opts.columns.preview) ||
  1740.             (opts.play_mode==PM_TETRIS && opts.tetris.preview) )
  1741.         set_preview();
  1742.     if ( (opts.play_mode==PM_COLUMNS && opts.columns.statistic) ||
  1743.             (opts.play_mode==PM_TETRIS && opts.tetris.statistic) )
  1744.         set_statistic();
  1745.     open_window();
  1746.  
  1747.     do_ctrl(0);
  1748.  
  1749.     do_exit(0);
  1750. }
  1751.  
  1752.