install: add install sources and resources
[doom2d-restoration.git] / SETUP / INSTALL.C
blobd21814b621e7899e8b3545571a23ca02ad2667fb
1 #include <stdio.h>
2 #include <malloc.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <direct.h>
7 #include <dos.h>
8 #include <sound.h>
9 #include <snddrv.h>
10 #include <keyb.h>
11 #include <vga.h>
12 #include <averr.h>
13 #include <harderr.h>
14 #include <process.h>
16 enum{END,BYTE,WORD,DWORD,SWITCH};
18 char _fast=0;
20 char bright[256];
22 extern int doom_sfnt,doom_bfnt;
24 #define TSNDS 10
25 snd_t *testsnd[TSNDS];
26 snd_t *ipath_snd,*igo_snd,*iend_snd;
28 //------------------------------------------------------------------//
30 extern void flame_sprf(void);
32 #define MAXFLM 1000
34 static struct{int x,y,xv,yv;short s;} flm[MAXFLM];
36 extern vgaimg flame01,flame02,flame03,flame04;
37 extern vgaimg flame05,flame06,flame07,flame08;
39 static vgaimg *fspr[8]={
40   &flame01,&flame02,&flame03,&flame04,
41   &flame05,&flame06,&flame07,&flame08
44 void init_flame(void) {
45   int i;
47   for(i=0;i<MAXFLM;++i) flm[i].s=-1;
50 void new_flame(int ax,int ay,int axv,int ayv) {
51   int i;
53   for(i=0;i<MAXFLM;++i) if(flm[i].s==-1) {
54     flm[i].x=ax;flm[i].y=ay;flm[i].xv=axv;flm[i].yv=ayv;flm[i].s=0;
55     return;
56   }
59 void add_flame(int x,int y,int xv,int yv,int d) {
60   int i,m;
62 //  fxv+=xv<<2;fyv+=yv<<2;
63   if(_fast) return;
64   m=max(abs(xv),abs(yv));
65   if(!m) m=1;
66   for(i=0;i<m;i+=3) {
67     new_flame((x<<3)+(xv<<3)*i/m+(rand()%(d*2+1)-d),
68       (y<<3)+(yv<<3)*i/m+(rand()%(d*2+1)-d),
69       rand()%33-16,-rand()%20);
70   }
73 void flame_act(void) {
74   int i;
76   for(i=0;i<MAXFLM;++i) if(flm[i].s>=0) {
77     if(flm[i].xv) flm[i].xv+=(flm[i].xv>0)?-1:1;
78     if(flm[i].yv) flm[i].yv+=(flm[i].yv>0)?-1:1;
79     flm[i].x+=flm[i].xv;
80     flm[i].y+=flm[i].yv;
81     if(++flm[i].s>=8) flm[i].s=-1;
82   }
85 void flame_draw(void) {
86   int i;
88   for(i=0;i<MAXFLM;++i) if(flm[i].s>=0) {
89     V_sprf(flm[i].x>>3,flm[i].y>>3,fspr[flm[i].s],flame_sprf);
90   }
93 void V_cursor(int x,int y) {
94   new_flame((x<<3)+rand()%17-8,(y<<3)+3*8+rand()%17-8,rand()%17-8,-rand()%15-5);
97 //------------------------------------------------------------------//
99 #define MAXFMOV 100
101 static struct{int x1,y1,x2,y2,t,d;} fmov[MAXFMOV];
103 void init_fmov(void) {
104   int i;
106   for(i=0;i<MAXFMOV;++i) fmov[i].t=0;
109 void new_fmov(int x1,int y1,int x2,int y2,int t,int d) {
110   int i;
112   for(i=0;i<MAXFMOV;++i) if(!fmov[i].t) {
113     fmov[i].t=t;fmov[i].t=d;
114     fmov[i].x1=x1;fmov[i].y1=y1;
115     fmov[i].x2=x2;fmov[i].y2=y2;
116     return;
117   }
120 void fmov_act(void) {
121   int x,y,i;
123   for(i=0;i<MAXFMOV;++i) if(fmov[i].t>0) {
124     x=fmov[i].x1;y=fmov[i].y1;
125     fmov[i].x1=(fmov[i].x1-fmov[i].x2)*(fmov[i].t-1)/fmov[i].t+fmov[i].x2;
126     fmov[i].y1=(fmov[i].y1-fmov[i].y2)*(fmov[i].t-1)/fmov[i].t+fmov[i].y2;
127     add_flame(x,y,fmov[i].x1-x,fmov[i].y1-y,fmov[i].d);
128     --fmov[i].t;
129   }
132 static char vputs_flm=0;
134 void vputs(char *s) {
135   int w,h;
137   if(vputs_flm) {
138     w=V_strlen(s);
139     h=(vf_font==&doom_sfnt)?4:8;
140     if(rand()&1) new_fmov(vf_x,vf_y+h,vf_x+w,vf_y+h,5,h);
141     else new_fmov(vf_x+w,vf_y+h,vf_x,vf_y+h,5,h);
142   }
143   V_puts(s);
146 //------------------------------------------------------------------//
148 enum{
149   NONE,MAIN,SOUND,SCARD,SPORT,SDMA,SIRQ,SFREQ,RKPL,RKEYS,
150   TESTYN,SNDYN,TESTSND,
151   IDIR,INST,IDONE,
152   MAX_MNU
155 int mnu=NONE,swmnu=SCARD,need_exit=0,redraw=0,def_k=0;
156 int cur[MAX_MNU];
157 int total[MAX_MNU]={0,3,6,SDRV__END,0,0,0,10,2,9,2,2,0,0,0,0};
159 extern vgapal doompal;
160 extern vgaimg cursor;
161 extern short *snd_par;
163 unsigned char plk[2][9]={
164   {75,77,72,80,0x9D,0xB8,73,71,54},
165   {31,33,18,32,16,30,19,17,15}
168 char newscr[64008];
170 char cfile[256]="DEF.CFG";
171 char ddir[256]="C:\\CMRTKA";
172 char sdir[256]="";
174 int snd_card=0;
176 typedef struct{
177   char *n;
178   char t;
179   void *p;
180 }cfg_t;
182 cfg_t cfg[]={
183   {"sound_card",DWORD,&snd_card},
184   {"sound_rate",WORD,&sfreq},
185   {"sound_port",WORD,&snd_port},
186   {"sound_dma",WORD,&snd_dma},
187   {"sound_irq",WORD,&snd_irq},
188   {"pl1_left",BYTE,&plk[0][0]},
189   {"pl1_right",BYTE,&plk[0][1]},
190   {"pl1_up",BYTE,&plk[0][2]},
191   {"pl1_down",BYTE,&plk[0][3]},
192   {"pl1_jump",BYTE,&plk[0][4]},
193   {"pl1_fire",BYTE,&plk[0][5]},
194   {"pl1_next",BYTE,&plk[0][6]},
195   {"pl1_prev",BYTE,&plk[0][7]},
196   {"pl1_use",BYTE,&plk[0][8]},
197   {"pl2_left",BYTE,&plk[1][0]},
198   {"pl2_right",BYTE,&plk[1][1]},
199   {"pl2_up",BYTE,&plk[1][2]},
200   {"pl2_down",BYTE,&plk[1][3]},
201   {"pl2_jump",BYTE,&plk[1][4]},
202   {"pl2_fire",BYTE,&plk[1][5]},
203   {"pl2_next",BYTE,&plk[1][6]},
204   {"pl2_prev",BYTE,&plk[1][7]},
205   {"pl2_use",BYTE,&plk[1][8]},
206   {NULL,END,NULL}
209 void close_all(void) {
210   V_done();K_done();S_done();
213 void error(int z,int t,int n,char *s1,char *s2) {
214   char *m;
216   close_all();
217   printf(av_ez_msg[z],s1,s2);
218   if(t==ET_STD) m=strerror(n); else m=av_err_msg[n];
219   printf(":\n  %s\n",m);
220   exit(1);
223 static char prbuf[500];
225 void V_printf(char *s,...) {
226   va_list ap;
228   va_start(ap,s);
229   vsprintf(prbuf,s,ap);
230   va_end(ap);
231   vf_font=&doom_sfnt;
232   vputs(prbuf);
235 void V_prhdr(int y,char *s) {
236   vf_font=&doom_bfnt;
237   vf_x=160-V_strlen(s)/2;vf_y=y;
238   vputs(s);
239   vf_font=&doom_sfnt;
242 #define gotoxy(x,y) {vf_x=(x);vf_y=(y);}
244 void save_cfg(void) {
245   FILE *oh;
246   cfg_t *c;
248   if(!(oh=fopen(cfile,"wt"))) return;
249     fprintf(oh,";Файл конфигурации\n\n");
250     fprintf(oh,"cd_path=%s\n",sdir);
251     fprintf(oh,"gamma=1\n");
252     fprintf(oh,"sound_volume=128\n");
253     fprintf(oh,"music_volume=128\n");
254     fprintf(oh,"sound_interp=off\n");
255   for(c=cfg;c->t;++c) switch(c->t) {
256     case BYTE:
257       fprintf(oh,"%s=%u\n",c->n,*(unsigned char*)c->p);
258       break;
259     case SWITCH:
260       fprintf(oh,"%s=%s\n",c->n,(*(char*)c->p)?"on":"off");
261       break;
262     case WORD:
263       fprintf(oh,"%s=%u\n",c->n,*(unsigned short*)c->p);
264       break;
265     case DWORD:
266       fprintf(oh,"%s=%u\n",c->n,*(unsigned*)c->p);
267       break;
268   }
269   fclose(oh);
272 void prmenu(int x,int y,int c,...) {
273   char **ap;
275   if(c>=0) V_cursor(x-10,y+c*10);
276   vf_font=(void*)&doom_sfnt;
277   ap=(char**)(&c+1);
278   while(*ap) {
279     vf_x=x;vf_y=y;
280     vputs(*ap);
281     ++ap;
282     y+=10;
283   }
286 char *keyname(short k) {
287   static char *nm[83]={
288     "ESC","1","2","3","4","5","6","7","8","9","0","-","=","BACKSPACE","TAB",
289     "Q","W","E","R","T","Y","U","I","O","P","[","]","ENTER","ЛЕВЫЙ CONTROL","A","S",
290     "D","F","G","H","J","K","L",";","\"","\'","ЛЕВЫЙ SHIFT","\\","Z","X","C","V",
291     "B","N","M","<",">","/","ПРАВЫЙ SHIFT","*","ЛЕВЫЙ ALT","ПРОБЕЛ","CAPS LOCK","F1","F2","F3","F4","F5",
292     "F6","F7","F8","F9","F10","NUM LOCK","SCROLL LOCK","[7]","[8]","[9]","СЕРЫЙ -","[4]","[5]","[6]","СЕРЫЙ +","[1]",
293     "[2]","[3]","[0]","[.]"
294   };
295   static char s[20];
297   if(k>=1 && k<=0x53) return nm[k-1];
298   if(k==0) return "???";
299   if(k==0x57) return "F11";
300   if(k==0x58) return "F12";
301   switch(k) {
302     case 0x9C: return "СЕРЫЙ ENTER";
303     case 0x9D: return "ПРАВЫЙ CONTROL";
304     case 0xB8: return "ПРАВЫЙ ALT";
305     case 0xC7: return "HOME";
306     case 0xC8: return "ВВЕРХ";
307     case 0xC9: return "PAGE UP";
308     case 0xCB: return "ВЛЕВО";
309     case 0xCD: return "ВПРАВО";
310     case 0xCF: return "END";
311     case 0xD0: return "ВНИЗ";
312     case 0xD1: return "PAGE DOWN";
313     case 0xD2: return "INSERT";
314     case 0xD3: return "DELETE";
315   }
316   sprintf(s,"КЛАВИША #%X",k);
317   return s;
320 void drawmenu(int m) {
321   short *p;
322   int i;
323   static char *kn[9]={
324     "ВЛЕВО","ВПРАВО","ВВЕРХ","ВНИЗ","ПРЫЖОК","ОГОНЬ",
325     "СЛЕД. ОРУЖИЕ","ПРЕД. ОРУЖИЕ","ОТКРЫВАТЬ"
326   };
328   V_setrect(0,320,0,200);
329 //  draw_back();
330   V_clr(0,320,0,200,0);
331   switch(m) {
332     case MAIN:
333       V_prhdr(35,"SETUP");
334       prmenu(100,80,cur[m],"НАСТРОЙКА ЗВУКА","ВЫБОР КЛАВИШ","ВЫХОД В DOS",NULL);
335       break;
336     case SOUND:
337       V_prhdr(35,"НАСТРОЙКА ЗВУКА");
338       gotoxy(100,80);
339       if(snd_card) V_printf("КАРТА %s",strupr(snd_name));
340         else vputs("ЗВУКОВОЙ КАРТЫ НЕТ");
341       p=snd_par;
342       gotoxy(100,90);vputs("ПОРТ ");
343       if(*p) V_printf("%X",snd_port); else vputs("НЕ НУЖЕН");
344       p+=*p+1;
345       gotoxy(100,100);vputs("DMA ");
346       if(*p) V_printf("%u",snd_dma); else vputs("НЕ НУЖНО");
347       p+=*p+1;
348       gotoxy(100,110);vputs("IRQ ");
349       if(*p) V_printf("%u",snd_irq); else vputs("НЕ НУЖНО");
350       gotoxy(100,120);V_printf("ЧАСТОТА %u ГЦ",sfreq);
351       gotoxy(100,130);vputs((snd_card)?"ПРОВЕРКА":"УСТАНОВКА");
352       V_cursor(100-10,80+cur[m]*10);
353       break;
354     case TESTSND:
355       V_prhdr(90,"ПРОВЕРКА ЗВУКА");
356       break;
357     case TESTYN:
358       V_prhdr(35,"НЕТ ЗВУКОВОЙ КАРТЫ");
359       gotoxy(90,60);vputs("ПРОДОЛЖИТЬ ПРОВЕРКУ ?");
360       gotoxy(10,80);vputs("(ЭТО МОЖЕТ ПРИВЕСТИ К ЗАВИСАНИЮ КОМПЬЮТЕРА)");
361       gotoxy(150,100);vputs("НЕТ");
362       gotoxy(150,110);vputs("ДА");
363       V_cursor(150-10,100+cur[m]*10);
364       break;
365     case SNDYN:
366       gotoxy(100,60);vputs("ВЫ СЛЫШАЛИ ЗВУК ?");
367       gotoxy(150,100);vputs("ДА");
368       gotoxy(150,110);vputs("НЕТ");
369       V_cursor(150-10,100+cur[m]*10);
370       break;
371     case SCARD:
372       V_prhdr(35,"ВЫБЕРИ ЗВУКОВУЮ КАРТУ");
373       for(i=0;i<SDRV__END;++i) {
374         set_snd_drv(i);
375         gotoxy(100,80+i*10);
376         vputs((i==0)?"БЕЗ ЗВУКА":strupr(snd_name));
377       }
378       V_cursor(100-10,80+cur[m]*10);
379       set_snd_drv(snd_card);
380       break;
381     case SPORT:
382       V_prhdr(35,"ВЫБЕРИ ПОРТ");
383       p=snd_par+1;
384       for(i=0;i<total[m];++i,++p) {
385         gotoxy(130,80+i*10);
386         V_printf("ПОРТ %X",*p);
387       }
388       V_cursor(130-10,80+cur[m]*10);
389       break;
390     case SDMA:
391       V_prhdr(35,"ВЫБЕРИ DMA");
392       p=snd_par;p+=*p+2;
393       for(i=0;i<total[m];++i,++p) {
394         gotoxy(140,80+i*10);
395         V_printf("DMA %u",*p);
396       }
397       V_cursor(140-10,80+cur[m]*10);
398       break;
399     case SIRQ:
400       V_prhdr(35,"ВЫБЕРИ IRQ");
401       p=snd_par;p+=*p+1;p+=*p+2;
402       for(i=0;i<total[m];++i,++p) {
403         gotoxy(140,80+i*10);
404         V_printf("IRQ %u",*p);
405       }
406       V_cursor(140-10,80+cur[m]*10);
407       break;
408     case SFREQ:
409       V_prhdr(35,"ВЫБЕРИ КАЧЕСТВО ЗВУКА");
410       prmenu(130,80,cur[m],
411         "5000 ГЦ","6000 ГЦ","7000 ГЦ","8000 ГЦ","9000 ГЦ",
412         "10000 ГЦ","11000 ГЦ","16000 ГЦ","22000 ГЦ","44000 ГЦ",NULL);
413       break;
414     case RKPL:
415       V_prhdr(35,"ВЫБОР КЛАВИШ");
416       prmenu(100,80,cur[m],"ПЕРВЫЙ ИГРОК","ВТОРОЙ ИГРОК",NULL);
417       break;
418     case RKEYS:
419       V_prhdr(35,"ВЫБЕРИ КЛАВИШИ");
420       for(i=0;i<9;++i) {
421         gotoxy(90,80+i*10);vputs(kn[i]);
422         gotoxy(180,80+i*10);vputs(keyname(plk[cur[RKPL]][i]));
423       }
424       V_cursor(90-10,80+cur[m]*10);
425       break;
426     case IDIR:
427       V_prhdr(35,"КУДА УСТАНАВЛИВАТЬ");
428       gotoxy(20,100);vputs(ddir);V_cursor(vf_x+8,vf_y);
429       break;
430     case INST:
431       V_prhdr(35,"ИДЕТ УСТАНОВКА");
432       gotoxy(90,70);vputs("F10 - ОТМЕНА УСТАНОВКИ");
433       break;
434     case IDONE:
435       V_prhdr(90,"УСТАНОВКА ЗАВЕРШЕНА");
436       break;
437   }
440 //----------------------------------------------------------------------//
442 void main_loop(void) {
443     fmov_act();
444     flame_act();
445       V_setscr(scrbuf);
446       drawmenu(mnu);
447         V_setscr(newscr+8);
448         memset(newscr+8,0,64000);
449         flame_draw();
450         V_setscr(scrbuf);
451         V_spr(0,0,(vgaimg*)newscr);
452       V_setscr(NULL);
453       memcpy(scra,scrbuf,64000);
454       redraw=0;
457 void setmnu(int m) {
458   int t;
460   if(m==IDIR && mnu==SNDYN) {
461     T_done();S_init();
462     if(snd_type!=ST_NONE) if(snd_card!=3 && snd_card!=4)
463       if(load_dmm("install.dmm")) S_startmusic();
464     if(snd_type!=ST_NONE) S_play(ipath_snd,7,1024,255);
465   }
466   vputs_flm=1;
467   V_setscr(scrbuf);drawmenu(mnu);drawmenu(m);
468   vputs_flm=0;
469   for(t=0;t<6;++t) {
470     timer=0;
471     main_loop();
472     while(timer<0xFFFF);
473   }
474   mnu=m;
475   V_setscr(NULL);
478 static int ed_k=0;
480 void menu_kp(short k) {
481   short *p;
482   static unsigned short ftab[10]={
483     5000,6000,7000,8000,9000,10000,11000,16000,22000,44000
484   };
485   static unsigned char kch[128]={
486      0 , 0 ,'1','2','3','4','5','6','7','8','9','0','-','=', 0 , 0 ,
487     'Q','W','E','R','T','Y','U','I','O','P','[',']', 0 , 0 ,'A','S',
488     'D','F','G','H','J','K','L',';','\'','`', 0 ,'\\','Z','X','C','V',
489     'B','N','M',',','.','/', 0 ,'*', 0 ,' ', 0 , 0 , 0 , 0 , 0 , 0 ,
490      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'-', 0 , 0 , 0 ,'+', 0 ,
491      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
492      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
493      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
494   };
495   static unsigned char kch_sh[128]={
496      0 , 0 ,'!','@','#','$','%','^','&','*','(',')','_','+', 0 , 0 ,
497     'Q','W','E','R','T','Y','U','I','O','P','{','}', 0 , 0 ,'A','S',
498     'D','F','G','H','J','K','L',':','\"','~', 0 ,'|','Z','X','C','V',
499     'B','N','M','<','>','?', 0 ,'*', 0 ,' ', 0 , 0 , 0 , 0 , 0 , 0 ,
500      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,'-', 0 , 0 , 0 ,'+', 0 ,
501      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
502      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
503      0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
504   };
506   if(mnu==IDIR) {
507     switch(k) {
508       case 1:
509         swmnu=SOUND;
510         S_stopmusic();free_music();
511         S_done();T_init();
512         break;
513       case 0x0E: ed_k=-1;break;
514       case 0x1C: case 0x9C: swmnu=INST;break;
515       default:
516         if(keys[0x2A] || keys[0x36]) ed_k=kch_sh[k&0x7F];
517         else ed_k=kch[k&0x7F];
518         break;
519     }return;
520   }
521   switch(k) {
522     case 0x44:
523       if(mnu==INST) need_exit=1;
524       break;
525     case 1:
526       switch(mnu) {
527         case MAIN: need_exit=1;break;
528         case SOUND: need_exit=1;break;
529         case IDIR: swmnu=SOUND;S_done();T_init();break;
530         case SCARD: swmnu=SOUND;break;
531         case SPORT: swmnu=SOUND;break;
532         case SDMA: swmnu=SOUND;break;
533         case SIRQ: swmnu=SOUND;break;
534         case SFREQ: swmnu=SOUND;break;
535         case RKPL: swmnu=MAIN;break;
536         case RKEYS: swmnu=RKPL;break;
537       }break;
538     case 0x48: case 0xC8:
539       if(--cur[mnu]<0) cur[mnu]=total[mnu]-1;
540       redraw=1;break;
541     case 0x50: case 0xD0: case 0x4C:
542       if(++cur[mnu]>=total[mnu]) cur[mnu]=0;
543       redraw=1;break;
544     case 0x1C: case 0x39: case 0x9C:
545       switch(mnu) {
546         case MAIN:
547           switch(cur[mnu]) {
548             case 0: swmnu=SOUND;break;
549             case 1: swmnu=RKPL;break;
550             case 2: need_exit=1;break;
551           }break;
552         case SOUND:
553           switch(cur[mnu]) {
554             case 0: swmnu=SCARD;break;
555             case 1: if(total[SPORT]>1) swmnu=SPORT; break;
556             case 2: if(total[SDMA]>1) swmnu=SDMA; break;
557             case 3: if(total[SIRQ]>1) swmnu=SIRQ; break;
558             case 4: swmnu=SFREQ;break;
559             case 5:
560               if(!S_detect()) {swmnu=TESTYN;cur[TESTYN]=0;break;}
561               swmnu=TESTSND;break;
562           }break;
563         case TESTYN:
564           swmnu=(cur[mnu])?TESTSND:SOUND;break;
565         case SNDYN:
566           swmnu=SOUND;break;
567         case SCARD:
568           set_snd_drv(snd_card=cur[mnu]);
569           p=snd_par;
570           if(total[SPORT]=*p) snd_port=p[1]; p+=*p+1;
571           if(total[SDMA]=*p) snd_dma=p[1]; p+=*p+1;
572           if(total[SIRQ]=*p) snd_irq=p[1];
573           cur[SPORT]=cur[SDMA]=cur[SIRQ]=0;
574           swmnu=SOUND;break;
575         case SPORT:
576           p=snd_par;
577           snd_port=p[cur[mnu]+1];
578           swmnu=SOUND;break;
579         case SDMA:
580           p=snd_par;p+=*p+1;
581           snd_dma=p[cur[mnu]+1];
582           swmnu=SOUND;break;
583         case SIRQ:
584           p=snd_par;p+=*p+1;p+=*p+1;
585           snd_irq=p[cur[mnu]+1];
586           swmnu=SOUND;break;
587         case SFREQ:
588           sfreq=ftab[cur[mnu]];
589           swmnu=SOUND;break;
590         case RKPL: swmnu=RKEYS;break;
591         case RKEYS:
592           plk[cur[RKPL]][cur[RKEYS]]=0;def_k=1;
593           V_setscr(scrbuf);drawmenu(mnu);V_setscr(NULL);
594           memcpy(scra,scrbuf,64000);
595           break;
596         case IDIR: need_exit=1;break;
597       }break;
598   }
601 volatile unsigned char defk_key;
603 void defk_kp(short k) {
604   defk_key=k;
607 int i_progr=0,i_file=0;
608 FILE *ifh=NULL,*iofh=NULL;
610 int IP_TOTAL=5000000;
612 enum{I_GO,I_OK};
614 #define IFILES 11
616 static char *i_fname[IFILES]={
617   "START.DAT","SETUP.DAT","INSTALL.DAT","README.DOC","DOS4GW.EXE",
618   "EDITOR.DAT","EDITOR.CFG",
619   "MEGADM.WAD","MEGADM.BAT",
620   "SUPERDM.WAD","SUPERDM.BAT"
622 static char *i_ofname[IFILES]={
623   "START.EXE","SETUP.EXE","CMRTKA.WAD","README.DOC","DOS4GW.EXE",
624   "EDITOR.EXE","EDITOR.CFG",
625   "MEGADM.WAD","MEGADM.BAT",
626   "SUPERDM.WAD","SUPERDM.BAT"
629 int fsize(char *fn) {
630   FILE *h;
631   int sz;
633   if(!(h=fopen(fn,"rb"))) return 0;
634   fseek(h,0,SEEK_END);
635   sz=ftell(h);
636   fclose(h);
637   return sz;
640 void inst_reset(void) {
641   int i,n;
643   i_progr=0;i_file=0;
644   ifh=iofh=NULL;
645   for(n=0,IP_TOTAL=1;n<IFILES;++n) {
646     if((i=fsize(i_fname[n]))<=0) {
647       V_done();K_done();S_done();
648       printf("\nНе могу открыть файл %s\n",i_fname[n]);
649       exit(1);
650     }
651     IP_TOTAL+=i;
652   }
655 #define BSZ 5000
657 int install(void) {
658   int s;
659   static char buf[BSZ];
661   if(ifh) {
662     s=fread(buf,1,BSZ,ifh);
663     if(s<=0) {
664       fclose(ifh);fclose(iofh);
665       ifh=iofh=NULL;
666       ++i_file;
667       return I_GO;
668     }
669     fwrite(buf,s,1,iofh);
670     i_progr+=s;
671   }else{
672     if(i_file>=IFILES) return I_OK;
673     if(!(ifh=fopen(i_fname[i_file],"rb"))) {
674       V_done();K_done();S_done();
675       printf("\nНе могу открыть файл %s\n",i_fname[i_file]);
676       exit(1);
677     }
678     sprintf(buf,"%s\\%s",ddir,i_ofname[i_file]);
679     if(!(iofh=fopen(buf,"wb"))) {
680       V_done();K_done();S_done();
681       printf("\nНе могу создать файл %s\n",buf);
682       exit(1);
683     }
684   }
685   return I_GO;
688 void load_res(void) {
689   int i;
690   static char s[40];
692   for(i=0;i<TSNDS;++i) {
693     sprintf(s,"TEST%02d.DMI",i+1);
694     if(!(testsnd[i]=load_dmi(s)))
695       {printf("Не могу открыть файл %s\n",s);exit(1);}
696   }
697   if(!(ipath_snd=load_dmi("INSTPATH.DMI")))
698     {puts("Не могу открыть файл INSTPATH.DMI");exit(1);}
699   if(!(igo_snd=load_dmi("INSTGO.DMI")))
700     {puts("Не могу открыть файл INSTGO.DMI");exit(1);}
701   if(!(iend_snd=load_dmi("INSTEND.DMI")))
702     {puts("Не могу открыть файл INSTEND.DMI");exit(1);}
705 int harderr_handler(int f,int d,int e) {
706   if(!keys[0x44]) return HARDERR_RETRY;
707   close_all();return HARDERR_ABORT;
710 void chk_blaster(void) {
711   char *p,c;
712   unsigned v;
714   if(!(p=getenv("BLASTER"))) return;
715   snd_card=5;snd_port=0x220;snd_irq=7;snd_dma=1;
716   swmnu=SOUND;
717   for(;*p;) {
718     if((*p>='A' && *p<='Z') || (*p>='a' && *p<='z')) {
719       c=*p;if(c>='a' && c<='z') c=c-'a'+'A';
720       v=strtoul(p+1,&p,(c=='I' || c=='D')?10:16);
721       switch(c) {
722         case 'A': snd_port=v;break;
723         case 'I': snd_irq=v;break;
724         case 'D': snd_dma=v;break;
725       }
726     }else ++p;
727   }
730 void build_dir(char *d) {
731   static char s[256],dir[256];
732   char *p;
734   strcpy(s,d);
735   dir[0]=0;if(s[0]=='\\') strcpy(dir,"\\");
736   for(p=strtok(s,"\\");p;p=strtok(NULL,"\\")) {
737     strcat(dir,p);
738     if(strchr(p,':')) {strcat(dir,"\\");continue;}
739     mkdir(dir);
740     strcat(dir,"\\");
741   }
744 int main(int ac,char *av[]) {
745   short *p;
746   int i,j;
747   static int cnt=0;
749   sfreq=11000;
750   snd_vol=128;
751   mus_vol=128;
752   for(i=0;i<256;++i)
753     bright[i]=VP_brightness(doompal[i].r,doompal[i].g,doompal[i].b)/2;
754   load_res();
755   if(ac>=2) {
756     if(stricmp(av[1],"-fast")==0) {
757       _fast=1;
758       if(ac>=3) strcpy(ddir,av[2]);
759     }else{
760       strcpy(ddir,av[1]);
761       if(ac>=3) if(stricmp(av[2],"-fast")==0) _fast=1;
762     }
763   }
764   if(ac>=1) {
765     strcpy(sdir,av[0]);
766     for(i=strlen(sdir)-1;i>=0;--i) {
767       if(sdir[i]=='\\' || sdir[i]==':') break;
768       sdir[i]=0;
769     }
770   }
771   strupr(ddir);
772   K_init();
773   harderr_inst(harderr_handler);
774   ((short*)newscr)[0]=320;
775   ((short*)newscr)[1]=200;
776   memset(newscr+4,0,4);
777   memset(cur,0,sizeof(cur));
778   chk_blaster();
779   set_snd_drv(snd_card);
780   p=snd_par;
781   p+=(total[SPORT]=*p)+1;
782   p+=(total[SDMA]=*p)+1;
783   total[SIRQ]=*p;
784   V_init();VP_setall(doompal);
785   vf_font=(void*)&doom_sfnt;vf_color=0;vf_step=-1;
786   K_setkeyproc(menu_kp);T_init();
787   init_flame();
788   init_fmov();
789   while(!need_exit) {
790     timer=0;
791     if(ed_k) {
792       i=strlen(ddir);
793       if(ed_k<0) {
794         if(i) ddir[i-1]=0;
795       }else{
796         if(i<40) {ddir[i]=ed_k;ddir[i+1]=0;}
797       }
798       ed_k=0;
799     }
800     main_loop();
801     if(def_k) {
802       plk[cur[RKPL]][cur[RKEYS]]=0;
803       defk_key=0;K_setkeyproc(defk_kp);
804       while(!defk_key);
805       K_setkeyproc(menu_kp);
806       plk[cur[RKPL]][cur[RKEYS]]=defk_key;
807       def_k=0;redraw=1;
808     }
809     if(mnu==INST) switch(install()) {
810       case I_GO:
811         j=240*i_progr/IP_TOTAL+40;
812         if(!_fast) {
813           for(i=40;i<=j;i+=5)
814             new_flame(i<<3,140*8,rand()%17-8,-rand()%40-10);
815         }else V_clr(40,j-39,140,5,0xD0);
816         break;
817       case I_OK:
818         swmnu=IDONE;cnt=40;
819         if(snd_type!=ST_NONE) S_play(iend_snd,7,1024,255);
820         break;
821     }
822     if(mnu==IDONE) if(--cnt<=0) need_exit=1;
823     if(swmnu) {
824       if(mnu==SNDYN && cur[SNDYN]==0) swmnu=IDIR;
825       if(swmnu==TESTSND && snd_card==0) swmnu=IDIR;
826       if(swmnu==INST) {
827         if(!ddir[0]) swmnu=IDIR; else {
828           if(ddir[i=strlen(ddir)-1]=='\\') ddir[i]=0;
829           build_dir(ddir);
830           inst_reset();
831           if(snd_type!=ST_NONE) S_play(igo_snd,7,1024,255);
832         }
833       }
834       setmnu(swmnu);
835       if(swmnu==TESTSND) {
836         T_done();S_init();
837         if(snd_type!=ST_NONE) S_play(testsnd[rand()%TSNDS],8,1024,255);
838         for(i=0;i<27;++i) {
839           timer=0;
840           main_loop();
841           while(timer<0xFFFF);
842         }
843         S_done();T_init();swmnu=SNDYN;cur[SNDYN]=1;
844       }else swmnu=0;
845     }
846     if(mnu!=INST) while(timer<0xFFFF);
847   }
848   V_done();K_done();S_done();
849   if(mnu==IDONE) {
850     sprintf(cfile,"%s\\DEFAULT.CFG",ddir);
851     save_cfg();
852     if(ddir[1]==':') _dos_setdrive(ddir[0]-'A'+1,(unsigned*)&j);
853     chdir(ddir);
854     if(spawnl(P_WAIT,"START.EXE","START.EXE",NULL)==-1)
855       puts("\nЗапустите START.EXE, чтобы начать игру.");
856   }
857   return 0;