home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK5 / DOS_38 / VT12B.ZIP / VTSRC.ZIP / VT.PAS < prev    next >
Pascal/Delphi Source File  |  1993-03-31  |  23KB  |  936 lines

  1. PROGRAM VT;
  2.  
  3. {$M 30000,20000,655360}
  4.  
  5. USES CleanHeap,
  6.      SoundDevices,                   { Sound output devices.               }
  7.      DevSbDAC, DevDAC, DevSB,        {                                     }
  8.      DevFile, DevAdLib, DevSpkr,     {                                     }
  9.      VTSpecial,                      { Installation check.                 }
  10.      VTStrConst, StrConst,           { Language support.                   }
  11.      Dos,                            { Standard TP UNITs.                  }
  12.      Objects,                        {                                     }
  13.      VTCfg, VTGlobal, VTCmd,         { VT-Specific UNITs.                  }
  14.      VTWins, VTPlay, VTPartitura,    {                                     }
  15.      VTScreens,                      {                                     }
  16.      SongUnit, SongElements,         { Song definition UNITs.              }
  17.      SongUtils,                      {                                     }
  18.      PlayMod, Filters, ModCommands,  {                                     }
  19.      SoundBlaster,                   {                                     }
  20.      Vid43, Output43,                { Video routines.                     }
  21.      Kbd, Debugging,                 { Miscelaneous UNITs.                 }
  22.      HexConversions,
  23.      CmdLine,                        {                                     }
  24.      Heaps,                          {                                     }
  25.      SwapStream, SwapManager,        {                                     }
  26.      FileUtil;                       {                                     }
  27.  
  28.  
  29.  
  30.  
  31. VAR
  32.   nt             : TFullNote;
  33.   pp             : PPattern;
  34.   omd,
  35.   md             : TPlayingNote;
  36.   ThereIsNewNote : BOOLEAN;
  37.   EmptySong      : TSong;
  38.  
  39. CONST
  40.   Funking    : BOOLEAN = FALSE;
  41.   FunkGoesUp : BOOLEAN = FALSE;
  42.   FadingOut  : BOOLEAN = FALSE;
  43.   FadedOut   : BOOLEAN = FALSE;
  44.   FadeCount  : WORD    = 0;
  45.   LastSeq    : BYTE    = 255;
  46.  
  47. VAR
  48.   Sequences  : ARRAY[1..256] OF BOOLEAN;
  49.  
  50.  
  51.  
  52.  
  53. { -------------------------------------------------------------------------- }
  54.  
  55. FUNCTION IsAConsole(VAR f) : BOOLEAN; ASSEMBLER;
  56.   ASM
  57.                 MOV     AX,$4400
  58.                 LES     BX,[f]
  59.                 MOV     BX,TextRec([ES:BX]).Handle
  60.                 INT     $21
  61.                 XOR     AX,AX
  62.                 TEST    DL,$80
  63.                 JZ      @@Fin
  64.                 INC     AX
  65. @@Fin:
  66.   END;
  67.  
  68. FUNCTION RJust(s: STRING; i: WORD) : STRING;
  69.   VAR
  70.     r : STRING;
  71.   BEGIN
  72.     IF i <= Length(s) THEN
  73.       BEGIN
  74.         RJust := s;
  75.         EXIT;
  76.       END;
  77.     r[0] := CHAR(i - Length(s));
  78.     FillChar(r[1], i - Length(s), ' ');
  79.     RJust := r + s;
  80.   END;
  81.  
  82.  
  83. FUNCTION LJust(s: STRING; i: WORD) : STRING;
  84.   VAR
  85.     r : STRING;
  86.   BEGIN
  87.     IF i <= Length(s) THEN
  88.       BEGIN
  89.         LJust := s;
  90.         EXIT;
  91.       END;
  92.     r[0] := CHAR(i - Length(s));
  93.     FillChar(r[1], i - Length(s), ' ');
  94.     LJust := s + r;
  95.   END;
  96.  
  97.  
  98. FUNCTION Char2Str(c: CHAR; n: BYTE) : STRING;
  99.   VAR
  100.     s : STRING;
  101.   BEGIN
  102.     FillChar(s, SIZEOF(s), c);
  103.     s[0] := CHAR(n);
  104.     Char2Str := s;
  105.   END;
  106.  
  107.  
  108. PROCEDURE MyWriteLn(s: STRING);
  109.   CONST
  110.     Linea : WORD = 0;
  111.   BEGIN
  112.     IF ((Linea > 24) OR (s = '')) AND IsAConsole(Output) THEN
  113.       BEGIN
  114.         Write(StdErr, GetString(StrUsagePressAKey));
  115.         KbdReadKey;
  116.         Write(StdErr, #13+Char2Str(' ', 79)+#13);
  117.         Linea := 0;
  118.       END;
  119.     IF s <> '' THEN WriteLn(Output, s);
  120.     INC(Linea);
  121.   END;
  122.  
  123.  
  124.  
  125. PROCEDURE UsagePart(Str: WORD);
  126.   BEGIN
  127.     MyWriteLn(GetString(StrUsageTop));
  128.  
  129.     WHILE GetString(Str) <> #0 DO
  130.       BEGIN
  131.         IF GetString(Str) = '' THEN
  132.           MyWriteLn(GetString(StrUsageEmpty))
  133.         ELSE
  134.           MyWriteLn(GetString(Str));
  135.         INC(Str);
  136.       END;
  137.  
  138.     MyWriteLn(GetString(StrUsageBottom));
  139.   END;
  140.  
  141. PROCEDURE USAGE;
  142.   VAR
  143.     i : WORD;
  144.     p : PSoundDevice;
  145.   BEGIN
  146.     MyWriteLn('                           ╔════════════════════════╗');
  147.     MyWriteLn('                           ║ VangeliSTracker  v'+Version+' ║');
  148.     MyWriteLn('                           ╚════════════════════════╝');
  149.  
  150.     IF Beta THEN
  151.       MyWriteLn('                                     (beta)');
  152.  
  153.     MyWriteLn(GetString(StrUsageTop));
  154.     MyWriteLn(GetString(StrUsage01));
  155.     MyWriteLn(GetString(StrUsageBottom));
  156.  
  157.     UsagePart(Strusage1Beg);
  158.     MyWriteLn('');
  159.  
  160.     UsagePart(Strusage2Beg);
  161.     MyWriteLn('');
  162.     
  163.     MyWriteLn(GetString(StrUsageTop));
  164.     MyWriteLn(GetString(StrUsage3Beg));
  165.  
  166.     FOR i := 1 TO NumDevices DO
  167.       BEGIN
  168.         p := IndexDevice(i);
  169.         MyWriteLn(LJust(' │   '+RJust(p^.DevID+':', SIZEOF(TDevID))+' '+p^.Name, 78)+'│');
  170.       END;
  171.  
  172.     MyWriteLn(GetString(StrUsageBottom));
  173.     MyWriteLn('');
  174.  
  175.     UsagePart(Strusage4Beg);
  176.  
  177.     HALT(1);
  178.   END;
  179.  
  180. { -------------------------------------------------------------------------- }
  181.  
  182. PROCEDURE ORROR(s: STRING; Go: BOOLEAN);
  183.   VAR
  184.     OldScr : WORD;
  185.   BEGIN
  186.     QuitaVideoMode43;
  187.  
  188.     WriteLn('ORROR: ', s);
  189.  
  190.     IF Go THEN
  191.       HALT(1);
  192.  
  193.     PoneVideoMode43;
  194.     InitWinF8Demo;
  195.     OldScr := ActiveWindows;
  196.     SetUser(0);
  197.     SetUser(OldScr);
  198.     RefreshMiscInfo(EmptySong);
  199.   END;
  200.  
  201. { -------------------------------------------------------------------------- }
  202.  
  203. PROCEDURE DoNotes(VAR Song: TSong; VAR note, NewNote, L2ndForz: BOOLEAN);
  204.   CONST
  205.     i     : WORD     = 0;
  206.     PSize : WORD     = 0;
  207.     Patt  : PPattern = NIL;
  208.   BEGIN
  209.     IF NewNote THEN BEGIN
  210.       md := NoteSound^;
  211.  
  212.       PSize := 0;
  213.       Patt := Song.GetPatternSeq(md.SeqPlaying);
  214.       IF (Patt <> NIL) AND (Patt^.Patt <> NIL) THEN
  215.         PSize := Patt^.Patt^.NNotes;
  216.  
  217.       UpdateRunInfo(md.Tempo, Song.GetPatternSequence(md.SeqPlaying), md.NotePlaying, md.SeqPlaying, PSize);
  218.  
  219.       w2ndLine.forz := L2ndForz;
  220.  
  221.  
  222.       FOR i := 1 TO Song.NumChannels DO BEGIN
  223.         Song.GetNote(md.SeqPlaying, md.NotePlaying, i, nt);
  224.  
  225.         UpdateNoteInfo  (Song, nt, i);
  226.         UpdateSampleInfo(Song, nt, i);
  227.         ParseBarInit    (nt, i);
  228.       END;
  229.  
  230.  
  231.       IF (md.SeqPlaying <= 256) AND (LastSeq <> md.SeqPlaying) THEN
  232.         BEGIN
  233.           IF (NOT VTLoopMod) AND Sequences[md.SeqPlaying] THEN
  234.             FadingOut := TRUE;
  235.  
  236.           Sequences[md.Seqplaying] := TRUE;
  237.           LastSeq := md.SeqPlaying;
  238.         END;
  239.  
  240.       NewNote  := FALSE;
  241.       L2ndForz := FALSE;
  242.     END;
  243.  
  244.     Update2ndLine(note);
  245.     TickSampleInfo;
  246.   END;
  247.  
  248.  
  249. CONST
  250.   StkSize = 500;
  251. VAR
  252.   Stack1 : ARRAY[1..StkSize] OF BYTE;
  253.  
  254. PROCEDURE TickProc(VAR Song: TSong; note: BOOLEAN); FAR;
  255.   CONST
  256.     Semaphor  : BYTE    = 0;
  257.     Semaphor2 : BYTE    = 0;
  258.     Semaphor3 : BYTE    = 0;
  259.     Semaphor4 : BYTE    = 0;
  260.     NewNote   : BOOLEAN = FALSE;
  261.     L2ndForz  : BOOLEAN = FALSE;
  262.     Count     : BYTE    = 0;
  263.     i         : WORD    = 0;
  264.     j         : WORD    = 0;
  265.     k         : WORD    = 0;
  266.     SS_1      : WORD    = 0;
  267.     SP_1      : WORD    = 0;
  268.     SongP     : PSong   = NIL;
  269.     noteP     : BOOLEAN = FALSE;
  270.   BEGIN
  271.  
  272.     IF (NOT Playing) AND (Semaphor4 = 0) THEN
  273.       BEGIN
  274.         INC(Semaphor4);
  275.         UpdateBars;
  276. {
  277.         FillChar(nt, SIZEOF(nt), 0);
  278.         FOR i := 1 TO ModUnit.NumChannels DO
  279.           UpdateSampleInfo(nt, i);
  280.         TickSampleInfo;
  281. }
  282.         DEC(Semaphor4);
  283.         EXIT;
  284.       END;
  285.  
  286.     IF note THEN BEGIN
  287.       NewNote        := TRUE;
  288.       ThereIsNewNote := TRUE;
  289.     END;
  290.  
  291.     L2ndForz := L2ndForz OR w2ndLine.forz;
  292.  
  293.     IF Semaphor = 0 THEN BEGIN
  294.       INC(Semaphor);
  295.  
  296.       SongP := @Song;
  297.       noteP := note;
  298.  
  299.        ASM
  300.                 MOV     [SS_1],SS
  301.                 MOV     [SP_1],SP
  302.                 MOV     AX,DS
  303.                 MOV     SS,AX
  304.                 MOV     SP,OFFSET Stack1 + StkSize
  305.        END;
  306.  
  307.        DoNotes(SongP^, noteP, NewNote, L2ndForz);
  308.  
  309.        ASM
  310.                 MOV     SS,[SS_1]
  311.                 MOV     SP,[SP_1]
  312.        END;
  313.  
  314.       DEC(Semaphor);
  315.     END;
  316.  
  317.     UpdateOscilloscInfo;
  318.  
  319.     IF Semaphor2 = 0 THEN
  320.       BEGIN
  321.         INC(Semaphor2);
  322.         IF Funking THEN
  323.           ASM
  324. {
  325.                 MOV     DX,$3DA
  326. @@lp1:           IN     AL,DX
  327.                  AND    AL,8
  328.                  JZ     @@lp1
  329.  
  330.                 MOV     DX,$3D4
  331.                 MOV     AL,$18
  332.                 MOV     AH,[Count]
  333.                 OUT     DX,AX
  334.  
  335.                 MOV     DL,[FunkGoesUp]
  336. @@otra:         AND     DL,DL
  337.                 JZ      @@down
  338.                  DEC    AH
  339.                 JMP     @@up
  340. @@down:          INC    AH
  341. @@up:           AND     AH,AH
  342.                 JNZ     @@ya
  343.                  AND    DL,1
  344.                  XOR    DL,1
  345.                  MOV    [FunkGoesUp],DL
  346.                  JMP    @@otra
  347. @@ya:           MOV     [Count],AH
  348. }
  349.           END;
  350.         DEC(Semaphor2);
  351.       END;
  352.  
  353.     IF (FadingOut) AND (Semaphor3 = 0) THEN
  354.       BEGIN
  355.         INC(Semaphor3);
  356.         IF NOT PermitFade THEN
  357.           FadedOut := TRUE
  358.         ELSE
  359.           BEGIN
  360.             INC(FadeCount, FadeIncr);
  361.             FOR j := 1 TO HI(FadeCount) DO
  362.               BEGIN
  363.                 FadedOut := TRUE; 
  364.                 FOR k := 1 TO MaxChannels DO
  365.                   IF UserVols[k] > 0 THEN
  366.                     BEGIN
  367.                       DEC(UserVols[k]);
  368.                       FadedOut := FALSE;
  369.                     END;
  370.               END;
  371.             FadeCount := LO(FadeCount);
  372.           END;
  373.         DEC(Semaphor3);
  374.       END;
  375.   END;
  376.  
  377. { -------------------------------------------------------------------------- }
  378.  
  379. PROCEDURE OsShell;
  380.   VAR
  381.     OldScr  : WORD;
  382.     OldHz   : WORD;
  383.     OldLMod : BOOLEAN;
  384.     OldVMod : BOOLEAN;
  385.     OldFall : BOOLEAN;
  386.     i       : WORD;
  387.     HeapSize: LONGINT;
  388.   BEGIN
  389.     OldFall       := MyCanFallBack;
  390.     OldScr        := ActiveWindows;
  391.     OldVMod       := VTLoopMod;
  392.     OldLMod       := MyLoopMod;
  393.     OldHz         := DesiredHz;
  394.  
  395.     MyCanFallBack := FALSE;
  396.     VTLoopMod     := TRUE;
  397.     MyLoopMod     := TRUE;
  398.  
  399.     SetNothing;
  400.     QuitaVideoMode43;
  401.     IF DesiredHz > ShellHz THEN
  402.       DesiredHz := ShellHz;
  403.     ChangeSamplingRate(DesiredHz);
  404.  
  405.     HeapSize := Heap.HTotalAvail;
  406.     ShrinkSystemHeap(0);
  407.     SwapVectors;
  408.     Exec(ShellPath, ShellParam);
  409.     SwapVectors;
  410.     ShrinkSystemHeap(HeapSize);
  411.  
  412. {FOR i := 1 TO 50000 DO;}
  413.  
  414.     ChangeSamplingRate(OldHz);
  415.     PoneVideoMode43;
  416.     InitWinF8Demo;
  417.     SetUser(OldScr);
  418.     RefreshMiscInfo(PlayingSong^);
  419.     MyLoopMod   := OldLMod;
  420.     VTLoopMod   := OldVMod;
  421.     MyCanFallBack := OldFall;
  422.   END;
  423.  
  424.  
  425.  
  426. PROCEDURE DoFunk;
  427.   VAR
  428.     f : BOOLEAN;
  429.   BEGIN
  430.     f := NOT Funking;
  431.     IF f THEN
  432.       ASM
  433.  
  434.           MOV     DX,$3D4
  435.  
  436.           MOV     AL,9
  437.           OUT     DX,AL
  438.           INC     DX
  439.           IN      AL,DX
  440.           AND     AL,$BF
  441.           OUT     DX,AL
  442.           DEC     DX
  443.  
  444.           MOV     AL,$11
  445.           OUT     DX,AL
  446.           INC     DX
  447.           IN      AL,DX
  448.           AND     AL,$7F
  449.           OUT     DX,AL
  450.           DEC     DX
  451.  
  452.           MOV     AL,7
  453.           OUT     DX,AL
  454.           INC     DX
  455.           IN      AL,DX
  456.           AND     AL,$EF
  457.           OUT     DX,AL
  458.           DEC     DX
  459.  
  460.           MOV     AL,$18
  461.           MOV     AH,8*10 - 1
  462.           OUT     DX,AX
  463.  
  464.           MOV     AL,f
  465.           MOV     Funking,AL
  466.  
  467.       END
  468.     ELSE
  469.       ASM
  470.  
  471.           MOV     AL,f
  472.           MOV     Funking,AL
  473.  
  474.           MOV     DX,$3D4
  475.  
  476.           MOV     AL,9
  477.           OUT     DX,AL
  478.           INC     DX
  479.           IN      AL,DX
  480.           OR      AL,$40
  481.           OUT     DX,AL
  482.           DEC     DX
  483.  
  484.           MOV     AL,7
  485.           OUT     DX,AL
  486.           INC     DX
  487.           IN      AL,DX
  488.           OR      AL,$10
  489.           OUT     DX,AL
  490.           DEC     DX
  491.  
  492.           MOV     AL,$11
  493.           OUT     DX,AL
  494.           INC     DX
  495.           IN      AL,DX
  496.           OR      AL,$80
  497.           OUT     DX,AL
  498.           DEC     DX
  499.  
  500.       END;
  501.   END;
  502.  
  503. { -------------------------------------------------------------------------- }
  504.  
  505. FUNCTION DoPlayMod(VAR Song: TSong) : BOOLEAN;
  506.   CONST
  507.     BarVals : ARRAY[1..3] OF CHAR = ( '▒', 'ª', 'ÿ' );
  508.     BarIdx  : BYTE = 1;
  509.   VAR
  510.     cr   : CHAR;
  511.     ch,
  512.     LastVol,
  513.     LastHz,
  514.     MyHz,
  515.     i, r : WORD;
  516.     s    : STRING;
  517.   BEGIN
  518.  
  519.     ThereIsNewNote := FALSE;
  520.  
  521.     IF FirstChannel > Song.NumChannels-3 THEN
  522.       FirstChannel := Song.NumChannels-3;
  523.  
  524.     DrawPartiture(Song, 0, 0);
  525.  
  526.     ModTickProc      := TickProc;
  527.     ModTickProcValid := TRUE;
  528.  
  529.     FadingOut := FALSE;
  530.     FadedOut  := FALSE;
  531.  
  532.     FillChar(Sequences, SIZEOF(Sequences), FALSE);
  533.     LastSeq := 255;
  534.  
  535.     FillChar(UserVols, SIZEOF(UserVols), VtVolume);
  536.  
  537.     LastHz := SoundHz;
  538.  
  539. {    VTLoopMod := TRUE;}
  540.  
  541.     FirstPattern := VT1stPattern;
  542.     RepStart     := VTRepStart;
  543.     SongLen      := VTSongLen;
  544.  
  545.     InitPlayData(Song);
  546.     PlayStart(Song);
  547.     ChangeSamplingRate(DesiredHz);
  548.     RefreshMiscInfo(Song);
  549.  
  550.     { Adjust looping flag. }
  551.  
  552. {
  553.     VTLoopMod := MyLoopMod;
  554.     IF (NOT MyLoopMod) AND (Song.SequenceRepStart < Song.SequenceLength) THEN
  555.       MyLoopMod := TRUE;
  556. }
  557.     REPEAT
  558.       ch := 0;
  559.       cr := #0;
  560.       IF KbdKeyPressed THEN BEGIN
  561.         ch := KbdReadKey;
  562.         cr := UPCASE(CHAR(ch));
  563.       END;
  564.  
  565.       CASE ch OF
  566.         kbPgDn: IF NextSeq < Song.SequenceLength THEN BEGIN
  567.                   Sequences[NextSeq]   := TRUE;
  568.                   Sequences[NextSeq+1] := FALSE;
  569.                   INC(NextSeq);
  570.                 END;
  571.         kbPgUp: IF NextSeq > 1 THEN BEGIN
  572.                   Sequences[NextSeq]   := FALSE;
  573.                   Sequences[NextSeq-1] := FALSE;
  574.                   DEC(NextSeq);
  575.                 END;
  576.         kbHome: BEGIN
  577.                   IF (NextNote < 8) AND (NextSeq > 1) THEN
  578.                     BEGIN
  579.                       Sequences[NextSeq]   := FALSE;
  580.                       Sequences[NextSeq-1] := FALSE;
  581.                       DEC(NextSeq);
  582.                     END;
  583.                   NextNote := 1;
  584.                 END;
  585.         kbEnd:  IF NextSeq < Song.SequenceLength THEN BEGIN
  586.                   Sequences[NextSeq]   := TRUE;
  587.                   Sequences[NextSeq+1] := FALSE;
  588.                   INC(NextSeq);
  589.                   NextNote := 1;
  590.                 END;
  591. {
  592.         kbLeft: BEGIN
  593.                   DEC(TicksPerSecond);
  594.                 END;
  595.         kbRight:BEGIN
  596.                   INC(TicksPerSecond);
  597.                 END;
  598. }
  599.         kbLeft: BEGIN
  600.                   IF FirstChannel > 1 THEN
  601.                     BEGIN
  602.                       DEC(FirstChannel);
  603.                       w2ndLine.forz             := TRUE;
  604.                       VTPartitura.PartWin^.forz := TRUE;
  605.                     END;
  606.                 END;
  607.         kbRight:BEGIN
  608.                   IF FirstChannel + 4 <= Song.NumChannels THEN
  609.                     BEGIN
  610.                       INC(FirstChannel);
  611.                       w2ndLine.forz             := TRUE;
  612.                       VTPartitura.PartWin^.forz := TRUE;
  613.                     END;
  614.                 END;
  615.         kbDown: BEGIN
  616.                   IF DMAOffset > 0 THEN
  617.                     BEGIN
  618.                       DEC(DMAOffset);
  619.                       HzChanged := TRUE;
  620.                     END;
  621.                 END;
  622.         kbUp:   BEGIN
  623.                   INC(DMAOffset);
  624.                   HzChanged := TRUE;
  625.                 END;
  626.         kbF5:   SetBig;
  627.         kbF6:   SetSmall_Samples;
  628.         kbF7:   SetSmall_Oscillosc;
  629.         kbF8:   SetCredits;
  630.         kbF9:   DoFunk;
  631.       ELSE
  632.         CASE cr OF
  633.           'L': DoEqualice := NOT DoEqualice;
  634.           'D': OsShell;
  635.           'N': FadingOut := TRUE;
  636.           '1'..'9':
  637.                BEGIN
  638.                  i := BYTE(cr) - BYTE('0');
  639.                  Permisos[i]               := NOT Permisos[i];
  640.                  w2ndLine.forz             := TRUE;
  641.                  VTPartitura.PartWin^.forz := TRUE;
  642.                END;
  643.           '0': BEGIN
  644.                  i := 10;
  645.                  Permisos[i]               := NOT Permisos[i];
  646.                  w2ndLine.forz             := TRUE;
  647.                  VTPartitura.PartWin^.forz := TRUE;
  648.                END;
  649.           'B': BEGIN
  650.                  INC(BarIdx);
  651.                  IF BarIdx > 3 THEN BarIdx := 1;
  652.                  BarVal := BarVals[BarIdx];
  653.                END;
  654.           'F': FilterOn  := TFilterMethod((BYTE(FilterOn)  + 1) MOD FilterMod);
  655.           'G': FilterOff := TFilterMethod((BYTE(FilterOff) + 1) MOD FilterMod);
  656.           'W': IF ModCommands.Tempo > 1 THEN
  657.                  DEC(ModCommands.Tempo);
  658.           'E': IF ModCommands.Tempo < $30 THEN
  659.                  INC(ModCommands.Tempo);
  660.           '+': IF (NOT FadingOut) THEN
  661.                  BEGIN
  662.                    IF (VtVolume < 255-9) THEN
  663.                      INC(VtVolume, 9)
  664.                    ELSE
  665.                      VtVolume := 255;
  666.                    FOR i := 1 TO MaxChannels DO UserVols[i] := VtVolume;
  667.                    RefreshMiscInfo(Song);
  668.                  END;
  669.           '-': IF (NOT FadingOut) THEN
  670.                  BEGIN
  671.                    IF (VtVolume > 9) THEN
  672.                      DEC(VtVolume, 9)
  673.                    ELSE
  674.                      VtVolume := 0;
  675.                    FOR i := 1 TO MaxChannels DO UserVols[i] := VtVolume;
  676.                    RefreshMiscInfo(Song);
  677.                  END;
  678.           'R': BEGIN
  679.                  MyHz := ActualHz;
  680.                  WHILE (MyHz = ActualHz) AND (MyHz <> ActiveDevice^.GetRealFreqProc(0)) DO
  681.                    BEGIN
  682.                      DEC(DesiredHz, 100);
  683.                      MyHz := ActiveDevice^.GetRealFreqProc(DesiredHz);
  684.                    END;
  685.                  ChangeSamplingRate(DesiredHz);
  686.                  RefreshMiscInfo(Song);
  687.                END;
  688.           'T': BEGIN
  689.                  MyHz := ActualHz;
  690.                  WHILE (MyHz = ActualHz) AND (MyHz <> ActiveDevice^.GetRealFreqProc(65535))  DO
  691.                    BEGIN
  692.                      INC(DesiredHz, 100);
  693.                      MyHz := ActiveDevice^.GetRealFreqProc(DesiredHz);
  694.                    END;
  695.                  ChangeSamplingRate(DesiredHz);
  696.                  RefreshMiscInfo(Song);
  697.                END;
  698.           'S': BEGIN
  699.                  Playing := NOT Playing;
  700.                END;
  701.         END;
  702.       END;
  703.  
  704.       IF (SoundHz <> LastHz) OR (UserVols[1] <> LastVol) THEN
  705.         BEGIN
  706.           RefreshMiscInfo(Song);
  707.           LastHz  := SoundHz;
  708.           LastVol := UserVols[1];
  709.         END;
  710.  
  711.       IF ThereIsNewNote THEN
  712.         DrawPartiture(Song, md.NotePlaying, md.SeqPlaying);
  713.  
  714.       PollDevice;
  715.  
  716.     UNTIL (ch = kbESC) OR FadedOut OR NOT Playing;
  717.  
  718.     DoPlayMod := ch = kbESC;
  719.  
  720.     PlayStop;
  721.   END;
  722.  
  723. { -------------------------------------------------------------------------- }
  724.  
  725. VAR
  726.   NoMods : BOOLEAN;
  727.  
  728. FUNCTION DoOneMOD(FName, InsidePath: PathStr) : BOOLEAN; FAR;
  729.   VAR
  730.     Song    : TSong;
  731.     NoMod   : BOOLEAN;
  732. {
  733.     Cmd     : TVTCmdSwitch;
  734. }
  735.     SwName  : PathStr;
  736.     Dir     : DirStr;
  737.     Name    : NameStr;
  738.     Ext     : ExtStr;
  739.   LABEL
  740.     Fin;
  741.   BEGIN
  742.     NoMods := FALSE;
  743.  
  744.     NoMod    := TRUE;
  745.     DoOneMOD := FALSE;
  746.  
  747. {
  748.     Cmd.Init;
  749. }
  750.     Song.Init;
  751.     REPEAT
  752.       Song.SetInsidePath(InsidePath);
  753.  
  754.       IF VT1stPattern <> 0 THEN
  755.         Song.SongStart := VT1stPattern;
  756.  
  757.       IF VTSongLen <> 0 THEN
  758.         Song.SongLen := VTSongLen;
  759.  
  760.       Song.LoadFName(FName);
  761.  
  762.       IF (Song.Status = msOk) OR (Song.Status = msFileTooShort) THEN
  763.         BEGIN
  764.           NoMod := FALSE;
  765. {
  766.           IF Song.GetInsidePath <> '' THEN
  767.             BEGIN
  768.               FSplit(Song.GetInsidePath, Dir, Name, Ext);
  769.               SwName := Name + '.VTO';
  770.               FSplit(FName, Dir, Name, Ext);
  771.               SwName := Dir + SwName;
  772.             END
  773.           ELSE
  774.             BEGIN
  775.               FSplit(FName, Dir, Name, Ext);
  776.               SwName := Dir + Name + '.VTO';
  777.             END;
  778.  
  779.           Cmd.ParseFile(SwName);
  780. }
  781.           InitVTScreens(Song);
  782.           RefreshVTScreens;
  783.  
  784.           IF DoPlayMod(Song) THEN GOTO Fin;
  785.         END;
  786.     UNTIL NOT Song.ThereIsMore;
  787.  
  788.     IF NoMod THEN
  789.       ORROR(Song.GetErrorString + ' [' + FName + ']', FALSE);
  790.  
  791.     DoOneMOD := TRUE;
  792. Fin:
  793.     Song.Done;
  794. {
  795.     Cmd.Done;
  796. }
  797.   END;
  798.  
  799. { -------------------------------------------------------------------------- }
  800.  
  801. CONST
  802.   AppID : STRING[Length(NombreApp) + 2 + Length(Version) + Length(BetaStr)] = NombreApp+' v'+Version+BetaStr;
  803.  
  804. VAR
  805.   Dir     : DirStr;
  806.   Name    : NameStr;
  807.   Ext     : ExtStr;
  808.   p       : POINTER;
  809.   l       : LONGINT;
  810.   s       : STRING;
  811.   i, r    : WORD;
  812. LABEL
  813.   Fin;
  814. BEGIN
  815.  
  816.   { Initialize heaps }
  817.  
  818.   InitHeapVariables;
  819.   InitUmbHeap;
  820.  
  821.  
  822.  
  823.   { Init command line objects }
  824.  
  825.   Cmd.Init;
  826.   SongColl.Init(2, 3);
  827.  
  828.  
  829.  
  830.   { Initialize Song variables }
  831.  
  832.   EmptySong.Init;
  833.  
  834.     
  835.  
  836.   { Set debugging flag. }
  837.  
  838.   Debugging.Debug := FALSE{TRUE};
  839.  
  840.  
  841.  
  842.   { Initialize language file. }
  843.  
  844.   StringsFName := FExpand(StringsFName);
  845.   FSplit(StringsFName, Dir, Name, Ext);
  846.   IF NOT FileExists(StringsFName) THEN
  847.     StringsFName := Name+Ext;
  848.   IF NOT FileExists(StringsFName) THEN
  849.     StringsFName := VTDir+Name+Ext;
  850.  
  851.   IF (NOT FileExists(StringsFName)) OR NOT InitStrings(StringsFName) THEN
  852.     BEGIN
  853.       WriteLn(StdErr, 'VT needs a valid language file to run.');
  854.       WriteLn(StdErr, 'VT necesita un fichero de lenguaje válido para funcionar.');
  855.       EXIT;
  856.     END;
  857.  
  858.  
  859.  
  860.   { Display usage and exit if no parameters. }
  861.  
  862.   IF ParamCount = 0 THEN USAGE;
  863.  
  864.  
  865.  
  866.   { Display Copyright notice. }
  867.  
  868.   WriteLn(AppID, ' (C) 1992-93, VangeliSTeam.');
  869.   WriteLn;
  870.   Write(GetString(StrInitializing));
  871.  
  872.  
  873.  
  874.   { Check for other VT's resident in memory. }
  875.  
  876.   VTResidentCheck(AppID);
  877.  
  878.  
  879.  
  880.   { Initialize Units. SoundDevices MUST be first. }
  881.  
  882.   InitSoundDevices;  Write('o');
  883.   IF NOT InitSwapManager(New(PSwapStream, Init)) THEN
  884.     BEGIN
  885.       DoneSwapManager;
  886.       WriteLn;
  887.       WriteLn;
  888.       WriteLn(GetString(StrSwapNotInit));
  889.       EXIT;
  890.     END;
  891.  
  892.   Write('o');
  893.  
  894.   InitVid43;          Write('o');
  895.   InitModUnit;        Write('o');
  896.   InitModVideoTables; Write('o');
  897.  
  898.  
  899.  
  900.   { Initialize and paint screen. }
  901.  
  902.   SetVTDevice;
  903.   SetVTFreq;
  904.  
  905.   InitVTScreens(EmptySong); WriteLn;
  906.   PoneVideoMode43;
  907.   InitWinF8Demo;
  908.   SetSmall_Samples;
  909.  
  910.   SetOffs(ScrOffset);
  911.  
  912.   OneModProc := DoOneMod;
  913.  
  914.  
  915.  
  916.   { Loop for all MODs. }
  917.  
  918.   NoMods := TRUE;
  919.  
  920.   Cmd.ParseLine(GetDOSCmdLine);
  921.   IF NOT DoSongColl(Cmd.FileDir) THEN GOTO Fin;
  922.  
  923.   IF NoMods THEN
  924.     ORROR(GetString(StrFileNotExist), FALSE);
  925.  
  926.  
  927. Fin:
  928.  
  929.   { Cleanup and finish. }
  930.  
  931.   EndSampling;
  932.   QuitaVideoMode43;
  933.   DoneSwapManager;
  934.  
  935. END.
  936.