; GRASP 4 interface to Play/D MIDI Engine         7/8/92
;
; Copyright 1992, Kevin Weiner, All rights reserved.

mfinit:
;
; Test for presence of MIDI player and initialize
;
;    returns 1 if initialized ok, else 0
;

  if !def(m_idnum)                      ; TesSeRact interface variables
    global m_idnum -1                   ;  Play/R id number
    global m_param faralloc(64)         ;  Paramter block
    global m_playrid "Play/R  "         ;  Id string
    global m_tessmpx 0x5453             ;  Tess multiplex id
    global note_on 0x90
    global ctrl_ch 0xb0
    global prog_ch 0xc0
					; mfstatus globals
    global etime 0                      ;   Elapsed time (ms)
    global songcount 0                  ;   Size of play list
    global cursong 0                    ;   Current song in playlist
  endif

  if @m_idnum<0
  ; Multiplex interrupt call to test for Play/R
    int 0x2f,-1,0,0,0,ofs(@m_playrid),0,seg(@m_playrid)
    int 0x2f,@m_tessmpx,0,0,0,ofs(@m_playrid),0,seg(@m_playrid)
    if @ax==0xffff
      set m_idnum @cx                   ; TSR found, cx is tsr id number
      poke @m_param 13                  ; m_param[0] =  13 (set timer mode)
      poke @m_param+1 3                 ; m_param[1] =  3  (mode 3)
      callplayr
      poke @m_param 12                  ; m_param[0] =  12 (reset interface)
      callplayr
      return 1                          ; Init was successful 
    else
      return 0                          ; Not found - return false
    endif
  else
    return 1                            ; Already initialized
  endif


mfload:
;
; Load MIDI file
;
;   mfload <filename>
;
;     returns:  0       Loaded successfully
;               1       File not found
;               2       Not MIDI file format
;               3       Unexpected end of file
;               4       Format not supported
;               5       Track not found
;               6       I/O error reading file
;               7       Not enough memory
;               255     Nothing loaded

  if @m_idnum>=0
    poke @m_param 8                     ; m_param[0]    =  8 (load file)
    set size len(@1)
    set pos 1
    mark @size                          ; m_param[1..size] =  file string
      poke @m_param+@pos asc(mid(@1,@pos,1))
      set pos @pos+1
    loop
    poke @m_param+@pos 0                ; m_param[size+1]  =  0 terminator
    callplayr
    return peek(@m_param)
  endif
  return 255


mfplay:
;
; Start or resume play

  if @m_idnum>=0
    poke @m_param 1                     ; m_param[0] =  1 (play)
    callplayr
  endif
  return


mfpause:
;
; Pause MIDI file play

  if @m_idnum>=0
    poke @m_param 9                     ; m_param[0] =  9 (quiet)
    callplayr
    poke @m_param 0                     ; m_param[0] =  0 (pause)
    callplayr
  endif
  return


mfrewind:
;
; Rewind to beginning of MIDI file and pause

  if @m_idnum>=0
    poke @m_param 3                     ; m_param[0] =  3 (rewind)
    callplayr
  endif
  return


mfsetpos:
;
; Set song position
;
;   mfsetpos <pos>
;
;     <pos> = Song position in milliseconds if positive.
;             Number of milliseconds to fast forward if negative.

  if @m_idnum>=0
    poke @m_param 16                    ; m_param[0] =  16 (set pos)
    set i 1                             ; m_param[1..4] = position
    set ttime @1
    mark 4
      poke @m_param+@i @ttime&0xff
      set ttime @ttime>>8
      set i @i+1
    loop
    callplayr
  endif
  return


mfskip:
;
; Skip to specific song in play list
;
;   mfsetpos <num>
;
;     <num> = Song number in play list.  If beyond last song, skip to 1st.

  if @m_idnum>=0
    poke @m_param 17                    ; m_param[0] = 17 (skip)
    poke @m_param+1 @1                  ; m_param[1] = num
    callplayr
  endif
  return


mfstatus:
;
; Get MIDI file play status
;
;    returns:   0       Paused
;               1       Playing
;               2       Done
;
;    global varibles set:
;       etime = elapsed time of song in milliseconds
;       songcount = size of play list
;       cursong = current song number

  if @m_idnum>=0
    poke @m_param 5                     ; m_param[0] =  5 (play status)
    callplayr
    set pstat peek(@m_param)            ; play status
    set dstat peek(@m_param+1)          ; done status
    set etime 0
    set i 5
    mark 4
      set etime (@etime*256)+peek(@m_param+@i)
      set i @i-1
    loop
    set songcount peek(@m_param+6)
    set cursong peek(@m_param+7)
    if @dstat==1
      return 2                          ; Done = 2
    else
      return @pstat                     ; Playing=1/Paused=0
    endif
  endif
  return 0

mstimer:
;
; Returns current value of millisecond timer
;
;   (Time since driver was loaded)
;

  if @m_idnum>=0
    poke @m_param 25                    ; m_param[0] =  25 (ms time)
    callplayr
    set temp 0
    set i 4                             ; time returned in pos 1-4
    mark 4
      set temp (@temp*256)+peek(@m_param+@i)
      set i @i-1
    loop
    return @temp
  endif
  return 0


mfvolume:
;
; Adjust MIDI file volume
;
;  mfvolume <vol>
;
;    <vol> = -127 to +127  (adjustment to initial volume)
;

  if @m_idnum>=0
    poke @m_param 11                    ; m_param[0] =  11 (rewind)
    poke @m_param+1 @1&0xff             ; vol is 8-bit 2's comp
    callplayr
  endif
  return

midisend:
;
; Send MIDI message
;
;  midiSend <status> <data1> <data2>
;
;    <status> = message + channel  (ex: note on = 0x90 + chan)
;    <data1>  = first data byte, if any
;    <data2>  = second data byte, if any
;

  if @m_idnum>=0
    poke @m_param 21                    ; m_param[0] = 21 (send bytes, short)
    poke @m_param+1 0                   ; m_param[1] = 0  (default device)
    poke @m_param+3 @1                  ; m_param[3] = status byte
    set len 1
    if @2<>""                           ; Add any data bytes
      poke @m_param+4 @2
      set len @len+1
      if @3<>""
	poke @m_param+5 @3
	set len @len+1
      endif
    endif
    poke @m_param+2 @len                ; m_param[2] = message length
    callplayr
  endif
  return

mididev:
;
; Returns default MIDI/sound device type as a 3-character string:
;
;     "MPU"   :   Roland MPU compatible
;     "MFC"   :   IBM PC Music Feature Card
;     "SBM"   :   Sound Blaster MIDI
;     "SBF"   :   Sound Blaster FM Sound
;     "MID"   :   Key MIDIator
;     "ADL"   :   AdLib FM Sound
;     "NUL"   :   No music interface
;

  if @m_idnum>=0
    poke @m_param 26                    ; m_param[0] = 26 (get default dev id)
    callplayr
    if peek(@m_param+1)>0               ; m_param[1] is dev id num
      poke @m_param 20                  ; m_param[0] = 20 (get dev name)
      callplayr
      return chr(peek(@m_param+2))$chr(peek(@m_param+3))$chr(peek(@m_param+4))
    endif
  endif
  return "NUL"
	 
callplayr:
;
; Call MIDI engine with contents of global parameter block m_param 

  if @m_idnum>=0
    set pseg @m_param>>16
    set pofs @m_param&0xffff
    int 0x2f,-1,0x20,@m_idnum,0,0,@pofs,0,@pseg
    int 0x2f,@m_tessmpx,0x20,@m_idnum,0,0,@pofs,0,@pseg
  endif
  return
