
{===========================================================================}
{ Konzept        : DATA BECKERs Sound Blaster Superbuch                     }
{ Prog. PlayVOC2 : Ein Programm zum Abspielen von VOC-Dateien mit komfor-   }
{                  tablen Funktionen wie Anhalten der VOICE-Ausgabe und     }
{                  Filtereinstellung. Dieses Programm benutzt den Treiber   }
{                  CTVDSK.                                                  }
{===========================================================================}
{ Autor          : Arthur Burda                                             }
{ Dateiname      : PLAYVOC2.PAS                                             }
{ entwickelt am  : 12.05.1993                                               }
{ letztes Update : 01.09.1993                                               }
{ Version        : 1.08                                                     }
{ Compiler       : Turbo Pascal 6.0 und hher                               }
{===========================================================================}

PROGRAM PlayVOC2;

{---------------------------------------------------------------------------}
{ Compiler-Schalter                                                         }
{---------------------------------------------------------------------------}

{$D-}                                        { keine Debugger-Informationen }
{$F-}                                             { FAR-Aufrufe nicht ntig }
{$G+}                                                   { 286-Code erzeugen }
{$I-}                                                   { keine I/O-Prfung }
{$R-}                                               { keine Bereichsprfung }
{$S-}                                                  { keine Stackprfung }
{$X+}                    { Behandlung von Funktionen wie Prozeduren mglich }

{$M 16384,131072,655360}       { 16 KB Stack, min. 128 KB Heap, max. 640 KB }

USES CRT, DOS, SBDrv;                 { CRT-, DOS- und SBDrv-Unit einbinden }

CONST

  BufSize = 60*1024;                                          { Puffergráe }

  {-------------------------------------------------------------------------}
  { Tastaturcodes                                                           }
  {-------------------------------------------------------------------------}

  kb_Esc   = #27;
  kb_Space = #32;
  kb_l     = 'l';
  kbL      = 'L';
  kb_r     = 'r';
  kbR      = 'R';
  kb_f     = 'f';

VAR
  VOCName  : String;                                   { Name der VOC-Datei }
  VOCFile  : File;                                      { VOC-Dateivariable }
  VOCBuf   : ^Byte;                             { Zeiger auf den VOC-Puffer }
  Status   : Word;                                    { Status des Treibers }
  VolLeft  : Word;                                { Lautstrke linker Kanal }
  VolRight : Word;                               { Lautstrke rechter Kanal }

{===========================================================================}
{ Prozedur ShowHelp: Hilfe zum Programm auf dem Bildschirm anzeigen.        }
{===========================================================================}
{ Eingabe: keine                                                            }
{ Ausgabe: keine                                                            }
{---------------------------------------------------------------------------}

PROCEDURE ShowHelp;

BEGIN
  WriteLn('Spielt eine VOC-Datei ab ymit komfortablen Funktionen wie '+
    'Anhalten der');
  WriteLn('VOICE-Ausgabe und Filtereinstellung. Das Programm benutzt '+
    'den Treiber');
  WriteLn('CTVDSK.');
  WriteLn;
  WriteLn('Syntax: PLAYVOC2 [Dateiname].VOC');
END;

{===========================================================================}
{ Funktion UpperString: Wandelt einen String beliebiger Lnge in Groá-      }
{                       schreibung um und liefert ihn an den Aufrufer der   }
{                       Funktion zurck.                                    }
{===========================================================================}
{ Eingabe: S = String, der in Groáschreibung umgewandelt werden soll        }
{ Ausgabe: String in Groáschreibung                                         }
{---------------------------------------------------------------------------}

FUNCTION UpperString(S : String) : String;

VAR
  Count : Word;                                                { ein Zhler }
  Upper : String;                  { in Groáschreibung umgewandelter String }

BEGIN
  UpperString := '';
  IF S <> '' THEN                               { Ist S kein leerer String? }
    BEGIN                                          { nein, S ist nicht leer }
      Upper := '';
      FOR Count := 1 TO Length(S) DO                     { String umwandeln }
        Upper := Upper+UpCase(S[Count]);
      UpperString := Upper;                      { neuen String zurckgeben }
    END;
END;

{===========================================================================}
{ Prozedur ShowKeysAndInfo: Zeigt die Tastenbelegung und Informationen wh- }
{                           rend des Abspielvorgangs auf dem Bildschirm an. }
{===========================================================================}
{ Eingabe: keine                                                            }
{ Ausgabe: keine                                                            }
{---------------------------------------------------------------------------}

PROCEDURE ShowKeysAndInfo;

VAR
  Count : Word;                                                { ein Zhler }

BEGIN
  GoToXY(18, 6);
  Write('Tastenbelegung:   [Esc]    VOICE-Ausgabe beenden');
  GoToXY(18, 7);
  Write('                  [Space]  Abspielen anhalten/fortsetzen');
  GoToXY(18, 8);
  Write('                  [f]      Ausgabefilter ein/aus');
  GotoXY(18, 16);
  Write('Info: STATUS -> VOICE-Ausgabe luft');
  GotoXY(18, 17);
  Write('      FILTER -> ein');
  TextColor(LightRed);
  IF NOT (GetBoardType IN [type_SBPro, type_SB16]) THEN
    BEGIN
      GoToXY(34, 8);
      Write('N');
    END;
  GoToXY(18, 24);
  Write('N ');
  TextColor(LightGray);
  Write('Funktion nicht verfgbar');
END;

{===========================================================================}
{ Prozedur HandleOutput: Verwaltet die VOICE-Ausgabe. Es wird permanent die }
{                        Tastatur abgefragt, um auf bestimmte Tasten eine   }
{                        Aktion auszulsen, zum Beispiel Vernderung der    }
{                        Lautstrke.                                        }
{===========================================================================}
{ Eingabe: keine                                                            }
{ Ausgabe: keine                                                            }
{---------------------------------------------------------------------------}

PROCEDURE HandleOutput;

VAR
  Done   : Boolean;          { TRUE, wenn das Abspielen beendet werden soll }
  Pause  : Boolean;                  { TRUE, wenn der Pausenmodus aktiv ist }
  Filter : Boolean;                { TRUE, wenn Eingabefilter eingeschaltet }
  Key    : Char;                                               { Tastencode }

BEGIN
  ClrScr;                                              { Bildschirm lschen }
  WriteLn(' DATA BECKERs Sound Blaster Superbuch  *  PLAYVOC2  *  (c) 1993 '+
    'by Arthur Burda');
  WriteLn('ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ'+
    'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ');
  WriteLn('Name der VOC-Datei: '+VOCName);
  Filter := TRUE;
  IF GetBoardType IN [type_SBPro, type_SB16] THEN      { SB Pro oder SB 16? }
    SendToDriver(1, sbd_SetFilterOnOff, 0, 0, 0, 0);       { ja, Filter ein }
  ShowKeysAndInfo;
  Done := FALSE;
  Pause := FALSE;
  REPEAT                                                  { Schleifenanfang }
    IF KeyPressed THEN                                    { Taste gedrckt? }
      BEGIN                                                            { ja }
        Key := ReadKey;                                 { Tastatur abfragen }
        IF Key = #0 THEN                          { erweiterter Tastencode? }
          Key := ReadKey                   { ja, Tastatur nochmals abfragen }
        ELSE                            { nein, eine normale Taste gedrckt }
          CASE Key OF
            kb_Space :                                { Leertaste bettigt? }
              BEGIN                { VOICE-Ausgabe anhalten bzw. fortsetzen }
                Pause := NOT Pause;
                IF Pause THEN                                   { anhalten? }
                  BEGIN                                                { ja }
                    HaltOutput;
                    GoToXY(34, 16);
                    Write('VOICE-Ausgabe angehalten');
                  END
                ELSE                                                 { nein }
                  BEGIN
                    ContinueOutput;                  { Abspielen fortsetzen }
                    GoToXY(34, 16);
                    Write('VOICE-Ausgabe luft     ');
                  END;
              END;
            kb_Esc :                                      { [Esc] gedrckt? }
              Done := TRUE;                     { ja, VOICE-Ausgabe beenden }
            kb_f :                                          { "f" gedrckt? }
              IF GetBoardType IN [type_SBPro, type_SB16] THEN          { ja }
                BEGIN
                  Filter := NOT Filter;
                  IF Filter THEN                     { Filter ein oder aus? }
                    BEGIN                                             { ein }
                      SendToDriver(1, sbd_SetFilterOnOff, 0, 0, 0, 0);
                      GoToXY(34, 17);
                      Write('ein');
                    END
                  ELSE                                                { aus }
                    BEGIN
                      SendToDriver(1, sbd_SetFilterOnOff, 1, 0, 0, 0);
                      GoToXY(34, 17);
                      Write('aus');
                    END;
                END;
          END;
      END;
    IF Status = 0 THEN                                   { Treiberstatus 0? }
      Done := TRUE;                     { Ja. Die VOC-Datei ist abgespielt. }
  UNTIL Done;                                               { Schleifenende }
END;

{===========================================================================}
{ Prozedur Play: Spielt die VOC-Datei ab.                                   }
{===========================================================================}
{ Eingabe: keine                                                            }
{ Ausgabe: keine                                                            }
{---------------------------------------------------------------------------}

PROCEDURE Play;

VAR
  HandlePtr : ^Word;                           { Zeiger auf VOC-Dateihandle }

BEGIN

  { Basis-Addresse, Interrupt-Nummer und }
  { DMA-Kanal (nur bei SB Pro) setzen    }

  SetBaseAddress(SB_BaseAddress);
  SetInterrupt(SB_Interrupt);
  IF GetBoardType IN [type_SBPro, type_SB16] THEN
    SetDMAChannel(SB_DMAChannel);

  IF DriverInit(BufSize SHR 12) THEN               { Treiber initialisiert? }
    BEGIN                                                              { ja }
      SpeakerOn;                                         { Lautsprecher ein }
      SendToDriver(Ofs(Status), sbd_SetStatusword, 0, Seg(Status), 0, 0);
      HandlePtr := Addr(VOCFile);
      SendToDriver(HandlePtr^, sbd_VoiceOutput, 0, 0, 0, 0);
      HandleOutput;      { Routine zum Verwalten der VOICE-Ausgabe aufrufen }
      SendToDriver(0, sbd_StopInOutput, 0, 0, 0, 0);    { Abspielen beenden }
      DriverEnd;                                       { Treiber abschalten }
      SpeakerOff;                                        { Lautsprecher aus }
    END
  ELSE                                     { Treiber-Initialisierungsfehler }
    BEGIN
      DriverEnd;                                       { Treiber abschalten }
      FreeMem(VOCBuf, BufSize);                      { VOC-Puffer freigeben }
      Close(VOCFile);                                 { VOC-Datei schlieáen }
      WriteLn;
      WriteLn('Fehler: Treiber CTVDSK konnte nicht initialisiert werden.');
      Halt;                                              { Programm beenden }
    END;
END;

{---------------------------------------------------------------------------}
{ Hauptprogramm                                                             }
{---------------------------------------------------------------------------}

VAR
  Result : Integer;                                 { Fehlerstatus-Variable }
  Dir    : DirStr;                              { Verzeichnis der VOC-Datei }
  Name   : NameStr;                   { Name der VOC-Datei ohne Erweiterung }
  Ext    : ExtStr;                                       { Dateierweiterung }

BEGIN
  TextColor(LightGray);                                { Textfarbe hellgrau }
  WriteLn;
  WriteLn('PLAYVOC2  *  Version 1.08  *  (c) 1993 by Arthur Burda');
  WriteLn('ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ'+
    'ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ');
  IF ParamCount = 0 THEN                   { keine Kommandozeilenparameter? }
    BEGIN                 { nein, Fehlermeldung auf dem Bildschirm ausgeben }
      WriteLn;
      WriteLn('Fehler: Keine VOC-Datei zum Abspielen angegeben.');
      Halt;
    END
  ELSE
    IF ParamStr(1) = '/?' THEN                         { Hilfe angefordert? }
      ShowHelp                    { ja, Hilfetext auf dem Bildschirm zeigen }
    ELSE          { keine Hilfe, wahrscheinlich ein VOC-Dateiname angegeben }
      BEGIN
        InitSBDrv;                              { Unit SBDrv initialisieren }
        VOCName := UpperString(ParamStr(1));      { VOC-Dateinamen auslesen }
        FSplit(VOCName, Dir, Name, Ext);          { VOC-Dateinamen zerlegen }
        IF Ext = '' THEN
          VOCName := VOCName+'.VOC';
        Assign(VOCFile, VOCName);              { Datei mit Namen verknpfen }
        Reset(VOCFile, 1);                                   { Datei ffnen }
        Result := IOResult;                         { Fehlerstatus abfragen }
        IF Result = 0 THEN                            { Fehler aufgetreten? }
          BEGIN                                         { nein, also weiter }
            IF Load_CTVDSK = 0 THEN           { Treiber CTVDSK.DRV geladen? }
              BEGIN                                                    { ja }
                GetMem(VOCBuf, BufSize);           { VOC-Puffer reservieren }
                SendToDriver(Ofs(VOCBuf^),               { Puffer festlegen }
                  sbd_SetBuffer, BufSize SHR 12, Seg(VOCBuf^), 0, 0);
                Play;                                    { Sample abspielen }
                FreeMem(VOCBuf, BufSize);                { Puffer freigeben }
                Close(VOCFile);                       { VOC-Datei schlieáen }
                ClrScr;                                { Bildschirm lschen }
              END
            ELSE                         { Treiber CTVDSK.DRV nicht geladen }
              BEGIN                           { Ausgabe einer Fehlermeldung }
                WriteLn;
                WriteLn('Fehler: Treiber CTVDSK.DRV konnte nicht '+
                  'geladen werden.');
                Halt;
              END
          END
        ELSE                      { leider ein Fehler beim ffnen der Datei }
          BEGIN                                    { Fehlermeldung ausgeben }
            WriteLn;
            WriteLn('Fehler: Datei '+VOCName+' konnte nicht geffnet '+
              'werden.');
            Halt;
          END;
      END;
END.
