program SB_16_Mixer;

const
  ReleaseDate = '21.08.1999';

  VolMasterL : Byte = 31;               { Defaults fr den Mixer }
  VolMasterR : Byte = 31;
  VolVoiceL : Byte = 30;
  VolVoiceR : Byte = 30;
  VolMidiL : Byte = 28;
  VolMidiR : Byte = 28;
  VolCdL : Byte = 28;
  VolCdR : Byte = 28;
  VolLineL : Byte = 27;
  VolLineR : Byte = 27;
  VolMic : Byte = 27;
  VolSpeaker : Byte = 27;

  TrebleL : Byte = 10;
  TrebleR : Byte = 10;
  BassL : Byte = 9;
  BassR : Byte = 9;

  InAmpL : Byte = 0;
  InAmpR : Byte = 0;
  OutAmpL : Byte = 0;
  OutAmpR : Byte = 0;

  OutLineL : Byte = 1;
  OutLineR : Byte = 1;
  OutCdL : Byte = 1;
  OutCdR : Byte = 1;
  OutMic : Byte = 1;

  InLMidiL : Byte = 0;
  InLMidiR : Byte = 0;
  InLLineL : Byte = 0;
  InLLineR : Byte = 0;
  InLCdL : Byte = 0;
  InLCdR : Byte = 0;
  InLMic : Byte = 0;
  InRMidiL : Byte = 0;
  InRMidiR : Byte = 0;
  InRLineL : Byte = 0;
  InRLineR : Byte = 0;
  InRCdL : Byte = 0;
  InRCdR : Byte = 0;
  InRMic : Byte = 0;

var
  BasePort : Word;
  MixerIni : String;

{----------------------------------------------------------}

function GetReg (Nr : Byte) : Byte; Assembler;

asm  { GetReg }
  mov dx, BasePort
  add dl, 04h
  mov al, Nr
  out dx, al
  inc dl
  in  al, dx
end; { GetReg }

{----------------------------------------------------------}

procedure SetReg (Nr, Wert : Byte); Assembler;

asm  { SetReg }
  mov dx, BasePort
  add dl, 04h
  mov al, Nr
  out dx, al
  inc dl
  mov al, Wert
  out dx, al
end; { SetReg }

{----------------------------------------------------------}

function ArgSet (Argument : String) : Boolean;

var
  Lauf : Byte;
  Ergebnis : Boolean;

begin { ArgSet }
  Ergebnis := false;
  if (ParamCount <> 0) then begin
    for Lauf := 1 to ParamCount do begin
      if (ParamStr(Lauf) = Argument) then Ergebnis := true;
    end;
  end;
  ArgSet := Ergebnis;
end;  { ArgSet }

{------------------------------------------------}

function ArgNo (Argument : String) : Byte;

var
  Lauf : Byte;
  Ergebnis : Byte;

begin { ArgNo }
  Ergebnis := 0;
  if (ParamCount <> 0) then begin
    for Lauf := 1 to ParamCount do begin
      if (ParamStr(Lauf) = Argument) then Ergebnis := Lauf;
    end;
  end;
  ArgNo := Ergebnis;
end;  { ArgNo }

{------------------------------------------------}

procedure DispRegs;

begin { DispRegs }
  WriteLn('30h Master-Lautst„rke links:    ',GetReg($30) and 248 shr 3:2,'/31 -> ',VolMasterL:2);
  WriteLn('31h Master-Lautst„rke rechts:   ',GetReg($31) and 248 shr 3:2,'/31 -> ',VolMasterR:2);
  WriteLn('32h Voice-Lautst„rke links:     ',GetReg($32) and 248 shr 3:2,'/31 -> ',VolVoiceL:2);
  WriteLn('33h Voice-Lautst„rke rechts:    ',GetReg($33) and 248 shr 3:2,'/31 -> ',VolVoiceR:2);
  WriteLn('34h MIDI-Lautst„rke links:      ',GetReg($34) and 248 shr 3:2,'/31 -> ',VolMidiL:2);
  WriteLn('35h MIDI-Lautst„rke rechts:     ',GetReg($35) and 248 shr 3:2,'/31 -> ',VolMidiR:2);
  WriteLn('36h CD-Lautst„rke links:        ',GetReg($36) and 248 shr 3:2,'/31 -> ',VolCdL:2);
  WriteLn('37h CD-Lautst„rke rechts:       ',GetReg($37) and 248 shr 3:2,'/31 -> ',VolCdR:2);
  WriteLn('38h Line-Lautst„rke links:      ',GetReg($38) and 248 shr 3:2,'/31 -> ',VolLineL:2);
  WriteLn('39h Line-Lautst„rke rechts:     ',GetReg($39) and 248 shr 3:2,'/31 -> ',VolLineR:2);
  WriteLn('39h Mikrofon-Lautst„rke:        ',GetReg($39) and 248 shr 3:2,'/31 -> ',VolMic:2);
  WriteLn('39h PC-Lautsprecher-Lautst„rke: ',GetReg($39) and 248 shr 3:2,'/31 -> ',VolSpeaker:2);

  WriteLn('44h H”hen links:                ',GetReg($44) and 240 shr 4:2,'/15 -> ',TrebleL:2);
  WriteLn('44h H”hen rechts:               ',GetReg($45) and 240 shr 4:2,'/15 -> ',TrebleR:2);
  WriteLn('44h B„sse links:                ',GetReg($46) and 240 shr 4:2,'/15 -> ',BassL:2);
  WriteLn('44h B„sse rechts:               ',GetReg($47) and 240 shr 4:2,'/15 -> ',BassR:2);

  WriteLn('3Fh Eing.-Vorverst„rker links:  ',GetReg($3F) and 192 shr 6:2,'/ 3 -> ',InAmpL:2);
  WriteLn('40h Eing.-Vorverst„rker rechts: ',GetReg($40) and 192 shr 6:2,'/ 3 -> ',InAmpR:2);
  WriteLn('41h Ausg.-Vorverst„rker links:  ',GetReg($41) and 192 shr 6:2,'/ 3 -> ',OutAmpL:2);
  WriteLn('42h Ausg.-Vorverst„rker rechts: ',GetReg($42) and 192 shr 6:2,'/ 3 -> ',OutAmpR:2);
end;  { DispRegs }

{------------------------------------------------}

procedure SetRegs;

begin { SetRegs }
  SetReg($30, GetReg($30) and 7 + VolMasterL shl 3);   { Lautst„rken setzen }
  SetReg($31, GetReg($31) and 7 + VolMasterR shl 3);
  SetReg($32, GetReg($32) and 7 + VolVoiceL shl 3);
  SetReg($33, GetReg($33) and 7 + VolVoiceR shl 3);
  SetReg($34, GetReg($34) and 7 + VolMidiL shl 3);
  SetReg($35, GetReg($35) and 7 + VolMidiR shl 3);
  SetReg($36, GetReg($36) and 7 + VolCdL shl 3);
  SetReg($37, GetReg($37) and 7 + VolCdR shl 3);
  SetReg($38, GetReg($38) and 7 + VolLineL shl 3);
  SetReg($39, GetReg($39) and 7 + VolLineR shl 3);
  SetReg($3A, GetReg($3A) and 7 + VolMic shl 3);
  SetReg($3B, GetReg($3B) and 7 + VolSpeaker shl 3);

  SetReg($44, GetReg($44) and 15 + TrebleL shl 4);  { H”hen / Tiefen setzen }
  SetReg($45, GetReg($45) and 15 + TrebleR shl 4);
  SetReg($46, GetReg($46) and 15 + BassL shl 4);
  SetReg($47, GetReg($47) and 15 + BassR shl 4);

  SetReg($3F, GetReg($3F) and 63 + InAmpL shl 6);    { Vorverst„rker setzen }
  SetReg($40, GetReg($40) and 63 + InAmpR shl 6);
  SetReg($41, GetReg($41) and 63 + OutAmpL shl 6);
  SetReg($42, GetReg($42) and 63 + OutAmpR shl 6);

                                               { Ein-/Ausg„nge freischalten }
  SetReg($3C, GetReg($3C) and 224 + OutLineL shl 4 + OutLineR shl 3 + OutCdL shl 2 + OutCdR shl 1 + OutMic);
  SetReg($3D, GetReg($3D) and 128 +
    InLMidiL shl 6 + InLMidiR shl 5 + InLLineL shl 4 + InLLineR shl 3 +
    InLCdL shl 2 + InLCdR shl 1 + InLMic);
  SetReg($3E, GetReg($3E) and 128 +
    InRMidiL shl 6 + InRMidiR shl 5 + InRLineL shl 4 + InRLineR shl 3 +
    InRCdL shl 2 + InRCdR shl 1 + InRMic);
end;  { SetRegs }

{------------------------------------------------}

procedure DispInfo;

begin { DispInfo }
  WriteLn('  Informationen:',#10#13);
  WriteLn('Dies ist mixer.exe Release ',ReleaseDate,' von Burkart Lingner.');
  WriteLn('Sonst noch Fragen?!');
end;  { DispInfo }

{------------------------------------------------}

procedure DispHelp;

begin { DispHelp }
  WriteLn('  Hilfe:',#10#13);
  WriteLn('-reset                    resettet den Mixer');
  WriteLn('-s                        keine Ausgabe');
  WriteLn('-readonly                 keine Werte„nderung');
  WriteLn('-ro                       s.o.');
  WriteLn('-readini                  liest die Werte aus der Ini-Datei ein');
  WriteLn('-writeini                 schreibt die aktuellen Werte in die Ini-Datei');
  WriteLn('-inifile: [Ini-Datei]     alternative Ini-Datei');
  WriteLn(#10#13,'-h                        Hilfe');
  WriteLn('-help                     Hilfe');
  WriteLn('/?                        Hilfe');
  WriteLn('-info                     Informationen ber mixer.exe');
end;  { DispHelp }

procedure ReadIniFile (Dateiname : String);

var
  IniFile  : Text;
  Zeile    : String;
  Variable : String;
  WertStr  : String;
  Wert     : Byte;
  Error    : Integer;

begin { ReadIniFile }
  {$I-}
  Assign(IniFile, Dateiname);
  Reset(IniFile);
  {$I+}
  if (IOResult = 0) then begin
    repeat
      ReadLn(IniFile, Zeile);
      if (Pos('=', Zeile) > 0) then begin
        Variable := Copy(Zeile, 1, Pos('=', Zeile)-1);
        WertStr := '';
        WertStr := Copy(Zeile, Pos('=', Zeile)+1, Length(Zeile)-Pos('=',Zeile)+1);
        Val(WertStr, Wert, Error);
        if (Error = 0) then begin
          if      (Variable = 'VolMasterL') then VolMasterL := Wert
          else if (Variable = 'VolMasterR') then VolMasterR := Wert
          else if (Variable = 'VolVoiceL') then VolVoiceL := Wert
          else if (Variable = 'VolVoiceR') then VolVoiceR := Wert
          else if (Variable = 'VolMidiL') then VolMidiL := Wert
          else if (Variable = 'VolMidiR') then VolMidiR := Wert
          else if (Variable = 'VolCdL') then VolCdL := Wert
          else if (Variable = 'VolCdR') then VolCdR := Wert
          else if (Variable = 'VolLineL') then VolLineL := Wert
          else if (Variable = 'VolLineR') then VolLineR := Wert
          else if (Variable = 'VolMic') then VolMic := Wert
          else if (Variable = 'VolSpeaker') then VolSpeaker := Wert
          else if (Variable = 'TrebleL') then TrebleL := Wert
          else if (Variable = 'TrebleR') then TrebleR := Wert
          else if (Variable = 'BassL') then BassL := Wert
          else if (Variable = 'BassR') then BassR := Wert
          else if (Variable = 'InAmpL') then InAmpL := Wert
          else if (Variable = 'InAmpR') then InAmpR := Wert
          else if (Variable = 'OutAmpL') then OutAmpL := Wert
          else if (Variable = 'OutAmpR') then OutAmpR := Wert
          else if (Variable = 'OutLineL') then OutLineL := Wert
          else if (Variable = 'OutLineR') then OutLineR := Wert
          else if (Variable = 'OutCdL') then OutCdL := Wert
          else if (Variable = 'OutCdR') then OutCdR := Wert
          else if (Variable = 'OutMic') then OutMic := Wert
          else if (Variable = 'InLMidiL') then InLMidiL := Wert
          else if (Variable = 'InLMidiR') then InLMidiR := Wert
          else if (Variable = 'InLLineL') then InLLineL := Wert
          else if (Variable = 'InLLineR') then InLLineR := Wert
          else if (Variable = 'InLCdL') then InLCdL := Wert
          else if (Variable = 'InLCdR') then InLCdR := Wert
          else if (Variable = 'InLMic') then InLMic := Wert
          else if (Variable = 'InRMidiL') then InRMidiL := Wert
          else if (Variable = 'InRMidiR') then InRMidiR := Wert
          else if (Variable = 'InRLineL') then InRLineL := Wert
          else if (Variable = 'InRLineR') then InRLineR := Wert
          else if (Variable = 'InRCdL') then InRCdL := Wert
          else if (Variable = 'InRCdR') then InRCdR := Wert
          else if (Variable = 'InRMic') then InRMic := Wert
          else WriteLn('Fehler in ',Dateiname,': Ungltige Variable (',Variable,')');
        end else WriteLn('Fehler in ',Dateiname,': Der Variable ',Variable,' wurde keine Zahl zugewiesen (',WertStr,')');
      end else WriteLn('Fehlerhafte Zeile in ',Dateiname,': ',Zeile);
    until (Eof(IniFile));
    Close(IniFile);
  end else WriteLn('Konnte die Datei ',Dateiname,' nicht ”ffnen.');
end;  { ReadIniFile }

{----------------------------------------------------------}

procedure WriteIniFile (Dateiname : String);

var
  IniFile : Text;

begin; { WriteIniFile }
  {$I-}
  Assign(IniFile, Dateiname);
  Rewrite(IniFile);
  {$I+}
  if (IOResult = 0) then begin
    WriteLn(IniFile, 'VolMasterL=',VolMasterL);
    WriteLn(IniFile, 'VolMasterR=',VolMasterR);
    WriteLn(IniFile, 'VolVoiceL=',VolVoiceL);
    WriteLn(IniFile, 'VolVoiceR=',VolVoiceR);
    WriteLn(IniFile, 'VolMidiL=',VolMidiL);
    WriteLn(IniFile, 'VolMidiR=',VolMidiR);
    WriteLn(IniFile, 'VolCdL=',VolCdL);
    WriteLn(IniFile, 'VolCdR=',VolCdR);
    WriteLn(IniFile, 'VolLineL=',VolLineL);
    WriteLn(IniFile, 'VolLineR=',VolLineR);
    WriteLn(IniFile, 'VolMic=',VolMic);
    WriteLn(IniFile, 'VolSpeaker=',VolSpeaker);
    WriteLn(IniFile, 'TrebleL=',TrebleL);
    WriteLn(IniFile, 'TrebleR=',TrebleR);
    WriteLn(IniFile, 'BassL=',BassL);
    WriteLn(IniFile, 'BassR=',BassR);
    WriteLn(IniFile, 'InAmpL=',InAmpL);
    WriteLn(IniFile, 'InAmpR=',InAmpR);
    WriteLn(IniFile, 'OutAmpL=',OutAmpL);
    WriteLn(IniFile, 'OutAmpR=',OutAmpR);
    WriteLn(IniFile, 'OutLineL=',OutLineL);
    WriteLn(IniFile, 'OutLineR=',OutLineR);
    WriteLn(IniFile, 'OutCdL=',OutCdL);
    WriteLn(IniFile, 'OutCdR=',OutCdR);
    WriteLn(IniFile, 'OutMic=',OutMic);
    WriteLn(IniFile, 'InLMidiL=',InLMidiL);
    WriteLn(IniFile, 'InLMidiR=',InLMidiR);
    WriteLn(IniFile, 'InLLineL=',InLLineL);
    WriteLn(IniFile, 'InLLineR=',InLLineR);
    WriteLn(IniFile, 'InLCdL=',InLCdL);
    WriteLn(IniFile, 'InLCdR=',InLCdR);
    WriteLn(IniFile, 'InLMic=',InLMic);
    WriteLn(IniFile, 'InRMidiL=',InRMidiL);
    WriteLn(IniFile, 'InRMidiR=',InRMidiR);
    WriteLn(IniFile, 'InRLineL=',InRLineL);
    WriteLn(IniFile, 'InRLineR=',InRLineR);
    WriteLn(IniFile, 'InRCdL=',InRCdL);
    WriteLn(IniFile, 'InRCdR=',InRCdR);
    WriteLn(IniFile, 'InRMic=',InRMic);
    Close(IniFile);
  end else WriteLn('Konnte die Datei ',Dateiname,' nicht ”ffnen.');
end;   { WriteIniFile }

{***************************************************************************}
{********** Hauptprogramm **************************************************}
{***************************************************************************}

var
  Temp : Byte;

begin { Hauptprogramm }

  BasePort := $0220;
  MixerIni := 'MIXER.INI';

  Temp := ArgNo('-inifile:');
  if (Temp <> 0) then MixerIni := ParamStr(Temp + 1);

  WriteLn(#10#13,'    -*- SB-16-Mixer -*-',#10#13,'    -*-  ',ReleaseDate,' -*-',#10#13);

  if (ArgSet('-help')) or (ArgSet('/?')) or (ArgSet('-h')) then DispHelp else if (ArgSet('-info')) then DispInfo else begin

    if (ArgSet('-writeini')) then WriteIniFile(MixerIni);
    if (ArgSet('-reset')) then SetReg($00, 0);
    if (ArgSet('-readini')) then ReadIniFile(MixerIni);
    if (not ArgSet('-s')) then DispRegs;
    if (not (ArgSet('-readonly') or ArgSet('-ro'))) then SetRegs;

  end;

end.  { Hauptprogramm }