Metropoli BBS
VIEWER: mse_tp.pas MODE: TEXT (CP437)
 {──────────────────────────────────────────────────────────────────────────}
 {              Bells, Whistles, and Sound Boards. Version 1.02             }
 {       Copyright (C) 1993-94, Edward Schlunder. All Rights Reserved.      }
 {══════════════════════════════════════════════════════════════════════════}
 { TP_MSE.PAS - Turbo Pascal <-> MSE Interface Unit file.                   }
 {              Requires TPX_MSE.OBJ to compile.                            }
 {              Written by Alex Chalfin (1994)                              }
 {                                                                          }
 {──────────────────────────────────────────────────────────────────────────}

Unit MSE_TP;
{$G+}  { Enable 286 Instructions }

Interface

Type
  { GDM file header Type definition. See DOCs for more details}

  GDMHeaderType = Record     
    IDString     : Longint;    { 'GDM■' = $FE4D4447 }
    SongTitle    : Array[0..31] of Char;
    SongMusician : Array[0..31] of Char;
    EOF          : Array[0..2] of Char;  { DOS EOF marker, 13,10,26 }
    IDString2    : Longint;    { 'GMFS' = $53464D47 }
    FormatMajor  : Byte;
    FormatMinor  : Byte;
    TrackerID    : Word;
    TrackerMajor : Byte;
    TrackerMinor : Byte;
    PanMap       : Array[0..31] of Byte;
    InitVol      : Byte;
    InitTempo    : Byte;
    InitBPM      : Byte;
    MusicFlags   : Word;
    OrderOffset  : Longint;
    NumOrders    : Byte;
    PatternOffset: Longint;
    NumPatterns  : Byte;
    OffsetSamHead: Longint;
    OffsetSamData: Longint;
    NumSamples   : Byte;
    OffsetMessage: Longint;
    MessageLen   : Longint;
    OffsetScrolly: Longint;
    ScrollyLen   : Word;
    OffsetGraph  : Longint;
    GraphLen     : Word;
  End;

Function LoadMSEASM(MSESeg, Ovr, BfSz : Word; Var Base : Word; Var IRQ, DMA : Byte) : Word;
Function LoadMSE(FileName : String; Ovr, BufferSize : Word; Var BaseIO : Word; Var IRQ, DMA : Byte) : Word;
Function StartOutput(Channels, Amp : ShortInt) : Word;
Function MixStatus : Word;
Function MusicStatus : Word;
Function MusicBPM(BPM : Byte) : Byte;
Function MusicTempo(Tempo : Byte) : Byte;
Function MusicOrder(Order : Byte) : Byte;
Function MusicPattern(Pat : Byte) : Byte;
Function MusicRow : Byte;
Function MusicLoop(LoopStatus : Byte) : Byte;
Function MusicVolume(Vol : Byte) : Byte;
Function ChannelPan(Chan, Pan : Byte) : Byte;
Function ChannelVU(Chan, Vu : Byte) : Byte;
Function ChannelVol(Chan, Volume : Byte) : Word;
Function LoadGDM(Handle : Word; FileOfs : Longint; Var Flags : Word; Var GHead) : Word;
Function EmsExist : Boolean;
Function OpenFile(Filename : String) : Word;
Procedure GetChannelTable(Chan : Byte; TSeg, TOff : Word);
Procedure FreeMSE;
Procedure StopOutput;
Procedure MixForground;
Procedure SetAutoMix(Mix : Byte);
Procedure StartMusic;
Procedure StopMusic;
Procedure GetSampleTable(Samp : Byte; TSeg, TOff : Word);
Procedure GetMainScope(Var Left, Right : Word);
Procedure UnloadModule;
Procedure CloseFile(Handle : Word);
Procedure PlaySample(Channel, Sample : Byte; Rate : Word; Volume, Pan : Byte);
Procedure AmigaHertz(Hertz : Longint);

Implementation

Const
  EmmIdCode : Array[0..7] of Char = ('E','M','M','X','X','X','X','0');

{$F+}
{$L TPX_MSE.OBJ}
Function LoadMSEASM(MSESeg, Ovr, BfSz : Word; Var Base : Word; Var IRQ, DMA : Byte) : Word; External;
Function StartOutput(Channels, Amp : ShortInt) : Word; External;
Function MixStatus : Word; External;
Function MusicStatus : Word; External;
Function MusicBPM(BPM : Byte) : Byte; External;
Function MusicTempo(Tempo : Byte) : Byte; External;
Function MusicOrder(Order : Byte) : Byte; External;
Function MusicPattern(Pat : Byte) : Byte; External;
Function MusicRow : Byte; External;
Function MusicLoop(LoopStatus : Byte) : Byte; External;
Function MusicVolume(Vol : Byte) : Byte; External;
Function ChannelPan(Chan, Pan : Byte) : Byte; External;
Function ChannelVU(Chan, Vu : Byte) : Byte; External;
Function ChannelVol(Chan, Volume : Byte) : Word; External;
Function LoadGDM(Handle : Word; FileOfs : Longint; Var Flags : Word; Var GHead) : Word; External;
Procedure FreeMSE; External;
Procedure StopOutput; External;
Procedure MixForground; External;
Procedure SetAutoMix(Mix : Byte); External;
Procedure StartMusic; External;
Procedure StopMusic; External;
Procedure GetChannelTable(Chan : Byte; TSeg, TOff : Word); External;
Procedure GetSampleTable(Samp : Byte; TSeg, TOff : Word); External;
Procedure GetMainScope(Var Left, Right : Word); External;
Procedure UnloadModule; External;
Procedure AmigaHertz(Hertz : Longint); External;
Procedure PlaySample(Channel, Sample : Byte; Rate : Word; Volume, Pan : Byte); External;
{$F-}

Function LoadMSE(FileName : String; Ovr, BufferSize : Word; Var BaseIO : Word; Var IRQ, DMA : Byte) : Word;

Var
  Diskfile : File;   { Binary file }
  Size : Word;       { Size of file }
  MSESeg : Word;     { Segment pointer to MSE memory location }
  P : Pointer;
  ReadIn : Word;     { Number of bytes read in }

Begin
  Assign(Diskfile, FileName);
  {$I-}
  Reset(Diskfile, 1);
  {$I+}
  If IOResult <> 0
    Then Begin
      LoadMSE := 11;       { MSE diskread error, file not found }
      Exit;
    End;
  Size := FileSize(Diskfile);   { Get size of MSE file }
  Asm
    Mov  ah,48h          { Allocate memory for MSE using DOS to }
    Mov  bx,Size         { ensure a segment boundary }
    Shr  bx,4
    Inc  bx
    Int  21h
    Jnc @AllocOK
    Mov  ax,$FFFF        { An error has occured }
   @AllocOK:
    Mov  MSESeg,ax
  End;
  If MSESeg = $FFFF
    Then Begin
      LoadMSE := 9;      { Couldn't allocate memory }
      Exit;
    End;
  P := Ptr(MSESeg, 0); { Create a temporary FAR pointer to allocated memory }
  BlockRead(Diskfile, P^, Size, Readin);
  If Readin <> Size
    Then Begin
      LoadMSE := 11;   { MSE read error }
      Exit;
    End;
  Close(Diskfile);
  LoadMSE := LoadMSEASM(MSESeg, Ovr, BufferSize, BaseIO, IRQ, DMA);
End;

Function OpenFile(Filename : String) : Word;
{ Bypasses TP's file handling routines.        }
{ Uses handles instead of file control blocks. }
{ in : Filename - Name of file to open         }
{ out: $FFFF - Error opening file or file not  }
{       found.                                 }
{      Anything else - File handle             }

Var
  TempP : Pointer;
  Handle : Word;

Begin
  Filename := FileName + #0;   { Make an ASCIIZ string }
  TempP := @Filename;          { Get a pointer to filename }
  Asm
    Push ds
    Lds  dx,TempP
    Inc  dx         { Get past length byte }
    Mov  ax,$3D02
    Int  21h        { Get a file handle using DOS }
    Jnc @OpenOK
    Mov  ax,$FFFF   { An error has occured }
   @OpenOK:
    Pop  ds
    Mov  Handle,ax
  End;
  OpenFile := Handle;
End;

Procedure CloseFile(Handle : Word); Assembler;
{ Closes a file via handle                 }
{ in: Handle - filehandle of file to close }
{ out : nothing                            }

Asm
  Mov  ah,$3E
  Mov  bx,Handle
  Int  21h
End;


Function EmsExist : Boolean; Assembler;
{ Checks to see if EMS memory exists }
{ Returns TRUE/FALSE                 }

Asm
  Xor     ax, ax
  Mov     es, ax
  Mov     bx, 19Eh
  Mov     ax, es:[bx]
  Mov     es, ax
  Mov     cl, 8
  Mov     si, 10
  Xor     bx, bx
 @CmpLoop:
  Mov     al, es:[si]
  Cmp     al, Byte Ptr ds:[EmmIdCode+bx]
  Jne     @EmsNoExist
  Inc     si
  Inc     bx
  Dec     cl
  Jnz     @CmpLoop
 @EmsYesExist:
  Mov     ax, 0FFFFh
  Ret
 @EmsNoExist:
  Xor     ax, ax
End;

End.

[ RETURN TO DIRECTORY ]