home *** CD-ROM | disk | FTP | other *** search
/ Chip: Special Sound & MIDI / Chip-Special_Sound-und-Midi-auf-dem-PC.bin / midiprog / uplay.asm < prev    next >
Assembly Source File  |  1993-09-27  |  39KB  |  1,548 lines

  1. title UPLAY - (U)ART - SMF1 PLAY Utility
  2. page 64,132
  3. .186
  4.  
  5. ; ----------
  6. ; Allgemeine Definitionen
  7. IS_NOPATCH     equ     1
  8. IS_OCTAVE      equ     2
  9. IS_TEST        equ     4
  10. IS_VERBOSE     equ     8
  11. IS_YAMAHA      equ     16
  12.  
  13. IS_PLAY        equ     32
  14.  
  15. STACKADDR      equ     2000h
  16.  
  17. TRACKNAME      equ     2200h
  18. INSTRNAME      equ     2800h
  19. EVENTS         equ     2e00h
  20. PATCH          equ     2f00h
  21. CHANNEL        equ     3000h
  22. COUNTER        equ     3200h
  23. TRACKFLAGS     equ     3800h
  24.  
  25. TRACKSTART     equ     3a00h
  26. MAX_TRACKS     equ     64
  27.  
  28.          code segment 'code'
  29.          assume cs:code,ds:code,es:code
  30.  
  31.          org 100h
  32.  
  33. start  : jmp   anfang
  34.  
  35. ; -----
  36. ; Texte
  37. msg_hello      db  'UPLAY - Uart Standard MIDI File Type 0/1 Play Utility'
  38.                db  13,10
  39.                db  'Version 1.00 - Copyright (c)  1993  by Andreas Nieden'
  40.                db  13,10,10,0
  41.  
  42. msg_help       db  'Aufruf: UPLAY [-novy] Datei[.MID] ...'
  43. msg_cr         db  13,10,0
  44. msg_fnf        db  'UPLAY: Keine passende(n) Datei(en) gefunden'
  45.                db  13,10,0
  46. msg_nosmf      db  'UPLAY: Keine Standard-Midi Datei (Typ 0/1)'
  47.                db  13,10,0
  48. msg_toomuch    db  'UPLAY: Zuviele Tracks im SMF - ich gebe auf ...'
  49.                db  13,10,0
  50. msg_invtbase   db  'UPLAY: Ungültige Timebase'
  51.                db  13,10,0
  52. msg_invtrack   db  'UPLAY: Ungültige Trackkennung'
  53.                db  13,10,0
  54. msg_invdelta   db  'UPLAY: Ungültiges Timedelta im Track'
  55.                db  13,10,0
  56. msg_trktoolong db  'UPLAY: Aktueller Track zu lang - ich gebe auf ...'
  57.                db  13,10,0
  58. msg_eof        db  'UPLAY: Unexpected EOF'
  59.                db  13,10,0
  60. msg_smfFile    db  'Aktuelle SMF-Datei: ',0
  61. msg_title      db  13,10
  62.                db  'Nr. Trackname               Instrument              Events  Channel Patch'
  63.                db  13,10,0
  64. msg_mult       db  '  MULT',0
  65.  
  66. ; -------
  67. ; General MIDI Mapper
  68. ALIGN 16
  69. gm_map label byte
  70. db 25h,  1             ; 001 Acoustic Grand Piano    - TG33-AP:Piano
  71. db 25h,  1             ; 002 Bright Acoustic Piano   - TG33-AP:Piano
  72. db 25h,  5             ; 003 Electric Grand Piano    - TG33-EP:Pin
  73. db 25h,  7             ; 004 Honky-Tonk              - TG33-EP:Fosta
  74. db 25h,  2             ; 005 Electric Piano 1        - TG33-EP:Malet
  75. db 25h,  6             ; 006 Electric Piano 2        - TG33-EP*NewDX
  76. db 25h, 13             ; 007 Harpsichord             - TG33-KY:Hrpsi
  77. db 25h, 15             ; 008 Clavi                   - TG33-KY:Clavi
  78. db 25h, 14             ; 009 Celesta                 - TG33-KY*Celst
  79. db 25h, 61             ; 010 Glockenspiel            - TG33-PC:Vibes
  80. db 25h, 60             ; 011 Music Box               - TG33-PC:Marim
  81. db 25h, 61             ; 012 Vibraphone              - TG33-PC:Vibes
  82. db 25h, 60             ; 013 Marimba                 - TG33-PC:Marim
  83. db 25h, 60             ; 014 Xylophone               - TG33-PC:Marim
  84. db 25h, 62             ; 015 Tubular Bells           - TG33-PC*Bells
  85. db 25h,  8             ; 016 Dulcimer                - TG33-OR*Gospl
  86. db 25h,  8             ; 017 Drawbar Organ           - TG33-OR*Gospl
  87. db 25h, 11             ; 018 Percussive Organ        - TG33-OR*Perc
  88. db 25h,  9             ; 019 Rock Organ              - TG33-OR*Rock
  89. db 25h, 10             ; 020 Church Organ            - TG33-OR*Pipe
  90. db 25h, 35             ; 021 Reed Organ              - TG33-BR*Reed
  91. db 25h, 12             ; 022 Accordion               - TG33-KY*Squez
  92. db 22h, 37             ; 023 Harmonica               - TG33-SL*Blues
  93. db 25h, 12             ; 024 Tango Accordion         - TG33-KY*Squez
  94. db 25h, 30             ; 025 Acoustic Guitar (Nylon) - TG33-PL*Nylon
  95. db 25h, 27             ; 026 Acoustic Guitar (Steel) - TG33-PL*Foksy
  96. db 25h, 30             ; 027 Electric Guitar (JAZZ ) - TG33-PL*Nylon
  97. db 22h, 32             ; 028 Electric Guitar (Clean) - TG33-SL*Sync
  98. db 22h, 33             ; 029 Electric Guitar         - TG33-SL*VCO
  99. db 25h, 31             ; 030 Overdriven Guitar       - TG33-PL*Dist
  100. db 25h, 31             ; 031 Distortion Guitar       - TG33-PL*Dist
  101. db 25h, 27             ; 032 Guitar harmonics        - TG33-PL*12Str
  102. db 25h, 20             ; 033 Acoustic Bass           - TG33-BA*Pick
  103. db 25h, 24             ; 034 Electric Bass (Finger ) - TG33-BA*Fingr
  104. db 25h, 20             ; 035 Electric Bass (Pick   ) - TG33-BA*Pick
  105. db 25h, 25             ; 036 Fretless Bass           - TG33-BA*Frtls
  106. db 25h, 16             ; 037 Slap Bass 1             - TG33-BA*Slap
  107. db 25h, 16             ; 038 Slap Bass 2             - TG33-BA*Slap
  108. db 25h, 21             ; 039 Synth Bass 1            - TG33-BA*Syn
  109. db 25h, 22             ; 040 Synth Bass 2            - TG33-BA*Rezz
  110. db 20h, 14             ; 041 Violin                  - TG33-ST:Viola
  111. db 25h, 14             ; 042 Viola                   - TG33-ST:Viola
  112. db 25h, 13             ; 043 Cello                   - TG33-ST:Cello
  113. db 25h, 52             ; 044 Contrabass              - TG33-ST*Celst
  114. db 25h, 53             ; 045 Tremolo Strings         - TG33-ST*Exel
  115. db 25h, 51             ; 046 Pizzicato Strings       - TG33-ST:Pizza
  116. db 25h, 14             ; 047 Orchestral Harp         - TG33-KY*Celst
  117. db 20h,  7             ; 048 Timpani                 - TG33-PC*Timpa
  118. db 25h, 49             ; 049 String Ensemble 1       - TG33-ST:Chmbr
  119. db 25h, 49             ; 050 String Ensemble 2       - TG33-ST:Chmbr
  120. db 25h, 54             ; 051 SynthStrings 1          - TG33-ST:Synth
  121. db 25h, 54             ; 052 SynthStrings 2          - TG33-ST:Synth
  122. db 25h, 58             ; 053 Choir Aa's              - TG33-CH:Itopy
  123. db 25h, 56             ; 054 Voice Ooh's             - TG33-CH*Modrn
  124. db 25h, 59             ; 055 Synth Voice             - TG33-CH*Astiz
  125. db 22h, 42             ; 056 Orchestra Hit           - TG33-PC*Hit+
  126. db 25h, 41             ; 057 Trumpet                 - TG33-BR*Trmpt
  127. db 25h, 42             ; 058 Trombone                - TG33-BR*Tromb
  128. db 25h, 42             ; 059 Tuba                    - TG33-BR*Tromb
  129. db 25h, 38             ; 060 Muted Trump             - TG33-BR*Moot
  130. db 25h, 40             ; 061 French Horn             - TG33-BR:FrHrn
  131. db 25h, 33             ; 062 Brass Section           - TG33-BR*Fanfr
  132. db 25h, 36             ; 063 SynthBrass 1            - TG33-BR*Chill
  133. db 25h, 34             ; 064 SynthBrass 2            - TG33-BR*Class
  134. db 25h, 43             ; 065 Soprano Sax             - TG33-WN*Sax
  135. db 25h, 43             ; 066 Alto Sax                - TG33-WN*Sax
  136. db 25h, 43             ; 067 Tenor Sax               - TG33-WN*Sax
  137. db 25h, 43             ; 068 Baritone Sax            - TG33-WN*Sax
  138. db 25h, 45             ; 069 Oboe                    - TG33-WN:Oboe
  139. db 25h, 40             ; 070 Englisch Horn           - TG33-WN:FrHrn
  140. db 25h, 45             ; 071 Bassoon                 - TG33-WN:Oboe
  141. db 25h, 46             ; 072 Clarinet                - TG33-WN:Clart
  142. db 25h, 47             ; 073 Piccolo                 - TG33-WN:Flute
  143. db 25h, 47             ; 074 Flute                   - TG33-WN:Flute
  144. db 22h, 36             ; 075 Recorder                - TG33-SL*Wisul
  145. db 25h, 44             ; 076 Pan Flute               - TG33-WN:Pan
  146. db 25h, 44             ; 077 Blown Bottle            - TG33-WN:Pan
  147. db 25h, 44             ; 078 Shakuhashi              - TG33-WN:Pan
  148. db 22h, 36             ; 079 Whistle                 - TG33-SL:Wisul
  149. db 22h, 36             ; 080 Ocarina                 - TG33-SL:Wisul
  150. db 22h, 33             ; 081 Lead 1 (square)         - TG33-SL:VCO
  151. db 22h, 34             ; 082 Lead 2 (sawtooth)       - TG33-SL:Chic
  152. db 22h, 39             ; 083 Lead 3 (calliope)       - TG33-SL:Super
  153. db 25h, 39             ; 084 Lead 4 (Chiff)          - TG33-BR*Anlog
  154. db 25h, 32             ; 085 Lead 5 (charang)        - TG33-BR*Power
  155. db 25h, 59             ; 086 Lead 6 (voice)          - TG33-CH*Astiz
  156. db 22h, 34             ; 087 Lead 7 (fifths)         - TG33-SL:VCO
  157. db 22h, 39             ; 088 Lead 8 (BASSLead)       - TG33-SL:Super
  158. db 22h, 41             ; 089 Pad 1 (new age)         - TG33-ME*NuAge
  159. db 22h, 13             ; 090 Pad 2 (warm)            - TG33-SP*Quire
  160. db 22h, 14             ; 091 Pad 3 (polysynth)       - TG33-SP*Digit
  161. db 22h, 13             ; 092 Pad 4 (choir)           - TG33-SP:Quire
  162. db 22h, 22             ; 093 Pad 5 (bowed)           - TG33-SC:Decay
  163. db 22h, 46             ; 094 Pad 6 (metallic)        - TG33-ME*Hitch
  164. db 22h, 33             ; 095 Pad 7 (halo)            - TG33-SL:VCO
  165. db 22h, 19             ; 096 Pad 8 (sweep)           - TG33-SC:Sweep
  166. db 22h, 54             ; 097 FX 1 (rain)             - TG33-Neuro
  167. db 22h, 44             ; 098 FX 2 (soundtrack)       - TG33-Astro
  168. db 22h, 25             ; 099 FX 3 (crystal)          - TG33-Bellz
  169. db 22h,  4             ; 100 FX 4 (atmosphere)       - TG33-Ice
  170. db 22h,  7             ; 101 FX 5 (brightness)       - TG33-BrVec
  171. db 22h,  8             ; 102 FX 6 (goblins)          - TG33-Matrx
  172. db 22h,  1             ; 103 FX 7 (echoes)           - TG33-Echo
  173. db 22h,  3             ; 104 FX 8 (scifi)            - TG33-Full
  174. db 22h, 23             ; 105 Sitar                   - TG33-Steel
  175. db 22h, 23             ; 106 Banjo                   - TG33-Steel
  176. db 22h, 23             ; 107 Shamisen                - TG33-Steel
  177. db 22h, 23             ; 108 Koto                    - TG33-Steel
  178. db 22h,  3             ; 109 Kalimba                 - TG33-Full
  179. db 22h, 36             ; 110 Bag Pipe                - TG33-Wisul
  180. db 20h, 14             ; 111 Fiddle                  - TG33-Viola
  181. db 22h, 14             ; 112 Shanai                  - TG33-Viola
  182. db 25h, 63             ; 113 Tinkle Bell             - TG33-Clang
  183. db 22h,  3             ; 114 Agogo                   - TG33-Full
  184. db 22h,  3             ; 115 Steel Drums             - TG33-Full
  185. db 25h, 26             ; 116 Woodblock               - TG33-Wood
  186. db 22h,  3             ; 117 Taiko Drums             - TG33-Full
  187. db 22h,  3             ; 118 Melodic Tom             - TG33-Full
  188. db 22h,  3             ; 119 Synth Drum              - TG33-Full
  189. db 22h,  3             ; 120 Reverse Cymbal          - TG33-Full
  190. db 22h,  9             ; 121 Guitar Fret Noise       - TG33-Gut
  191. db 22h, 53             ; 122 Breath Noise            - TG33-Hades
  192. db 22h, 48             ; 123 Seashore                - TG33-Mount
  193. db 22h, 61             ; 124 BirdTweet               - TG33-Devol
  194. db 22h, 61             ; 125 Telephone Ring          - TG33-Devol
  195. db 22h, 61             ; 126 Helicopter              - TG33-Devol
  196. db 22h, 54             ; 127 Applause                - TG33-Neuro
  197. db 22h, 61             ; 128 Gunshot                 - TG33-Devol
  198.  
  199. ; ---------
  200. ; Variablen
  201. ; Doppelwortvariablen
  202. ALIGN 4
  203. timedelta      dd  0
  204. oldvec08       dd  0
  205.  
  206. ; -------------
  207. ; Wortvariablen
  208. trackseg       dw  MAX_TRACKS dup (0)  ; Segmente der Tracks
  209. trackaddr      dw  MAX_TRACKS dup (0)  ; Trackadressen
  210. stellen        dw  8
  211. fileaddr       dw  0
  212. shandle        dw  0
  213. tracks         dw  0                   ; Anzahl der Gesamttracks
  214. atracks        dw  0                   ; Aktive Tracks
  215. tracklen       dw  0                   ; Länge des Aktuellen Tracks
  216. timebase       dw  0                   ; Timebase des SMF's
  217. tempo          dw  120                 ; Current Tempo
  218. org_cnt        dw  0
  219. int_cnt        dw  0
  220. save_bx        dw  0
  221.  
  222. ; -------------
  223. ; Bytevariablen
  224. u2flag         db  0
  225.  
  226. ; -------------
  227. ; Textvariablen
  228. smf_ext        db  '.MID',0
  229. drums          db  0b9h, 0,0, 0b9h, 20h, 22h, 0c9h, 62
  230. options        db  'NOTVY',0
  231.  
  232. ; ---------
  233. ; Utilities
  234. ALIGN 16
  235. ; ------
  236. ; timint - Clock Interupt Routine
  237. timint : test  cs:u2flag,IS_PLAY
  238.          jnz   timi10
  239.  
  240. tim_far  proc  far
  241.          jmp   cs:oldvec08
  242. tim_far  endp
  243.  
  244. timi10 : push  ax
  245.          pusha
  246.          push  ds
  247.          push  es
  248.  
  249.          mov   ax,cs
  250.          mov   ds,ax
  251.          mov   es,ax
  252.          cld
  253. timi20 : call  tmain
  254.  
  255. timi30 : pop   es
  256.          pop   ds
  257.          popa
  258.  
  259. timi40 : inc   cs:int_cnt
  260.          mov   ax,cs:int_cnt
  261.          cmp   ax,cs:org_cnt
  262.          jb    timi50
  263.  
  264.          mov   cs:int_cnt,0
  265.  
  266.          pop   ax
  267.          jmp   short tim_far
  268.  
  269. timi50 : mov   al,20h
  270.          out   20h,al
  271.          pop   ax
  272.          iret
  273.  
  274. ; -------
  275. ; timiset - Setzt den Timer auf das neue Tempo
  276. timiset: pushf
  277.          push  bx
  278.          push  dx
  279.          cli
  280.          mov   al,36h
  281.          out   43h,al
  282.          mov   bx,tempo
  283.          shl   bx,1
  284.          mov   ax,34dch
  285.          mov   dx,12h
  286.          div   bx
  287.          push  ax
  288.          out   40h,al
  289.          mov   al,ah
  290.          out   40h,al
  291.          pop   bx
  292.          xor   ax,ax
  293.          mov   dx,1
  294.          div   bx
  295.          mov   org_cnt,ax
  296.          mov   int_cnt,0
  297.          pop   dx
  298.          pop   bx
  299.          popf
  300.          ret
  301.  
  302. ; -------
  303. ; timrest - Zurücksetzen Real Time Clock + Interrupts
  304.  
  305. timrest: push  ds
  306.          lds   dx,oldvec08
  307.          mov   ax,2508h
  308.          int   21h
  309.          pop   ds
  310.          cli
  311.          mov   al,36h
  312.          out   43h,al
  313.          xor   ax,ax
  314.          out   40h,al
  315.          mov   al,ah
  316.          out   40h,al
  317.          sti
  318.          call  settimer
  319.          ret
  320.  
  321. ; ------
  322. ; rtimer
  323.  
  324. rtimer : pushf
  325.          cli
  326.          push  dx
  327.          mov   dx,70h
  328.          out   dx,al
  329.          inc   dx
  330.          in    al,dx
  331.          pop   dx
  332.          popf
  333.          ret
  334.  
  335. bcd    : mov    bl,al
  336.          shr    al,1
  337.          shr    al,1
  338.          shr    al,1
  339.          shr    al,1
  340.          mov    ah,0ah
  341.          mul    ah
  342.          and    bl,0fh
  343.          add    al,bl
  344.          ret
  345.  
  346. settimer:mov    al,4
  347.          call   rtimer
  348.          call   bcd
  349.          mov    ch,al
  350.          mov    al,2
  351.          call   rtimer
  352.          call   bcd
  353.          mov    cl,al
  354.          mov    al,0
  355.          call   rtimer
  356.          call   bcd
  357.          mov    dh,al
  358.          mov    dl,0
  359.          mov    ah,2dh
  360.          int    21h
  361.          ret
  362.  
  363. ; -------
  364. ; wstring
  365.  
  366. wstring: push  ax
  367.          push  si
  368. wstr100: lodsb
  369.          or    al,al
  370.          jz    wstr200
  371.          call  wchar
  372.          jmp   short wstr100
  373. wstr200: pop   si
  374.          pop   ax
  375.          ret
  376.  
  377. wchar  : push  ax
  378.          push  dx
  379.          mov   dl,al
  380.          mov   ah,2
  381.          int   21h
  382.          pop   dx
  383.          pop   ax
  384.          ret
  385.  
  386. ; ------
  387. ; werror
  388.  
  389. werror : push  bx
  390.          push  cx
  391.          push  si
  392.          xor   cx,cx
  393.          mov   dx,si
  394.  
  395. werr10 : lodsb
  396.          or    al,al
  397.          jz    werr20
  398.          inc   cx
  399.          jmp   short werr10
  400.  
  401. werr20 : mov   ax,4000h
  402.          mov   bx,2
  403.          int   21h
  404.          pop   si
  405.          pop   cx
  406.          pop   bx
  407.          ret
  408.  
  409. dz     : push  ax
  410.          push  bx
  411.          push  cx
  412.          push  dx
  413.          xor   cx,cx
  414. de100  : call  dv
  415.          push  bx
  416.          inc   cx
  417.          or    ax,ax
  418.          jnz   de100
  419.          or    dx,dx
  420.          jnz   de100
  421.          mov   bx,stellen
  422. de200  : cmp   bx,cx
  423.          jz    de300
  424.          mov   al,' '
  425.          call  wchar
  426.          dec   bx
  427.          jmp   short de200
  428. de300  : pop   ax
  429.          or    al,'0'
  430.          call  wchar
  431.          loop  de300
  432.          pop   dx
  433.          pop   cx
  434.          pop   bx
  435.          pop   ax
  436.          ret
  437.  
  438. dv     : push  cx
  439.          xor   bx,bx
  440.          mov   cx,20h
  441. dv10   : shl   ax,1
  442.          rcl   dx,1
  443.          rcl   bx,1
  444.          sub   bx,10
  445.          jnb   dv20
  446.          add   bx,10
  447.          add   ax,1
  448.          adc   dx,0
  449. dv20   : loop  dv10
  450.          not   ax
  451.          not   dx
  452.          pop   cx
  453.          ret
  454.  
  455. toupper: cmp   al,'a'
  456.          jb    tou_ex
  457.          cmp   al,'z'
  458.          ja    tou_ex
  459.          and   al,not 32
  460. tou_ex : ret
  461.  
  462. hexw   : xchg  al,ah
  463.          call  hexb
  464.          xchg  al,ah
  465.  
  466. hexb   : push  ax
  467.          push  cx
  468.          mov   ah,al
  469.          mov   cl,4
  470.          shr   al,cl
  471.          call  hexb500
  472.          mov   al,ah
  473.          and   al,15
  474.          call  hexb500
  475.          pop   cx
  476.          pop   ax
  477.          ret
  478.  
  479. hexb500: add   al,'0'
  480.          cmp   al,'9'
  481.          jbe   hexb600
  482.          add   al,7
  483. hexb600: call  wchar
  484.          ret
  485.  
  486. ; -----
  487. ; ludiv - Long Unsigned Division
  488. ; Eingabe: Dividend in AX:DX
  489. ;          Divisor  in CX:BX
  490. ; Ausgabe: Quotient in AX:DX
  491. ;          Rest     in CX:BX
  492.  
  493. ludiv  : test  bx,bx
  494.          jnz   lud200
  495.          cmp   cx,dx
  496.          ja    lud100
  497.          push  ax
  498.          mov   ax,dx
  499.          sub   dx,dx
  500.          div   cx
  501.          mov   bx,ax
  502.          pop   ax
  503.          div   cx
  504.          mov   cx,dx
  505.          mov   dx,bx
  506.          sub   bx,bx
  507.          ret
  508.  
  509. lud100 : div   cx
  510.          mov   cx,dx
  511.          mov   dx,bx
  512.          ret
  513.  
  514. lud200 : push  bp
  515.          push  di
  516.          push  si
  517.          mov   si,cx
  518.          mov   di,bx
  519.          sub   bx,bx
  520.          sub   bp,bp
  521.          mov   cx,32
  522.  
  523. lud220 : shl   ax,1
  524.          rcl   dx,1
  525.          rcl   bp,1
  526.          rcl   bx,1
  527.          sub   bp,si
  528.          sbb   bx,di
  529.          js    lud280
  530.  
  531. lud240 : inc   ax
  532.          loop  lud220
  533.          jmp   short lud300
  534.  
  535. lud260 : shl   ax,1
  536.          rcl   dx,1
  537.          rcl   bp,1
  538.          rcl   bx,1
  539.          add   bp,si
  540.          adc   bx,di
  541.          jns   lud240
  542.  
  543. lud280 : loop  lud260
  544.          add   bp,si
  545.          adc   bx,di
  546.  
  547. lud300 : mov   cx,bp
  548.          pop   si
  549.          pop   di
  550.          pop   bp
  551.          ret
  552.  
  553. ; -----
  554. ; wtick - Wartet für einen Timertick ...
  555. wtick  : push  ax
  556.          push  bx
  557.          push  cx
  558.          push  dx
  559.          sti
  560.          xor   ax,ax
  561.          int   1ah
  562.          mov   bx,dx
  563. wtick10: xor   ax,ax
  564.          int   1ah
  565.          cmp   dx,bx
  566.          jz    wtick10
  567.          pop   dx
  568.          pop   cx
  569.          pop   bx
  570.          pop   ax
  571.          ret
  572.  
  573. ; ------
  574. ; alloff - ALL OFF über ACK !
  575. alloff : mov   al,0feh
  576.          call  put_midi
  577.  
  578.          mov   cx,24
  579. alloff10:call  wtick
  580.          loop  alloff10
  581.  
  582.          mov   cx,16
  583.          mov   ah,0
  584.  
  585. alloff20:mov   al,0b0h
  586.          or    al,ah
  587.          call  put_midi
  588.          mov   al,79h
  589.          call  put_midi
  590.          mov   al,0
  591.          call  put_midi
  592.          inc   ah
  593.          loop  alloff20
  594.  
  595.          ret
  596.  
  597. ; -------
  598. ; waitrcv Wait For MPU Receive Ready
  599. waitrcv: push  ax
  600.          push  dx
  601.          mov   dx,0331h
  602.  
  603. waitr10: in    al,dx
  604.          test  al,40h
  605.          jnz   waitr10
  606.  
  607.          pop   dx
  608.          pop   ax
  609.          ret
  610.  
  611. ; --------
  612. ; put_midi Ausgabe eines MidiBytes
  613. put_midi:push  ax
  614.          push  dx
  615.          call  waitrcv
  616.  
  617.          mov   dx,0330h
  618.          pushf
  619.          cli
  620.          out   dx,al
  621.          popf
  622.  
  623.          pop   dx
  624.          pop   ax
  625.          ret
  626.  
  627. ; -------
  628. ; put_cmd Ausgabe eines MPU-Kommandos
  629. put_cmd: push  ax
  630.          push  cx
  631.          push  dx
  632.  
  633.          call  waitrcv
  634.  
  635.          pushf
  636.          cli
  637.          mov   dx,0331h
  638.          out   dx,al
  639.          mov   cx,4000h
  640.  
  641. put_c20: in    al,dx
  642.          test  al,80h
  643.          jz    put_c30
  644.          loop  put_c20
  645.  
  646.          mov   ax,0e07h
  647.          int   10h
  648.          jmp   ende
  649.  
  650. put_c30: dec   dx
  651.          in    al,dx
  652.          inc   dx
  653.          cmp   al,0feh
  654.          jnz   put_c20
  655.  
  656. put_c90: popf
  657.          pop   dx
  658.          pop   cx
  659.          pop   ax
  660.          ret
  661.  
  662. ; -------
  663. ; resetmpu Reset MPU
  664. resetmpu:push  ax
  665.          push  dx
  666.          call  waitrcv
  667.  
  668.          pushf
  669.          cli
  670.          mov   dx,0331h
  671.          mov   al,0ffh
  672.          out   dx,al
  673.  
  674.          call  waitrcv
  675.          dec   dx
  676.          in    al,dx
  677.          popf
  678.  
  679.          pop   dx
  680.          pop   ax
  681.          ret
  682.  
  683. ; -------
  684. ; parscmd - Die Kommandozeile untersuchen
  685.  
  686. parscmd: lea   si,msg_hello
  687.          call  werror
  688.          mov   si,80h
  689.          lodsw
  690.          or    al,al
  691.          jnz   pars100
  692.  
  693. helpexit:lea   si,msg_help
  694.  
  695. err_exit:call  werror
  696.          mov   al,1
  697.          jmp   ende
  698.  
  699. pars100: call  pars500
  700.          jb    helpexit
  701.  
  702.          cmp   byte ptr [si],'-'
  703.          jz    pars120
  704.          cmp   byte ptr [si],'/'
  705.          jnz   pars200
  706.  
  707. pars120: lodsw
  708.          mov   al,ah
  709. pars130: call  toupper
  710.          lea   di,options
  711.          mov   bl,1
  712.  
  713. pars140: cmp   byte ptr [di],0
  714.          jz    helpexit
  715.          scasb
  716.          jz    pars160
  717.          shl   bl,1
  718.          jmp   short pars140
  719.  
  720. pars160: or    u2flag,bl
  721.          cmp   byte ptr [si],' '
  722.          jz    pars100
  723.          cmp   byte ptr [si],9
  724.          jz    pars100
  725.          cmp   byte ptr [si],13
  726.          jz    helpexit
  727.          lodsb
  728.          jmp   short pars130
  729.  
  730. pars200: lea   di,filename
  731.          mov   fileaddr,di
  732.  
  733.          mov   bl,0            ; BL kennzeichnet "."
  734. pars220: lodsb
  735.          cmp   al,13
  736.          jz    pars300
  737.  
  738.          cmp   al,'.'
  739.          jnz   pars240
  740.          inc   bl
  741.  
  742. pars240: call  toupper
  743.          stosb
  744.  
  745.          cmp   al,'\'
  746.          jz    pars260
  747.          cmp   al,':'
  748.          jnz   pars220
  749. pars260: mov   fileaddr,di
  750.          jmp   short pars220
  751.  
  752. pars300: or    bl,bl
  753.          jnz   pars320
  754.  
  755.          lea   si,smf_ext
  756.          mov   cx,5
  757.          rep   movsb
  758.          ret
  759.  
  760. pars320: mov   al,0
  761.          stosb
  762.          ret
  763.  
  764. pars500: cmp   byte ptr [si],' '
  765.          jz    pars540
  766.          cmp   byte ptr [si],9
  767.          jz    pars540
  768.          cmp   byte ptr [si],13
  769.          jnz   pars520
  770.          stc
  771.          ret
  772.  
  773. pars520: clc
  774.          ret
  775.  
  776. pars540: inc   si
  777.          jmp   short pars500
  778.  
  779. ; --------
  780. ; getdelta - Liest Timedelta nach AX:DX
  781. getdelta:push  bx
  782.          push  cx
  783.          push  di
  784.  
  785.          xor   ax,ax
  786.          xor   dx,dx
  787.          mov   di,4
  788.  
  789. getdel10:mov   cx,7
  790. getdel20:shl   ax,1
  791.          rcl   dx,1
  792.          loop  getdel20
  793.  
  794.          mov   cl,[si]
  795.          inc   si
  796.  
  797.          mov   bl,cl
  798.          and   cx,07fh
  799.          add   ax,cx
  800.          adc   dx,0
  801.          test  bl,80h
  802.          jz    getdelex
  803.  
  804.          dec   di
  805.          jnz   getdel10
  806.  
  807.          mov   ax,si
  808.          call  hexw
  809.  
  810.          mov   ax,cs
  811.          mov   ds,ax
  812.          lea   si,msg_invdelta
  813.          jmp   err_exit
  814.  
  815. getdelex:pop   di
  816.          pop   cx
  817.          pop   bx
  818.          ret
  819.  
  820. ; --------
  821. ; getxdelt - Liest Timedelta nach AX:DX
  822. getxdelt:push  bx
  823.          push  cx
  824.  
  825.          xor   ax,ax
  826.          xor   dx,dx
  827.  
  828. getxdel1:mov   cx,7
  829. getxdel2:shl   ax,1
  830.          rcl   dx,1
  831.          loop  getxdel2
  832.  
  833.          push  bx
  834.          push  ax
  835.          call  getbyte
  836.          mov   cl,al
  837.          pop   ax
  838.  
  839.          mov   bl,cl
  840.          and   cx,07fh
  841.          add   ax,cx
  842.          adc   dx,0
  843.          test  bl,80h
  844.          pop   bx
  845.          jnz   getxdel1
  846.  
  847.          pop   cx
  848.          pop   bx
  849.          ret
  850.  
  851. ; -------
  852. ; getbyte
  853. getbyte: push  bx
  854.          push  si
  855.          push  ds
  856.          shl   bx,1
  857.          mov   si,trackaddr[bx]
  858.          mov   ds,trackseg [bx]
  859.          lodsb
  860.          pop   ds
  861.          mov   trackaddr[bx],si
  862.          pop   si
  863.          pop   bx
  864.          ret
  865.  
  866. ; --------
  867. ; loadfile - Lädt und überprüft SMF-Datei
  868. loadfile:mov   di,TRACKNAME
  869.          xor   ax,ax
  870.          mov   cx,TRACKSTART
  871.          sub   cx,di
  872.          rep   stosb
  873.  
  874.          mov   ax,3f00h
  875.          mov   bx,shandle
  876.          mov   cx,14
  877.          mov   dx,STACKADDR
  878.          int   21h
  879.          mov   si,dx
  880.          lodsw
  881.          cmp   ax,'TM'
  882.          jz    loadf100
  883.  
  884. nosmf  : lea   si,msg_nosmf
  885.          jmp   err_exit
  886.  
  887. loadf100:lodsw
  888.          cmp   ax,'dh'
  889.          jnz   nosmf
  890.          lodsw
  891.          or    ax,ax
  892.          jnz   nosmf
  893.          lodsw
  894.          xchg  al,ah
  895.          cmp   al,6
  896.          jnz   nosmf
  897.  
  898.          lodsw
  899.          xchg  al,ah
  900.          cmp   ax,1
  901.          ja    nosmf           ; Typ muss 0 oder 1 sein
  902.  
  903.          lodsw                 ; Anzahl der Tracks
  904.          xchg  al,ah
  905.          mov   tracks,ax
  906.          cmp   ax,MAX_TRACKS
  907.          jb    loadf120
  908.  
  909.          lea   si,msg_toomuch
  910.          jmp   err_exit
  911.  
  912. loadf120:lodsw
  913.          xchg  al,ah
  914.          push  ax
  915.          mov   bx,24
  916.          xor   dx,dx
  917.          div   bx
  918.          or    ax,ax
  919.          jnz   loadf140
  920.  
  921.          lea   si,msg_invtbase
  922.          jmp   err_exit
  923.  
  924. loadf140:pop   ax
  925.          mov   timebase,ax
  926.  
  927.          mov   ax,cs
  928.          mov   bx,TRACKSTART
  929.          shr   bx,4
  930.          add   ax,bx
  931.  
  932.          mov   word ptr trackseg,ax
  933.          mov   atracks,0
  934.  
  935. ; -------
  936. ; nachdem der Header abgehandelt ist, werden jetzt die Tracks eingelesen!
  937. loadf200:mov   ax,3f00h
  938.          mov   bx,shandle
  939.          mov   cx,8
  940.          mov   dx,STACKADDR
  941.          int   21h
  942.          mov   si,dx
  943.          lodsw
  944.          cmp   ax,'TM'
  945.          jz    loadf220
  946.  
  947. invtrack:lea   si,msg_invtrack
  948.          jmp   err_exit
  949.  
  950. loadf220:lodsw
  951.          cmp   ax,'kr'
  952.          jnz   invtrack
  953.          lodsw
  954.          or    ax,ax
  955.          jz    loadf240
  956.  
  957. toolong: lea   si,msg_trktoolong
  958.          jmp   err_exit
  959.  
  960. loadf240:lodsw
  961.          xchg  al,ah
  962.          mov   tracklen,ax
  963.          cmp   ax,0fff0h
  964.          ja    toolong
  965.  
  966.          mov   bx,atracks
  967.          shl   bx,1
  968.  
  969.          add   ax,15
  970.          shr   ax,4
  971.          add   ax,trackseg[bx]
  972.  
  973.          mov   trackseg[bx+2],ax
  974.          ; Startsegment des nächsten Tracks ermitteln
  975.  
  976.          mov   word ptr trackaddr[bx],0
  977.  
  978.          push  ds
  979.          mov   ds,trackseg[bx]
  980.          mov   ax,3f00h
  981.          mov   bx,cs:shandle
  982.          mov   cx,cs:tracklen
  983.          xor   dx,dx
  984.          int   21h
  985.  
  986.          cmp   ax,cx
  987.          jz    loadf260
  988.  
  989.          mov   ax,cs
  990.          mov   ds,ax
  991.          lea   si,msg_eof
  992.          jmp   err_exit
  993.  
  994. loadf260:xor   si,si
  995.  
  996. ; ----
  997. ; Hier wird der Track schlicht überprüft!
  998. loadf300:call  getdelta        ; Timedelta nach ax:dx
  999.  
  1000.          mov   bx,cs:atracks
  1001.          shl   bx,2
  1002.          add   word ptr cs:[bx+EVENTS],1
  1003.          adc   word ptr cs:[bx+EVENTS+2],0
  1004.  
  1005.          lodsb                 ; Event nach AL einlesen
  1006.          cmp   al,0ffh         ; META Event ?
  1007.          jnz   loadf400        ; nein, weitermachen
  1008.  
  1009. ; ------------
  1010. ; Hier beginnt die Abhandlung der von uns unterstützten META Events
  1011.          lodsb                 ; EVENT nach AL
  1012.          cmp   al,3            ; Trackname (?)
  1013.          jnz   loadf320        ; nein, weitersuchen
  1014.  
  1015.          lodsb
  1016.          mov   ah,0
  1017.          mov   cx,ax           ; Länge nach CX
  1018.          mov   di,cs:atracks   ; Welcher Track ist aktuell (?)
  1019.          shl   di,5            ; * 32
  1020.          add   di,TRACKNAME    ; + Adresse TRACKNAME
  1021.          xor   bx,bx
  1022. loadf304:movsb
  1023.          inc   bx
  1024.          cmp   bx,32
  1025.          jz    loadf306
  1026.          loop  loadf304
  1027.  
  1028. loadf306:mov   al,0
  1029.          stosb
  1030.          jcxz  loadf310
  1031.  
  1032. loadf308:lodsb
  1033.          loop  loadf308
  1034.  
  1035. loadf310:jmp   loadf300
  1036.  
  1037. loadf320:cmp   al,4            ; Instrname (?)
  1038.          jnz   loadf340        ; nein, weitersuchen
  1039.  
  1040.          lodsb
  1041.          mov   ah,0
  1042.          mov   cx,ax           ; Länge nach CX
  1043.          mov   di,cs:atracks   ; Welcher Track ist aktuell (?)
  1044.          shl   di,5            ; * 32
  1045.          add   di,INSTRNAME    ; + Adresse INSTRNAME
  1046.          xor   bx,bx
  1047. loadf324:movsb
  1048.          inc   bx
  1049.          cmp   bx,32
  1050.          jz    loadf326
  1051.          loop  loadf324
  1052.  
  1053. loadf326:mov   al,0
  1054.          stosb
  1055.          jcxz  loadf330
  1056.  
  1057. loadf328:lodsb
  1058.          loop  loadf328
  1059.  
  1060. loadf330:jmp   loadf300
  1061.  
  1062. loadf340:cmp   al,2fh          ; End Of Track (?)
  1063.          jnz   loadf360
  1064.          jmp   loadf900        ; Abbrechen und unten weitermachen!
  1065.  
  1066. ; ---------------
  1067. ; Uninteressanter META-Event - überlesen!
  1068. loadf360:lodsb                 ; Länge nach AL
  1069.          mov   ah,0
  1070.          mov   cx,ax
  1071.  
  1072. loadf362:lodsb
  1073.          loop  loadf362
  1074.          jmp   loadf300
  1075.  
  1076. ; ---------
  1077. ; Kein META Event, also hier weiterprüfen
  1078. loadf400:cmp   al,0f0h
  1079.          jz    loadf420
  1080.  
  1081.          cmp   al,0f7h         ; SYSEX - oder SYSEX Continue Events
  1082.          jnz   loadf500
  1083.  
  1084. loadf420:lodsb                 ; Länge nach AL
  1085.          mov   ah,0
  1086.          mov   cx,ax
  1087.  
  1088. loadf440:lodsb
  1089.          loop  loadf440
  1090.          jmp   loadf300
  1091.  
  1092. ; ----------
  1093. ; Hier kommt ein reinrassiger MIDI-Event!
  1094. loadf500:test  al,80h
  1095.          jnz   loadf520        ; MIDI Runtime Message
  1096.  
  1097.          lodsb                 ; Velocity lesen
  1098.          jmp   loadf300        ; und weitermachen
  1099.  
  1100. loadf520:mov   bx,cs:atracks
  1101.          add   bx,CHANNEL
  1102.          mov   cl,al
  1103.          and   cl,0fh
  1104.          mov   cs:[bx],cl
  1105.  
  1106.          mov   cl,al
  1107.          and   al,0f0h
  1108.          cmp   al,0c0h
  1109.          jnz   loadf540
  1110.          mov   cl,[si]
  1111.          mov   bx,cs:atracks
  1112.          add   bx,PATCH
  1113.          cmp   byte ptr cs:[bx],0
  1114.          jz    loadf530
  1115.          mov   byte ptr cs:[bx],-1
  1116.          jmp   short loadf540
  1117.  
  1118. loadf530:inc   cl
  1119.          mov   byte ptr cs:[bx],cl
  1120.  
  1121. loadf540:shr   al,4
  1122.          cmp   al,0ch
  1123.          jz    loadf580
  1124.          cmp   al,0dh
  1125.          jz    loadf580
  1126.          lodsb
  1127. loadf580:lodsb
  1128.          jmp   loadf300
  1129.  
  1130. ; --------
  1131. ; Hier ist der Track abgehandelt
  1132. loadf900:pop   ds
  1133.          inc   atracks
  1134.          mov   ax,atracks
  1135.          cmp   ax,tracks
  1136.          jz    loadfex
  1137.          jmp   loadf200
  1138. loadfex: ret
  1139.  
  1140. ; -----
  1141. ; uplay - Spielt SMF Datei !
  1142. uplay  : call  resetmpu
  1143.          mov   al,3fh
  1144.          call  put_cmd
  1145.  
  1146.          xor   bx,bx
  1147.          mov   di,COUNTER
  1148.          mov   cx,tracks
  1149.  
  1150. uplay020:call  getxdelt
  1151.          stosw
  1152.          mov   ax,dx
  1153.          stosw
  1154.          mov   byte ptr [bx+TRACKFLAGS],0
  1155.          inc   bx
  1156.          loop  uplay020
  1157.  
  1158.          test  u2flag,IS_YAMAHA
  1159.          jz    uplay060
  1160.  
  1161.          mov   cx,8
  1162.          lea   si,drums
  1163.  
  1164. uplay040:lodsb
  1165.          call  put_midi
  1166.          loop  uplay040
  1167.  
  1168. uplay060:push  es
  1169.          mov   ax,3508h
  1170.          int   21h
  1171.          mov   word ptr oldvec08,bx
  1172.          mov   word ptr oldvec08+2,es
  1173.          pop   es
  1174.          mov   tempo,120
  1175.          lea   dx,timint
  1176.          mov   ax,2508h
  1177.          int   21h
  1178.          or    u2flag,IS_PLAY
  1179.  
  1180. uplay120:test  u2flag,IS_PLAY
  1181.          jz    uplay180
  1182.  
  1183. uplay140:mov   ah,1
  1184.          int   16h
  1185.          jz    uplay120
  1186.          mov   ah,0
  1187.          int   16h
  1188.          cmp   al,27
  1189.          jnz   uplay120
  1190.  
  1191. uplay180:and   u2flag,not IS_PLAY
  1192.          call  timrest
  1193.          call  alloff
  1194.          call  resetmpu
  1195.          ret
  1196.  
  1197. ; ---------------
  1198. ; TMAIN! Erster Einstieg - alle Tracks
  1199. tmain  : xor   bx,bx
  1200.          mov   cx,tracks
  1201.  
  1202. ; ---------
  1203. ; Einzelner Track
  1204. uplay220:cmp   byte ptr [TRACKFLAGS+bx],-1
  1205.          jz    uplay500        ; Wenn Track nicht aktiv, weitermachen
  1206.  
  1207.          mov   si,bx
  1208.          shl   si,2
  1209.          add   si,COUNTER
  1210.          lodsw
  1211.          mov   dx,[si]
  1212.          or    ax,ax
  1213.          jnz   uplay300
  1214.          or    dx,dx
  1215.          jnz   uplay300
  1216.  
  1217. ; -----
  1218. ; Timer abgelaufen - Event ausgeben und weitermachen
  1219.  
  1220.          call  putevent
  1221.          call  getxdelt
  1222.          mov   di,bx
  1223.          shl   di,2
  1224.          add   di,COUNTER
  1225.          stosw
  1226.          mov   ax,dx
  1227.          stosw
  1228.          or    ax,ax
  1229.          jnz   uplay500
  1230.  
  1231.          or    dx,dx
  1232.          jz    uplay220
  1233.  
  1234.          jmp   short uplay500
  1235.  
  1236. ; -----
  1237. ; Timer dekrementieren
  1238. uplay300:sub   ax,1
  1239.          sbb   dx,0
  1240.          mov   word ptr [si],dx
  1241.          mov   word ptr [si-2],ax
  1242.  
  1243. uplay500:inc   bx
  1244.          loop  uplay220
  1245.          ret
  1246.  
  1247. ; --------
  1248. ; PutEvent - Verarbeitet Event
  1249. putevent:call  getbyte
  1250.          cmp   al,-1           ; META Event ?
  1251.          jnz   putev200        ; Nein, dann weiter
  1252.  
  1253. ; ----------
  1254. ; Abhandlung META Event
  1255.  
  1256.          call  getbyte         ; Event lesen
  1257.          cmp   al,2fh          ; Event Trackende!
  1258.          jnz   putev100
  1259.  
  1260.          dec   atracks
  1261.          mov   byte ptr [bx+TRACKFLAGS],-1
  1262.          call  getbyte
  1263.          cmp   atracks,0
  1264.          jnz   putev020
  1265.          and   u2flag,not IS_PLAY
  1266. putev020:ret
  1267.  
  1268. putev100:cmp   al,51h          ; Change Tempo wäre noch interessant (!)
  1269.          jnz   putev120
  1270.          push  bx
  1271.          push  cx
  1272.          call  getbyte
  1273.  
  1274.          call  getbyte
  1275.          push  ax
  1276.          call  getbyte
  1277.          mov   ch,al
  1278.          call  getbyte
  1279.          pop   bx
  1280.          mov   cl,al
  1281.          mov   bh,0
  1282.          mov   ax,8700h
  1283.          mov   dx,393h
  1284.          call  ludiv
  1285.  
  1286.          mul   word ptr timebase
  1287.          mov   bx,120
  1288.          div   bx
  1289.  
  1290.          mov   tempo,ax
  1291.          call  timiset
  1292.          pop   cx
  1293.          pop   bx
  1294.          ret
  1295.  
  1296. ; -----------
  1297. ; Ein für uns uninteressanter EVENT - überlesen und zurück!
  1298. putev120:call  getbyte         ; Länge nach AL
  1299.          mov   ah,0
  1300.          push  cx              ; Nach CX
  1301.          mov   cx,ax
  1302.          jcxz  putev160
  1303.  
  1304. putev140:call  getbyte
  1305.          loop  putev140        ; Und Event überlesen
  1306.  
  1307. putev160:pop   cx
  1308.          ret
  1309.  
  1310. ; ----
  1311. ; Kein META-Event - also weitermachen
  1312. putev200:cmp   al,0f0h         ; SYSEX's
  1313.          jz    putev120        ; die überlesen wir einfach
  1314.  
  1315.          cmp   al,0f7h
  1316.          jz    putev120
  1317.  
  1318.          test  al,80h
  1319.          jnz   putev220
  1320.  
  1321.          ; Runtime EVENT
  1322.          call  put_midi
  1323.          call  getbyte
  1324.          call  put_midi
  1325.          ret
  1326.  
  1327. putev220:mov   ah,al
  1328.          shr   ah,4
  1329.          cmp   ah,0bh
  1330.          jbe   putev240
  1331.          cmp   ah,0eh
  1332.          jz    putev240
  1333.  
  1334.          cmp   ah,0ch          ; PRG CHG
  1335.          jz    putev260
  1336.  
  1337.          call  put_midi
  1338.          call  getbyte
  1339.          call  put_midi
  1340.          ret
  1341.  
  1342. putev240:call  put_midi
  1343.          call  getbyte
  1344.          call  put_midi
  1345.          call  getbyte
  1346.          call  put_midi
  1347.          ret
  1348.  
  1349. ; -------
  1350. ; PRG Chg Event
  1351. putev260:test  u2flag,IS_YAMAHA
  1352.          jz    putev280
  1353.          call  map
  1354.          ret
  1355.  
  1356. putev280:call  put_midi
  1357.          call  getbyte
  1358.          call  put_midi
  1359.          ret
  1360. ; ---
  1361. ; map General MIDI
  1362. map    : push  bx
  1363.  
  1364.          push  ax              ; AL = Program Change Controller sichern
  1365.          and   al,0fh          ; Kanal filtern
  1366.          or    al,0b0h         ; Or 0b0h - Control Change
  1367.          mov   ah,al           ; nach AH sichern
  1368.          call  put_midi        ; ausgeben
  1369.          mov   al,0            ; 0 ausgeben
  1370.          call  put_midi
  1371.          mov   al,0            ; 0 ausgeben
  1372.          call  put_midi
  1373.  
  1374.          mov   al,ah           ; Control Change
  1375.          call  put_midi        ; ausgeben
  1376.          mov   al,20h          ; Bank Select Low Byte
  1377.          call  put_midi        ; ausgeben
  1378.          lea   bx,gm_map       ; Adresse GM Map
  1379.          call  getbyte         ; nächstes byte lesen PRG CHANGE
  1380.          mov   ah,0
  1381.          shl   ax,1
  1382.          add   bx,ax           ; Offset in GM Tabelle
  1383.          mov   al,[bx]         ; ausgeben
  1384.          call  put_midi
  1385.  
  1386.          pop   ax              ; PRG Change Controller
  1387.          call  put_midi        ; ausgeben
  1388.          mov   al,[bx+1]       ; PRG
  1389.          call  put_midi        ; ausgeben
  1390.  
  1391.          pop   bx              ; und zurück
  1392.          ret
  1393.  
  1394. ; --------
  1395. ; dispfile - Stellt Informationen dar
  1396. dispfile:lea   si,msg_smfFile
  1397.          call  wstring
  1398.          lea   si,filename
  1399.          call  wstring
  1400.          lea   si,msg_title
  1401.          call  wstring
  1402.          mov   al,'-'
  1403.          mov   cx,73
  1404. dispf100:call  wchar
  1405.          loop  dispf100
  1406.          lea   si,msg_cr
  1407.          call  wstring
  1408.          xor   bx,bx
  1409.  
  1410. ; ---------
  1411. ; Für jeden Track entsprechende Meldung ausgeben!
  1412. dispf120:mov   ax,bx
  1413.          inc   ax
  1414.          cwd
  1415.          mov   stellen,3
  1416.          call  dz
  1417.          mov   al,' '
  1418.          call  wchar
  1419.          mov   cx,24
  1420.          mov   si,bx
  1421.          shl   si,5
  1422.          add   si,TRACKNAME
  1423. dispf140:lodsb
  1424.          or    al,al
  1425.          jz    dispf160
  1426.          call  wchar
  1427.          loop  dispf140
  1428.  
  1429. dispf160:jcxz  dispf200
  1430.          mov   al,' '
  1431. dispf180:call  wchar
  1432.          loop  dispf180
  1433.  
  1434. dispf200:mov   cx,24
  1435.          mov   si,bx
  1436.          shl   si,5
  1437.          add   si,INSTRNAME
  1438. dispf240:lodsb
  1439.          or    al,al
  1440.          jz    dispf260
  1441.          call  wchar
  1442.          loop  dispf240
  1443.  
  1444. dispf260:jcxz  dispf300
  1445.          mov   al,' '
  1446. dispf280:call  wchar
  1447.          loop  dispf280
  1448.  
  1449. dispf300:mov   si,bx
  1450.          shl   si,2
  1451.          add   si,EVENTS
  1452.          lodsw
  1453.          mov   dx,[si]
  1454.          mov   stellen,6
  1455.          call  dz
  1456.          mov   al,' '
  1457.          call  wchar
  1458.  
  1459.          mov   si,bx
  1460.          add   si,CHANNEL
  1461.          lodsb
  1462.          inc   al
  1463.          mov   ah,0
  1464.          cwd
  1465.          mov   stellen,8
  1466.          call  dz
  1467.  
  1468.          mov   si,bx
  1469.          add   si,PATCH
  1470.          lodsb
  1471.          cmp   al,-1
  1472.          jnz   dispf320
  1473.          lea   si,msg_mult
  1474.          call  wstring
  1475.          jmp   short dispf340
  1476.  
  1477. dispf320:mov   ah,0
  1478.          cwd
  1479.          mov   stellen,6
  1480.          call  dz
  1481.  
  1482. dispf340:lea   si,msg_cr
  1483.          call  wstring
  1484.          inc   bx
  1485.          cmp   bx,tracks
  1486.          jz    dispfex
  1487.          jmp   dispf120
  1488.  
  1489. dispfex: ret
  1490.  
  1491. ; --------
  1492. ; fileloop - Durchsucht alle Dateien
  1493. fileloop:mov   ax,1a00h
  1494.          mov   dx,80h
  1495.          int   21h
  1496.  
  1497.          mov   ax,4e00h
  1498.          mov   cx,27h
  1499.          lea   dx,filename
  1500.          int   21h
  1501.          jnb   filel100
  1502.  
  1503. fnf_exit:lea   si,msg_fnf
  1504.          jmp   err_exit
  1505.  
  1506. filel100:mov   si,9eh
  1507.          mov   di,fileaddr
  1508.          mov   cx,6
  1509.          rep   movsw
  1510.          mov   al,0
  1511.          stosb
  1512.          lea   dx,filename
  1513.          mov   ax,3d00h
  1514.          int   21h
  1515.          jb    fnf_exit
  1516.  
  1517.          mov   shandle,ax
  1518.          call  loadfile
  1519.          call  dispfile
  1520.          test  u2flag,IS_TEST
  1521.          jnz   filel120
  1522.  
  1523.          call  uplay
  1524.  
  1525. filel120:mov   ax,3e00h
  1526.          mov   bx,shandle
  1527.          int   21h
  1528.          mov   ax,4f00h
  1529.          int   21h
  1530.          jnb   filel100
  1531.          ret
  1532.  
  1533. ; ------
  1534. ; anfang
  1535. anfang : cld
  1536.          mov   sp,STACKADDR-2
  1537.          call  parscmd
  1538.          call  fileloop
  1539.  
  1540. ende   : mov   ah,4ch
  1541.          int   21h
  1542.  
  1543. ALIGN 16
  1544. filename       label byte
  1545.  
  1546. code     ends
  1547.          end   start
  1548.