home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / AMOD095.ZIP / ADNMOD.PAS < prev    next >
Pascal/Delphi Source File  |  1995-12-21  |  54KB  |  2,274 lines

  1. {$m 6000,60000,60000}
  2. uses crt,dos,modunit,modtypes,memunit,list,txt3d;
  3. const
  4. _c1 = 0;
  5. _Db1 = 1;
  6. _D1 = 2;
  7. _Eb1 = 3;
  8. _E1 = 4;
  9. _F1 = 5;
  10. _Gb1 = 6;
  11. _G1 = 7;
  12. _Ab1 = 8;
  13. _A1 = 9;
  14. _Bb1 = 10;
  15. _B1 = 11;
  16.  
  17. _c2 = 0+16;
  18. _Db2 = 1+16;
  19. _D2 = 2+16;
  20. _Eb2 = 3+16;
  21. _E2 = 4+16;
  22. _F2 = 5+16;
  23. _Gb2 = 6+16;
  24. _G2 = 7+16;
  25. _Ab2 = 8+16;
  26. _A2 = 9+16;
  27. _Bb2 = 10+16;
  28. _B2 = 11+16;
  29.  
  30. _c3 = 0+32;
  31. _Db3 = 1+32;
  32. _D3 = 2+32;
  33. _Eb3 = 3+32;
  34. _E3 = 4+32;
  35. _F3 = 5+32;
  36. _Gb3 = 6+32;
  37. _G3 = 7+32;
  38. _Ab3 = 8+32;
  39. _A3 = 9+32;
  40. _Bb3 = 10+32;
  41. _B3 = 11+32;
  42.  
  43. col_backr = 0;
  44. col_backg = 0;
  45. col_backb = 10;
  46. col_back = 2;
  47. col_flash = 20;
  48. flash_val : integer= 0;
  49. strobo_speed : integer = 8;
  50.  
  51. note_txt : array[0..15] of string[2] =
  52.              ('C-','C#','D-','D#','E-','F-','F#','G-','G#','A-','A#','B-',
  53.              '??','??','??','??');
  54.  
  55. hex_tbl : array[0..15] of char = ('0','1','2','3','4','5','6','7',
  56.                                   '8','9','A','B','C','D','E','F');
  57. fx_txt : array[0..25] of string[3] = (
  58.          'ARP','PR^','PRv','TON','VIB','T&S',
  59.          'V&S','trm','PAN','SO=','VLs','JMP',
  60.          'VL=','BRK','EFX','SPD','SPD','PRv',
  61.          'PR^','PRv','PR^','FVL','TRG','GVL','!!!','!!!');
  62.  
  63. s3mfx_txt : array[0..23] of char = (
  64.          'J','?','?','G','H','L','K','R','X','O',
  65.          '?','B','-','C','S','T','A','E','F','?',
  66.          '?','D','Q','V');
  67.  
  68. efx_txt : array[0..15] of string[4] = (
  69.          'filt','FPR^','FPRv','glis','vibf',
  70.          'FTUN','LOOP','trmf','PAN=','TRIG',
  71.          'FVL^','FVLv','NCUT','NDEL','PDEL',
  72.          'funk');
  73.  
  74. savertime : integer = 18*60*5;
  75.  
  76. defpan : array[0..31] of integer =
  77.   (3,12,12,3,3,12,12,3,3,12,12,3,3,12,12,3,3,12,12,3,3,12,12,3,3,12,12,3,3,12,12,3);
  78. pan_sign : array[0..31] of integer =
  79.   (-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1,-1,1,1,-1);
  80. pan_mode : boolean = false;
  81. pan_speed : integer = 16;
  82. pan_cnt : integer = 16*4;
  83. pan_inc : integer = 1;
  84. qualitymode : boolean = false;
  85. lockquality : boolean = false;
  86. keybled : boolean = true;
  87.  
  88.   temp_path : string = 'c:\';
  89.   unzip_opt = ' -o';
  90.  
  91. {$i compdate}   {Remove this if you don't have compdate.sys driver}
  92. {$i adnpic1.inc}
  93. {$i adnpic2.inc}
  94. {$i adnpic3.inc}
  95. {$i adnpic4.inc}
  96. {$i adnpic5.inc}
  97. {$i adnpic6.inc}
  98.  
  99. var
  100.   gusmem : longint;
  101.   start_sample,cur_sample,play_sample : integer;
  102.   cur_octave : integer;
  103.   old_row : integer;
  104.   mod_name : string;
  105.   pause : byte;
  106.   oldintfc,oldint8,oldint9 : procedure;
  107.   alt_tab,int8use : boolean;
  108.   strobo_sam : array[0..99] of boolean;
  109.   strobo_val : integer;
  110.   strobo_col : array[1..3] of integer;
  111.   strobo_fx : boolean;
  112.   help : boolean;
  113.   {golmap1,golmap2 : array[0..51,0..81] of byte;}
  114.   golmap1 : array[0..51,0..81] of byte absolute $b800:8000;
  115.   golmap2 : array[0..51,0..81] of byte absolute $b800:13000;
  116.   normpal,pal : array[0..63,0..2] of byte;
  117.   normkbf : byte;
  118.   int_cnt : integer;
  119.   start_chn : integer;
  120.  
  121.   lpic : pointer;
  122.   listpic : ^t_memarray;
  123.   flist : t_list;
  124.   strlist : array[0..maxline+1] of string[20];
  125.   typelist : array[0..maxline+1] of integer;
  126.   org_path,old_path,cur_path : string;
  127.   drives : array[1..28] of boolean;
  128.   new_mod,archive : boolean;
  129.   old_st3_per : array[0..15] of integer;
  130.  
  131. {$s-}
  132. procedure hide_cursor; assembler;
  133. asm
  134.   mov  ax,0100h
  135.   mov  cx,2607h
  136.   int  10h
  137. end;
  138.  
  139. procedure show_cursor; assembler;
  140. asm
  141.   mov  ax,0100h
  142.   mov  cx,2607h
  143.   int  10h
  144. end;
  145.  
  146. procedure wait_vr; assembler;
  147. asm
  148.   mov  dx,3dah
  149. @@1:
  150.   in   al,dx
  151.   test al,8
  152.   jz   @@1
  153. end;
  154.  
  155. procedure wait_novr; assembler;
  156. asm
  157.   mov  dx,3dah
  158. @@1:
  159.   in   al,dx
  160.   test al,8
  161.   jnz  @@1
  162. end;
  163.  
  164. procedure fillword(var p;count : word;value : word); assembler;
  165. asm
  166.   mov  es,word ptr p+2
  167.   mov  di,word ptr p
  168.   mov  cx,count
  169.   mov  ax,value
  170.   rep  stosw
  171. end;
  172.  
  173. procedure rmove(var source,target; count : word); assembler;
  174. asm
  175.   mov  es,word ptr target+2
  176.   mov  di,word ptr target
  177.   add  di,count
  178.   mov  si,word ptr source
  179.   add  si,count
  180.   push ds
  181.   mov  ds,word ptr source+2
  182.   mov  cx,count
  183.   std
  184.   rep  movsb
  185.   cld
  186.   pop  ds
  187. end;
  188.  
  189. procedure setvgapal(pal,col1,col2,col3 : byte); assembler;
  190. asm
  191.   cli
  192.   mov  dx,3c8h
  193.   mov  al,pal
  194.   out  dx,al
  195.   inc  dx
  196.   mov  al,col1
  197.   out  dx,al
  198.   mov  al,col2
  199.   out  dx,al
  200.   mov  al,col3
  201.   out  dx,al
  202.   sti
  203. end;
  204.  
  205. procedure set_scr_ofs(ofs : word); assembler;
  206. asm
  207.   cli
  208.   mov  bx,ofs
  209.   mov  dx,$3d4
  210.   mov  al,0Ch       {Start address high}
  211.   out  dx,al
  212.   inc  dx
  213.   mov  al,bh
  214.   out  dx,al
  215.   dec  dx
  216.   mov  al,0Dh      {Start address high}
  217.   out  dx,al
  218.   inc  dx
  219.   mov  al,bl
  220.   out  dx,al
  221.   sti
  222. end;
  223.  
  224. procedure line_comp(lc : word);
  225. var
  226. b : byte;
  227. begin
  228.   port[$3d4] := 7;
  229.   if lc and 256 > 0 then b := 31
  230.   else b := 15;
  231.   port[$3d5] := b;
  232.   port[$3d4] := 9;
  233.   port[$3d5] := port[$3d5] and $bf;
  234.   port[$3d4] := $18;
  235.   port[$3d5] := lo(lc);
  236. end;
  237.  
  238. procedure getpal(p : pointer); assembler;
  239. asm
  240.   cld
  241.   cli
  242.   mov  es,word ptr p+2
  243.   mov  di,word ptr p
  244.   xor  ax,ax
  245.   mov  dx,3c7h
  246.   out  dx,al
  247.   mov  dx,3c9h
  248.   mov  cx,64*3
  249. @@1:
  250.   in   al,dx
  251.   stosb
  252.   loop @@1
  253.   sti
  254. end;
  255.  
  256. procedure setpal(p : pointer); assembler;
  257. asm
  258.   cld
  259.   cli
  260.   push ds
  261.   mov  ds,word ptr p+2
  262.   mov  si,word ptr p
  263.   xor  ax,ax
  264.   mov  dx,3c8h
  265.   out  dx,al
  266.   inc  dx
  267.   mov  cx,64*3
  268. @@1:
  269.   lodsb
  270.   out  dx,al
  271.   loop @@1
  272.   pop  ds
  273.   sti
  274. end;
  275.  
  276. function fixgetmem(p : pointer) : pointer;
  277. var
  278. hi,lo : word;
  279. p2 : pointer;
  280. begin
  281.   asm
  282.     mov  ax,word ptr p
  283.     mov  lo,ax
  284.     mov  ax,word ptr p+2
  285.     mov  hi,ax
  286.   end;
  287.   if lo <> 0 then hi := hi+(lo+15) div 16;
  288.   asm
  289.     mov  ax,0
  290.     mov  word ptr p2,ax
  291.     mov  ax,hi
  292.     mov  word ptr p2+2,ax
  293.   end;
  294.   fixgetmem := p2;
  295. end;
  296. {$s-}
  297. procedure free_ticks; assembler;
  298. asm
  299.   int  28h
  300. end;
  301.  
  302. function peekkey : char;
  303. var
  304. c : char;
  305. begin
  306.   c := #0;
  307. asm
  308.   mov  ah,1
  309.   int  16h
  310.   jnz   @@end
  311.   mov  ax,0
  312. @@end:
  313.   mov  c,al
  314. end;
  315.   peekkey := c;
  316. end;
  317.  
  318. procedure fillattr(x,y,xl : integer; attr : byte); assembler;
  319. asm
  320.   mov  ax,0b800h
  321.   mov  es,ax
  322.   mov  ax,y
  323.   mov  di,ax
  324.   shl  ax,7
  325.   shl  di,4
  326.   add  di,x
  327.   add  di,di
  328.   add  di,ax
  329.   sub  di,161
  330.   mov  cx,xl
  331.   mov  al,attr
  332. @@1:
  333.   mov  es:[di],al
  334.   add  di,2
  335.   loop @@1
  336. end;
  337.  
  338. procedure fastwrite(x,y : word;s : string);
  339. begin
  340. asm
  341.     push ds
  342.     lea  si,s
  343.     mov  ax,ss
  344.     mov  ds,ax
  345.     mov  ax,0b800h
  346.     mov  es,ax
  347.     lodsb
  348.     cmp  al,0
  349.     je   @@end
  350.     mov  cl,al
  351.     xor  ch,ch
  352.     mov  di,y
  353.     dec  di
  354.     dec  x
  355.     mov  ax,160
  356.     mul  di
  357.     mov  di,ax
  358.     add  di,x
  359.     add  di,x
  360. @@1:
  361.     movsb
  362.     inc  di
  363.     loop @@1
  364. @@end:
  365.     pop  ds
  366. end;
  367. end;
  368.  
  369. procedure fastwritel(x,y,l : word;s : string); assembler;
  370. asm
  371.     push ds
  372.     mov  cx,l
  373.     cmp  cx,0
  374.     je   @@end
  375.     mov  si,word ptr s
  376.     inc  si
  377.     mov  ds,word ptr s+2
  378.     mov  ax,0b800h
  379.     mov  es,ax
  380.     mov  ax,y
  381.     mov  di,ax
  382.     shl  ax,7
  383.     shl  di,4
  384.     add  di,x
  385.     add  di,di
  386.     add  di,ax
  387.     sub  di,162
  388.     mov  ah,$ff
  389. @@1:
  390.     lodsb
  391.     test al,0ffh
  392.     je   @@3
  393. @@2:
  394.     and  al,ah
  395.     stosb
  396.     inc  di
  397.     loop @@1
  398.     jmp  @@end
  399. @@3:
  400.     xor  ah,ah
  401.     jmp  @@2
  402. @@end:
  403.     pop  ds
  404. end;
  405.  
  406. procedure scroll_up(y1,yl : word); assembler;
  407. asm
  408.   mov  ax,y1
  409.   mov  cx,160
  410.   mul  cx
  411.   mov  y1,ax
  412.   push ds
  413.   mov  ax,0b800h
  414.   mov  ds,ax
  415.   mov  es,ax
  416.   mov  si,y1
  417.   add  si,160
  418.   mov  di,y1
  419.   mov  bx,yl
  420. @@1:
  421.   mov  cx,80
  422.   rep  movsw
  423.   dec  bx
  424.   jnz  @@1
  425.   pop  ds
  426. end;
  427.  
  428. function byte2hex(b : byte) : string;
  429. begin
  430.   byte2hex := hex_tbl[b shr 4]+hex_tbl[b and 15];
  431. end;
  432.  
  433. function nibb2hex(b : byte) : char;
  434. begin
  435.   nibb2hex := hex_tbl[b and 15];
  436. end;
  437.  
  438. function int2str(i,n : longint) : string;
  439. var
  440. s : string;
  441. begin
  442.   str(i:n,s);
  443.   int2str := s;
  444. end;
  445.  
  446. function word2str(i,n : word) : string;
  447. var
  448. s : string;
  449. begin
  450.   str(i:n,s);
  451.   word2str := s;
  452. end;
  453.  
  454. procedure showbyte(x,y : integer;b : byte); assembler;
  455. asm
  456.   dec  y
  457.   dec  x
  458.   mov  ax,0b800h
  459.   mov  es,ax
  460.   mov  di,y
  461.   mov  ax,160
  462.   mul  di
  463.   mov  di,ax
  464.   add  di,x
  465.   add  di,x
  466.   mov  ah,0
  467.   mov  al,b
  468.   mov  cl,10
  469.   div  cl
  470.   add  ax,3030h
  471.   mov  es:[di],al
  472.   add  di,2
  473.   mov  es:[di],ah
  474. end;
  475.  
  476. procedure showint4(x,y : integer;w : word); assembler;
  477. asm
  478.   dec  y
  479.   dec  x
  480.   mov  ax,0b800h
  481.   mov  es,ax
  482.   mov  di,y
  483.   mov  ax,di
  484.   shl  ax,5
  485.   shl  di,7
  486.   add  di,ax
  487.   add  di,x
  488.   add  di,x
  489.   xor  dx,dx
  490.   mov  ax,w
  491.   mov  cx,1000
  492.   div  cx
  493.   add  al,30h
  494.   mov  es:[di],al
  495.   mov  ax,dx
  496.   mov  cl,100
  497.   div  cl
  498.   mov  bx,ax
  499.   add  al,30h
  500.   mov  es:[di+2],al
  501.   mov  al,bh
  502.   mov  ah,0
  503.   mov  cl,10
  504.   div  cl
  505.   add  ax,3030h
  506.   mov  es:[di+4],al
  507.   mov  es:[di+6],ah
  508. end;
  509.  
  510. procedure showhex(x,y : integer;b : byte);
  511. begin
  512.   mem[$b800:(y-1)*160+2*x-2] := byte(hex_tbl[b shr 4]);
  513.   mem[$b800:(y-1)*160+2*x] := byte(hex_tbl[b and 15]);
  514. end;
  515.  
  516. procedure show_pic(ofs,dest : word;pic : pointer); assembler;
  517. asm
  518.   mov  ax,dest
  519.   mov  es,ax
  520.   mov  dx,0
  521.   mov  ax,700h
  522.   mov  cx,0
  523.   mov  di,ofs
  524.   push ds
  525.   mov  si,word ptr pic
  526.   mov  ds,word ptr pic+2
  527. @@start:
  528.   lodsb
  529.   cmp  al,8
  530.   jae  @@char
  531.   cmp  al,0
  532.   je   @@end
  533.   cmp  al,1
  534.   je   @@attr
  535.   cmp  al,2
  536.   je   @@pack
  537.   cmp  al,3
  538.   je   @@space
  539.   jmp  @@start
  540. @@attr:
  541.   lodsb
  542.   mov  ah,al
  543.   jmp  @@start
  544. @@space:
  545.   lodsb
  546.   mov  cl,al
  547.   mov  al,32
  548.   rep  stosw
  549.   jmp  @@start
  550. @@pack:
  551.   lodsb
  552.   mov  cl,al
  553.   lodsb
  554.   rep  stosw
  555.   jmp  @@start
  556. @@char:
  557.   stosw
  558.   jmp  @@start
  559. @@end:
  560.   pop  ds
  561. end;
  562.  
  563. procedure normscr;
  564. var
  565. n : integer;
  566. begin
  567.   hide_cursor;
  568.   setvgapal(col_back,col_backr,col_backg,col_backb);
  569.   show_pic(8000+0,$b800,@image1);
  570.   show_pic((50+5+header.usedchns)*160,$b800,@image2);
  571.   show_pic(160,$b800,@image3);
  572.   for n := 0 to header.usedchns do move(image4,mem[$b800:(4+n)*160+8000],160);
  573.   line_comp((header.usedchns+9)*8);
  574.   set_scr_ofs(4000);
  575.   if qualitymode then begin
  576.     fastwrite(8,51,'QUALITY MODE');
  577.     fastwrite(62,51,'QUALITY MODE');
  578.   end;
  579. end;
  580.  
  581. function note2txt(note : byte) : string;
  582. var
  583. o,n : byte;
  584. begin
  585.   o := note shr 4;
  586.   n := note and 15;
  587.   if note = 255 then note2txt := '...'
  588.   else if note = 254 then note2txt := '^^^'
  589.   else note2txt := note_txt[n]+char(o+48);
  590. end;
  591.  
  592. procedure makepertbl;
  593. var
  594. n,i : integer;
  595. begin
  596.   if not qualitymode then move(old_st3_per,st3_per,sizeof(st3_per))
  597.   else for n := 0 to 15 do begin
  598.     st3_per[n] := round(old_st3_per[n]*(0.975+random(10)/200));
  599.   end;
  600. end;
  601.  
  602. {$s-}
  603. procedure bar(x,y,l : integer;c : char); assembler;
  604. asm
  605.   cld
  606.   mov  ax,0b800h
  607.   mov  es,ax
  608.  
  609.   mov  di,y
  610.   dec  di
  611.   mov  ax,160
  612.   mul  di
  613.   dec  x
  614.   add  ax,x
  615.   add  ax,x
  616.   mov  di,ax
  617.   cmp  l,0
  618.   jz   @@3
  619.   mov  cx,l
  620.   mov  al,c
  621. @@1:
  622.   stosb
  623.   inc  di
  624.   dec  cx
  625.   jnz  @@1
  626. @@3:
  627.   mov  cx,16
  628.   sub  cx,l
  629.   cmp  cx,0
  630.   je   @@end
  631.   mov  al,32
  632. @@2:
  633.   stosb
  634.   inc  di
  635.   dec  cx
  636.   jnz  @@2
  637. @@end:
  638. end;
  639.  
  640. procedure show_sample(sam,x,y : integer);
  641. begin
  642.   fillattr(x,y,3,1);
  643.   fastwrite(x,y,int2str(sam,2));
  644.   if strobo_sam[sam] then fillattr(x,y,30,6)
  645.   else fillattr(x+3,y,27,7);
  646.   if sam = cur_sample then fillattr(x,y,3,15);
  647.   fastwritel(x+4,y,26,samples[sam].name);
  648.   fastwrite(x+31,y,word2str(samples[sam].length,5));
  649.   fastwrite(x+39,y,word2str(samples[sam].loopstart,5));
  650.   fastwrite(x+47,y,word2str(samples[sam].loopend,5));
  651.   if header.modtype = mt_mod then begin
  652.     if samples[sam].ftune > 7 then
  653.       fastwrite(x+56,y,int2str(integer(samples[sam].ftune or $fff0),2))
  654.     else fastwrite(x+56,y,int2str(samples[sam].ftune,2));
  655.   end
  656.   else fastwrite(x+54,y,int2str(samples[sam].c4spd,5));
  657.   fastwrite(x+62,y,int2str(samples[sam].volume,2));
  658. end;
  659.  
  660. const
  661. ycol : array[0..73] of byte =
  662. (1,1,
  663. 9,9,
  664. 11,11,
  665. 15,15,
  666. 11,11,
  667. 9,9,
  668. 1,1,
  669. 9,9,
  670. 11,11,
  671. 15,15,
  672. 11,11,
  673. 9,9,
  674. 1,1,
  675. 9,9,
  676. 11,11,
  677. 15,15,
  678. 11,11,
  679. 9,9,
  680. 1,1,
  681. 9,9,
  682. 11,11,
  683. 15,15,
  684. 11,11,
  685. 9,9,
  686. 1,1,
  687. 9,9,
  688. 11,11,
  689. 15,15,
  690. 11,11,
  691. 9,9,
  692. 1,1,
  693. 9,9,
  694. 11,11,
  695. 15,15,
  696. 11,11,
  697. 9,9,
  698. 1,1);
  699.  
  700. const
  701. scroll_txt : string = 'Welcome to ADNMOD 0.95! The best mod/s3m player '+
  702.                       'for TP ever :)'+
  703.                       '                  '+
  704.                       'REMEMBER: You MUST send me e-mail if you use this program!'+
  705.                       '                  '+
  706.                       'Greets fly out to: Psyko, Distance, Jaba, Black Hole,'+
  707.                       ' Solar, flap, Wog & RedT';
  708. var
  709. scroll_msg : array[0..1000] of char;
  710. scroll_len : integer;
  711.  
  712. procedure scrsaver;
  713. var
  714. n,count : integer;
  715.  
  716. procedure showgol(yc : integer); assembler;
  717. asm
  718.   push ds
  719.   mov  ax,0b800h
  720.   mov  es,ax
  721.   mov  ds,ax
  722.   mov  di,1
  723.   mov  si,offset golmap1+82+2
  724.   mov  dx,49
  725. @@2:
  726.   mov  cx,80
  727.   pop  ds
  728.   mov  bx,dx
  729.   add  bx,yc
  730.   mov  ah,[bx+offset ycol]
  731.  
  732.   push ds
  733.   mov  bx,es
  734.   mov  ds,bx
  735. @@1:
  736.   mov  al,ds:[si]
  737.   inc  si
  738.   shl  al,5
  739.   add  al,ah
  740.   mov  es:[di],al
  741.   add  di,2
  742.   dec  cx
  743.   jnz  @@1
  744.   add  si,2
  745.   dec  dx
  746.   jnz  @@2
  747.   pop  ds
  748. end;
  749.  
  750. procedure muunnagol;
  751. begin
  752.   asm
  753.      push ds
  754.      mov  ax,0b800h
  755.      mov  ds,ax
  756.      mov  es,ax
  757.      mov  di,offset golmap2+82+1
  758.      mov  si,offset golmap1+82+1
  759.      mov  dx,49
  760. @@yloop:
  761.  
  762.      mov  cx,81-1
  763.      mov  bx,81
  764.      inc  si
  765.      inc  di
  766. @@xloop:
  767.      mov  al,[si-81-2]
  768.      add  al,[si-81-1]
  769.      add  al,[si-81]
  770.      add  al,[si-1]
  771.      add  al,[si+1]
  772.      add  al,[si+81]
  773.      add  al,[si+81+1]
  774.      add  al,[si+81+2]
  775.      mov  ah,[si]
  776.      cmp  al,3
  777.      je   @@live
  778.      cmp  ah,0
  779.      je   @@die_scum
  780.      cmp  al,2
  781.      je   @@live
  782. @@die_scum:
  783.      xor  al,al
  784.      stosb
  785.      jmp  @@loop_end
  786. @@live:
  787.      mov  al,1
  788.      stosb
  789. @@loop_end:
  790.      inc  si
  791.      loop @@xloop
  792.      inc  si
  793.      inc  di
  794.  
  795.      dec  dx
  796.      jnz  @@yloop
  797. @@end:
  798.      pop  ds
  799. end;
  800.   move(golmap2,golmap1,sizeof(golmap1));
  801. end;
  802.  
  803. procedure plot(x,y : integer);
  804. var
  805. _x,_y : integer;
  806. begin
  807.   for _y := -2 to 2 do for _x := -2 to 2 do
  808.     golmap1[y+_y,x+_x] := random(2);
  809. end;
  810.  
  811. procedure initgol;
  812. var
  813. n : integer;
  814. begin
  815.   fillchar(golmap1,sizeof(golmap1),0);
  816.   fillchar(golmap2,sizeof(golmap2),0);
  817.   for n := 1 to 20 do plot(random(70)+5,random(40)+5);
  818. end;
  819.  
  820. procedure fadeout;
  821. var
  822. n,i : integer;
  823. begin
  824.   for n := 30 downto 0 do begin
  825.     wait_vr;
  826.     for i := 0 to 63 do
  827.       setvgapal(i,word(pal[i,0]*n) div 30,
  828.                   word(pal[i,1]*n) div 30,
  829.                   word(pal[i,2]*n) div 30);
  830.   end;
  831. end;
  832.  
  833. procedure fadein;
  834. var
  835. n,i : integer;
  836. begin
  837.   for n := 0 to 30 do begin
  838.     wait_vr;
  839.     for i := 0 to 63 do
  840.       setvgapal(i,word(pal[i,0]*n) div 30,
  841.                   word(pal[i,1]*n) div 30,
  842.                   word(pal[i,2]*n) div 30);
  843.   end;
  844. end;
  845.  
  846. procedure scroll(sc : integer);
  847. var
  848. n : integer;
  849. begin
  850.   for n := 0 to 79 do memw[$b800:49*160+n*2] := 15*256+byte(scroll_msg[sc+n]);
  851. end;
  852.  
  853. type
  854. ta = array[0..50000] of byte;
  855. pa = ^ta;
  856.  
  857. var
  858. yc : integer;
  859. pspeed,i : integer;
  860. obj_kx,obj_ky,obj_kz : integer;
  861. buf,p : pointer;
  862. sc,sc2 : integer;
  863.  
  864. begin
  865.   scroll_len := byte(scroll_txt[0])+102;
  866.   fillchar(scroll_msg,sizeof(scroll_msg),0);
  867.   move(scroll_txt[1],scroll_msg[82],scroll_len-102);
  868.   getmem(p,16000+16);
  869.   buf := ptr(seg(p^)+1,0);
  870.   fillchar(buf^,16000,0);
  871.   txt3d.scr_seg := seg(buf^);
  872.   obj_kx := 0;
  873.   obj_ky := 0;
  874.   obj_kz := 0;
  875.   pan_cnt := integer(pan_cnt*5) div 7;
  876.   pspeed := integer(pan_speed*5) div 7;
  877.   if pspeed < 1 then pspeed := 1;
  878.   getpal(@pal);
  879.   fadeout;
  880.   fillchar(mem[$b800:0],160*100,0);
  881.   textmode(font8x8+co80);
  882.   setfont;
  883.   hide_cursor;
  884.   init3d;
  885.   l3d_adnmod;
  886.   initgol;
  887.   count := 0;
  888.   yc := 0;
  889.   matriisi(matrix,0,0,0);
  890.   rotatep;
  891.   time_counter := 0;
  892.   time_counter2 := 0;
  893.   time_counter3 := 0;
  894.   sc := 0;
  895.   sc2 := 0;
  896.   repeat
  897.     wait_vr;
  898.     mix;
  899.     free_ticks;
  900.     if time_counter > 0 then begin
  901.       inc(yc);
  902.       if yc > 10 then yc := 0;
  903.       showgol(yc);
  904.       muunnagol;
  905.       inc(sc2);
  906.       if sc2 > scroll_len*2 then sc2 := 0;
  907.       sc := sc2 shr 1;
  908.       dec(time_counter);
  909.       inc(count);
  910.       if count mod (6*30) = 0 then case random(3) of
  911.         0 : l3d_cube;
  912.         1 : l3d_pyramid;
  913.         2 : l3d_adnmod;
  914.       end;
  915.       if count > 18*20 then begin
  916.         time_counter := 0;
  917.         count := 0;
  918.         initgol;
  919.       end;
  920.     end;
  921.     scroll(sc);
  922.     free_ticks;
  923.     hide;
  924.     matriisi(matrix,obj_kx,obj_ky,obj_kz);
  925.     rotatep;
  926.     free_ticks;
  927.     show;
  928.     free_ticks;
  929.     inc(obj_kx,word(time_counter3) div 7);
  930.     inc(obj_ky,word(time_counter3) div 7);
  931.     inc(obj_kz,word(time_counter3) div 7);
  932.     time_counter3 := 0;
  933.     if obj_kx > 1000 then dec(obj_kx,1000);
  934.     if obj_ky > 1000 then dec(obj_ky,1000);
  935.     if obj_kz > 1000 then dec(obj_kz,1000);
  936.     if pan_mode and (time_counter2 > 0) then begin
  937.       inc(pan_cnt,pan_inc*time_counter2);
  938.       if (pan_cnt<=-pspeed*7-pspeed+1) or
  939.       (pan_cnt>=pspeed*7+pspeed-1) then pan_inc := -pan_inc;
  940.       if pan_cnt < -pspeed*7-pspeed+1 then pan_cnt := -pspeed*7;
  941.       if pan_cnt > pspeed*7+pspeed-1 then pan_cnt := pspeed*8;
  942.       for n := 0 to header.usedchns-1 do begin
  943.         i := integer(pan_sign[i]*pan_cnt) div pspeed;
  944.         if i > 0 then
  945.           channels[n].pan := 8+i
  946.         else channels[n].pan := 7+i;
  947.         gussetbalance(n,channels[n].pan);
  948.       end;
  949.       time_counter2 := 0;
  950.     end;
  951.     free_ticks;
  952.   until keypressed;
  953.   readkey;
  954.   freemem(p,16000+16);
  955.   for n := 0 to 63 do setvgapal(n,0,0,0);
  956.   fillchar(mem[$b800:0],80*100*2,0);
  957.   textmode(co80+font8x8);
  958.   for n := 0 to 63 do setvgapal(n,0,0,0);
  959.   fillchar(mem[$b800:0],80*100*2,0);
  960.   normscr;
  961.   for n := 0 to 63 do setvgapal(n,0,0,0);
  962.   for n := 0 to 24-header.usedchns do show_sample(n+start_sample,9,n+17);
  963.   old_row := 666;
  964.   fadein;
  965. end;
  966.  
  967. procedure show_chn(chn,st : byte);
  968. var
  969. fx,fxdata : byte;
  970. start : integer;
  971. n : integer;
  972. begin
  973.   start := 5-st+50;
  974.   inc(chn,st);
  975.   fx := channels[chn].fx;
  976.   fxdata := channels[chn].fxdata;
  977.   if channels[chn].on = 1 then
  978.     fastwritel(3,chn+start,27,samples[channels[chn].sample].name)
  979.   else fastwritel(3,chn+start,27,'     ---MUTED---             ');
  980.   fastwrite(34,chn+start,int2str(channels[chn].vol,2));
  981.   fastwritel(37,chn+start,3,note2txt(channels[chn].note));
  982.   fastwrite(41,chn+start,int2str(channels[chn].per,4));
  983.   fastwrite(46,chn+start,int2str(channels[chn].dper,4));
  984.   fastwrite(58,chn+start,int2str(shortint(channels[chn].pan)-7,2));
  985.   if fx = 14 then
  986.     fastwritel(51,chn+start,5,efx_txt[fxdata shr 4]+nibb2hex(fxdata and 15))
  987.   else if ((fx < 255) and (fx >0)) or ((fx = 0) and (fxdata > 0)) then
  988.     fastwritel(51,chn+start,5,fx_txt[fx]+byte2hex(fxdata))
  989.   else fastwritel(51,chn+start,5,'     ');
  990.   bar(63,chn+start,(channels[chn].bar+2) shr 2,'≈');
  991.   if channels[chn].hit <> 0 then begin
  992.     fillattr(3,chn+start,27,15);
  993.     fillattr(34,chn+start,26,15);
  994.     channels[chn].hit := 2;
  995.   end else begin
  996.     fillattr(3,chn+start,27,7);
  997.     fillattr(34,chn+start,26,7);
  998.   end;
  999. end;
  1000.  
  1001. procedure show_row(ptn,row : integer);
  1002. const
  1003. wid = 16;
  1004. x = 12;
  1005. var
  1006.   n : integer;
  1007.   sam : integer;
  1008.   vol,fx,fxdata : byte;
  1009.   chn : integer;
  1010.   st : integer;
  1011.   _ptn : p_pattern;
  1012.   s : string[2];
  1013. begin
  1014.   _ptn := virt_getptn(ptn);
  1015.   st := 13;
  1016.   fastwrite(8,st,byte2hex(row)+':');
  1017.   for n := 0 to 3 do begin
  1018.     chn := start_chn+n;
  1019.     fastwrite(n*wid+x+1,st,
  1020.       note2txt(_ptn^[row*header.chns+chn].note)+' ');
  1021.     sam := _ptn^[row*header.chns+chn].sample;
  1022.     if sam > 0 then fastwrite(n*wid+x+5,st,byte2hex(sam)+' ')
  1023.     else fastwrite(n*wid+x+5,st,'.. ');
  1024.     fx := _ptn^[row*header.chns+chn].fx;
  1025.     fxdata := _ptn^[row*header.chns+chn].fxdata;
  1026.     if (fx=0) and (fxdata = 0) then fx := 255;
  1027.     if header.modtype = mt_mod then begin
  1028.       case fx of
  1029.         0 : if fxdata > 0 then
  1030.           fastwrite(n*wid+x+9,st,fx_txt[fx]+byte2hex(fxdata))
  1031.         else fastwrite(n*wid+x+9,st,'     ');
  1032.         1..$D : fastwrite(n*wid+x+9,st,fx_txt[fx]+byte2hex(fxdata));
  1033.         $E : fastwrite(n*wid+x+9,st,
  1034.              efx_txt[fxdata shr 4]+nibb2hex(fxdata and 15));
  1035.         $F : fastwrite(n*wid+x+9,st,fx_txt[fx]+byte2hex(fxdata));
  1036.         else fastwrite(n*wid+x+9,st,'     ');
  1037.       end;
  1038.     end
  1039.     else if header.modtype = mt_s3m then begin
  1040.       vol := _ptn^[row*header.chns+chn].vol;
  1041.       if vol <> 255 then begin
  1042.         s := int2str(vol,2);
  1043.         if s[1] = ' ' then s[1] := '0';
  1044.       end else s := '  ';
  1045.       fastwrite(n*wid+x+8,st,s);
  1046.       if fx <> 255 then begin
  1047.         fastwrite(n*wid+x+11,st,s3mfx_txt[fx]);
  1048.         fastwrite(n*wid+x+12,st,byte2hex(fxdata));
  1049.       end
  1050.       else fastwrite(n*wid+x+11,st,'   ');
  1051.     end;
  1052.   end;
  1053. end;
  1054.  
  1055. procedure show_info(ptn:integer);
  1056. var
  1057. st : integer;
  1058. begin
  1059.   st := 50+8 + header.usedchns;
  1060.   fastwrite(30,st,int2str(amp_vol,2));
  1061.   fastwrite(41,st,int2str(speed,2));
  1062.   if not vblank then fastwrite(53,st,int2str(tempo,3)+'   ')
  1063.   else fastwrite(53,st,'VBlank');
  1064.   fastwrite(30,st+1,int2str(cur_ptn,2)+'/'+int2str(header.length-1,2));
  1065.   fastwrite(41,st+1,int2str(ptn,2)+'/'+int2str(max_ptn-1,2));
  1066.   fastwrite(53,st+1,int2str(cur_row,2));
  1067. end;
  1068.  
  1069. procedure updateinfo;
  1070. var
  1071. i,n : integer;
  1072. kbf : byte;
  1073. begin
  1074.   if not loaded then exit;
  1075.   wait_vr;
  1076.   if strobo_fx then for i := 0 to header.usedchns-1 do
  1077.     if (channels[i].hit = 1) and (channels[i].on <> 0) then
  1078.       if strobo_sam[channels[i].sample]=true then strobo_val := 62;
  1079.   i := strobo_val and strobo_col[3];
  1080.   if i < col_backb then i := col_backb;
  1081.   setvgapal(0,strobo_val and strobo_col[1],
  1082.               strobo_val and strobo_col[2],
  1083.               strobo_val and strobo_col[3]);
  1084.   setvgapal(2,strobo_val and strobo_col[1],
  1085.               strobo_val and strobo_col[2],
  1086.               i);
  1087.   if strobo_val > 0 then dec(strobo_val,strobo_speed);
  1088.   if strobo_val < 0 then strobo_val := 0;
  1089.   dec(flash_val);
  1090.   if flash_val<-19 then flash_val := 20;
  1091.   n := abs(flash_val)+43;
  1092.   setvgapal(col_flash,n,n,n);
  1093.   if keybled then begin
  1094.     kbf := mem[$40:$17] and 15;
  1095.     if channels[start_chn].hit=1 then kbf := kbf or $20;
  1096.     if channels[start_chn+1].hit=1 then kbf := kbf or $40;
  1097.     if channels[start_chn+2].hit=1 then kbf := kbf or $10;
  1098.     mem[$40:$17] := kbf;
  1099.     mem[$40:$18] := 0;
  1100.   end;
  1101.   if pan_mode then begin
  1102.     inc(pan_cnt,pan_inc);
  1103.     if (pan_cnt=-pan_speed*7-pan_speed+1) or
  1104.     (pan_cnt=pan_speed*7+pan_speed-1) then pan_inc := -pan_inc;
  1105.     for i := 0 to header.usedchns-1 do begin
  1106.       n := integer(pan_sign[i]*pan_cnt) div pan_speed;
  1107.       if n > 0 then
  1108.         channels[i].pan := 8+n
  1109.       else channels[i].pan := 7+n;
  1110.       gussetbalance(i,channels[i].pan);
  1111.     end;
  1112.   end;
  1113.   for i := 0 to header.usedchns-1 do show_chn(i,0);
  1114.   show_info(orders[cur_ptn]);
  1115. end;
  1116.  
  1117. procedure show_ptn(clear : boolean);
  1118. var
  1119.   ptn : word;
  1120. var
  1121.   i,n : integer;
  1122.   s : string;
  1123.   c : char;
  1124.   helpcnt : integer;
  1125.  
  1126. begin
  1127.   helpcnt := 0;
  1128.   strobo_val := 0;
  1129.   fastwrite(30,50+7+header.usedchns,header.name);
  1130.   for i := 0 to 24-header.usedchns do show_sample(i+start_sample,9,i+17);
  1131.   if clear then begin
  1132.     s := '                                                                   ';
  1133.     for i := 0 to 7 do fastwritel(8,14+50+header.usedchns+i,65,s);
  1134.   end;
  1135.   time_counter := 0;
  1136.   repeat
  1137.     updateinfo;
  1138.     free_ticks;
  1139.     ptn := orders[cur_ptn];
  1140.     time_counter2 := 0;
  1141.     if (not help) and (cur_row <> old_row) then begin
  1142.       i := cur_row;
  1143.       fillattr(13,13,61,7+2*16);
  1144.       scroll_up(4,8);
  1145.       show_row(orders[cur_ptn],i);
  1146.       old_row := cur_row;
  1147.       fillattr(13,13,61,15+2*16);
  1148.     end;
  1149.     free_ticks;
  1150.     if upcase(peekkey) = 'H' then begin
  1151.       readkey;
  1152.       time_counter := 0;
  1153.       if help then begin
  1154.         show_pic(160,$b800,@image3);
  1155.         fastwritel(30,50+7+header.usedchns,20,header.name);
  1156.         for i := 0 to 24-header.usedchns do show_sample(i+start_sample,9,i+17);
  1157.         help := false;
  1158.       end
  1159.       else begin
  1160.         help := true;
  1161.         show_pic(160,$b800,@image5);
  1162.       end;
  1163.     end;
  1164.     if time_counter > savertime then begin
  1165.       time_counter := 0;
  1166.       scrsaver;
  1167.     end;
  1168.     free_ticks;
  1169.   until keypressed;
  1170.   if help then begin
  1171.     show_pic(160,$b800,@image3);
  1172.     help := false;
  1173.   end;
  1174.   if keybled then begin
  1175.     mem[$40:$17] := mem[$40:$17] and 15;
  1176.     mem[$40:$18] := 0;
  1177.   end;
  1178. end;
  1179.  
  1180. {$s-,i-}
  1181. {$i tsr.inc}
  1182.  
  1183. {Do NOT use this!}
  1184. {procedure int9; interrupt;
  1185. var
  1186. regs : array[0..5] of longint;
  1187. n : integer;
  1188. begin
  1189.   if test8086 > 1 then asm
  1190.     db  66h
  1191.     mov  word ptr regs[0],ax
  1192.     db  66h
  1193.     mov  word ptr regs[4],bx
  1194.     db  66h
  1195.     mov  word ptr regs[8],cx
  1196.     db  66h
  1197.     mov  word ptr regs[12],dx
  1198.     db  66h
  1199.     mov  word ptr regs[16],si
  1200.     db  66h
  1201.     mov  word ptr regs[20],di
  1202.   end;
  1203.   if (mem[$40:$17] and 8 > 0) and (port[$60] = $f) then
  1204.     if alt_tab then begin
  1205.       alt_tab := false;
  1206.       fillword(mem[$b800:160*41-160*header.usedchns],(9+header.usedchns)*80,7*256);
  1207.       mem[$40:$84] := 49;
  1208.       set_scr_ofs(0);
  1209.       line_comp(128*8);
  1210.     end
  1211.     else begin
  1212.       alt_tab := true;
  1213.       if wherey > (41-header.usedchns) then begin
  1214.         for n := 0 to 40-header.chns do
  1215.           move(mem[$b800:(n+header.chns+9)*160],mem[$b800:n*160],160);
  1216.         gotoxy(wherex,41-header.chns);
  1217.         port[$3d4] := 7;
  1218.         port[$3d5] := port[$3d5] and $df;
  1219.       end;
  1220.       mem[$40:$84] := 40-header.usedchns;
  1221.       set_scr_ofs(4000);
  1222.       line_comp((9+header.usedchns)*8);
  1223.     end;
  1224.   if test8086 > 1 then asm
  1225.     db  66h
  1226.     mov  ax,word ptr regs[0]
  1227.     db  66h
  1228.     mov  bx,word ptr regs[4]
  1229.     db  66h
  1230.     mov  cx,word ptr regs[8]
  1231.     db  66h
  1232.     mov  dx,word ptr regs[12]
  1233.     db  66h
  1234.     mov  si,word ptr regs[16]
  1235.     db  66h
  1236.     mov  di,word ptr regs[20]
  1237.   end;
  1238.   asm
  1239.     pushf
  1240.     cli
  1241.     call oldint9;
  1242.   end;
  1243. end;}
  1244.  
  1245. procedure fwritel(x,y,l : integer;s : pointer); assembler;
  1246. asm
  1247.   push ds
  1248.   mov  ax,word ptr s+2
  1249.   mov  ds,ax
  1250.   mov  ax,0b800h
  1251.   mov  es,ax
  1252.   mov  si,word ptr s
  1253.   inc  si
  1254.   mov  cx,l
  1255.   cmp  cx,0
  1256.   jne  @@2
  1257.   ret
  1258. @@2:
  1259.   mov  di,y
  1260.   dec  di
  1261.   dec  x
  1262.   mov  ax,160
  1263.   mul  di
  1264.   mov  di,ax
  1265.   add  di,x
  1266.   add  di,x
  1267. @@1:
  1268.   movsb
  1269.   inc  di
  1270.   loop @@1
  1271.   pop  ds
  1272. end;
  1273.  
  1274. procedure int8; interrupt;
  1275. const
  1276. regs : array[0..5] of longint = (0,0,0,0,0,0);
  1277. n : integer = 0;
  1278. i : integer=0;
  1279. pspeed : integer=0;
  1280. p : longint = 0;
  1281. fx: byte = 0;
  1282. fxdata : byte = 0;
  1283. st : integer = 0;
  1284. begin
  1285.   asm
  1286.     pushf
  1287.     cli
  1288.     call oldint8
  1289.   end;
  1290.   dec(int_cnt);
  1291.   if (int8use = false) and (int_cnt = 0) then begin
  1292.    int8use := true;
  1293.    if test8086 > 1 then asm
  1294.      cli
  1295.      db  66h
  1296.      mov  word ptr regs[0],ax
  1297.      db  66h
  1298.      mov  word ptr regs[4],bx
  1299.      db  66h
  1300.      mov  word ptr regs[8],cx
  1301.      db  66h
  1302.      mov  word ptr regs[12],dx
  1303.      db  66h
  1304.      mov  word ptr regs[16],si
  1305.      db  66h
  1306.      mov  word ptr regs[20],di
  1307.    end;
  1308.    int_cnt := 35;
  1309.    asm sti end;
  1310.    if alt_tab then begin
  1311.     if pan_mode then begin
  1312.       pspeed := pan_speed;
  1313.       if pspeed < 1 then pspeed := 1;
  1314.       inc(pan_cnt,pan_inc);
  1315.       if (pan_cnt<=-pspeed*8+1) or
  1316.       (pan_cnt>=pspeed*8-1) then pan_inc := -pan_inc;
  1317.       if pan_cnt < -pspeed*8+1 then pan_cnt := -pspeed*7;
  1318.       if pan_cnt > pspeed*8-1 then pan_cnt := pspeed*7;
  1319.     end;
  1320.     st := 50+9+header.usedchns;
  1321.     showbyte(53,st,cur_row);
  1322.     showbyte(41,st,speed);
  1323.     showbyte(30,st,cur_ptn);
  1324.     showbyte(33,st,header.length-1);
  1325.     showbyte(41,st,orders[cur_ptn]);
  1326.     showbyte(44,st,max_ptn-1);
  1327.     for n := 0 to header.usedchns-1 do begin
  1328.       if strobo_val < 0 then strobo_val := 0;
  1329.       if strobo_fx then begin
  1330.         port[$3c8] := 0;
  1331.         port[$3c9] := strobo_val and strobo_col[1];
  1332.         port[$3c9] := strobo_val and strobo_col[2];
  1333.         port[$3c9] := strobo_val and strobo_col[3];
  1334.       end;
  1335.       dec(strobo_val,strobo_speed);
  1336.       dec(strobo_val,strobo_speed);
  1337.       if pan_mode then begin
  1338.         i := integer(pan_sign[n]*pan_cnt) div pspeed;
  1339.         if i > 0 then
  1340.           channels[n].pan := 8+i
  1341.         else channels[n].pan := 7+i;
  1342.         gussetbalance(n,channels[n].pan);
  1343.       end;
  1344.       fx := channels[n].fx;
  1345.       fxdata := channels[n].fxdata;
  1346.       p := longint(@samples[channels[n].sample].name);
  1347.       fwritel(3,n+55,27,pointer(p));
  1348.       showbyte(34,n+55,channels[n].vol);
  1349.       fwritel(37,n+55,2,@note_txt[channels[n].note and 15]);
  1350.       {fastwrite(39,n+55,nibb2hex(channels[n].note shr 4));}
  1351.       showint4(41,n+55,channels[n].per);
  1352.       showint4(46,n+55,channels[n].dper);
  1353.       showbyte(58,n+55,channels[n].pan);
  1354.       if fx = 14 then begin
  1355.         showhex(54,n+55,fxdata and 15);
  1356.         fwritel(51,n+55,4,@efx_txt[fxdata shr 4]);
  1357.       end
  1358.       else if (fx < 16) and (fx >0) then begin
  1359.         fwritel(51,n+55,3,@fx_txt[fx]);
  1360.         showhex(54,n+55,fxdata);
  1361.       end;
  1362.       if fx > 15 then fillchar(mem[$b800:(n+54)*160+50*2],10,0);
  1363.       bar(63,55+n,(channels[n].bar+2) shr 2,'≈');
  1364.       if channels[n].hit = 1 then begin
  1365.         fillattr(3,n+55,27,15);
  1366.         fillattr(34,n+55,26,15);
  1367.         if strobo_fx then
  1368.           if strobo_sam[channels[n].sample] then strobo_val := 62;
  1369.       end else begin
  1370.         fillattr(3,n+55,27,7);
  1371.         fillattr(34,n+55,26,7);
  1372.       end;
  1373.     end;
  1374.    end;
  1375.    if test8086 > 1 then asm
  1376.      db  66h
  1377.      mov  ax,word ptr regs[0]
  1378.      db  66h
  1379.      mov  bx,word ptr regs[4]
  1380.      db  66h
  1381.      mov  cx,word ptr regs[8]
  1382.      db  66h
  1383.      mov  dx,word ptr regs[12]
  1384.      db  66h
  1385.      mov  si,word ptr regs[16]
  1386.      db  66h
  1387.      mov  di,word ptr regs[20]
  1388.    end;
  1389.    int8use := false;
  1390.   end;
  1391. end;
  1392. {i+}
  1393.  
  1394. procedure init_dos;
  1395. var
  1396. n : integer;
  1397. begin
  1398.   directvideo := false;
  1399.   gotoxy(1,1);
  1400.   alt_tab := true;
  1401.   int_cnt := 14;
  1402.   int8use := false;
  1403.   {getintvec(9,@oldint9);}
  1404.   getintvec(dos_irq,@oldint8);
  1405.   asm
  1406.     cld
  1407.     mov  ax,0B800h
  1408.     mov  es,ax
  1409.     mov  di,0
  1410.     mov  cx,4000
  1411.     mov  ax,0720h
  1412.     rep  stosw
  1413.   end;
  1414.   mem[$40:$84] := 40-header.usedchns;
  1415.   set_scr_ofs(4000);
  1416.   line_comp((9+header.usedchns)*8);
  1417.   show_cursor;
  1418.   setpal(@normpal);
  1419.   {setintvec(9,@int9);}
  1420.   setintvec(dos_irq,@int8);
  1421. end;
  1422.  
  1423. procedure end_dos;
  1424. begin
  1425.   setintvec(dos_irq,@oldint8);
  1426.   {setintvec(9,@oldint9);}
  1427. end;
  1428.  
  1429. procedure initlist;
  1430. var
  1431. f : file;
  1432. n,i,maxdrive : integer;
  1433. s : string;
  1434. begin
  1435.   s := getenv('TEMP');
  1436.   if s <> '' then temp_path := s;
  1437.   archive := false;
  1438.   textmode(co80+font8x8);
  1439.   getdir(0,org_path);
  1440.   getdir(0,cur_path);
  1441.   fillchar(drives,sizeof(drives),0);
  1442.   drives[1] := true;
  1443.   drives[2] := false;
  1444.   for n := 3 to 28 do if diskfree(n)>-1 then drives[n] := true;
  1445.  
  1446.   getmem(lpic,8000);
  1447.   listpic := fixgetmem(lpic);
  1448. end;
  1449.  
  1450. function getmodname(s : string) : string;
  1451. var
  1452. f : file;
  1453. s2 : string;
  1454. begin
  1455.   assign(f,s);
  1456.   reset(f,1);
  1457.   blockread(f,s2[1],20);
  1458.   s2[0] := #20;
  1459.   close(f);
  1460.   getmodname := s2;
  1461. end;
  1462.  
  1463. procedure load;
  1464. var
  1465. dirinfo : searchrec;
  1466. n : integer;
  1467. s : string;
  1468. maxstr : integer;
  1469.  
  1470. begin
  1471.   maxstr := 0;
  1472.   findfirst('*.mod',anyfile,dirinfo);
  1473.   while (doserror = 0) and (maxstr < maxline) do begin
  1474.     strlist[maxstr] := dirinfo.name;
  1475.     typelist[maxstr] := t_mod;
  1476.     inc(maxstr);
  1477.     findnext(dirinfo);
  1478.   end;
  1479.   findfirst('*.s3m',anyfile,dirinfo);
  1480.   while (doserror = 0) and (maxstr < maxline) do begin
  1481.     strlist[maxstr] := dirinfo.name;
  1482.     typelist[maxstr] := t_mod;
  1483.     inc(maxstr);
  1484.     findnext(dirinfo);
  1485.   end;
  1486.   if not archive then begin
  1487.     findfirst('*.zip',anyfile,dirinfo);
  1488.     while (doserror = 0) and (maxstr < maxline) do begin
  1489.       strlist[maxstr] := dirinfo.name;
  1490.       typelist[maxstr] := t_zip;
  1491.       inc(maxstr);
  1492.       findnext(dirinfo);
  1493.     end;
  1494.     findfirst('*.*',$10,dirinfo);
  1495.     while (doserror = 0) and (maxstr < maxline) do begin
  1496.       if dirinfo.attr and $18 <> 0 then begin
  1497.         strlist[maxstr] := dirinfo.name;
  1498.         typelist[maxstr] := t_dir;
  1499.         inc(maxstr);
  1500.       end;
  1501.       findnext(dirinfo);
  1502.     end;
  1503.   end
  1504.   else begin
  1505.     strlist[maxstr] := '..';
  1506.     typelist[maxstr] := t_dir;
  1507.     inc(maxstr);
  1508.   end;
  1509.   dec(maxstr);
  1510.   if not archive then for n := 1 to 28 do if drives[n]=true then begin
  1511.     inc(maxstr);
  1512.     strlist[maxstr] := char(n+64)+':';
  1513.     typelist[maxstr] := t_drive;
  1514.   end;
  1515.   for n := 0 to maxstr do begin
  1516.     case typelist[n] of
  1517.       t_dir : s := 'DIR';
  1518.       t_zip : s := 'ARCHIVE';
  1519.       t_mod : s := getmodname(strlist[n]);
  1520.       else s := '';
  1521.     end;
  1522.     flist.insline(strlist[n],s,'',typelist[n]);
  1523.   end;
  1524.   flist.qsort;
  1525. end;
  1526.  
  1527. procedure unzip(s : string);
  1528. var
  1529. zippath : string;
  1530. begin
  1531.   zippath := fsearch('PKUNZIP.EXE',getenv('PATH'));
  1532.   chdir(temp_path);
  1533.   exec(zippath,s+' *.mod *.s3m '+unzip_opt);
  1534.   if doserror <> 0 then begin
  1535.     writeln('Dos error ',doserror,#7);
  1536.     delay(500);
  1537.   end;
  1538. end;
  1539.  
  1540. function countfiles(s : string) : integer;
  1541. var
  1542. dir : searchrec;
  1543. n : integer;
  1544. begin
  1545.   n := 0;
  1546.   findfirst(s,anyfile,dir);
  1547.   while doserror = 0 do begin
  1548.     inc(n);
  1549.     findnext(dir);
  1550.   end;
  1551.   countfiles := n;
  1552. end;
  1553.  
  1554. procedure delall;
  1555. var
  1556. s : searchrec;
  1557. f : file;
  1558. begin
  1559.   findfirst('*.mod',anyfile,s);
  1560.   while (doserror = 0) do begin
  1561.     assign(f,s.name);
  1562.     erase(f);
  1563.     findnext(s);
  1564.   end;
  1565.   findfirst('*.s3m',anyfile,s);
  1566.   while (doserror = 0) do begin
  1567.     assign(f,s.name);
  1568.     erase(f);
  1569.     findnext(s);
  1570.   end;
  1571. end;
  1572.  
  1573. procedure doit(num : integer);
  1574. var
  1575. n : integer;
  1576. begin
  1577.   if not archive then case flist.lines^[num].t of
  1578.     t_mod : begin
  1579.               clrscr;
  1580.               stop_playing;
  1581.               free_mod;
  1582.               move(old_st3_per,st3_per,sizeof(st3_per));
  1583.               writeln('Loading');
  1584.               load_mod(flist.lines^[num].s[0]);
  1585.               makepertbl;
  1586.               start_playing;
  1587.               new_mod := true;
  1588.               chdir(cur_path);
  1589.               cur_sample := 1;
  1590.               start_sample := 1;
  1591.               hide_cursor;
  1592.             end;
  1593.     t_dir : begin
  1594.               chdir(flist.lines^[num].s[0]);
  1595.               getdir(0,cur_path);
  1596.               flist.delete;
  1597.               load;
  1598.               move(listpic^,mem[$b800:0],6400);
  1599.               flist.draw;
  1600.            end;
  1601.     t_drive : begin
  1602.                 chdir(flist.lines^[num].s[0]);
  1603.                 getdir(0,cur_path);
  1604.                 flist.delete;
  1605.                 load;
  1606.                 move(listpic^,mem[$b800:0],6400);
  1607.                 flist.draw;
  1608.               end;
  1609.     t_zip : begin
  1610.               getdir(0,old_path);
  1611.               cur_path := temp_path;
  1612.               fillchar(mem[$b800:0],6400,0);
  1613.               textattr := 0;
  1614.               gotoxy(1,1);
  1615.               if old_path[length(old_path)]='\' then
  1616.                 unzip(old_path+flist.lines^[num].s[0])
  1617.               else unzip(old_path+'\'+flist.lines^[num].s[0]);
  1618.               textattr := 7;
  1619.               n := countfiles('*.mod');
  1620.               n := n+countfiles('*.s3m');
  1621.               if n = 0 then begin
  1622.                 fillchar(mem[$b800:0],8000,0);
  1623.                 move(listpic^,mem[$b800:0],6400);
  1624.                 hide_cursor;
  1625.                 chdir(old_path);
  1626.                 flist.delete;
  1627.                 load;
  1628.                 flist.draw;
  1629.               end
  1630.               else if n = 1 then begin
  1631.                 archive := false;
  1632.                 flist.delete;
  1633.                 load;
  1634.                 stop_playing;
  1635.                 free_mod;
  1636.                 move(old_st3_per,st3_per,sizeof(st3_per));
  1637.                 writeln('Loading');
  1638.                 load_mod(flist.lines^[1].s[0]);
  1639.                 makepertbl;
  1640.                 start_playing;
  1641.                 delall;
  1642.                 new_mod := true;
  1643.                 fillchar(mem[$b800:0],8000,0);
  1644.                 {move(listpic^,mem[$b800:0],6400);}
  1645.                 cur_sample := 1;
  1646.                 start_sample := 1;
  1647.                 hide_cursor;
  1648.                 chdir(old_path);
  1649.                 flist.delete;
  1650.               end
  1651.               else begin
  1652.                 archive := true;
  1653.                 flist.delete;
  1654.                 load;
  1655.                 hide_cursor;
  1656.                 move(listpic^,mem[$b800:0],6400);
  1657.                 flist.draw;
  1658.               end;
  1659.             end;
  1660.   end
  1661.   else begin
  1662.     if flist.lines^[num].t = t_mod then begin
  1663.       chdir(temp_path);
  1664.       stop_playing;
  1665.       free_mod;
  1666.       move(old_st3_per,st3_per,sizeof(st3_per));
  1667.       load_mod(flist.lines^[num].s[0]);
  1668.       makepertbl;
  1669.       start_playing;
  1670.       new_mod := true;
  1671.       fillchar(mem[$b800:0],8000,0);
  1672.       {move(listpic^,mem[$b800:0],6400);
  1673.       flist.draw;}
  1674.       cur_sample := 1;
  1675.       start_sample := 1;
  1676.       hide_cursor;
  1677.     end
  1678.     else begin
  1679.       archive := false;
  1680.       chdir(temp_path);
  1681.       delall;
  1682.       chdir(old_path);
  1683.       cur_path := old_path;
  1684.       flist.delete;
  1685.       load;
  1686.       hide_cursor;
  1687.       move(listpic^,mem[$b800:0],6400);
  1688.       flist.draw;
  1689.     end;
  1690.   end;
  1691. end;
  1692.  
  1693. procedure dolist;
  1694. var
  1695. ch : char;
  1696. n : integer;
  1697. begin
  1698.   n := 30;
  1699.   if header.usedchns > 10 then dec(n,header.usedchns-10);
  1700.   flist.init(maxline,11,3,68,n,listpic);
  1701.   flist.c2x := 21;
  1702.   fillchar(listpic^,8000,0);
  1703.   show_pic(0,seg(listpic^),@image6);
  1704.   move(listpic^,mem[$b800:0],8000);
  1705.   flist.delete;
  1706.   if archive then chdir(temp_path);
  1707.   load;
  1708.   flist.draw;
  1709.   repeat
  1710.     new_mod := false;
  1711.     repeat
  1712.       updateinfo;
  1713.     until keypressed;
  1714.     ch := readkey;
  1715.     case upcase(ch) of
  1716.       'A'..'Z' : begin
  1717.                    flist.gotokey(upcase(ch));
  1718.                  end;
  1719.       #0 : begin
  1720.              ch := readkey;
  1721.              case ch of
  1722.                #72 : flist.upline;
  1723.                #80 : flist.downline;
  1724.                #73 : flist.uppage;
  1725.                #81 : flist.downpage;
  1726.                #71 : flist.gohome;
  1727.                #79 : flist.goend;
  1728.              end;
  1729.            end;
  1730.       ' ' : flist.tagline;
  1731.       #8 : flist.draw;
  1732.       #13 : doit(flist.curline);
  1733.     end;
  1734.   until (ch=#27) or (new_mod);
  1735.   flist.done;
  1736.   if new_mod then begin
  1737.     strobo_fx := false;
  1738.     for n := 0 to 99 do strobo_sam[n] := false;
  1739.     pan_mode := false;
  1740.   end;
  1741.   fillchar(mem[$b800:0],16000,0);
  1742.   normscr;
  1743. end;
  1744.  
  1745. procedure soita(sam,note : integer);
  1746. var
  1747. freq,vol,st_ofs : integer;
  1748. begin
  1749.   gusstopvoice(13);
  1750.   gussetbalance(13,7);
  1751.   if samples[sam].length < 3 then exit;
  1752.   freq := (8363 * 4 * (st3_per[note and 15] shr (note shr 4)))
  1753.            div samples[sam].c4spd;
  1754.   freq := per2gus(freq);
  1755.   vol := gusvol[samples[sam].volume]*amp_vol+20000;
  1756.   st_ofs := 2;
  1757.   if (samples[sam].loop) then
  1758.     gusplayall(13,8,gus_addr[sam]+st_ofs,
  1759.                      gus_addr[sam]+samples[sam].loopstart,
  1760.                      gus_addr[sam]+samples[sam].loopend,freq,vol)
  1761.     else gusplayall(13,0,gus_addr[sam]+st_ofs,
  1762.                           gus_addr[sam]+st_ofs,
  1763.                           gus_addr[sam]+samples[sam].length,freq,vol);
  1764. end;
  1765.  
  1766. function key2note(ch : char;okt : integer) : integer;
  1767. var
  1768. note : integer;
  1769. begin
  1770.   case ch of
  1771.     'Q' : note := _C2+okt;
  1772.     'W' : note := _D2+okt;
  1773.     'E' : note := _E2+okt;
  1774.     'R' : note := _F2+okt;
  1775.     'T' : note := _G2+okt;
  1776.     'Y' : note := _A2+okt;
  1777.     'U' : note := _B2+okt;
  1778.     'I' : note := _C3+okt;
  1779.     'O' : note := _D3+okt;
  1780.     'P' : note := _E3+okt;
  1781.     '2' : note := _Db2+okt;
  1782.     '3' : note := _Eb2+okt;
  1783.     '5' : note := _Gb2+okt;
  1784.     '6' : note := _Ab2+okt;
  1785.     '7' : note := _Bb2+okt;
  1786.     '9' : note := _Db3+okt;
  1787.     'Z' : note := _C1+okt;
  1788.     'X' : note := _D1+okt;
  1789.     'C' : note := _E1+okt;
  1790.     'V' : note := _F1+okt;
  1791.     'B' : note := _G1+okt;
  1792.     'N' : note := _A1+okt;
  1793.     'M' : note := _B1+okt;
  1794.     'S' : note := _Db1+okt;
  1795.     'D' : note := _Eb1+okt;
  1796.     'G' : note := _Gb1+okt;
  1797.     'H' : note := _Ab1+okt;
  1798.     'J' : note := _Bb1+okt;
  1799.     else note := 0;
  1800.   end;
  1801.   key2note := note;
  1802. end;
  1803.  
  1804. procedure menu;
  1805. var
  1806. ch : char;
  1807. clr : boolean;
  1808. n,i : integer;
  1809. begin
  1810.   clr := true;
  1811.   start_chn := 0;
  1812.   pause := 0;
  1813.   old_row := 666;
  1814.   start_sample := 1;
  1815.   cur_sample := 1;
  1816.   play_sample := 0;
  1817.   cur_octave := 2;
  1818.   help := false;
  1819.   if loaded then start_playing;
  1820.   hide_cursor;
  1821.   getpal(@normpal);
  1822.   setvgapal(col_back,col_backr,col_backg,col_backb);
  1823.   {show_pic(0,seg(listpic^),@image6);}
  1824.   show_pic(8000+0,$b800,@image1);
  1825.   show_pic((50+5+header.usedchns)*160,$b800,@image2);
  1826.   if loaded then show_pic(160,$b800,@image3)
  1827.   else show_pic(160,$b800,@image6);
  1828.   for n := 0 to header.usedchns do
  1829.     move(image4,mem[$b800:(4+n)*160+8000],160);
  1830.   line_comp((header.usedchns+9)*8);
  1831.   set_scr_ofs(4000);
  1832.   repeat
  1833.     if loaded then show_ptn(clr);
  1834.     clr := false;
  1835.     if loaded then ch := readkey
  1836.     else ch := #13;
  1837.     if (play_sample <> 0) and (key2note(upcase(ch),cur_octave*16) <> 0) then begin
  1838.       soita(play_sample,key2note(upcase(ch),cur_octave*16));
  1839.       ch := #1;
  1840.     end;
  1841.     if (play_sample <> 0) and (key2note(upcase(ch),cur_octave*16)=0) then begin
  1842.       if (ch = '+') and (cur_octave<6) then inc(cur_octave);
  1843.       if (ch = '-') and (cur_octave>0) then dec(cur_octave);
  1844.       if upcase(ch) in ['A'..'Z','+','-'] then ch := #1;
  1845.     end;
  1846.     case ch of
  1847.       '+' : if amp_vol < 16 then begin
  1848.               inc(amp_vol);
  1849.               for n := 0 to header.usedchns-1 do begin
  1850.                 i := gusvol[word(channels[n].vol*main_vol) div 64]*amp_vol+20000;
  1851.                 gus_chn[n].status := gus_chn[n].status or gst_vol;
  1852.                 gus_chn[n].vol := i;
  1853.                 {gussetvolume(n,i);}
  1854.               end;
  1855.             end;
  1856.       '-' : if amp_vol > 0 then begin
  1857.               dec(amp_vol);
  1858.               for n := 0 to header.usedchns-1 do begin
  1859.                 i := gusvol[word(channels[n].vol*main_vol) div 64]*amp_vol+20000;
  1860.                 gus_chn[n].status := gus_chn[n].status or gst_vol;
  1861.                 gus_chn[n].vol := i;
  1862.                 {gussetvolume(n,i);}
  1863.               end;
  1864.             end;
  1865.       ',' : if start_chn > 0 then begin
  1866.               dec(start_chn);
  1867.               clr := true;
  1868.             end;
  1869.       '.' : if start_chn < header.usedchns-4 then begin
  1870.               inc(start_chn);
  1871.               clr := true;
  1872.             end;  
  1873.       'P','p' : if pause = 0 then begin
  1874.                   pause := speed;
  1875.                   speed := 0;
  1876.                   for n := 0 to maxchn-1 do gusstopvoice(n);
  1877.                   strobo_val := 0;
  1878.                 end else begin
  1879.                   speed := pause;
  1880.                   pause := 0;
  1881.                 end;
  1882.       'R','r' : if playing then begin
  1883.                   stop_playing;
  1884.                   playing := false;
  1885.                 end else begin
  1886.                   clr := true;
  1887.                   start_playing;
  1888.                   playing := true;
  1889.                 end;
  1890.       'V','v' : if vblank then vblank := false
  1891.                 else vblank := true;
  1892.       'b','B' : if strobo_sam[cur_sample]=true then strobo_sam[cur_sample]:=false
  1893.                 else begin
  1894.                   strobo_sam[cur_sample] := true;
  1895.                   strobo_fx := true;
  1896.                 end;
  1897.       'A','a' : if pan_mode then begin
  1898.                   for n := 0 to header.usedchns-1 do begin
  1899.                     channels[n].pan := defpan[n];
  1900.                     gussetbalance(n,defpan[n]);
  1901.                   end;
  1902.                   pan_mode := false;
  1903.                   pan_cnt := 4*pan_speed;
  1904.                 end
  1905.                 else begin
  1906.                   pan_mode := true;
  1907.                   pan_cnt := 4*pan_speed;
  1908.                   pan_inc := 1;
  1909.                 end;
  1910.       'Q','q' : if qualitymode and not lockquality then begin
  1911.                   qualitymode := false;
  1912.                   makepertbl;
  1913.                   normscr;
  1914.                 end
  1915.                 else begin
  1916.                   qualitymode := true;
  1917.                   makepertbl;
  1918.                   normscr;
  1919.                 end;
  1920.       ' ' : if play_sample <> 0 then begin
  1921.               gussetvolume(13,0);
  1922.               gusstopvoice(13);
  1923.               play_sample := 0;
  1924.             end
  1925.             else play_sample := cur_sample;
  1926.       #13 : dolist;
  1927.       #8 : begin      {bkspc}
  1928.              goto_mod(cur_ptn,0);
  1929.              clr := true;
  1930.            end;
  1931.       #0 : begin
  1932.              ch := readkey;
  1933.              case ch of
  1934.                #81 : if speed < 31 then begin  {pgdn}
  1935.                        inc(nspeed);
  1936.                        inc(speed);
  1937.                      end;
  1938.                #73 : if speed > 0 then begin   {pgup}
  1939.                        dec(nspeed);
  1940.                        dec(speed);
  1941.                      end;
  1942.                #71 : begin                     {home}
  1943.                        dec(tempo);
  1944.                        timer_rate := 25000 div (tempo);
  1945.                      end;
  1946.                #79 : begin                     {end}
  1947.                        inc(tempo);
  1948.                        timer_rate := 25000 div (tempo);
  1949.                      end;
  1950.                #59..#68 : if byte(ch)-59 < header.usedchns then {F1-F10}
  1951.                           begin
  1952.                             channels[byte(ch)-59].on :=
  1953.                               channels[byte(ch)-59].on xor 1;
  1954.                             gusstopvoice(byte(ch)-59);
  1955.                           end;
  1956.                #84..#93 : if byte(ch)-74 < header.usedchns then {SHIFT F1-F10}
  1957.                           begin  {F1-F10}
  1958.                             channels[byte(ch)-74].on :=
  1959.                               channels[byte(ch)-74].on xor 1;
  1960.                             gusstopvoice(byte(ch)-74);
  1961.                           end;
  1962.                #75 : begin    {left arrow}
  1963.                        if cur_ptn > 0 then
  1964.                          goto_mod(cur_ptn-1,0)
  1965.                        else goto_mod(0,0);
  1966.                        clr := true;
  1967.                      end;
  1968.                #77 : begin    {right arrow}
  1969.                        if cur_ptn < header.length-1 then
  1970.                          goto_mod(cur_ptn+1,0)
  1971.                        else goto_mod(cur_ptn,0);
  1972.                        clr := true;
  1973.                      end;
  1974.                #72 : begin {up}
  1975.                        if cur_sample > 1 then dec(cur_sample);
  1976.                        if cur_sample < start_sample then dec(start_sample);
  1977.                        if play_sample <> 0 then play_sample := cur_sample;
  1978.                      end;
  1979.                #80 : begin  {down}
  1980.                        if cur_sample < header.samples then inc(cur_sample);
  1981.                        if cur_sample > (start_sample+24-header.usedchns) then
  1982.                          inc(start_sample);
  1983.                        if play_sample <> 0 then play_sample := cur_sample;
  1984.                      end;
  1985.              end;
  1986.            end;
  1987.       'S','s' : scrsaver;
  1988.       '!' : begin
  1989.               textmode(co80);
  1990.               exec(getenv('COMSPEC'),'');
  1991.               textmode(co80+font8x8);
  1992.               normscr;
  1993.               old_row := 666;
  1994.             end;
  1995.       '"' : begin
  1996.               init_dos;
  1997.               exec(getenv('COMSPEC'),'');
  1998.               end_dos;
  1999.               textmode(co80+font8x8);
  2000.               normscr;
  2001.               old_row := 666;
  2002.             end;
  2003.     end;
  2004.   until (ch = #27) or (not loaded);
  2005.   stop_playing;
  2006. end;
  2007.  
  2008.  
  2009.  
  2010. function toupper(s : string) : string;
  2011. var
  2012. n,i : integer;
  2013. begin
  2014.   n := length(s);
  2015.   if n < 1 then begin
  2016.     toupper := '';
  2017.     exit;
  2018.   end;
  2019.   for i := 1 to n do s[i] := upcase(s[i]);
  2020.   toupper := s;
  2021. end;
  2022.  
  2023. function exists(s : string) : boolean;
  2024. var
  2025. f : file of byte;
  2026. i : integer;
  2027. begin
  2028.   assign(f,s);
  2029.   {$i-}
  2030.   reset(f);
  2031.   i := ioresult;
  2032.   {$i+}
  2033.   if i = 0 then begin
  2034.     close(f);
  2035.     exists := true;
  2036.   end else exists := false;
  2037. end;
  2038.  
  2039. function addext(str,ext: string) : string;
  2040. begin
  2041.   if pos('.',str) > 0 then addext := str
  2042.   else addext := str+ext;
  2043. end;
  2044.  
  2045. function findgus : word;
  2046. var
  2047. n,c,i : word;
  2048. s : string;
  2049. begin
  2050.   s := getenv('ultrasnd');
  2051.   if s = '' then begin
  2052.     findgus := 0;
  2053.     exit;
  2054.   end;
  2055.   val(copy(s,1,3),n,c);
  2056.   if c <> 0 then begin
  2057.     findgus := 0;
  2058.     exit;
  2059.   end;
  2060.   case n of
  2061.     210 : i := $210;
  2062.     220 : i := $220;
  2063.     230 : i := $230;
  2064.     240 : i := $240;
  2065.     250 : i := $250;
  2066.     260 : i := $260;
  2067.     270 : i := $270;
  2068.     else begin
  2069.       findgus := 0;
  2070.       exit;
  2071.     end;
  2072.   end;
  2073.   for n := 1 to 3 do delete(s,1,pos(',',s));
  2074.   if gus_irq = 0 then begin
  2075.     val(copy(s,1,pos(',',s)-1),gus_irq,c);
  2076.     if c <> 0 then gus_irq := 0;
  2077.   end;
  2078.   findgus := i;
  2079. end;
  2080.  
  2081. procedure getcmd;
  2082. var
  2083. s : string;
  2084. b : byte;
  2085. i,n,c : integer;
  2086.  
  2087. begin
  2088.   mod_name :=  '';
  2089.   for n := 0 to 99 do strobo_sam[n] := false;
  2090.   strobo_fx := false;
  2091.   strobo_col[1] := $ff;
  2092.   strobo_col[2] := $ff;
  2093.   strobo_col[3] := $ff;
  2094.   writeln('Adrenalin module player v 0.95  By: Beta/A-Men');
  2095.   if paramcount > 0 then for n := 1 to paramcount do begin
  2096.     s := toupper(s);
  2097.     if copy(paramstr(n),1,1) <> '/' then begin
  2098.       s := addext(paramstr(n),'.mod');
  2099.       if not exists(s) then begin
  2100.         s := addext(paramstr(n),'.s3m');
  2101.         if not exists(s) then begin
  2102.           writeln('Module ',s,' not found!');
  2103.           halt(2);
  2104.         end;
  2105.       end;
  2106.       mod_name := s;
  2107.     end
  2108.     else if copy(paramstr(n),1,5) = '/port' then begin
  2109.       s := copy(paramstr(n),6,3);
  2110.       if s = '210' then gus_base := $210;
  2111.       if s = '220' then gus_base := $220;
  2112.       if s = '230' then gus_base := $230;
  2113.       if s = '240' then gus_base := $240;
  2114.       if s = '250' then gus_base := $250;
  2115.       if s = '260' then gus_base := $260;
  2116.       if s = '270' then gus_base := $270;
  2117.     end
  2118.     else if copy(paramstr(n),1,4)='/tmr' then gus_irq := 100
  2119.     else if copy(paramstr(n),1,5)='/desq' then keybled := false
  2120.     else if copy(paramstr(n),1,5)='/ssam' then begin
  2121.       val(copy(paramstr(n),6,2),i,c);
  2122.       if (i > 0) and (i < 32) then begin
  2123.         strobo_fx := true;
  2124.         strobo_sam[i] := true;
  2125.       end;
  2126.     end
  2127.     else if copy(paramstr(n),1,5)='/scol' then begin
  2128.       strobo_col[1] := 0;
  2129.       strobo_col[2] := 0;
  2130.       strobo_col[3] := 0;
  2131.       val(copy(paramstr(n),6,2),i,c);
  2132.       if (i > 0) and (i < 8) then begin
  2133.         if i and 1 > 0 then strobo_col[3] := $ff;
  2134.         if i and 2 > 0 then strobo_col[2] := $ff;
  2135.         if i and 4 > 0 then strobo_col[1] := $ff;
  2136.       end;
  2137.     end
  2138.     else if copy(paramstr(n),1,5)='/sspd' then begin
  2139.       val(copy(paramstr(n),6,2),i,c);
  2140.       if i > 0 then strobo_speed := i;
  2141.     end
  2142.     else if copy(paramstr(n),1,5)='/pspd' then begin
  2143.       val(copy(paramstr(n),6,2),i,c);
  2144.       if i > 0 then pan_speed := i;
  2145.       pan_cnt := 4*pan_speed;
  2146.     end
  2147.     else if copy(paramstr(n),1,2)='/?' then begin
  2148.       writeln('Usage: ADNMOD modname [options]');
  2149.       writeln('options:  /portxxx    set gus address');
  2150.       writeln('          /scolx      set strobo color');
  2151.       writeln('          /sspdxx     set strobo speed');
  2152.       writeln('          /tmr        dont use GUS irq');
  2153.       writeln('          /desq       disable some desqview unfriendly features');
  2154.       halt(0);
  2155.     end;
  2156.   end;
  2157.   s := toupper(getenv('CAPAMOD'));
  2158.   if length(s) > 0 then begin
  2159.     b := 0;
  2160.     n := 1;
  2161.     while (n <= length(s)) and (b = 0) do begin
  2162.       if s[n] = '/' then begin
  2163.         if toupper(copy(s,n+1,3)) = 'AMP' then begin
  2164.           val(copy(s,n+4,2),i,c);
  2165.           i := i div 3;
  2166.           if i > 0 then amp_vol := i;
  2167.           b := 1;
  2168.         end;
  2169.       end;
  2170.       inc(n);
  2171.     end;
  2172.   end;
  2173. end;
  2174.  
  2175. procedure initialize;
  2176. var
  2177. w : word;
  2178. begin
  2179.   if gus_base = $200 then if findgus > 0 then gus_base := findgus;
  2180.   if gus_irq > 15 then gus_irq := 0;
  2181.   gusfind;
  2182.   if gus_base = $200 then begin
  2183.     writeln('GUS not found. Assuming address 220');
  2184.     gus_base := $220;
  2185.     gusfind;
  2186.   end;
  2187.   write('GUS found at ',nibb2hex(hi(gus_base)),byte2hex(lo(gus_base)));
  2188.   gusmem := gusfindmem;
  2189.   writeln(' with ',gusmem,' bytes of memory');
  2190.   gusreset;
  2191.   move(st3_per,old_st3_per,sizeof(st3_per));
  2192.   if keybled then normkbf := mem[$40:$17];
  2193.   asm
  2194.     mov  ax,1600h
  2195.     int  2fh
  2196.     mov  w,ax
  2197.   end;
  2198.   if lo(w)=4 then begin
  2199.     lockquality := true;
  2200.     qualitymode := true;
  2201.     makepertbl;
  2202.   end;
  2203. end;
  2204.  
  2205. procedure showerr(error : integer);
  2206. begin
  2207.   case error of
  2208.     1 : writeln('Too many channels');
  2209.     2 : begin
  2210.           writeln;
  2211.           writeln('Load error!');
  2212.         end;
  2213.     3 : begin
  2214.           writeln;
  2215.           writeln('Out of memory');
  2216.         end;
  2217.     255 : writeln('Error');
  2218.   end;
  2219. end;
  2220.  
  2221. var
  2222. i,n : integer;
  2223.  
  2224. begin
  2225.   amp_vol := 16;
  2226.   randomize;
  2227.   checkbreak := false;
  2228.   getcmd;
  2229.   initialize;
  2230.   init_mod;
  2231.   if initxms <> 0 then begin
  2232.     writeln('XMS not found');
  2233.     halt(3);
  2234.   end;
  2235.   if mod_name <> '' then begin
  2236.     load_mod(mod_name);
  2237.     if mod_error <> 0 then begin
  2238.       showerr(mod_error);
  2239.       halt(mod_error);
  2240.     end;
  2241.   end;
  2242.   initlist;
  2243.   getintvec($fc,@oldintfc);
  2244.   setintvec($fc,@intfc);
  2245.   menu;
  2246.   setintvec($fc,@oldintfc);
  2247.   freemem(lpic,8000);
  2248.   free_mod;
  2249.   if isxms then donexms;
  2250.   chdir(temp_path);
  2251.   delall;
  2252.   chdir(org_path);
  2253.   done_mod;
  2254.   textmode(co80);
  2255.   if keybled then begin
  2256.     mem[$40:$17] := 0;
  2257.     mem[$40:$18] := 0;
  2258.   end;
  2259.   if mod_error <> 0 then showerr(mod_error);
  2260.   if virt_info.err_wptn <> -1 then begin
  2261.     writeln('Error in warnptn. Please report error numbers and module name to author');
  2262.     writeln('cptn: ',virt_info.err_cptn);
  2263.     writeln('wptn: ',virt_info.err_wptn);
  2264.     writeln('nptn: ',virt_info.err_nptn);
  2265.   end;
  2266.   textcolor(15);
  2267.   writeln('Thank you for using ADNMOD 0.95');
  2268.   textcolor(7);
  2269.   write('Send e-mail to ');
  2270.   textcolor(14);
  2271.   writeln('beta@triplex.fipnet.fi');
  2272.   textcolor(7);
  2273. end.
  2274.