 Unit PlayMods;

  interface

   uses
       NewCrt,SysProc,Errors_e;

   type
       MiscData       = array[0..31] of word;
       PointerArray   = array[0..9] of pointer;
   const
       DMASize : word = 4096; {must be a multiple of 8}

   {* loads and initializes module}
   {* check Err_Type after call (see errors_e unit}
   procedure Load_Module(Nom_Module : string);

   {* resets hardware and sets interrupt handler}
   {* must be called first}
   {* check Err_Type after call}
   procedure InitHardware;

   {* closes hardware and frees interrupt line}
   {* must be called at end}
   procedure CloseHardware;

   {* starts module playing}
   procedure Start_Module;

   {* play a sample-type file at C-3,
      check ... to know whether the file
      is if sample type (WAV, XI) }
   procedure Play_WAVE;

   {* self explaining routines ...}
   procedure Pause_Play;
   procedure Continue_Play;

   {* check if module or sample has stopped,
      if it has, the DMA output is halted
      and memory is freed}
   procedure Poll_Stop;

   {* stops module with fade out and frees memory}
   {* call be called anywhere and more than once}
   procedure Stop_Module;

   {* gives module information while playing}
      ArrayOfWord[0]  order
      ArrayOfWord[1]  pattern
      ArrayOfWord[2]  row
      ArrayOfWord[3]  speed
      ArrayOfWord[4]  base tempo
      ArrayOfWord[5]  # of tracks minus 1
      ArrayOfWord[6]  is 1 if module playing
      ArrayOfWord[7]  DMA buffer currently read (0 first half, 1 second half)
      ArrayOfWord[8]  length of order list
      ArrayOfWord[9]  # of patterns
      ArrayOfWord[10] # of instruments
      ArrayOfWord[11] is 1 if module file is truncated
      ArrayOfWord[12] DMA position in current half buffer
      ArrayOfWord[13] unused
      ArrayOfWord[14] is 1 if instruments are truncated to 64KB (EMS or DOS mode}
      ArrayOfWord[15] is 1 if a S3M pattern is corrupted
      ArrayOfWord[16] is 1 if module is an S3M
      ArrayOfWord[17] # of used instruments
      ArrayOfWord[18] # of used patterns
      ArrayOfWord[19] # of instruments in file
      ArrayOfWord[20] is 1 if linear frequency table is used (XM)
      ArrayOfWord[21] # of samples if module is an XM,
                      # of instruments otherwise
   procedure Get_Module_Status(var ArrayOfWord : MiscData);


   {* returns true if the module is currently playing}
   function  Module_Playing:boolean;

   {* gives loaded file informations}
      File_Type identifier string (e.g 'M.K.' for MODs)
      Date_Time date and time of file
      File_Size file size
      Comp_Size computed file size from headers
      Inst_Size total samples size
      Inst_Mem  memory used for samples
      Comp_Patt_Size memory used for patterns
      Patt_Size total total patterns size
   procedure Get_File_Info(var File_Type,Date_Time : string;
   var File_Size,Comp_Size,Inst_Size,Inst_Mem,Comp_Patt_Size,Patt_Size : longint);

   procedure Get_Mem_Info(var MemBeforeMod,MemAfterMod : longint);

   {* returns memory mode used}
      $FF if mode undefined (shouldn't occur}
      1   DOS
      2   DOS/EMS
      3   DOS/XMS-32
      if Mode<>$FF then
        begin
          if 'Windows is present' then
           Mode:=Mode+$FF
          else
          if 'CPU is in virtual 8086 mode' then
           Mode:=-Mode;
        end;
   procedure Get_Mem_Mode(var Mode : integer);

   procedure Get_XMS_Mem(var Before,After : word);
   procedure Get_EMS_Mem(var Before,After : word);

   {* returns pointer to song title string}
   function  Song_Title_Pointer:pointer;

   {* returns instrument string}
   function  Inst_Name_String(Inst : byte):string;

   {* returns true if instrument is valid}
   function  Inst_Defined(Inst : byte):boolean;

   {* returns informations on a track}
       ArrayOfWord_2[0] :=  Panning+64
       ArrayOfWord_2[1] := final volume
       if 'instrument is set on track' then
        ArrayOfWord_2[2] := Instrument number - 1
       else
        ArrayOfWord_2[2] := $FF

       if 'note is set on track' then
        ArrayOfWord_2[3] := Note number - 1
       else
        ArrayOfWord_2[3] :=0

       ArrayOfWord_2[4] := Note number for display
       ArrayOfWord_2[5] := current effect
       ArrayOfWord_2[6] := current effect datum
       ArrayOfWord_2[7] := 1 if sample on track is playing
                           (i.e if it hasn't reached his end}
       ArrayOfWord_2[8] := 1 if track is active
   procedure Get_Track_Status(Track : word;var ArrayOfWord_2 : MiscData);

   {* returns power of signal on track}
   procedure Get_Power(Track : word;var Power : word);

   procedure Get_Time(var TimeStr : string);

   procedure Get_Total_Time(var TimeStr : string);

   {* returns player informations}
      Status[1] := DMA buffer size
      Status[2] := Hardware ouput resolution (16 or 8 bits}
      Status[3] := Output mode
	 {0,3 8-bit stereo, 16-bit mono
	  1   16-bit stereo
	  2   8-bit mono}
       if 'Module is MOD' or 'Module is MTM' then Status[4] := sample frequency for MODs
      else
       if 'Module is 669' then Status[4] := sample frequency for 669s
      {following unused}
      Status[5] := 16384 div Period_Max
      Status[6] := 1 if DMA buffer is signed
   procedure Get_Player_Status(var Status : MiscData);

   {* returns pointers}
        Pointers[0] DMA buffer
        Pointers[1] sample frequency table (array '# of samples' of word)
   procedure Get_Pointers(var Pointers : PointerArray);

   {* sends a pattern break command}
   procedure Break_Pattern;

   {* sets digital low-pass filter}
   procedure Set_Filter(Mode : boolean);

   {* sets oversampling}
   procedure Set_LDI(Mode : boolean);

   {* sets global surround}
   procedure Set_Global_Surround(Mode : boolean);

   {* sets digital low-pass filter depth,
      0-9}
   procedure Set_Iter_Filtre(Iter : byte);

   {* sets digital amplification
      31 gives amplification of 1.0
      max. is 496 = 16.0*31
      Be careful, there's no check on maximum,
      the maximum amplification available is
      the number of tracks divided by 2, e.g,
      for a 16 tracks module, maximum amplification
      is 8.0 times (Ampli_Num = 8.0*31 = 248 )}
   procedure Set_Ampl_Num(Ampli_Num : word);

   procedure Set_Base_Tempo(BaseT : byte);

   {* sets fade out delay in ms}
   procedure Set_Fade_Out_Delay(FO_Delay : word);

   {* returns base tempo}
   function Base_Tempo:byte;

   {* volume routines ...
      Master_Vol max. is 64,
      IT MUST BE SET AT LEAST ONCE}
   procedure Set_Master_Volume(Master_Vol : byte);
   procedure Get_Global_Volume(var Glob_Vol : byte);

   {* sets loop mode}
     0 allowed
     1 forbidden
     2 forced
   procedure Set_Loop_Mode(Loop_Mod : byte);

   procedure Set_Default_Pan(Pan : shortint);

   {* sets panning enabled}
   procedure Set_Pan_Enabled(Enable : boolean);

   {* unused}
   procedure Set_Test_CPU_Load(TestCPU : byte);

   {* returns closest output frequency available with current hardware}
   procedure Adjust_Freq(var Freq : word);

   {* returns CPU load string}
   function  CPU_Load:string;

   {* enter MIDI or PC keyboard input
      MUST be called after module start}
   procedure Set_MIDI_Mode(MIDI_Mode_Input : boolean);

   {* set instrument number on MIDI channel}
   procedure Set_MIDI_Inst(Channel,Inst : byte);

   {* set the number of channels for playback
      useful only with samples in MIDI or
      PC keyboard input mode}
   procedure Set_Channels(Max_Channel : byte);

   {* stop all tracks immediatly}
   procedure Stop_Tracks;

   {* create a WAV file in the 'Write_Path'
      path with the name 'Nom', from a module.
      The module MUST have been loaded before
      with 'Load_Module'}
   procedure Write_Module(Write_Path,Nom : Dir);

   {* don't change those variables}
  var
     DMAIndex           : byte;
     ErrMsg             : string[80];
  const
     Hardware_Init      : word = 0;

  end.
